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

Should we fire navigate for cross-document history.back()? #78

Closed
domenic opened this issue Mar 16, 2021 · 5 comments · Fixed by #182
Closed

Should we fire navigate for cross-document history.back()? #78

domenic opened this issue Mar 16, 2021 · 5 comments · Fixed by #182
Labels
foundational Foundational open questions whose resolution may change the model dramatically

Comments

@domenic
Copy link
Collaborator

domenic commented Mar 16, 2021

(All of this applies to forward as well as back, but I'll only mention back for simplicity.)

The current table has slightly divergent entries for history.back() vs. browser-UI-initiated back navigations. Summarizing:

  • Browser back, same-document: cancelable = false, canRespond = true
  • Browser back, cross-document: no event
    • Rationale: cancelable = false per above, and canRespond = false because we can't let you convert cross-document history traversals into same-document ones. So, don't fire the event, since it's not actionable.
  • history.back(), same-document: cancelable = true, canRespond = true
    • Rationale: unlike browser back, back-trapping prevention isn't important
  • history.back(), cross-document: cancelable = true, canRespond = false
    • Rationale: unlike browser back, back-trapping prevention isn't important, so the event can fire and be canceled

Since this design, a couple of data points have come up:

  • @natechapin reports that distinguishing history.back() from browser back is currently hard in Chrome, so it'd be kind of nice if we didn't have to.

  • As part of the discussions in Probably don't allow interception of navigations from other documents #75, we realized that history.back() might originate from another frame, and letting that be canceled could be weird. Although it doesn't have the security difficulty discussed there of exposing the navigated-to URL, it might be good to treat the situations similarly.

These might lean toward something more conservative like making history.back() behave the same as browser back: never cancelable, and no event at all when it's cross-document:

  • Browser back, same-document: cancelable = false, canRespond = true
  • Browser back, cross-document: no event
  • history.back(), same-document: cancelable = false, canRespond = true
  • history.back(), cross-document: no event

However, #32's use case of allowing pages to show "are you sure you want to leave?", and in particular some of the latest ideas in #32 (comment), tugs us in a different direction, even if we did want to unify: something like

  • Browser back, same-document: cancelable = true once per user activation, canRespond = true
  • Browser back, cross-document: cancelable = true once per user activation, canRespond = false
  • history.back(), same-document: cancelable = true once per user activation, canRespond = true
  • history.back(), cross-document: cancelable = true once per user activation, canRespond = false

And at that point tying history.back() to user activation seems pretty strange, so I'd suggest

  • Browser back, same-document: cancelable = true once per user activation, canRespond = true
  • Browser back, cross-document: cancelable = true once per user activation, canRespond = false
  • history.back(), same-document: cancelable = true, canRespond = true
  • history.back(), cross-document: cancelable = true, canRespond = false

and none of the above ideas even start taking into account the initiator, per #75.

So: I'm considering this blocked on #32 and #75 for now.

@domenic domenic added the foundational Foundational open questions whose resolution may change the model dramatically label Mar 16, 2021
@tbondwilkinson
Copy link
Contributor

I agree that history.back() should be equivalent to pressing the back button. The distinction between app vs user initiator is probably overly complicated for limited benefit.

Can people use the beforeUnload handler and associated dialog to satisfy #32?

Do we fire other events, besides navigate, for these cases, to enable users to cache resources before the page unloads? Or would we expect that to also be part of an beforeUnload handler?

@domenic
Copy link
Collaborator Author

domenic commented Mar 17, 2021

Can people use the beforeUnload handler and associated dialog to satisfy #32?

Not currently, as beforeunload only works for cross-document navigations. We would need to invent some new kind of single-page beforeunload for the cases described there.

Do we fire other events, besides navigate, for these cases, to enable users to cache resources before the page unloads? Or would we expect that to also be part of an beforeUnload handler?

I think we have plenty of events in the same-document case. And in the cross-document case, yeah, the usual pagehide/beforeunload/unload events seem good to me.

@tbondwilkinson
Copy link
Contributor

To me, it's illogical to add have a respondable event that's not cancellable - because if you can respond to a thing and defer its resolution indefinitely, you should be able to prevent it entirely.

But I would defer to the security folks for what they're comfortable with, who I assume you're talking to in #32.

@domenic
Copy link
Collaborator Author

domenic commented Mar 17, 2021

In my opinion it's very different. If you respond to a back navigation, the back navigation still goes through: you just change the contents of the page that is displayed, i.e. you make it a single-page navigation. Whereas, canceling it stops the back navigation, and leaves you in the current place in the history stack.

@tbondwilkinson
Copy link
Contributor

I mean from an abuse perspective.

If I use respondWith and just leave the promise unresolved, that's a weird user UI too - because it looks like the page is forever loading.

But I suppose you're right, if they click back again they're not trapped

domenic added a commit that referenced this issue Mar 18, 2021
Closes #75, although this leaves open potential issues with history traversal from other documents which we'll track in #78.
domenic added a commit that referenced this issue Mar 19, 2021
Closes #75, although this leaves open potential issues with history traversal from other documents which we'll track in #78.
@domenic domenic added addition A proposed addition which could be added later without impacting the rest of the API foundational Foundational open questions whose resolution may change the model dramatically and removed foundational Foundational open questions whose resolution may change the model dramatically addition A proposed addition which could be added later without impacting the rest of the API labels Nov 4, 2021
domenic added a commit that referenced this issue Nov 4, 2021
Closes #78 and closes #178 by implementing the conclusion in the latter, of firing non-cancelable navigate events for all traversals. #32 remains open as a desired future feature, and is now explicitly called out as such in the README.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
foundational Foundational open questions whose resolution may change the model dramatically
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants