Skip to content
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

Gracefully handle documents that are not fully active #90

Merged
merged 8 commits into from
Jul 15, 2021

Conversation

marcoscaceres
Copy link
Member

@marcoscaceres marcoscaceres commented Jun 9, 2021

Closes #78

The following tasks have been completed:

  • Modified Web platform tests - unfortunately, we don't have the capability to test this with WPT.

Implementation commitment:

cc @rakina


Preview | Diff

Copy link
Member

@rakina rakina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Looks good to me, just need the WPTs now :)

@reillyeon
Copy link
Member

Maybe I'm missing the issue this change is attempting to fix but what happens after the following sequence of events,

  1. Document is fully active.
  2. Script calls navigator.geolocation.watchPosition().
  3. Document becomes not fully active.
  4. A "significant" change in position occurs.
  5. Document becomes fully active.

As written it seems like when a significant change in position occurs while the document is not fully active it will cause the watch to be canceled. Is this intentional? More likely it seems like we want to explicitly cancel all pending requests on transition to being not fully active. We definitely don't want to deliver a position update while not fully active but we may want to preserve active watches and check on transition back to fully active whether a significant change in position has occurred.

@marcoscaceres
Copy link
Member Author

Yeah, I agree. We might need some kind of independent watcher that checks before the callbacks happen.

@marcoscaceres
Copy link
Member Author

marcoscaceres commented Jul 9, 2021

@rakina @reillyeon, I've reworked this a bit so now:

  1. if not fully active and the API is called, gracefully return an arbitrary number.
  2. if document suddenly becomes not fully active, drop the position request on the floor (and keep dropping them until such time as as the doc becomes fully active).
  3. Do the above also for page visibility too - so that only fully active visible documents receive position updates.

I'll put together some tests for what I can.

changes.
</li>
<li>If |document| is not [=Document/fully active=] or not
[=Document/visible=], go back to the previous step and again
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to remember that it happened (not the exact position, but just that we dropped an update) so that we can send an update with the current position when the document becomes fully active and visible again? Otherwise when a page is restored from bfcache and the user stopped moving (?) it might be stuck with a stale location.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In w3ctag/design-principles#317 the example explicitly calls out the Geolocation API as a case where updates should not be queued and delivered once the document becomes fully active. It is however important to note that a site which has called watchPosition() expects geolocation updates when there is a significant change in position. To do otherwise will likely cause the site to appear stale when it is restored from bfcache and result in a poor user experience. Therefore, while updates SHOULD NOT be queued so that the site can observe the history of location changes while it was not fully active a single update SHOULD be delivered if the location is significantly different from the last value the site received while it was fully active.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that's what I wanted to say. I guess we need to track the last position when the page becomes not fully active / visible then, so that we can compare it to the position when it becomes fully active & visible again?

Copy link
Member Author

@marcoscaceres marcoscaceres Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@reillyeon wrote:

watchPosition() expects geolocation updates when there is a significant change in position.

That's true, but iff the document is visible (and fully active).

If the document transitions from "hidden" to "visible", it's perfectly reasonable for the page to call getCurrentPosition() to get a position update. But, .watchPosition() must only receive new significant position changes when visible. That is, if the page was hidden and there was a significant update, then that's too bad/too late - it has to wait for the next significant change.

See code below.

@rakina wrote:

Yep that's what I wanted to say. I guess we need to track the last position when the page becomes not fully active / visible then, so that we can compare it to the position when it becomes fully active & visible again?

My opinion is that we don't need to go to this level, because it can be handled by the developer:

// handle switching tabs
window.onvisibilitychange = () => {
   if (document.visibilityState === 'visible') {
    navigator.geolocation.getCurrentPosition(updateMap);
  }
}
// keep getting significant updates indefinitely...
navigator.geolocation.watchPosition(updateMap);
Copy link
Member

@rakina rakina Jul 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My opinion is that we don't need to go to this level, because it can be handled by the developer:

I guess that sounds reasonable, for the bfcache case web devs can listen for the pageshow event as well. I guess I'm a bit worried that most web devs are not aware of bfcache and thus might miss this edge case (and we kinda want to have existing pages to "just work" with bfcache), but I don't really have a strong opinion on this so I'll trust your decision here!

@marcoscaceres
Copy link
Member Author

I think it might not be possible to test this with WPT. The limitation that we have is that I can't spin up a tab, then switch back to the original test's tab, which would cause the background tab to be "hidden".

Similarly, with an iframe: removing the iframe makes it "hidden", but it simultaneously trashes the iframe's window object, hence you can't call geolocation on it (unless you steal a reference to geolocation before it is GC'ed, but at that point you are dealing with dead objects).

@rakina
Copy link
Member

rakina commented Jul 14, 2021

Similarly, with an iframe: removing the iframe makes it "hidden", but it simultaneously trashes the iframe's window object, hence you can't call geolocation on it (unless you steal a reference to geolocation before it is GC'ed, but at that point you are dealing with dead objects).

Is this still true for the window on a nested iframe too? (so you detach the parent iframe but watch on the nested iframe). Also what about testing the "watch position -> detach, update position -> attach again, see no location update is sent"?

If that's not possible, I guess the only way to test this is through BFCache. Currently @hiroshige-g is setting up the foundations for BFCache WPTs at web-platform-tests/wpt#28950. I think he's planning to write a Geolocation WPT eventually, but if you want to try writing one now you're more than welcome to! (also it's great to have a feedback on the WPT foundations from a non-BFCache person :) )

@marcoscaceres
Copy link
Member Author

Is this still true for the window on a nested iframe too? (so you detach the parent iframe but watch on the nested iframe). Also what about testing the "watch position -> detach, update position -> attach again, see no location update is sent"?

I holds true there too. Once the iframe is removed, the whole document and the window object is GC'd. Reattaching it creates a both a new Window and a new Document (i.e., so position updates are not sent).

Currently @hiroshige-g is setting up the foundations for BFCache WPTs at web-platform-tests/wpt#28950. I think he's planning to write a Geolocation WPT eventually, but if you want to try writing one now you're more than welcome to! (also it's great to have a feedback on the WPT foundations from a non-BFCache person :) )

@hiroshige-g I've be happy to help review those, as it would be an opportunity for me to learn about BFCache.

I'm going to go ahead and merge this, as at least it gets all the browsers aligned on behavior and it's a great privacy improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants