New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of source browsing context in navigation seems totally broken to me #1130

Open
bzbarsky opened this Issue Apr 26, 2016 · 38 comments

Comments

4 participants
@bzbarsky
Collaborator

bzbarsky commented Apr 26, 2016

The way HTML does navigation is that the input is a "source browsing context". This is then used in phrases like "the origin of the source browsing context" (not defined anywhere; browsing contexts don't have origins) and "Set request's client to the source browsing context's active document's Window object's environment settings object".

The problem is that the active document of the source browsing context may not be the document responsible for the navigation, no? Unless we're very careful to ensure that scripts in no-longer-active documents can't perform window.open (even on other windows!), can't submit forms, can't trigger targeted anchors, etc. I'm pretty darned sure nothing prevents the window.open thing, at least.

We should really be passing in the source window or source document or something here.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 26, 2016

Member

That makes sense. (FWIW, see #1117 and #1128 for some initial cleanup of the navigate algorithm. If those land, I plan on producing a lot more. Really want to get it in a much better shape.)

Member

annevk commented Apr 26, 2016

That makes sense. (FWIW, see #1117 and #1128 for some initial cleanup of the navigate algorithm. If those land, I plan on producing a lot more. Really want to get it in a much better shape.)

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 28, 2016

Member

As far as I can tell this is the concept that Fetch calls "client". That would mean that the relevant settings object of the active document would be the way to go.

Member

annevk commented Apr 28, 2016

As far as I can tell this is the concept that Fetch calls "client". That would mean that the relevant settings object of the active document would be the way to go.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 28, 2016

Member

Perhaps we should also start calling it the "client" parameter to the navigate algorithm to indicate the break from the broken current pattern.

Member

annevk commented Apr 28, 2016

Perhaps we should also start calling it the "client" parameter to the navigate algorithm to indicate the break from the broken current pattern.

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky Apr 28, 2016

Collaborator

That would mean that the relevant settings object of the active document would be the way to go

Even when the navigation was started by one of the inactive documents?

I agree that fundamentally what we want here is the Fetch "client".

Collaborator

bzbarsky commented Apr 28, 2016

That would mean that the relevant settings object of the active document would be the way to go

Even when the navigation was started by one of the inactive documents?

I agree that fundamentally what we want here is the Fetch "client".

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 28, 2016

Member

Even when the navigation was started by one of the inactive documents?

Ah, window.open() and similar cases. I'm not sure what would be best. "Current settings object"?

Member

annevk commented Apr 28, 2016

Even when the navigation was started by one of the inactive documents?

Ah, window.open() and similar cases. I'm not sure what would be best. "Current settings object"?

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky Apr 28, 2016

Collaborator

We should start by checking what UAs actually do...

Collaborator

bzbarsky commented Apr 28, 2016

We should start by checking what UAs actually do...

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 2, 2016

Member

Here's a simple test using window.open() from an <iframe>. It seems to have no effect: http://software.hixie.ch/utilities/js/live-dom-viewer/saved/4130. @domenic thoughts? You're way better versed in this than I am.

Member

annevk commented May 2, 2016

Here's a simple test using window.open() from an <iframe>. It seems to have no effect: http://software.hixie.ch/utilities/js/live-dom-viewer/saved/4130. @domenic thoughts? You're way better versed in this than I am.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic May 2, 2016

Member

I am? Dang now I have to try to understand this issue... Will give it a try later today or tomorrow.

Member

domenic commented May 2, 2016

I am? Dang now I have to try to understand this issue... Will give it a try later today or tomorrow.

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 2, 2016

Collaborator

It seems to have no effect:

No effect in what sense? This open() call is being blocked by the popup blocker, right? Try http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4132 and click the button.

Collaborator

bzbarsky commented May 2, 2016

It seems to have no effect:

No effect in what sense? This open() call is being blocked by the popup blocker, right? Try http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4132 and click the button.

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 2, 2016

Collaborator

Oh, and what http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4132 shows is that the referrer being used for window.open is coming from either the incumbent global or the entry global, not from the current or relevant global. I think.

Collaborator

bzbarsky commented May 2, 2016

Oh, and what http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4132 shows is that the referrer being used for window.open is coming from either the incumbent global or the entry global, not from the current or relevant global. I think.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 2, 2016

Member

I meant that the referrer is not coming from the <iframe>, sorry.

Member

annevk commented May 2, 2016

I meant that the referrer is not coming from the <iframe>, sorry.

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 2, 2016

Collaborator

OK, true, and useful data. But that's not quite exercising the case I was really worried about above.

The case I was worried about above is what happens when a window.open call happens and the incumbent global (and/or the entry global if we can arrange that somehow) corresponds to a no-longer-active document. In other words, load some frame, grab a function f from it, where f performs a window.open() call on some window (probably not the iframe's window itself, though it's interesting to test how UAs handle that too; I know Firefox has some security checks around it). Then navigate the iframe so the global of f corresponds to a no-longer-current document. Then call f either from your own script (so you're entry but f is incumbent) or by setting f as an event listener (so f is entry).

Then see what happens.

In practice, based on past testing I've done, I expect that the "f as event listener" case won't call the function at all in Firefox. I think it won't in IE either. Not sure about Safari/Chrome. The "f as incumbent" case will throw an exception trying to call f in at least some IE versions, but iirc call it successfully in other browsers. And the behavior in terms of whether f is called or not is quite different, with some web compat constraints, if we remove the iframe from the DOM instead of navigating it. :( None of that says what the referrer will be, of course. Or the place that determines our secure context state, for that matter (ideally this is the same thing, but I have low confidence in this being the case in specs or impls right now, because secure context state is defined in terms of openers iirc and the opener is the relevant global, I think).

Basically, we need to write an actual set of principled tests, using wpt or something; live dom viewer poking is going to get pretty confusing, esp. as people want to add more tests and modify existing ones to test more edge cases.

Collaborator

bzbarsky commented May 2, 2016

OK, true, and useful data. But that's not quite exercising the case I was really worried about above.

The case I was worried about above is what happens when a window.open call happens and the incumbent global (and/or the entry global if we can arrange that somehow) corresponds to a no-longer-active document. In other words, load some frame, grab a function f from it, where f performs a window.open() call on some window (probably not the iframe's window itself, though it's interesting to test how UAs handle that too; I know Firefox has some security checks around it). Then navigate the iframe so the global of f corresponds to a no-longer-current document. Then call f either from your own script (so you're entry but f is incumbent) or by setting f as an event listener (so f is entry).

Then see what happens.

In practice, based on past testing I've done, I expect that the "f as event listener" case won't call the function at all in Firefox. I think it won't in IE either. Not sure about Safari/Chrome. The "f as incumbent" case will throw an exception trying to call f in at least some IE versions, but iirc call it successfully in other browsers. And the behavior in terms of whether f is called or not is quite different, with some web compat constraints, if we remove the iframe from the DOM instead of navigating it. :( None of that says what the referrer will be, of course. Or the place that determines our secure context state, for that matter (ideally this is the same thing, but I have low confidence in this being the case in specs or impls right now, because secure context state is defined in terms of openers iirc and the opener is the relevant global, I think).

Basically, we need to write an actual set of principled tests, using wpt or something; live dom viewer poking is going to get pretty confusing, esp. as people want to add more tests and modify existing ones to test more edge cases.

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic May 2, 2016

Member

OK, trying to get my head around this.

The difference between the OP's suggestion of "source document" and using a settings object is the cases where that relationship is not 1:1. That is: the about:blank initial navigation, where a window = settings object has two documents; and document.open(), where multiple window = settings objects end up mapping to the same document.

It's not clear to me whether these cases matter for what we're talking about, maybe because I am having trouble piecing together a comprehensive list of the ways in which source browsing context is currently used. It sounds like we have mainly that it's used as the fetch client, which impacts referrer, and ... what else?

I guess the discussion has probably moved on beyond that and is now assuming that it should be "source settings object". Seems fine. The question is then whether the navigation algorithm, when invoked, should be invoked with the current, entry, incumbent, or relevant settings object as the "source settings object".

I agree that a comprehensive set of tests would be helpful. It seems like we'd need a matrix of all the places that invoke the navigate algorithm, and in each case, ways to maximally vary the incumbent/entry/current/relevant settings objects, so we can see which one ends up being used. (How do we test which one is being used? I guess by making sure each is at a different URL, and then checking the resulting referrer?)

Member

domenic commented May 2, 2016

OK, trying to get my head around this.

The difference between the OP's suggestion of "source document" and using a settings object is the cases where that relationship is not 1:1. That is: the about:blank initial navigation, where a window = settings object has two documents; and document.open(), where multiple window = settings objects end up mapping to the same document.

It's not clear to me whether these cases matter for what we're talking about, maybe because I am having trouble piecing together a comprehensive list of the ways in which source browsing context is currently used. It sounds like we have mainly that it's used as the fetch client, which impacts referrer, and ... what else?

I guess the discussion has probably moved on beyond that and is now assuming that it should be "source settings object". Seems fine. The question is then whether the navigation algorithm, when invoked, should be invoked with the current, entry, incumbent, or relevant settings object as the "source settings object".

I agree that a comprehensive set of tests would be helpful. It seems like we'd need a matrix of all the places that invoke the navigate algorithm, and in each case, ways to maximally vary the incumbent/entry/current/relevant settings objects, so we can see which one ends up being used. (How do we test which one is being used? I guess by making sure each is at a different URL, and then checking the resulting referrer?)

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 3, 2016

Collaborator

It's not clear to me whether these cases matter for what we're talking about

That's a good question.

The answer is that navigations can be triggered either via scripted APIs, which are naturally associated with a settings object, not a document per se, or via elements, which are more naturally associated with a document.

We should test what UAs do with the obvious edge case here: inserting an anchor into an initial about:blank, waiting for the new document to get loaded, and then doing click() on that anchor. I'm hoping the answer is "there is no navigation" or something and then I think the distinction becomes irrelevant....

and is now assuming that it should be "source settings object"

I certainly didn't mean to give that impression.

The question is then whether the navigation algorithm, when invoked, should be invoked with the current, entry, incumbent, or relevant settings object as the "source settings object".

The answer likely depends on the way its invoked. When a user clicks a link, there is no current, entry, or incumbent settings object at all. There's a relevant one for the link node, of course. On the other hand, when setting location.href or doing window.open I'm pretty sure that relevant settings object is not the right thing (in the sense of matching browsers or being web-compatible). Needs to be checked, of course.

How do we test which one is being used? I guess by making sure each is at a different URL

Yes.

And yes, we should figure out what other than referrer is affected. I think https state might be (and may not match referrer behavior in browsers!); not sure what else.

Collaborator

bzbarsky commented May 3, 2016

It's not clear to me whether these cases matter for what we're talking about

That's a good question.

The answer is that navigations can be triggered either via scripted APIs, which are naturally associated with a settings object, not a document per se, or via elements, which are more naturally associated with a document.

We should test what UAs do with the obvious edge case here: inserting an anchor into an initial about:blank, waiting for the new document to get loaded, and then doing click() on that anchor. I'm hoping the answer is "there is no navigation" or something and then I think the distinction becomes irrelevant....

and is now assuming that it should be "source settings object"

I certainly didn't mean to give that impression.

The question is then whether the navigation algorithm, when invoked, should be invoked with the current, entry, incumbent, or relevant settings object as the "source settings object".

The answer likely depends on the way its invoked. When a user clicks a link, there is no current, entry, or incumbent settings object at all. There's a relevant one for the link node, of course. On the other hand, when setting location.href or doing window.open I'm pretty sure that relevant settings object is not the right thing (in the sense of matching browsers or being web-compatible). Needs to be checked, of course.

How do we test which one is being used? I guess by making sure each is at a different URL

Yes.

And yes, we should figure out what other than referrer is affected. I think https state might be (and may not match referrer behavior in browsers!); not sure what else.

annevk added a commit that referenced this issue May 3, 2016

Regression: define source browsing context for iframe and frame
1490eba, from PR #484, removed the
source browsing context definition along with "explicit
self-navigation override". This restores the definition of source
browsing context for these elements as it was before that commit.

This fixes #1131, but note that per #1130 further changes are
required here, as browsing contexts are not a good concept to use as
source.

domenic added a commit that referenced this issue May 3, 2016

Regression fix: define source browsing context for iframe and frame
1490eba, from PR #484, removed the
source browsing context definition while removing the "explicit
self-navigation override". This restores the definition of source
browsing context for these elements as it was before that commit.

This fixes #1131, but note that per #1130 further changes are
required here, as browsing contexts are not a good concept to use as
source.
@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

We should test what UAs do with the obvious edge case here: inserting an anchor into an initial about:blank, waiting for the new document to get loaded, and then doing click() on that anchor. I'm hoping the answer is "there is no navigation" or something and then I think the distinction becomes irrelevant....

No browser navigates there. Only Edge throws for click(). Only Firefox dispatches a click event. However, does that not mean that the distinction between global and document is relevant? Or would we put an active document check with the <a> element somewhere?

Member

annevk commented May 20, 2016

We should test what UAs do with the obvious edge case here: inserting an anchor into an initial about:blank, waiting for the new document to get loaded, and then doing click() on that anchor. I'm hoping the answer is "there is no navigation" or something and then I think the distinction becomes irrelevant....

No browser navigates there. Only Edge throws for click(). Only Firefox dispatches a click event. However, does that not mean that the distinction between global and document is relevant? Or would we put an active document check with the <a> element somewhere?

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

I created web-platform-tests/wpt#3060 to share the demos/tests I'm making.

Member

annevk commented May 20, 2016

I created web-platform-tests/wpt#3060 to share the demos/tests I'm making.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

The case I was worried about above is what happens when a window.open call happens and the incumbent global (and/or the entry global if we can arrange that somehow) corresponds to a no-longer-active document. In other words, load some frame, grab a function f from it, where f performs a window.open() call on some window (probably not the iframe's window itself, though it's interesting to test how UAs handle that too; I know Firefox has some security checks around it). Then navigate the iframe so the global of f corresponds to a no-longer-current document. Then call f either from your own script (so you're entry but f is incumbent) or by setting f as an event listener (so f is entry).

I tried the very simple case here and Edge gives "SCRIPT5011: Can't execute code from a freed script", Chrome gives "TypeError: Cannot read property 'open' of null", and Safari and Firefox log nothing and do nothing. This is the commit "Example 2" in my PR linked above.

Member

annevk commented May 20, 2016

The case I was worried about above is what happens when a window.open call happens and the incumbent global (and/or the entry global if we can arrange that somehow) corresponds to a no-longer-active document. In other words, load some frame, grab a function f from it, where f performs a window.open() call on some window (probably not the iframe's window itself, though it's interesting to test how UAs handle that too; I know Firefox has some security checks around it). Then navigate the iframe so the global of f corresponds to a no-longer-current document. Then call f either from your own script (so you're entry but f is incumbent) or by setting f as an event listener (so f is entry).

I tried the very simple case here and Edge gives "SCRIPT5011: Can't execute code from a freed script", Chrome gives "TypeError: Cannot read property 'open' of null", and Safari and Firefox log nothing and do nothing. This is the commit "Example 2" in my PR linked above.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

Example 3 targets a named frame (instead of _self). Edge and Chrome give the same error. Firefox and Safari navigate the named frame to "HI" (Firefox used to sometimes fail in a non-deterministic way, but that might have been a cache issue).

Member

annevk commented May 20, 2016

Example 3 targets a named frame (instead of _self). Edge and Chrome give the same error. Firefox and Safari navigate the named frame to "HI" (Firefox used to sometimes fail in a non-deterministic way, but that might have been a cache issue).

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

Example 4 uses window.location from a navigated away document. Edge and Chrome give the same error as with 3. Safari fails silently. Works in Firefox.

Member

annevk commented May 20, 2016

Example 4 uses window.location from a navigated away document. Edge and Chrome give the same error as with 3. Safari fails silently. Works in Firefox.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

(This seems to suggest that navigation does not have to work if the "relevant document" is not active. It does not really answer what "source browsing context" should become. Guess I should work on that next through finding some ways to navigate that do work across all browsers.)

Member

annevk commented May 20, 2016

(This seems to suggest that navigation does not have to work if the "relevant document" is not active. It does not really answer what "source browsing context" should become. Guess I should work on that next through finding some ways to navigate that do work across all browsers.)

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

Example 5/6 demonstrates that browsers mostly agree on referrer. For part 1 Edge differs and uses the top-level browsing context's document, whereas everyone else uses the document of the child as referrer. For part 2 everyone uses the top document. The difference is that in part 1 we invoke a function in the child from an event listener and in part 2 we invoke location in the child from the parent directly from the event listener.

Does that mean that Edge uses "entry" and everyone else uses "incumbent"? I'm having a hard time with this. 😟

Member

annevk commented May 20, 2016

Example 5/6 demonstrates that browsers mostly agree on referrer. For part 1 Edge differs and uses the top-level browsing context's document, whereas everyone else uses the document of the child as referrer. For part 2 everyone uses the top document. The difference is that in part 1 we invoke a function in the child from an event listener and in part 2 we invoke location in the child from the parent directly from the event listener.

Does that mean that Edge uses "entry" and everyone else uses "incumbent"? I'm having a hard time with this. 😟

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 20, 2016

Collaborator

I mentioned this to @annevk on IRC, but also worth testing what happens when documents are navigated away from vs what happens when their containing iframe is removed from the DOM. Gecko, for example, will block webidl callback invocation when the callback is backed by a function from a navigated-away-from document, but iirc we discovered that for web compat we had to support it when the callback is backed by a function from a document whose containing iframe was removed...

Collaborator

bzbarsky commented May 20, 2016

I mentioned this to @annevk on IRC, but also worth testing what happens when documents are navigated away from vs what happens when their containing iframe is removed from the DOM. Gecko, for example, will block webidl callback invocation when the callback is backed by a function from a navigated-away-from document, but iirc we discovered that for web compat we had to support it when the callback is backed by a function from a document whose containing iframe was removed...

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 20, 2016

Member

From IRC:

7:35 PM <bz> annevk: We should just put together a test matrix here
7:35 PM <bz> annevk: type of entry (ok, navigated-from, removed)
7:35 PM <bz> annevk: type of incumbent
7:35 PM <bz> annevk: type of this object
7:35 PM <bz> annevk: type of current realm of open method....
7:35 PM — bz counts 81, cries
7:36 PM — annevk has about 9
7:36 PM <bkelly> bz: actually, we do still need the FetchDriver notification callback because necko only propagates headers on internal redirect
7:36 PM <annevk> Also, it's not immediately obvious to me how to recreate all those scenarios
7:37 PM <annevk> And since most thus far seems to be failing we're not much closer to figuring out what "source browsing context" should be either
7:38 PM <bz> You should check location sets too
7:38 PM <bz> not just window.open
7:38 PM <bz> Obviously the failing cases we can just spec to fail if we want
7:38 PM <bz> But we should figure out the nonfailing ones
7:39 PM <bz> If they can all fail, so much the better.
7:39 PM <annevk> Sure, and <a>...
7:39 PM <bz> But then browsers need to actually do that consistently.....
7:39 PM <annevk> Getting browsers to align on the <iframe> is navigated away from or removed case will be hard, but I don't disagree

I should probably research the section @domenic added on this to see if that helps me figure out how to create this text matrix. My current nine or so tests show that browsers don't really navigate much.

Member

annevk commented May 20, 2016

From IRC:

7:35 PM <bz> annevk: We should just put together a test matrix here
7:35 PM <bz> annevk: type of entry (ok, navigated-from, removed)
7:35 PM <bz> annevk: type of incumbent
7:35 PM <bz> annevk: type of this object
7:35 PM <bz> annevk: type of current realm of open method....
7:35 PM — bz counts 81, cries
7:36 PM — annevk has about 9
7:36 PM <bkelly> bz: actually, we do still need the FetchDriver notification callback because necko only propagates headers on internal redirect
7:36 PM <annevk> Also, it's not immediately obvious to me how to recreate all those scenarios
7:37 PM <annevk> And since most thus far seems to be failing we're not much closer to figuring out what "source browsing context" should be either
7:38 PM <bz> You should check location sets too
7:38 PM <bz> not just window.open
7:38 PM <bz> Obviously the failing cases we can just spec to fail if we want
7:38 PM <bz> But we should figure out the nonfailing ones
7:39 PM <bz> If they can all fail, so much the better.
7:39 PM <annevk> Sure, and <a>...
7:39 PM <bz> But then browsers need to actually do that consistently.....
7:39 PM <annevk> Getting browsers to align on the <iframe> is navigated away from or removed case will be hard, but I don't disagree

I should probably research the section @domenic added on this to see if that helps me figure out how to create this text matrix. My current nine or so tests show that browsers don't really navigate much.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 23, 2016

Member

I committed a bunch of window.open() tests trying to follow the text matrix established above in web-platform-tests/wpt#3060. I'm not entirely sure what conclusions to draw however and what to require in the specification. Tentatively, I think following Gecko/Safari in using "entry" for referrer (Fetch's client concept) makes sense (Chrome uses "incumbent", Edge is unclear as it always logs the empty string). We could probably further require that if the "entry" doesn't have an associated browsing context, we won't navigate anything. Not sure beyond that.

Member

annevk commented May 23, 2016

I committed a bunch of window.open() tests trying to follow the text matrix established above in web-platform-tests/wpt#3060. I'm not entirely sure what conclusions to draw however and what to require in the specification. Tentatively, I think following Gecko/Safari in using "entry" for referrer (Fetch's client concept) makes sense (Chrome uses "incumbent", Edge is unclear as it always logs the empty string). We could probably further require that if the "entry" doesn't have an associated browsing context, we won't navigate anything. Not sure beyond that.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 23, 2016

Member

So I think based on the various tests what we can conclude is that window.open() uses entry and location maybe uses incumbent, but that Safari definitely doesn't implement that distinction in the same way Firefox does. I suspect @domenic will find the same once he tries to figure out what various pieces of the platform need to use...

What Edge does is less clear since it seems for a lot of cases there simply is no referrer.

Member

annevk commented May 23, 2016

So I think based on the various tests what we can conclude is that window.open() uses entry and location maybe uses incumbent, but that Safari definitely doesn't implement that distinction in the same way Firefox does. I suspect @domenic will find the same once he tries to figure out what various pieces of the platform need to use...

What Edge does is less clear since it seems for a lot of cases there simply is no referrer.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 25, 2016

Member

Further testing from @bzbarsky revealed that I'm wrong and that "current" or some such is more likely. Ugh. I have a new plan:

  1. Write some new tests to determine what the source is in "common" scenarios across browsers.
  2. Based on that outcome update the specification.
  3. Open a new issue for determining and updating the specification with respect to destroyed browsing contexts, etc.
Member

annevk commented May 25, 2016

Further testing from @bzbarsky revealed that I'm wrong and that "current" or some such is more likely. Ugh. I have a new plan:

  1. Write some new tests to determine what the source is in "common" scenarios across browsers.
  2. Based on that outcome update the specification.
  3. Open a new issue for determining and updating the specification with respect to destroyed browsing contexts, etc.

annevk added a commit that referenced this issue May 30, 2016

Get origin from a browsing context's active document
A browsing context does not have an origin, but its active document
does. This is unlikely to be a complete fix for #1130, but at least it
makes the current state of play more readable.
@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 30, 2016

Member

From web-platform-tests/wpt#3060 it does actually seem like inactive documents might not be able to be a source for navigation. At least not consistently across browsers.

I created a fix for the problem with grabbing origin from a browsing context as mentioned in OP. At this point I'd rather not do away with the source browsing context concept just yet. It requires a lot of refactoring and it doesn't seem like we're clear on what it should be.

Member

annevk commented May 30, 2016

From web-platform-tests/wpt#3060 it does actually seem like inactive documents might not be able to be a source for navigation. At least not consistently across browsers.

I created a fix for the problem with grabbing origin from a browsing context as mentioned in OP. At this point I'd rather not do away with the source browsing context concept just yet. It requires a lot of refactoring and it doesn't seem like we're clear on what it should be.

annevk added a commit that referenced this issue May 30, 2016

Get origin from a browsing context's active document
A browsing context does not have an origin, but its active document
does. This is unlikely to be a complete fix for #1130, but at least it
makes the current state of play more readable.
@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 30, 2016

Member

So I think what's left here:

  1. Preventing non-active documents from reaching the point where they can invoke navigate. More tests might be needed, but it seems there's some agreement on that.
  2. There might still be some problems then since "navigate" goes asynchronous at some point. So perhaps "navigate" needs to grab stuff such as "active document" of the "source browsing context" early on...

So some further redesign is probably warranted, but note that changing "source browsing context" to something like "source settings object" is not without issues, since it's passed to a number of things such as "can navigate" and "familiar with" that expect a browsing context (it could be that those are wrongish too of course...).

Member

annevk commented May 30, 2016

So I think what's left here:

  1. Preventing non-active documents from reaching the point where they can invoke navigate. More tests might be needed, but it seems there's some agreement on that.
  2. There might still be some problems then since "navigate" goes asynchronous at some point. So perhaps "navigate" needs to grab stuff such as "active document" of the "source browsing context" early on...

So some further redesign is probably warranted, but note that changing "source browsing context" to something like "source settings object" is not without issues, since it's passed to a number of things such as "can navigate" and "familiar with" that expect a browsing context (it could be that those are wrongish too of course...).

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky Jun 2, 2016

Collaborator

If we can get to a situation where non-active documents simply don't invoke navigation ever, then passing a browsing context to navigate and then snapshotting the parts of it we care about before going async sounds fine.

Collaborator

bzbarsky commented Jun 2, 2016

If we can get to a situation where non-active documents simply don't invoke navigation ever, then passing a browsing context to navigate and then snapshotting the parts of it we care about before going async sounds fine.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 27, 2017

Member

So thinking about this some more the fundamental problem seems to be to derive authority from browsing contexts, which do not really represent anything. (I appreciate this was clear to others in this thread, just stating it for myself.)

Given that, defining algorithms such as "familiar with" and "allowed to navigate" on top of browsing contexts also doesn't help. For better or worse, it seems these should all be documents. A global object would be nicer, but I suspect that in browsers it's mostly the document that carries all the baggage and globals would get tricky with the initial about:blank case.

That still doesn't take away the other things from above, that we should try to assert that non-active documents cannot cause navigation (which I think is true since their event loop simply doesn't run).

Member

annevk commented Apr 27, 2017

So thinking about this some more the fundamental problem seems to be to derive authority from browsing contexts, which do not really represent anything. (I appreciate this was clear to others in this thread, just stating it for myself.)

Given that, defining algorithms such as "familiar with" and "allowed to navigate" on top of browsing contexts also doesn't help. For better or worse, it seems these should all be documents. A global object would be nicer, but I suspect that in browsers it's mostly the document that carries all the baggage and globals would get tricky with the initial about:blank case.

That still doesn't take away the other things from above, that we should try to assert that non-active documents cannot cause navigation (which I think is true since their event loop simply doesn't run).

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky Apr 27, 2017

Collaborator

we should try to assert that non-active documents cannot cause navigation

Consider the following situation. Page A loads same-origin page B, grabs a function from B, and adds it as an event listener to some node in A. Then it unloads B, so B is no longer an active document.

Now the event fires, the function is called, that function causes navigation (e.g. by setting top.location.href). What document is considered as "causing the navigation"?

Collaborator

bzbarsky commented Apr 27, 2017

we should try to assert that non-active documents cannot cause navigation

Consider the following situation. Page A loads same-origin page B, grabs a function from B, and adds it as an event listener to some node in A. Then it unloads B, so B is no longer an active document.

Now the event fires, the function is called, that function causes navigation (e.g. by setting top.location.href). What document is considered as "causing the navigation"?

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Apr 28, 2017

Member

@bzbarsky that scenario is what you also described earlier in this thread, I think, and what I tried to test with the various tests I wrote in web-platform-tests/wpt#3060. What I got stuck with is deciding who's right and who's wrong.

Member

annevk commented Apr 28, 2017

@bzbarsky that scenario is what you also described earlier in this thread, I think, and what I tried to test with the various tests I wrote in web-platform-tests/wpt#3060. What I got stuck with is deciding who's right and who's wrong.

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky Apr 28, 2017

Collaborator

Ah, ok. I mean, we could maybe argue that the thing that "caused the navigation" is A, not B (though that makes life a lot more complicated in terms of both implementation and specification, I expect, because you have to track more stuff around JS execution). But it definitely shouldn't be the C that got loaded in place of B, no matter what.

Collaborator

bzbarsky commented Apr 28, 2017

Ah, ok. I mean, we could maybe argue that the thing that "caused the navigation" is A, not B (though that makes life a lot more complicated in terms of both implementation and specification, I expect, because you have to track more stuff around JS execution). But it definitely shouldn't be the C that got loaded in place of B, no matter what.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 2, 2017

Member

Notes from discussion on IRC:

  • Gecko grabs "source origin", "referrer", and a few other things before invoking "navigate", so those don't necessarily come from the same source.
  • Gecko uses browsing contexts to determine "allowed to navigate"; in practice that's only needed for <a> and <form> (browsing context that contains their node document), and window.open() (browsing context that contains its relevant global object). And then the origin that gets compared is that of the current document origin (which I think is the active document in the specification).
Member

annevk commented May 2, 2017

Notes from discussion on IRC:

  • Gecko grabs "source origin", "referrer", and a few other things before invoking "navigate", so those don't necessarily come from the same source.
  • Gecko uses browsing contexts to determine "allowed to navigate"; in practice that's only needed for <a> and <form> (browsing context that contains their node document), and window.open() (browsing context that contains its relevant global object). And then the origin that gets compared is that of the current document origin (which I think is the active document in the specification).
@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 3, 2017

Member

Progress: in #2615 I've managed to exclude all elements that can cause navigation as being problematic, since they can all be made to require a fully active document. That still leaves window.open() and window.location, but makes the overall problem a bit more focused.

Member

annevk commented May 3, 2017

Progress: in #2615 I've managed to exclude all elements that can cause navigation as being problematic, since they can all be made to require a fully active document. That still leaves window.open() and window.location, but makes the overall problem a bit more focused.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk May 15, 2017

Member

@bzbarsky do you know when "source origin" and "referrer" don't come from the same source?

Member

annevk commented May 15, 2017

@bzbarsky do you know when "source origin" and "referrer" don't come from the same source?

@bzbarsky

This comment has been minimized.

Show comment
Hide comment
@bzbarsky

bzbarsky May 15, 2017

Collaborator

Not offhand. I'd have to go audit all the loading codepaths. Note that this would include all codepaths via the UI (e.g. modifier+click, context menu options on links, etc).

Collaborator

bzbarsky commented May 15, 2017

Not offhand. I'd have to go audit all the loading codepaths. Note that this would include all codepaths via the UI (e.g. modifier+click, context menu options on links, etc).

@kengraWin

This comment has been minimized.

Show comment
Hide comment
@kengraWin

kengraWin commented Dec 9, 2017

Good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment