Re: WebIDL and prototype chains

2009-08-08 Thread Adam Barth
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

2009-08-07 Thread Ian Hickson
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

2009-07-16 Thread Jonas Sicking
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

2009-07-16 Thread Adam Barth
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

2009-07-16 Thread Geoffrey Garen
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

2009-07-16 Thread Jonas Sicking
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

2009-07-16 Thread Adam Barth
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

2009-07-16 Thread Adam Barth
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

2009-07-16 Thread Maciej Stachowiak


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

2009-07-16 Thread Ian Hickson
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

2009-07-16 Thread Maciej Stachowiak


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

2009-07-16 Thread Ian Hickson
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

2009-07-16 Thread Maciej Stachowiak


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