Open Bug 1123986 Opened 10 years ago Updated 2 years ago

Suppress onbeforeunload dialogs when closing a tab.

Categories

(Firefox :: Tabbed Browser, defect)

defect

Tracking

()

People

(Reporter: jruderman, Unassigned)

References

(Blocks 1 open bug)

Details

As dolske noted in bug 1050638 comment 0, no mobile browsers support onbeforeunload when closing a tab. (Some support it for navigation.)

We should pick up the same behavior for desktop Firefox, for the reasons described in bug 578828.
Blocks: 1116977
Blocks: 1125285
I fail to see how tab-closing is a special case which is exempt from the examples given in bug 578828 comment 70 and bug 578828 comment 71.

For example, 
> You are hosting a virtual conference (webcam), instead of clicking on the next tab to google something you hit the tab's close button
(In reply to Stephan Sokolow from comment #1)
> I fail to see how tab-closing is a special case which is exempt from the
> examples given in bug 578828 comment 70 and bug 578828 comment 71.
> 
> For example, 
> > You are hosting a virtual conference (webcam), instead of clicking on the next tab to google something you hit the tab's close button

You can always:
-pin the tab
-do searching or etc. in other browser windows
-not click blindly
(In reply to Virtual_ManPL [:Virtual] from comment #2)
> (In reply to Stephan Sokolow from comment #1)
> > I fail to see how tab-closing is a special case which is exempt from the
> > examples given in bug 578828 comment 70 and bug 578828 comment 71.
> > 
> > For example, 
> > > You are hosting a virtual conference (webcam), instead of clicking on the next tab to google something you hit the tab's close button
> 
> You can always:
> -pin the tab
> -do searching or etc. in other browser windows
> -not click blindly

Talk to them, not me. They're concerned about making Firefox the best it can be for typical users.

I've already conceded defeat after all of the cases of "follow Chrome's lead... even when it makes no sense" so I'll just do as I've always done. Grab an addon like Classic Theme Restorer or twiddle an about:config key like browser.urlbar.trimURLs and then get on with my life.
Hi everyone, if I may add my 2 cents?

I've been reviewing/commenting several bugs related to this issue today, since I happened upon bug 1116977 yesterday, and there's one possible solution I've not seen anywhere.

To me, simple user and family/friends help-desk, this reminds me of the automatic auth. In that this feature can be useful in some use cases, but an attack vector in others/most.

Ideally, the solution would be the same a white-list like "network.automatic-ntlm-auth.trusted-uris", but I understand the caution in changing the current behavior.
Maybe the answer could be a black-list that allows wild-cards? Or better yet, a white-list that's disabled?
This way, nothing changes in the default install, and people (me and everybody that I personally know :) will have one more step in personalizing a new install.

Thanks,
Marco
(In reply to Marco Marujo from comment #4)
> useful in some use cases, but an
> attack vector in others/most.

Absolutely.
I think at this point we really do need some solution here (how many years has this bug been documented for? years worth of history from a quick google searc), I can't believe there are people defending how leaving onbeforeunload dialogs unsupressed (and uncontrollable) is the right thing to do!

More and more sites are now exploiting this flaw and there is still no simple way to disable the dialog boxes. I'd really like to turn them off completely at this point, they are doing far more harm than good.

I like the idea of having a white list as Marco suggests, giving permission to individual domains I trust to use this feature, and no other. Default behaviour can still be the (horrible) current default behaviour, just give me the option to block it from all sites or all sites but a specific whitelist.
(In reply to Zaibatsu from comment #5)
> More and more sites are now exploiting this flaw and there is still no
> simple way to disable the dialog boxes.

There is dom.disable_beforeunload in about:config.
(In reply to Zaibatsu from comment #5)
> (In reply to Marco Marujo from comment #4)
> > useful in some use cases, but an
> > attack vector in others/most.
> 
> Absolutely.
> I think at this point we really do need some solution here (how many years
> has this bug been documented for? years worth of history from a quick google
> searc), I can't believe there are people defending how leaving
> onbeforeunload dialogs unsupressed (and uncontrollable) is the right thing
> to do!
> 
> More and more sites are now exploiting this flaw and there is still no
> simple way to disable the dialog boxes. I'd really like to turn them off
> completely at this point, they are doing far more harm than good.
> 
> I like the idea of having a white list as Marco suggests, giving permission
> to individual domains I trust to use this feature, and no other. Default
> behaviour can still be the (horrible) current default behaviour, just give
> me the option to block it from all sites or all sites but a specific
> whitelist.

I still haven't seen a convincing reason why they can't be fixed by this set of changes:
0. (done according to my tests) Ignore site-provided text and provide safe "are you sure?" text.
1. Make the dialog tab-modal.
2. Interpret Ctrl+W or clicking the tab close button as meaning "yes, I'm sure" (easier to implement
   and more obviously a course of action the user can take once it's tab-modal)
3. Possibly something equivalent to the "don't show these anymore" checkbox on alert() and friends
   after the first one.

I'd say Firefox and Chrome both did a pretty good job of neutering the exploit potential of alert() and related modal dialog calls... and those are far less directly useful than onbeforeunload.
(In reply to Stephan Sokolow from comment #7)
> I still haven't seen a convincing reason why they can't be fixed by this set
> of changes:
> 0. (done according to my tests) Ignore site-provided text and provide safe
> "are you sure?" text.
> 1. Make the dialog tab-modal.
> 2. Interpret Ctrl+W or clicking the tab close button as meaning "yes, I'm
> sure" (easier to implement
>    and more obviously a course of action the user can take once it's
> tab-modal)
> 3. Possibly something equivalent to the "don't show these anymore" checkbox
> on alert() and friends
>    after the first one.

0-2 of these are all done.

The issue that other people are having is that there are pages that try really really hard to create more of these dialogs / keep people on the page. You would be surprised in how many ways this is possible (hint: frames, calling window.open from the event, simulating link clicks on target="_blank" links from window blur events, onkeypress, etc.). We've been "boarding up the holes" on those vectors, but really, when you get 10000 people to land on a page like this and 100 can't figure out how to close them without paying you money, that translates into a lot of motivation for authors to find more holes.

So we need to do "at least" 3 (ie, more than 0-2) or something like it. See also e.g. bug 636905.


As a general note to everyone participating, I'll add that the incredulity-back-and-forth here isn't super helpful. If you have ideas on what to do besides the above, especially if it's easier to implement than the checkbox or 636905, that'd be helpful. More comments along the "I don't understand how your experience is so different from mine / why doing X/Y/Z isn't good enough" line are not helpful. Please provide concrete suggestions and their up/downsides.
I understand there are a lot of holes, but this still feels like scapegoating a feature which, if removed from general use, might result in uglier "not the right way in a theoretical sense, but easier for browser-makers to implement" workarounds involving either one of the local storage mechanisms or synchronous XHR.

(I'm a UI/UX guy, so, when I say uglier, I'm talking about things like having a website unexpectedly remember state in a confusing or potentially embarrassing way, giving sites like Google more excuse to waste bandwidth and make mildly private data available for data mining by real-time syncing all state to the server, plugging up the user's hard drive because every site used localstorage/indexeddb/etc. to re-implement the concept of an undo cache but the browser didn't provide a way for a site to set an expiry period without the user visiting again so it can expire things manually, etc.)

There's a reason that, in this era of abundant hard drive space, MS Word still displays an "Are you sure?" dialog rather than greeting your significant other with your aborted attempt at erotic fiction when they open it the next morning.

As for the ways it's possible, the apparent difficulty of solving bugs like bug 636905 and bug 659285 gives me the impression that something about Firefox's internal architecture makes it more difficult than it should be to retrofit guards based on questions like "Is this the result of a user-triggered action?" or "Are we inside an onbeforeunload handler?"

The former was already implemented in the ad-blocker, yet it's been ages and bug 659285 doesn't even have an experimental fix, and both feel like the kind of things where, if something about Firefox (eg. an asynchronous invocation somewhere along the way) prevents just setting a boolean in a higher stack frame, then there should be a generalized workaround.

I'm honestly curious to know what about Firefox's guts complicates that approach. (I'd dive in and learn, but I'm more interested in learning Rust and I haven't even managed to make time for that yet.)
(In reply to Stephan Sokolow from comment #9)
> As for the ways it's possible, the apparent difficulty of solving bugs like
> bug 636905 and bug 659285 gives me the impression that something about
> Firefox's internal architecture makes it more difficult than it should be to
> retrofit guards based on questions like "Is this the result of a
> user-triggered action?" or "Are we inside an onbeforeunload handler?"

ITYM "The web's architecture", not Firefox's. That, as well as "backwards compatibility / don't break the web", cf.

// good luck not breaking this but stopping JS-based autoplay.
node.addEventListener("click", function(e) { setTimeout(function() { mediaElement.play(); }, 0); });

> The former was already implemented in the ad-blocker.

This bug is long enough without me explaining everything that's wrong with our popup blocker, but suffice it to say that it is not perfect and people complain about that all the time, too. I'd want to make a number of changes before being comfortable reusing its decision model for media autoplay (and that would take some refactoring on top of those changes still).

More importantly, we're talking about two different problems:

a) is invocation X the result of direct interaction Y
b) has the user ever directly interacted with the page at any time

(where (b) is what bug 636905 needs)

> yet it's been ages and
> bug 659285 doesn't even have an experimental fix, and both feel like the
> kind of things where, if something about Firefox (eg. an asynchronous
> invocation somewhere along the way) prevents just setting a boolean in a
> higher stack frame, then there should be a generalized workaround.
> 
> I'm honestly curious to know what about Firefox's guts complicates that
> approach. (I'd dive in and learn, but I'm more interested in learning Rust
> and I haven't even managed to make time for that yet.)

It's not that bug 636905 is *too* complicated, it's that it takes time that is hard to find, and will add some measure of code complexity. Having something that takes less time to implement and adds less code complexity would be helpful.
(In reply to :Gijs Kruitbosch from comment #6)
> (In reply to Zaibatsu from comment #5)
> > More and more sites are now exploiting this flaw and there is still no
> > simple way to disable the dialog boxes.
> 
> There is dom.disable_beforeunload in about:config.

Thanks kindly, which version of FF did this become an option in? 
Does it just disable those dialog boxes entirely (whether tabs or windows)?
Are there any others (apart from beforeunload) that are commonly exploited and I could/should disable at the same time?

I'm new here but I've been searching for a solution for a while now and actually signed up purely for this reason. Clearly I wasn't looking hard enough, my apologies and I shall venture back into my hole.
(In reply to :Gijs Kruitbosch from comment #10)
> ITYM "The web's architecture", not Firefox's. That, as well as "backwards
> compatibility / don't break the web", cf.
> 
> // good luck not breaking this but stopping JS-based autoplay.
> node.addEventListener("click", function(e) { setTimeout(function() {
> mediaElement.play(); }, 0); });
> 

I said "Firefox's internal architecture" because, in my outsider hindsight, it seems obvious that, in an event-driven, cooperatively multitasked environment (which JavaScript's main/DOM thread essentially is), a runtime for untrusted code should provide some way to set contextual annotations which persist across "yield time to other tasks" operations (ie. setTimeout).

(eg. play() could check "Regardless of how many setTimeout calls sat in between then and now, did this chain of events begin with user input?" It wouldn't be perfect in the case of things like video ads being triggered by a <body onclick> but it'd be sufficient to prevent playback as a result of "open in a background tab" before the user has chosen to actually interact with said tab and it could form a base for more advanced checks.)

Sorry for the delayed response. I was distracted by a cold I caught.
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:42.0) Gecko/20100101 Firefox/42.0
20150828004008

In the latest FDE, I no longer get a prompt when closing either a tab or the whole window. See bug 1199645.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.