WICG / close-watcher

A web API proposal for watching for close requests (e.g. Esc, Android back button, ...)
https://html.spec.whatwg.org/multipage/interaction.html#close-requests-and-close-watchers
71 stars 5 forks source link

<dialog> integration compat issue #17

Closed domenic closed 10 months ago

domenic commented 2 years ago

The current spec attempts to integrate <dialog> with close watchers very directly. However, due to the anti-abuse restrictions, this breaks compat on desktop OSes in some cases.

As background, our anti-abuse restrictions are that you basically get to intercept one close signal per user activation, to avoid back trapping with the Android back button. If you try to intercept more, you will either not be able to create a CloseWatcher, or you will not get a cancel event.

However, we apply those restrictions uniformly across platforms, including on desktop platforms where the signal is the non-abusable Esc key. The idea is to avoid platform-specific differences and make it easier to test-once, run-on-any-user's-device.

This seems fine for the new CloseWatcher class. But for <dialog> this does have compat impacts:

I think these behaviors are good for integrating the Android back button with <dialog>s. (Note that no browser has such integration today, so it's a question about whether the proposed integration, subject to the above restrictions, is better than nothing.)

And I think in the real world these restrictions should be survivable for <dialog>s even on desktop. People should generally not open more than one <dialog> without user activation. But, it is a concern.

Ideas:

/cc @smaug---- @annevk @josepharhar

annevk commented 2 years ago

Isn't consuming Esc potentially dangerous on desktop too? E.g., when <dialog> is used in combination with the fullscreen API?

domenic commented 2 years ago

It turns out no, since all browsers prioritize leaving fullscreen before any dialog processing. This is now specced rigorously, and I suppose it's possible we could even web platform test it.

dvoytenko commented 2 years ago

On the surface, I'd think this is mainly a problem of a specific "back gesture". The reason for that is because "back gesture" on Android (and possibly other devices) is "global" and thus abuse of it is bad. The same would be the case in a hypothetical case of a TV-like remote with a back button - abusing that global button would be bad. Not sure how to express this in the CloseWatcher API though. Really the only obvious solution I'd see is if a browser were to mediate the vetoable "cancel" signal, just as we do today in the onbeforeunload with the system prompt. It's a bad UX, but clean abuse protection. Maybe there could be a compromise and a browser could prompt on a repeated "cancel" event?

domenic commented 2 years ago

To restate what I think @dvoytenko is saying, we have a fundamental conflict between encouraging platform-agnostic code, vs. desktop compat. I.e., if we preserve behavior on desktop by not limiting Esc, then desktop and Android will behave observably differently.

One way around this would potentially be to have desktop and Android behave the same to a web developer, but different to the user. For example, we would allow unlimited close watchers / cancel event preventDefault()s on both platforms, but sometimes on Android that would pop up a dialog to the user saying "this page seems to be trying to prevent you from leaving. Do you want to leave anyway?" and then the page would navigate away if the user said yes.

In the end these are all tradeoffs.

My preference is still the current spec auto-mitigation on both desktop and mobile, if we can get away with it. But if we cannot then I think I still prefer the current spec auto-mitigation on just mobile. The cost will be an increase in poorly-coded but non-malicious sites since testing on desktop won't automatically give the same behavior on mobile.

annevk commented 2 years ago

The prompt gives a malicious site a window for further abuse I suppose, but maybe that's okay (as the user should be safe either way).

josepharhar commented 2 years ago

If you showModal() many <dialog>s without user activation, only the first (bottommost) will be closeable with Esc. Others will ignore close signals. (This avoids creating tons of <dialog>s on Android which consume all the back button presses.)

This WPT tests this behavior: https://github.com/web-platform-tests/wpt/blob/9beb905959/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html https://wpt.fyi/results/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html?label=experimental&label=master&aligned If we choose to do full CloseWatcher for dialog, I would have to basically invert the expectations.

On one hand, websites probably don't open multiple modal dialogs at the same time, right...? Maybe I should add a UseCounter for this.

On the other hand, the escape key isn't used to navigate the page like the back button does on android, so I don't see why there should be any CloseWatcher user activation stuff with the escape key. If CloseWatcher could consume the navigate back button in the browser UI on desktop, then it would be easy choice to do the same on android and desktop.

Does CloseWatcher do anything on desktop besides consume the escape key?

dvoytenko commented 2 years ago

@josepharhar the idea is that a developer doesn't need to specifically support a particular platform: whatever the most natural gesture to cancel is present on the platform - the dialog implementation propagates it as a cancel signal.

domenic commented 2 years ago

To recap: after #23, the potential behavior changes for <dialog> if we ship https://wicg.github.io/close-watcher/#patch-dialog are:

I hope to add use counters to capture how often these cases would come up, to help us determine whether changing behavior in these cases is feasible.

domenic commented 10 months ago

The use counters came back very low, and we resolved this compat issue to be negligible: