html icon indicating copy to clipboard operation
html copied to clipboard

Define when navigator and location objects are replaced

Open foolip opened this issue 7 years ago • 19 comments

The document attribute returns the associated Document and the history attribute is defined in terms of that as well.

For navigator and location, there isn't anything to suggest that these objects are replaced when navigating an iframe.

https://jsbin.com/jagiruh/edit?html,output is a test that passes in Chrome, Firefox and Safari, showing that a bunch of objects are replaced when navigating an iframe. It fails with "Permission denied" in Edge.

foolip avatar Apr 18 '17 04:04 foolip

Is this all entangled with the reasons that WindowProxy exist, perhaps?

foolip avatar Apr 18 '17 04:04 foolip

This came up in https://codereview.chromium.org/2805763004 where I wanted to propose something like an "is active" check for the navigator object.

foolip avatar Apr 18 '17 04:04 foolip

Yeah, WindowProxy typically persists, but its underlying Window object definitely changes upon navigation (unless initial about:blank).

annevk avatar Apr 18 '17 04:04 annevk

The spec here is pretty bad for Navigator:

The navigator attribute of the Window interface must return an instance of the Navigator interface, which represents...

It could be any instance! The entire browser could share a single instance!! Ugh.

For Location it's much better:

Each Window object is associated with a unique instance of a Location object, allocated when the Window object is created.

and Window objects are created explicitly during navigation and other scenarios.

domenic avatar Apr 18 '17 04:04 domenic

I wrote this test:

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe></iframe>
<script>
async_test(t => {
  const frameLocation = self[0].location,
        frameNavigator = self[0].navigator,
        frameHistory = self[0].history
  self[0].frameElement.onload = t.step_func_done(() => {
    assert_equals(self[0].location, frameLocation)
    assert_equals(self[0].navigator, frameNavigator)
    assert_equals(self[0].history, frameHistory)
  })
  self[0].location.href = "/common/blank.html"
})
</script>

Note that History objects are technically associated with documents, so it should change here, but in Firefox it does not and it passes the test. However, in Chrome and Safari I get

assert_equals: expected [stringifying object threw TypeError: Cannot convert object to primitive value with type object] but got object "http://web-platform.test:8000/common/blank.html"

which I'm not sure what to do with.

annevk avatar Apr 20 '17 13:04 annevk

@foolip @cdumez any clues why the above test throws a TypeError? It looks perfectly reasonable to me.

annevk avatar Apr 20 '17 17:04 annevk

It looks like the exception is thrown when test harness tries to construct a string for the error message from frameLocation. All those assertions fail in WebKit, we do not return the same objects after the navigation. Therefore, frameLocation is in a state where it throws when trying to do whatever the test harness does.

cdumez avatar Apr 20 '17 19:04 cdumez

That seems like a bug in itself as everything is same-origin and nothing would end up throwing like that (it seems to simply try to ToString it). And not returning the same object is a bug too. I guess all this is even less interoperable than I thought.

annevk avatar Apr 21 '17 07:04 annevk

I believe our location object relies on having a frame to be useful. However, after the navigation, it seems we create a new Location object and the old one ends up being frameless.

cdumez avatar Apr 21 '17 17:04 cdumez

If I reduce my above test to just Navigator objects I get different objects in Chrome and Safari, I get "Permission denied" in Edge, and I get a pass in Firefox.

I think what Firefox does makes the most sense, unless we really want to tie all these objects to Document objects while they are accessed from the Window object...

annevk avatar Apr 24 '17 14:04 annevk

Created a test for window.location with @domenic's excellent per-global framework: https://github.com/w3c/web-platform-tests/pull/5778. All browsers are different. 🎉

  • https://bugzilla.mozilla.org/show_bug.cgi?id=1361975
  • https://bugs.chromium.org/p/chromium/issues/detail?id=718363
  • https://bugs.webkit.org/show_bug.cgi?id=171648
  • https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11895829/

Once we make progress there I'd propose we make History and Navigator per-global as well.

annevk avatar May 04 '17 09:05 annevk

Wow, thanks for the excellent research! I've merged https://github.com/w3c/web-platform-tests/pull/5778, do you think we should wait for that to be sorted out implementation-side before doing anything further here?

foolip avatar May 04 '17 13:05 foolip

Yeah, I'm wondering whether Chromium and WebKit have architectural reasons for having almost everything associated with Document objects. If they're okay with moving some things to the global object I think we're good, but if not, we probably want to reconsider a couple of things before pushing this further.

annevk avatar May 04 '17 13:05 annevk

I'm not sure either. A change like this might end up with @tkent-google to ponder, WDYT?

foolip avatar May 04 '17 13:05 foolip

I guess fixing this is not easy due to out-of-process iframe.

tkent-google avatar May 08 '17 02:05 tkent-google

I'm actually now confused how it can work securely to associate things with the global object. If you grab a reference to this associated thing and then navigate the initial about:blank frame cross-origin, what happens? @bzbarsky how does Firefox handle that?

annevk avatar May 08 '17 08:05 annevk

If you grab a reference to this associated thing and then navigate the initial about:blank frame cross-origin, what happens?

The same thing that happens when you navigate any other page cross-origin. You get a new global object, with a different origin from the old global object. The things you were holding on to are still referencing the old global object. Do you have a specific scenario or API you're concerned about?

bzbarsky avatar May 08 '17 16:05 bzbarsky

Thanks, I had just missed that replacement only happens same-origin. @tkent-google so what exactly is the issue with out-of-process child documents then?

annevk avatar May 10 '17 16:05 annevk

I don't have an idea of exact technical issues at this moment. It's just a guess, and I don't think fixing it is impossible.

tkent-google avatar May 11 '17 08:05 tkent-google