Re: WebIDL and prototype chains
On Fri, Aug 7, 2009 at 5:51 PM, Ian Hicksoni...@hixie.ch wrote: How should I address this for HTML5? We talked over several option in #whatwg. Here's something that might make sense. The approach below is designed to allow for robust implementation and to isolated the magical properties in the window object. Principle: Two distinct origins should have distinct JavaScript object graphs. The only point of contact between the JavaScript objects of different origins should be window objects (or, more precisely, WindowProxy objects). Rules: 1) When a script gets a property from a same-origin window object, the script gets the same object as the page itself gets. 2) When a script gets a property from a cross-origin window object, the script gets a *new* object with the appropriate interface. a) This new object is created in context of the accessing script (i.e., the current lexical scope). That means it gets a prototype chain as appropriate for the accessing script. b) If two scripts from the same context access the same property, they get the same object. That is, we cache these newly created objects per accessing window. (They will likely be garbage collected with that window as well.) Corollaries: 1) Suppose property foo is visible across origins and a script changes it's own window.foo property in some way. That change is not visible to cross-origin viewers (because they get a fresh instance of whatever the foo object originally was.) Note: This behavior matches Firefox but differs from IE. In IE, cross-origin viewers tend to see the value |undefined| when viewing properties that have been modified by the page. This causes minor security issues. 2) If two scripts from two same-origin windows get some property from the same cross-origin window, the values they obtain will not be ===. This is to avoid having different behavior based on which script accesses the property first. 3) If one script grabs some property from a cross-origin window and then later because same-origin with that window (e.g., via document.domain tricks), then that script will get a different object (the real one) if it access the property again. Adam
Re: WebIDL and prototype chains
On Thu, 16 Jul 2009, Maciej Stachowiak wrote: On Jul 16, 2009, at 8:04 PM, Ian Hickson wrote: On Thu, 16 Jul 2009, Maciej Stachowiak wrote: HTML5 just says that new History, Location, etc, objects are created for each (inner) Window object. Is this not accurate? What do browsers do? Creating new ones on navigation is indeed correct, but a separate issue from making sure cross-origin cross-frame access to things like history.back() is safe for both parties. In HTML5, you can't access .history cross-domain, and you can't get to the prototype of the .location object (the only thing you can do to .location is set the .href member). Are these restrictions Web-incompatible? WebKit-based browsers allow cross-origin back(), forward() and go() on History, and replace(), reload() and assign() on Location, in addition to setting of href. I can't say definitively that all of those are needed to be Web compatible. Firefox allows access to at least location.replace() and history.back() cross-domain, and I would tentatively guess at least these two are required for Web compatibility. IE doesn't seem to allow history.back() cross-domain. I've made HTML5 allow everything IE8 seems to allow. postMessage() (or, say, focus()) is another example of something that needs to be accessible cross-origin, and I don't think you can fully hide its prototype because call() and apply() should be usable on it, for example. I haven't thought through exactly how this needs to work. The point is mainly that anything accessible cross-origin probably can't just follow the normal rules for building a prototype chain. How should I address this for HTML5? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 10:45 AM, Adam Barthw...@adambarth.com wrote: When a browser creates an instance of a DOM object defined by an WebIDL interface, the browser must choose where to connect it's prototype chain. For example, consider this case (where frames[0] is a same-origin child frame): var doc = frames[0].document; 1) To which global object's prototypes ought |doc| connect to, the parent frame running the script or the child frame from which we obtained the document? My best guess is that the prototype chain ought to connect to the child's prototype Absolutely. |doc| will simply be pointing to the same object that frames[0].document does. So the prototype chain must be the same for both. And it's clear that when code inside frames[0] accesses that frames document it should have a protochain based on the globals in that frame. I don't have any strong opinions on where this is specced. / Jonas
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 1:13 PM, Jonas Sickingjo...@sicking.cc wrote: On Thu, Jul 16, 2009 at 10:45 AM, Adam Barthw...@adambarth.com wrote: When a browser creates an instance of a DOM object defined by an WebIDL interface, the browser must choose where to connect it's prototype chain. For example, consider this case (where frames[0] is a same-origin child frame): var doc = frames[0].document; 1) To which global object's prototypes ought |doc| connect to, the parent frame running the script or the child frame from which we obtained the document? My best guess is that the prototype chain ought to connect to the child's prototype Absolutely. |doc| will simply be pointing to the same object that frames[0].document does. So the prototype chain must be the same for both. And it's clear that when code inside frames[0] accesses that frames document it should have a protochain based on the globals in that frame. Firefox is much more consistent in this regard than Safari or Chrome: http://webblaze.org/abarth/tests/protoconfused/test1.html However, Firefox does not appear to attach function prototypes correctly. Maybe I should file a bug. :) Adam
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 10:45 AM, Adam Barthw...@adambarth.com wrote: When a browser creates an instance of a DOM object defined by an WebIDL interface, the browser must choose where to connect it's prototype chain. Hopefully, we can spec the behavior non-DOM objects, like Array.prototype.push, and primitives converted to object, as well. Geoff
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 2:59 PM, Maciej Stachowiakm...@apple.com wrote: On Jul 16, 2009, at 10:45 AM, Adam Barth wrote: When a browser creates an instance of a DOM object defined by an WebIDL interface, the browser must choose where to connect it's prototype chain. For example, consider this case (where frames[0] is a same-origin child frame): var doc = frames[0].document; 1) To which global object's prototypes ought |doc| connect to, the parent frame running the script or the child frame from which we obtained the document? 2) Where is this behavior specified? If the behavior is currently not specified, which spec ought to contain the requirements? My best guess is that the prototype chain ought to connect to the child's prototype (because the document is owned by the child frame) and that the WebIDL spec ought to include this requirement (because WebIDL explains how to reify abstract DOM interfaces in ECMAScript). Thoughts? One thing to note: any object or method that is exposed cross-origin should specifically *not* have this behavior. Instead, it should create a separate interface object in every frame that accesses the property. window.history, window.location and window.postMessage are examples that require this treatment. Web IDL needs to give a hook to other specs so they can specify that cross-origin properties need to get this different treatment. I definitely agree you definitely don't want the inner windows prototype values if it's a cross-origin window. What you should get is less clear to me. If you should get the outer windows prototype or some sort of blank prototype. Personally it'd make the most sense to me if you got a blank prototype since that seems like the most consistent behavior. / Jonas
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 2:58 PM, Jonas Sickingjo...@sicking.cc wrote: There's currently a bug in 3.5 which is why functions are failing. It is fixed in the upcoming 3.5.1 release. The only other non-PASS thing I see in firefox is .content, which basically is the same as .top and so is working as expected. This is a leftover from some old code which we should just remove. So no bug necessary :) Awesome. I've removed content from the test. Adam
Re: WebIDL and prototype chains
On Thu, Jul 16, 2009 at 3:08 PM, Jonas Sickingjo...@sicking.cc wrote: On Thu, Jul 16, 2009 at 2:59 PM, Maciej Stachowiakm...@apple.com wrote: One thing to note: any object or method that is exposed cross-origin should specifically *not* have this behavior. Instead, it should create a separate interface object in every frame that accesses the property. window.history, window.location and window.postMessage are examples that require this treatment. Web IDL needs to give a hook to other specs so they can specify that cross-origin properties need to get this different treatment. I definitely agree you definitely don't want the inner windows prototype values if it's a cross-origin window. What you should get is less clear to me. If you should get the outer windows prototype or some sort of blank prototype. Personally it'd make the most sense to me if you got a blank prototype since that seems like the most consistent behavior. Either behavior seems fine to me. I'd just like to see it speced somewhere so we can all do the same thing. :) Adam
Re: WebIDL and prototype chains
On Jul 16, 2009, at 3:08 PM, Jonas Sicking wrote: I definitely agree you definitely don't want the inner windows prototype values if it's a cross-origin window. What you should get is less clear to me. If you should get the outer windows prototype or some sort of blank prototype. Personally it'd make the most sense to me if you got a blank prototype since that seems like the most consistent behavior. Window itself is even more of a special case. What I had in mind is objects hanging off of Window that are accessible to a limited extent cross-origin, such as History, or Location, or the postMessage function. I don't think it would work to give those a blank prototype. And you can't just give them the prototype chain from their home window because that would be an XSS violation. Regards, Maciej
Re: WebIDL and prototype chains
On Thu, 16 Jul 2009, Maciej Stachowiak wrote: On Jul 16, 2009, at 3:08 PM, Jonas Sicking wrote: I definitely agree you definitely don't want the inner windows prototype values if it's a cross-origin window. What you should get is less clear to me. If you should get the outer windows prototype or some sort of blank prototype. Personally it'd make the most sense to me if you got a blank prototype since that seems like the most consistent behavior. Window itself is even more of a special case. What I had in mind is objects hanging off of Window that are accessible to a limited extent cross-origin, such as History, or Location, or the postMessage function. I don't think it would work to give those a blank prototype. And you can't just give them the prototype chain from their home window because that would be an XSS violation. HTML5 just says that new History, Location, etc, objects are created for each (inner) Window object. Is this not accurate? What do browsers do? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: WebIDL and prototype chains
On Jul 16, 2009, at 5:58 PM, Ian Hickson wrote: On Thu, 16 Jul 2009, Maciej Stachowiak wrote: On Jul 16, 2009, at 3:08 PM, Jonas Sicking wrote: I definitely agree you definitely don't want the inner windows prototype values if it's a cross-origin window. What you should get is less clear to me. If you should get the outer windows prototype or some sort of blank prototype. Personally it'd make the most sense to me if you got a blank prototype since that seems like the most consistent behavior. Window itself is even more of a special case. What I had in mind is objects hanging off of Window that are accessible to a limited extent cross-origin, such as History, or Location, or the postMessage function. I don't think it would work to give those a blank prototype. And you can't just give them the prototype chain from their home window because that would be an XSS violation. HTML5 just says that new History, Location, etc, objects are created for each (inner) Window object. Is this not accurate? What do browsers do? Creating new ones on navigation is indeed correct, but a separate issue from making sure cross-origin cross-frame access to things like history.back() is safe for both parties. Regards, Maciej
Re: WebIDL and prototype chains
On Thu, 16 Jul 2009, Maciej Stachowiak wrote: HTML5 just says that new History, Location, etc, objects are created for each (inner) Window object. Is this not accurate? What do browsers do? Creating new ones on navigation is indeed correct, but a separate issue from making sure cross-origin cross-frame access to things like history.back() is safe for both parties. In HTML5, you can't access .history cross-domain, and you can't get to the prototype of the .location object (the only thing you can do to .location is set the .href member). Are these restrictions Web-incompatible? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: WebIDL and prototype chains
On Jul 16, 2009, at 8:04 PM, Ian Hickson wrote: On Thu, 16 Jul 2009, Maciej Stachowiak wrote: HTML5 just says that new History, Location, etc, objects are created for each (inner) Window object. Is this not accurate? What do browsers do? Creating new ones on navigation is indeed correct, but a separate issue from making sure cross-origin cross-frame access to things like history.back() is safe for both parties. In HTML5, you can't access .history cross-domain, and you can't get to the prototype of the .location object (the only thing you can do to .location is set the .href member). Are these restrictions Web-incompatible? WebKit-based browsers allow cross-origin back(), forward() and go() on History, and replace(), reload() and assign() on Location, in addition to setting of href. I can't say definitively that all of those are needed to be Web compatible. Firefox allows access to at least location.replace() and history.back() cross-domain, and I would tentatively guess at least these two are required for Web compatibility. postMessage() (or, say, focus()) is another example of something that needs to be accessible cross-origin, and I don't think you can fully hide its prototype because call() and apply() should be usable on it, for example. I haven't thought through exactly how this needs to work. The point is mainly that anything accessible cross-origin probably can't just follow the normal rules for building a prototype chain. Regards, Maciej