Defining the WindowProxy, Window, and Location objects
Until recently, the HTML Standard lacked a precise definition of the
Location objects. As you might imagine, these are fairly important objects, so having them be underdefined was not great for the web. (Note that the global object used for documents is the
WindowProxy object, which serves as a proxy and security boundary for the
Each navigable frame (top-level tab,
<iframe> element, et cetera) is called a browsing context in the HTML Standard. A browsing context has an associated
Window object. As you navigate a browsing context, the associated
Window object changes. But the whole time, the
WindowProxy object stays the same. Ergo, one
WindowProxy object is a proxy for many
To make matters more interesting, scripts in these different browsing contexts can access each other, through
window.open(), et cetera. The same-origin policy generally forbids code from one origin from accessing code from a different origin, which prevents evil.com from prying into bank.com. The two legacy exceptions to this rule are the
Location objects, which have some properties that can be accessed across origins.
document.domain makes this even trickier, as it effectively allows you to observe a
Location object as cross-origin initially, and same-origin later, or vice versa. Since the object remains the same during that time, the same-origin versus cross-origin logic needs to be part of the same object and cannot be spread across different classes.
Defining this all in detail has been a multi-year effort spearheaded by Bobby Holley, Boris Zbarsky, Ian Hickson, Adam Barth, Domenic Denicola, and Anne van Kesteren, and completed in the “define security around
Location objects properly” pull request. The basic setup we ended up with is that
Location objects have specific cross-origin branches in their internal method implementation. These take care to only expose specific properties, and even for those properties, generating specific accessor functions per origin. This ensures that cross-origin access is not inadvertently allowed through something like
Object.getOwnPropertyDescriptor(otherWindowProxy, "window").get. After filtering, a
WindowProxy object will forward to its
Window object as appropriate, whereas a
Location object simply gives access to its own properties.
Having these objects defined in detail will make it easier for implementations to refactor, and for new novel implementations like Servo to achieve web-compatibility. It will reduce debugging time for web developers after implementations have converged on the edge cases. And it drastically simplifies extending these objects, as well as placing new restrictions upon them, within this well-defined subsystem. Well-understood, stable foundations are the key to future extensions.
(Many thanks to Bobby Holley for his contributions to this post.)
Web developers should additionally rejoice at this brave new world, because it enables the exciting possibility for Location objects to have cyclic
Object.setPrototypeOf(Location.prototype, location); // doesn’t throw a TypeError
In fact, Firefox nightly builds already implement this important advance in the web platform. So give it a try! You never knew what you were missing.
…okay, more seriously, this is good stuff that’ll make the web platform better specified and, in time, more interoperably implemented. Even if cracktastic behavior like in the previous comment occasionally, unavoidably, falls out of the process. 🙂
Will this help Chrome and Firefox behave the same with respect to non-writable, non-configurable properties of the window proxy when the location/window changes (the window proxy’s target)? Currently, in Chrome they disappear and in Firefox they are kept.