-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Nested contexts and unload prompts #6446
Comments
I'm not aware of anything and I agree it sounds great. I have asked some other people to weigh in as needed. (Gijs provided https://bugzilla.mozilla.org/show_bug.cgi?id=1131187 and https://bugzilla.mozilla.org/show_bug.cgi?id=1655866, and suggested the frame in the tests in OP might not be interacted with by the user as the cause.) |
Aww, I was hoping we could just ignore unload prompts from frames. I guess not. I've updated the results and recommendation. |
The "weird" behaviour of moving history position without updating the active document came up in #6483 too, but it seems reasonable there, so I might end up specing that anyway. If the top level shows a prompt, and the user cancels, the traversal should cancel. Ideally, for iframes, we should cancel traversal if any iframe shows a prompt and the user cancels (and limit to one prompt). But if that isn't implementable, we should allow the traversal to go ahead but avoid changing the active documents for frames that show a prompt (and it's cancelled). We should avoid the mix of iframe behaviours we currently see in Chrome and Firefox. |
There's also the case of navigations that fail the allowed to navigate test. Again, it feels like we should cancel the whole traversal if any part of it is not allowed. |
If the page has two iframes, both with unload listeners, and the top-level page is navigated, all browsers ignore the second prompt (although the event still runs). I haven't tested this with cross-origin iframes (is it racey?), but it seems like browsers are trying not to show multiple prompts, but just forgot (or don't care about) the |
This came up as I was working through the session history rewrite. How should navigations behave when a page, an iframe, or multiple iframes request to show an unload prompt?
Here's what I've noticed by poking browsers:
Firefox
For top-level navigations, Firefox shows unload prompts, and if the user cancels, they stay on the same session history entry.
Firefox ignores requests to show unload prompts for iframes unless the user has interacted with the iframe (eg clicked it). Otherwise:
For iframes, if going back 1 position, Firefox shows unload prompts, and if the user cancels, they stay on the same session history entry.
If going back more than 1 position, things get weird. Firefox shows unload prompts, and if the user cancels, the cancelled frame doesn't navigate, but the position in session history is changed, which is weird.
If going back 2 positions, involving 2 iframes each with an unload prompt, you get two prompts and if you cancel both you stay on the same session history entry.
Chrome
For top-level navigations, Chrome shows unload prompts, and if the user cancels, they stay on the same session history entry.
For iframes, if going back 1 position, it does the same. Chrome shows unload prompts, and if the user cancels, they stay on the same session history entry.
If going back more than 1 position, things get weird. Chrome shows unload prompts, and if the user cancels, the cancelled frame doesn't navigate, but the position in session history is changed, which is weird.
If going back 2 positions, involving 2 iframes each with an unload prompt, you get two prompts but even if you cancel both Chrome will navigate one of the iframes anyway 🙃. It also changes the position in session history.
Safari
For top-level same-origin navigations, Safari shows unload prompts, and if the user cancels, they stay on the same session history entry.
For top-level cross-origin, Safari does not show a prompt.
Safari allows unload prompts for iframes. It changes the position in session history but doesn't navigate the cancelled frames. Again this is weird, but it seems to do it more consistently in Chrome. Not sure if this is a good thing.
Due to moving the session history position, but not navigating the page, Safari can be 'tricked' into displaying the wrong URL in the URL bar. However, this only happens for same-origin so it isn't a security issue.
The 'correct' behaviour
If we want to allow unload prompts for iframes, I like to spec it so: If any unloading document requests an unload prompt, show one prompt. If cancelled, abort the navigation/traversal. However, I'm not sure UAs are in a good position to 'synchronise' navigations in a way where unloading happens across all documents before moving to the next steps.
When I first saw Firefox's behaviour, I thought we could maybe ignore all unload prompts from iframes, but given it allows them after interaction, maybe not.
I'm less sure about Safari's behaviour of ignoring unload prompts for cross-origin navigations. Feels like that would miss a lot of legitimate use-cases.
The tests
Test: Same origin top level navigation
Firefox: Shows prompt. Cancelling keeps you on the same session history entry.
Chrome: Shows prompt. Cancelling keeps you on the same session history entry.
Safari: Shows prompt. Cancelling keeps you on the same session history entry.
Behaviour here seems to make sense.
Test: Cross origin top level navigation
Firefox: Shows prompt. Cancelling keeps you on the same session history entry.
Chrome: Shows prompt. Cancelling keeps you on the same session history entry.
Safari: No prompt. Navigates.
Interesting that Safari is different.
Test: Same origin top level navigation, go(-2)
history.go(-2)
or long-press back button), cancel promptFirefox: Shows prompt. Cancelling keeps you on the same session history entry.
Chrome: Shows prompt. Cancelling keeps you on the same session history entry.
Safari: Prompt shown. Cancelling keeps you on the same session history entry, however, the URL bar changes to https://iframe-session-history.glitch.me/page.html?one (thankfully
location.href
doesn't change).Safari's behaviour here is a bug, surely.
Test: Traverse single nested context with prompt
https://iframe-session-history.glitch.me/
Firefox: No prompt shown unless the iframe has been interacted with (eg clicked). Otherwise, prompt shown. Cancelling keeps you in the same position in session history.
Chrome: Prompt shown. Cancelling keeps you in the same position in session history.
Safari: Prompt shown. Cancelling moves you to the previous position in session history, but the iframe doesn't navigate. Going back again doesn't reshow the prompt (it navigates iframe-1 as expected). Going forward twice (to the point where iframe-2 was navigated) shows the prompt again, and reloads the iframe page unless cancelled.
Safari's behaviour seems broken here. Chrome/Firefox behaviour is better.
Test: Traverse two nested contexts at once, one with prompt
https://iframe-session-history.glitch.me/
history.go(-2)
or long-press back button), cancel promptFirefox: No prompt shown unless the iframe has been interacted with (eg clicked). Otherwise, cancelling moves you back two places in session history. ifame-2 navigates, iframe-1 does not. Going forward shows the prompt again.
Chrome: Prompt shown. Cancelling moves you back two places in session history. ifame-2 navigates, iframe-1 does not. Going forward shows the prompt again.
Safari: Prompt shown. Cancelling moves you back two places in session history. ifame-2 navigates, iframe-1 does not. Same behaviour as previous test in terms of navigating back & forth.
Safari's behaviour is weird but consistent with the last test. The way Chrome/Firefox seems to have changed behaviour with this example is weird.
The results are the same if iframe-2 has the prompt instead.
Test: Traverse two nested contexts at once, both with prompt
history.go(-2)
or long-press back button), cancel prompts.Firefox: No prompt shown unless the iframe has been interacted with (eg clicked). Otherwise, two prompts are shown. Cancelling both keeps you on the same session history entry.
Chrome: Two prompts shown. Cancelling both moves you back two places in session history. However, iframe-2 is still navigated.
Safari: Two prompts show. Cancelling both moves you back two places in session history. It prevents the navigation of both frames. Going forward doesn't show a prompt, but going forward again shows a prompt for iframe-2.
Safari's behaviour is kinda consistent with previous behaviours, although the lack of prompt when going forward seems unusual compared to previous results. Chrome navigating iframe-2 is just a bug, surely.
The text was updated successfully, but these errors were encountered: