WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
56397
Suppress modal JavaScript/HTML dialogs during unload events
https://bugs.webkit.org/show_bug.cgi?id=56397
Summary
Suppress modal JavaScript/HTML dialogs during unload events
Sreeram Ramachandran
Reported
2011-03-15 11:58:26 PDT
Suppressing modal JavaScript/HTML dialogs (i.e., calls to alert(), confirm(), prompt() and showModalDialog()) during unload events (onbeforeunload() and onunload()) can reduce annoyance and help speed up the appearance of closing a tab. The onbeforeunload() event handler offers an opportunity for a page to request user confirmation before a page is unloaded (by returning a non-NULL value), so the other dialogs are not really needed. References:
http://code.google.com/p/chromium/issues/detail?id=68780
https://bugzilla.mozilla.org/show_bug.cgi?id=391834
Attachments
Patch
(19.42 KB, patch)
2011-03-16 23:32 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Patch
(26.99 KB, patch)
2011-04-09 01:56 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Adds a console message for blocked alerts. Adds Chromium-specific test expectations.
(23.95 KB, patch)
2011-06-14 16:24 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Removes indirection. Uses StringBuilder.
(24.11 KB, patch)
2011-06-14 17:28 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Adds #include for StringBuilder
(24.27 KB, patch)
2011-06-14 17:51 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Diff of test expectations from current files to newly added chromium-specific files
(5.02 KB, text/plain)
2011-06-15 14:58 PDT
,
Sreeram Ramachandran
no flags
Details
Identifies page dismissal event more specifically
(31.24 KB, patch)
2011-06-26 08:35 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Updated test expectation
(31.20 KB, patch)
2011-06-26 08:41 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Diff of test expectations from current files to newly added chromium-specific files
(7.67 KB, patch)
2011-06-28 08:15 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Now logging page dismissal type explicitly in the histograms
(31.65 KB, patch)
2011-06-28 08:44 PDT
,
Sreeram Ramachandran
abarth
: review-
Details
Formatted Diff
Diff
Diff of test expectations from current files to newly added chromium-specific files
(7.69 KB, patch)
2011-06-28 08:45 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Addressed most of abarth's comments
(30.53 KB, patch)
2011-06-28 18:40 PDT
,
Sreeram Ramachandran
webkit.review.bot
: commit-queue-
Details
Formatted Diff
Diff
Addressed most of abarth's comments; fixed build errors
(30.74 KB, patch)
2011-06-28 19:58 PDT
,
Sreeram Ramachandran
abarth
: review-
Details
Formatted Diff
Diff
Now checking all frames in the page
(30.49 KB, patch)
2011-06-29 11:33 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ec2-cr-linux-01
(1.41 MB, application/zip)
2011-06-29 13:05 PDT
,
WebKit Review Bot
no flags
Details
Updated test and expectations
(35.01 KB, patch)
2011-06-29 21:07 PDT
,
Sreeram Ramachandran
abarth
: review+
Details
Formatted Diff
Diff
Diff of test expectations from current files to newly added chromium-specific files
(10.31 KB, patch)
2011-06-29 21:08 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Don't pass ChromeClient explicitly
(34.95 KB, patch)
2011-06-30 07:30 PDT
,
Sreeram Ramachandran
abarth
: review+
webkit.review.bot
: commit-queue-
Details
Formatted Diff
Diff
Fix debug build
(34.99 KB, patch)
2011-06-30 11:14 PDT
,
Sreeram Ramachandran
no flags
Details
Formatted Diff
Diff
Show Obsolete
(17)
View All
Add attachment
proposed patch, testcase, etc.
Sreeram Ramachandran
Comment 1
2011-03-16 23:32:43 PDT
Created
attachment 86035
[details]
Patch
Eric Seidel (no email)
Comment 2
2011-03-17 04:22:48 PDT
Do other browsers block these?
Sreeram Ramachandran
Comment 3
2011-03-17 08:54:00 PDT
(In reply to
comment #2
)
> Do other browsers block these?
None that I know of. The patch is conservative; only blocks these dialogs in Chromium for now. Firefox seems to want to do it as well (
https://bugzilla.mozilla.org/show_bug.cgi?id=391834
).
Sreeram Ramachandran
Comment 4
2011-03-25 10:02:39 PDT
ping?
Ryosuke Niwa
Comment 5
2011-03-25 14:39:25 PDT
Comment on
attachment 86035
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=86035&action=review
> LayoutTests/fast/loader/unload-alert.html:9 > + // Once dialogs are disabled on all platforms, change these to "FAIL" so that > + // if the dialogs appear, it's obvious that the test failed. > + alert("PASS"); > + confirm("PASS"); > + prompt("PASS", "PASS");
This test doesn't make sense on chromium, does it? If any of PASS appear on chromium platform, it actually failed, right? I don't think it's clear at all from the test output or from the comment here.
> Source/WebCore/page/Chrome.cpp:62 > +static inline bool canRunModalDuringUnload() > +{ > +#if PLATFORM(CHROMIUM) > + return false; > +#else > + return true; > +#endif > +}
I don't think this is the right way to do it if we want to make decisions per port. We should add a new callback to WebView or some other class instead.
Ryosuke Niwa
Comment 6
2011-03-25 14:46:54 PDT
Comment on
attachment 86035
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=86035&action=review
> Source/WebCore/page/Chrome.cpp:66 > + return page->mainFrame()->loader()->pageDismissalEventBeingDispatched();
Does this mean that we will disable modal dialogs only when the main frame is unloading? Why do we allow modal dialogs during unload event in subframes? I'd like to see some explanation as to why such a decision was made in the change log entry.
Sreeram Ramachandran
Comment 7
2011-03-28 13:21:39 PDT
Comment on
attachment 86035
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=86035&action=review
>> LayoutTests/fast/loader/unload-alert.html:9 >> + prompt("PASS", "PASS"); > > This test doesn't make sense on chromium, does it? If any of PASS appear on chromium platform, it actually failed, right? I don't think it's clear at all from the test output or from the comment here.
Right, it's misleading for chromium. What would be the preferred way of doing this? Should I: 1. Change the text to read something like "FAIL on chromium; PASS on other platforms"? 2. Somehow fork the test itself for chromium? (I only saw a way to specify a platform-specific expected.ext.) Other ways?
>> Source/WebCore/page/Chrome.cpp:62 >> +} > > I don't think this is the right way to do it if we want to make decisions per port. We should add a new callback to WebView or some other class instead.
Darin (Fisher) explicitly didn't want this (decision to suppress alerts) to be something platform-specific. Though the current patch only enables it for chromium, the goal is to convince other platforms, and make it the default behaviour eventually.
>> Source/WebCore/page/Chrome.cpp:66 >> + return page->mainFrame()->loader()->pageDismissalEventBeingDispatched(); > > Does this mean that we will disable modal dialogs only when the main frame is unloading? Why do we allow modal dialogs during unload event in subframes? I'd like to see some explanation as to why such a decision was made in the change log entry.
My mistake. After chancing upon "allowsBeforeUnloadListeners()" in page/DOMWindow.cpp, I assumed that unload/beforeunload listeners were not allowed for subframes. I created some test pages just now, and I see that in fact, that's not the case; subframes can register listeners for those events. I'll change the patch to disallow alerts in these events for all frames. Meanwhile, before I create that patch, could we get agreement on the approach (i.e., global or platform-specific implementation)?
Sreeram Ramachandran
Comment 8
2011-03-28 21:42:43 PDT
Comment on
attachment 86035
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=86035&action=review
>>> LayoutTests/fast/loader/unload-alert.html:9 >>> + prompt("PASS", "PASS"); >> >> This test doesn't make sense on chromium, does it? If any of PASS appear on chromium platform, it actually failed, right? I don't think it's clear at all from the test output or from the comment here. > > Right, it's misleading for chromium. What would be the preferred way of doing this? Should I: > 1. Change the text to read something like "FAIL on chromium; PASS on other platforms"? > 2. Somehow fork the test itself for chromium? (I only saw a way to specify a platform-specific expected.ext.) > Other ways?
Looking closer, it appears that LayoutTests/platform can also contain .html files, and not just expected.txt files. I'll use that to fork the test for chromium (and add the overridden one to Skipped, if needed).
Ryosuke Niwa
Comment 9
2011-03-28 22:12:47 PDT
(In reply to
comment #7
)
> Right, it's misleading for chromium. What would be the preferred way of doing this? Should I: > 1. Change the text to read something like "FAIL on chromium; PASS on other platforms"? > 2. Somehow fork the test itself for chromium? (I only saw a way to specify a platform-specific expected.ext.) > Other ways?
Put a test in LayoutTests/platform/chromium/. IMO, there's no need to add a test for other ports.
> >> Source/WebCore/page/Chrome.cpp:62 > >> +} > > > > I don't think this is the right way to do it if we want to make decisions per port. We should add a new callback to WebView or some other class instead. > > Darin (Fisher) explicitly didn't want this (decision to suppress alerts) to be something platform-specific. Though the current patch only enables it for chromium, the goal is to convince other platforms, and make it the default behaviour eventually.
If we're trying to convince other platforms to do the same on other ports, then the right approach should be to convince others first, then implement this patch. It's generally a bad idea to introduce a behavioral difference between ports that is visible to JavaScript.
Sreeram Ramachandran
Comment 10
2011-04-09 01:56:23 PDT
Created
attachment 88926
[details]
Patch
Ryosuke Niwa
Comment 11
2011-04-09 14:57:20 PDT
Comment on
attachment 88926
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=88926&action=review
Please separate changes to the existing tests because there's no reason they should be in the same patch.
> Source/WebCore/page/Chrome.cpp:209 > +static inline bool canRunModalDuringPageDismissal() > +{ > +#if PLATFORM(CHROMIUM) > + return false; > +#else > + return true; > +#endif > +}
I don't think this is the right way to do it. Since we already have willRunModalDialogDuringPageDismissal on chrome client, we should rename it to shouldRunModalDialogDuringPageDismissal and have it return a boolean value. I know that we want all ports to eventually disallow modal dialogs but that's not the case at least for now so it seems more natural to have chrome client decide it.
Alexey Proskuryakov
Comment 12
2011-04-09 23:38:08 PDT
One case where this change would be a problem is for people trying to debug their JavaScript code with alerts.
Ojan Vafai
Comment 13
2011-04-10 02:15:08 PDT
(In reply to
comment #12
)
> One case where this change would be a problem is for people trying to debug their JavaScript code with alerts.
That's a fair point. I think most cases where you'd want this could be addressed by adding a "debugger;" line and breaking in the debugger.
Sreeram Ramachandran
Comment 14
2011-04-10 09:16:47 PDT
(In reply to
comment #13
)
> (In reply to
comment #12
) > > One case where this change would be a problem is for people trying to debug their JavaScript code with alerts. > > That's a fair point. I think most cases where you'd want this could be addressed by adding a "debugger;" line and breaking in the debugger.
Agreed. Easier than a debugger is console.log() which is as easy as alert(), especially if we can persist the console output across navigations. It's not as portable as alert(), however it does have an advantage over alert(): It doesn't steal the focus, which is very handy if you are trying to debug something in onblur(), for example.
Ian 'Hixie' Hickson
Comment 15
2011-06-09 00:33:53 PDT
Please don't forget to report your findings to the WHATWG mailing list when you've done this, so I can update the spec to make this conforming behaviour (assuming it isn't found to be ill-advised). This seems like a great idea.
Alexey Proskuryakov
Comment 16
2011-06-14 13:32:46 PDT
FWIW, I was just debugging something in onload, and had a thought that it would have been a problem for me if we were suppressing these alerts.
Sreeram Ramachandran
Comment 17
2011-06-14 14:53:36 PDT
(In reply to
comment #16
)
> FWIW, I was just debugging something in onload, and had a thought that it would have been a problem for me if we were suppressing these alerts.
Did you mean unload? There's no plan to suppress alerts during onload.
Alexey Proskuryakov
Comment 18
2011-06-14 15:22:54 PDT
Yes, sorry for the typo.
Sreeram Ramachandran
Comment 19
2011-06-14 15:26:37 PDT
(In reply to
comment #18
)
> Yes, sorry for the typo.
How about if we add a console message whenever an alert in unload is blocked? Since console messages can be made persistent across page loads, would that be an acceptable compromise?
Adam Barth
Comment 20
2011-06-14 16:21:01 PDT
You might want to check the behavior in Firefox 4. Because their alerts are no longer modal, they might well be effectively suppressed in unload also.
Sreeram Ramachandran
Comment 21
2011-06-14 16:24:38 PDT
Created
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations.
Ryosuke Niwa
Comment 22
2011-06-14 16:33:52 PDT
Comment on
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations. View in context:
https://bugs.webkit.org/attachment.cgi?id=97187&action=review
> Source/WebCore/page/Chrome.cpp:210 > +static inline bool isDuringPageDismissal(const Frame* frame) > +{ > + return frame->loader()->pageDismissalEventBeingDispatched(); > +}
I don't see any point in adding this inline function. It needlessly adds new indirection. We can just call frame->loader()->pageDismissalEventBeingDispatched() directly.
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:959 > + logMessage += " during page dismissal (beforeunload, pagehide or unload).";
Can't we identify which one it is?
Adam Barth
Comment 23
2011-06-14 16:42:36 PDT
Comment on
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations. View in context:
https://bugs.webkit.org/attachment.cgi?id=97187&action=review
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:942 > + String logMessage = "Blocked ";
StringBuilder plz.
Sreeram Ramachandran
Comment 24
2011-06-14 17:05:59 PDT
Comment on
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations. View in context:
https://bugs.webkit.org/attachment.cgi?id=97187&action=review
>> Source/WebCore/page/Chrome.cpp:210 >> +} > > I don't see any point in adding this inline function. It needlessly adds new indirection. We can just call frame->loader()->pageDismissalEventBeingDispatched() directly.
Done.
>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:942 >> + String logMessage = "Blocked "; > > StringBuilder plz.
Done.
>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:959 >> + logMessage += " during page dismissal (beforeunload, pagehide or unload)."; > > Can't we identify which one it is?
Sure, if you are okay with instrumenting stuff in WebCore/loader/FrameLoader.cpp. Instead of that, it might be better (but more hacky) to pass along the JS source file and line number here.
Ryosuke Niwa
Comment 25
2011-06-14 17:06:56 PDT
Comment on
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations. View in context:
https://bugs.webkit.org/attachment.cgi?id=97187&action=review
>>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:959 >>> + logMessage += " during page dismissal (beforeunload, pagehide or unload)."; >> >> Can't we identify which one it is? > > Sure, if you are okay with instrumenting stuff in WebCore/loader/FrameLoader.cpp. Instead of that, it might be better (but more hacky) to pass along the JS source file and line number here.
Oh, that's not what I meant. Can we say whether it was beforeunload, pagehide, or unload?
Sreeram Ramachandran
Comment 26
2011-06-14 17:12:31 PDT
Comment on
attachment 97187
[details]
Adds a console message for blocked alerts. Adds Chromium-specific test expectations. View in context:
https://bugs.webkit.org/attachment.cgi?id=97187&action=review
>>>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:959 >>>> + logMessage += " during page dismissal (beforeunload, pagehide or unload)."; >>> >>> Can't we identify which one it is? >> >> Sure, if you are okay with instrumenting stuff in WebCore/loader/FrameLoader.cpp. Instead of that, it might be better (but more hacky) to pass along the JS source file and line number here. > > Oh, that's not what I meant. Can we say whether it was beforeunload, pagehide, or unload?
Yeah, I understood you. To differentiate between those, we need to add some hooks in FrameLoader.cpp. Say by changing m_pageDismissalEventBeingDispatched from a bool to an enum or such. As an alternative, instead of saying which type of unload handler it was, we might as well just emit the JS source details (file and line number), though I think passing along that information to this spot will be much hackier.
Sreeram Ramachandran
Comment 27
2011-06-14 17:24:16 PDT
(In reply to
comment #20
)
> You might want to check the behavior in Firefox 4. Because their alerts are no longer modal, they might well be effectively suppressed in unload also.
I tested Firefox 4.0.1 on Mac. Alerts showed up in all unload handlers (beforeunload, pagehide and unload). Moreover, they were app-modal. I couldn't switch to any other tab.
Sreeram Ramachandran
Comment 28
2011-06-14 17:28:11 PDT
Created
attachment 97200
[details]
Removes indirection. Uses StringBuilder.
WebKit Review Bot
Comment 29
2011-06-14 17:36:11 PDT
Comment on
attachment 97200
[details]
Removes indirection. Uses StringBuilder.
Attachment 97200
[details]
did not pass chromium-ews (chromium-xvfb): Output:
http://queues.webkit.org/results/8836831
Sreeram Ramachandran
Comment 30
2011-06-14 17:51:29 PDT
Created
attachment 97206
[details]
Adds #include for StringBuilder
Ryosuke Niwa
Comment 31
2011-06-15 14:40:27 PDT
Comment on
attachment 97206
[details]
Adds #include for StringBuilder View in context:
https://bugs.webkit.org/attachment.cgi?id=97206&action=review
> LayoutTests/ChangeLog:25 > + * platform/chromium/fast/dom/Geolocation/notimer-after-unload-expected.txt: Added. > + * platform/chromium/fast/events/onbeforeunload-focused-iframe-expected.txt: Added. > + * platform/chromium/fast/events/onunload-clears-onbeforeunload-expected.txt: Added. > + * platform/chromium/fast/events/onunload-expected.txt: Added. > + * platform/chromium/fast/events/onunload-not-on-body-expected.txt: Added. > + * platform/chromium/fast/events/onunload-window-property-expected.txt: Added. > + * platform/chromium/fast/events/pageshow-pagehide-on-back-uncached-expected.txt: Added. > + * platform/chromium/fast/history/timed-refresh-in-cached-frame-expected.txt: Added. > + * platform/chromium/fast/loader/frames-with-unload-handlers-in-page-cache-expected.txt: Added. > + * platform/chromium/fast/loader/page-dismissal-modal-dialogs-expected.txt: Added. > + * platform/chromium/fast/loader/recursive-before-unload-crash-expected.txt: Added.
Please use svn mv first. It's hard to see what changes you're making to expected results because you're adding new files.
Ryosuke Niwa
Comment 32
2011-06-15 14:46:56 PDT
Oops, I meant to say "svn cp".
Sreeram Ramachandran
Comment 33
2011-06-15 14:58:55 PDT
Created
attachment 97368
[details]
Diff of test expectations from current files to newly added chromium-specific files
Ryosuke Niwa
Comment 34
2011-06-15 15:07:01 PDT
Comment on
attachment 97206
[details]
Adds #include for StringBuilder View in context:
https://bugs.webkit.org/attachment.cgi?id=97206&action=review
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:966 > + logMessage.append(" during page dismissal (beforeunload, pagehide or unload).");
As I commented earlier, we should identify the event from which the modal dialog was open (beforeunload, pagehide, or unload.
Ryosuke Niwa
Comment 35
2011-06-15 15:14:36 PDT
Comment on
attachment 97206
[details]
Adds #include for StringBuilder Removing r- per IRC discussion.
Alexey Proskuryakov
Comment 36
2011-06-15 15:45:44 PDT
If I remember correctly, Firefox solves the perceived performance problem much easier. You could just hide the tab immediately, and re-display it if it shows an alert in onunload (which would be a very rare thing in practice, basically only for debugging). Or even if Firefox doesn't do that, we could.
Adam Barth
Comment 37
2011-06-15 15:50:02 PDT
> If I remember correctly, Firefox solves the perceived performance problem much easier. You could just hide the tab immediately, and re-display it if it shows an alert in onunload (which would be a very rare thing in practice, basically only for debugging).
We considered that approach but it was rejected by the user experience folks as being an unpleasant user experience.
Ojan Vafai
Comment 38
2011-06-15 15:52:53 PDT
(In reply to
comment #34
)
> (From update of
attachment 97206
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=97206&action=review
> > Source/WebKit/chromium/src/ChromeClientImpl.cpp:966 > > + logMessage.append(" during page dismissal (beforeunload, pagehide or unload)."); > > As I commented earlier, we should identify the event from which the modal dialog was open (beforeunload, pagehide, or unload.
This doesn't seem worth complicating the WebKit code over. Web developers who encounter this can easily add the appropriate logging to figure this out.
Alexey Proskuryakov
Comment 39
2011-06-15 16:22:50 PDT
> We considered that approach but it was rejected by the user experience folks as being an unpleasant user experience.
Did they consider that there is no user experience to affect? Web pages aren't displaying alerts from unload, so regular users aren't going to see any difference either way. I'm not sure if we can have a meaningful discussion here if there is a third party that mandates such behavior for Chrome.
Darin Fisher (:fishd, Google)
Comment 40
2011-06-15 16:38:52 PDT
(In reply to
comment #39
)
> > We considered that approach but it was rejected by the user experience folks as being an unpleasant user experience. > > Did they consider that there is no user experience to affect? Web pages aren't displaying alerts from unload, so regular users aren't going to see any difference either way. > > I'm not sure if we can have a meaningful discussion here if there is a third party that mandates such behavior for Chrome.
There is no mandate. However, folks on the Chrome team have discussed this issue, and we all agreed that we didn't like hiding and re-showing a tab. Adam was summarizing that, and it is true that our "user experience folks" agree. Regardless, we can certainly talk about this topic here. My take: I have long argued that hiding a tab and showing it again would be a jarring experience. I also contend that if it is the last tab, then it will be really wonky to hide the entire window and then show it again. Keep in mind that it can take seconds before the unload handler runs as you may need to swap a child process back into memory. Meanwhile the user has gone to work on something else. It is not good UI to then pop back up the window they previously dismissed, possibly forcing them away from what they were doing. Moreover, because it is rare that unload handlers call alert, I believe that we would avoid a great deal of complexity (extra state) by NOT having to code support for it at all. The complexity of hiding and re-showing the tab or browser window would be avoided too. We already have a lot of complex code for allowing alerts to be generated as a child process is being torn down to be replaced by a different child process all housed within the same tab. I would love to delete that code!
Sreeram Ramachandran
Comment 41
2011-06-26 08:35:59 PDT
Created
attachment 98623
[details]
Identifies page dismissal event more specifically
Sreeram Ramachandran
Comment 42
2011-06-26 08:41:26 PDT
Created
attachment 98624
[details]
Updated test expectation
Sreeram Ramachandran
Comment 43
2011-06-26 09:52:15 PDT
[Copy paste from
https://lists.webkit.org/pipermail/webkit-dev/2011-June/017296.html
] Briefly, from a histogram we added a while ago, I find that 2.3% of all users encounter at least one such modal dialog every week. This is much larger than I expected. I think it means that it's not just web developers who encounter them while debugging their pages. To me, this makes a very strong case for disallowing them. Here are some examples of sites that show an alert when their pages are unloaded:
http://ddl.vidplayer.net/
http://www.buenosprofesionales.com/
http://www.watchsaleshop.com/
http://52-teurseu.blogspot.com/
http://aaz-armor.blogspot.com/
The last two sites above are just two examples out of hundreds of such blogs.
Sreeram Ramachandran
Comment 44
2011-06-28 08:15:42 PDT
Created
attachment 98925
[details]
Diff of test expectations from current files to newly added chromium-specific files
Sreeram Ramachandran
Comment 45
2011-06-28 08:44:51 PDT
Created
attachment 98931
[details]
Now logging page dismissal type explicitly in the histograms
Sreeram Ramachandran
Comment 46
2011-06-28 08:45:49 PDT
Created
attachment 98932
[details]
Diff of test expectations from current files to newly added chromium-specific files
Adam Barth
Comment 47
2011-06-28 17:18:52 PDT
Comment on
attachment 98931
[details]
Now logging page dismissal type explicitly in the histograms View in context:
https://bugs.webkit.org/attachment.cgi?id=98931&action=review
> Source/WebCore/loader/FrameLoader.h:280 > + NumDismissalTypes = 4,
Please remove this enum value. It's not necessary.
> Source/WebCore/page/Chrome.cpp:209 > -bool Chrome::canRunModalNow() const > +bool Chrome::canRunModalNow(const Frame* frame) const
We don't use "const Frame", just "Frame". Shouldn't this function be per-Page? If one of the frames is processing unload, that should probably suppress alerts in the whole Page.
> Source/WebCore/page/Chrome.cpp:311 > - willRunModalDialog(frame, ChromeClient::ConfirmDialog, m_client); > + FrameLoader::PageDismissalType dismissal = frame->loader()->pageDismissalEventBeingDispatched(); > + if (dismissal != FrameLoader::NoDismissal && !m_client->shouldRunModalDialogDuringPageDismissal(ChromeClient::ConfirmDialog, message, dismissal)) > + return false;
Can we factor this copy/paste code into a comment method? Also, these functions have the same Frame-or-Page issue.
> Source/WebCore/page/ChromeClient.h:330 > - virtual void willRunModalDialogDuringPageDismissal(const DialogType&) const { } > + virtual bool shouldRunModalDialogDuringPageDismissal(const DialogType&, const String&, FrameLoader::PageDismissalType) const { return true; }
What is this string argument? We probably need a parameter name to know.
> Source/WebCore/page/DOMWindow.cpp:393 > - return page->chrome()->canRunModalNow(); > + return page->chrome()->canRunModalNow(frame);
Notice that this caller has a nice page for you. :)
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:949 > + int numDismissalTypes = static_cast<int>(FrameLoader::NumDismissalTypes); > + int numDialogTypes = static_cast<int>(NumDialogTypes); > + int intDialog = static_cast<int>(dialogType); > + int intDismissal = static_cast<int>(dismissal); > + PlatformBridge::histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", intDialog * numDismissalTypes + intDismissal, numDismissalTypes * numDialogTypes);
This is a giant hack. Can we please not have these sorts of hacks?
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:957 > + logMessage.append("Blocked alert('"); > + logMessage.append(message); > + logMessage.append("')"); > + break;
This code is all super redundant. Consider using String::format to make this code prettier.
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:972 > + default: > + logMessage.append("Blocked modal dialog");
Please remove these default cases and explicitly handle all the enum values.
Sreeram Ramachandran
Comment 48
2011-06-28 18:39:22 PDT
Comment on
attachment 98931
[details]
Now logging page dismissal type explicitly in the histograms View in context:
https://bugs.webkit.org/attachment.cgi?id=98931&action=review
>> Source/WebCore/loader/FrameLoader.h:280 >> + NumDismissalTypes = 4, > > Please remove this enum value. It's not necessary.
Done (I needed it for computing the largest value for the histogram, but I've hardcoded that number now).
>> Source/WebCore/page/Chrome.cpp:209 >> +bool Chrome::canRunModalNow(const Frame* frame) const > > We don't use "const Frame", just "Frame". > > Shouldn't this function be per-Page? If one of the frames is processing unload, that should probably suppress alerts in the whole Page.
If a frame is navigating somewhere, it doesn't necessarily mean that the page is, right? It could just be a subframe alone that's navigating, with no change to the top-level page URL. I don't understand this fully; am just adding on top of what is already there. Specifically, the current m_pageDismissalEventBeingDispatched variable is in FrameLoader, and not at the Page level, so that's why I'm passing a Frame (to get to its loader). I'll fix the const part in the next patch.
>> Source/WebCore/page/Chrome.cpp:311 >> + return false; > > Can we factor this copy/paste code into a comment method? Also, these functions have the same Frame-or-Page issue.
Done (for the common part). Again, not sure about the Frame/Page thing.
>> Source/WebCore/page/ChromeClient.h:330 >> + virtual bool shouldRunModalDialogDuringPageDismissal(const DialogType&, const String&, FrameLoader::PageDismissalType) const { return true; } > > What is this string argument? We probably need a parameter name to know.
Done.
>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:949 >> + PlatformBridge::histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", intDialog * numDismissalTypes + intDismissal, numDismissalTypes * numDialogTypes); > > This is a giant hack. Can we please not have these sorts of hacks?
Do you mean that the histogram as a whole is a hack, or some specific part of this code? The histogram is needed; it's what let us collect the 2.3% stat we discussed on webkit-dev. I'd like to keep this around for a few more months, to see if there are any shifts in web developers' behaviour due to disallowing these modal dialogs. I have previously promised to remove the histogram once the data collection experiment is over; I certainly intend to honour that.
>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:957 >> + break; > > This code is all super redundant. Consider using String::format to make this code prettier.
Done.
>> Source/WebKit/chromium/src/ChromeClientImpl.cpp:972 >> + logMessage.append("Blocked modal dialog"); > > Please remove these default cases and explicitly handle all the enum values.
I am handling all the enum cases explicitly (well, all except for the NumFoo enum value which is not expected to be used). The default is just a catch all, just in case somebody adds a new enum value and forgets to update this code.
Sreeram Ramachandran
Comment 49
2011-06-28 18:40:51 PDT
Created
attachment 99024
[details]
Addressed most of abarth's comments
WebKit Review Bot
Comment 50
2011-06-28 18:55:42 PDT
Comment on
attachment 99024
[details]
Addressed most of abarth's comments
Attachment 99024
[details]
did not pass chromium-ews (chromium-xvfb): Output:
http://queues.webkit.org/results/8958058
Early Warning System Bot
Comment 51
2011-06-28 18:56:38 PDT
Comment on
attachment 99024
[details]
Addressed most of abarth's comments
Attachment 99024
[details]
did not pass qt-ews (qt): Output:
http://queues.webkit.org/results/8958061
Sreeram Ramachandran
Comment 52
2011-06-28 19:11:02 PDT
Comment on
attachment 98931
[details]
Now logging page dismissal type explicitly in the histograms View in context:
https://bugs.webkit.org/attachment.cgi?id=98931&action=review
>>> Source/WebCore/page/Chrome.cpp:209 >>> +bool Chrome::canRunModalNow(const Frame* frame) const >> >> We don't use "const Frame", just "Frame". >> >> Shouldn't this function be per-Page? If one of the frames is processing unload, that should probably suppress alerts in the whole Page. > > If a frame is navigating somewhere, it doesn't necessarily mean that the page is, right? It could just be a subframe alone that's navigating, with no change to the top-level page URL. > > I don't understand this fully; am just adding on top of what is already there. Specifically, the current m_pageDismissalEventBeingDispatched variable is in FrameLoader, and not at the Page level, so that's why I'm passing a Frame (to get to its loader). > > I'll fix the const part in the next patch.
I had to put back the const, because DOMWindow.cpp only gets a const pointer (line 386).
>>> Source/WebCore/page/ChromeClient.h:330 >>> + virtual bool shouldRunModalDialogDuringPageDismissal(const DialogType&, const String&, FrameLoader::PageDismissalType) const { return true; } >> >> What is this string argument? We probably need a parameter name to know. > > Done.
I had to remove the parameter names because otherwise they give an "unused variable" error (since this is not a pure virtual function, but completely defined inline here). I've added a comment naming the params; if that's not proper webkit style, do let me know.
Sreeram Ramachandran
Comment 53
2011-06-28 19:58:23 PDT
Created
attachment 99029
[details]
Addressed most of abarth's comments; fixed build errors
Adam Barth
Comment 54
2011-06-28 20:41:37 PDT
> (From update of
attachment 98931
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=98931&action=review
> > >> Source/WebCore/page/Chrome.cpp:209 > >> +bool Chrome::canRunModalNow(const Frame* frame) const > > > > We don't use "const Frame", just "Frame". > > > > Shouldn't this function be per-Page? If one of the frames is processing unload, that should probably suppress alerts in the whole Page. > > If a frame is navigating somewhere, it doesn't necessarily mean that the page is, right? It could just be a subframe alone that's navigating, with no change to the top-level page URL.
>
> I don't understand this fully; am just adding on top of what is already there. Specifically, the current m_pageDismissalEventBeingDispatched variable is in FrameLoader, and not at the Page level, so that's why I'm passing a Frame (to get to its loader).
Sure, that's fine. The point is that whether we can run a modal dialog is per-Page state, not per Frame state. That means you'll probably need to crawl the Frame tree to see if anyone is handling a page dismissal event.
> >> Source/WebKit/chromium/src/ChromeClientImpl.cpp:949 > >> + PlatformBridge::histogramEnumeration("Renderer.ModalDialogsDuringPageDismissal", intDialog * numDismissalTypes + intDismissal, numDismissalTypes * numDialogTypes); > > > > This is a giant hack. Can we please not have these sorts of hacks? > > Do you mean that the histogram as a whole is a hack, or some specific part of this code? The histogram is needed; it's what let us collect the 2.3% stat we discussed on webkit-dev. I'd like to keep this around for a few more months, to see if there are any shifts in web developers' behaviour due to disallowing these modal dialogs. I have previously promised to remove the histogram once the data collection experiment is over; I certainly intend to honour that.
I meant the packing of a bunch of enum values into a single int.
> >> Source/WebKit/chromium/src/ChromeClientImpl.cpp:972 > >> + logMessage.append("Blocked modal dialog"); > > > > Please remove these default cases and explicitly handle all the enum values. > > I am handling all the enum cases explicitly (well, all except for the NumFoo enum value which is not expected to be used). The default is just a catch all, just in case somebody adds a new enum value and forgets to update this code.
We generally leave off the default case and have the compiler alert us that we've added a new enum by breaking the build. That's another reason to remove the NumFoo enum values.
> >>> Source/WebCore/page/Chrome.cpp:209 > >>> +bool Chrome::canRunModalNow(const Frame* frame) const > >> > >> We don't use "const Frame", just "Frame". > >> > >> Shouldn't this function be per-Page? If one of the frames is processing unload, that should probably suppress alerts in the whole Page. > > > > If a frame is navigating somewhere, it doesn't necessarily mean that the page is, right? It could just be a subframe alone that's navigating, with no change to the top-level page URL. > > > > I don't understand this fully; am just adding on top of what is already there. Specifically, the current m_pageDismissalEventBeingDispatched variable is in FrameLoader, and not at the Page level, so that's why I'm passing a Frame (to get to its loader). > > > > I'll fix the const part in the next patch. > > I had to put back the const, because DOMWindow.cpp only gets a const pointer (line 386).
That code is wrong then. It's not sensible for Frame* to be const. Rather than spreading const to more places incorrectly, we should remove the offending consts.
> >>> Source/WebCore/page/ChromeClient.h:330 > >>> + virtual bool shouldRunModalDialogDuringPageDismissal(const DialogType&, const String&, FrameLoader::PageDismissalType) const { return true; } > >> > >> What is this string argument? We probably need a parameter name to know. > > > > Done. > > I had to remove the parameter names because otherwise they give an "unused variable" error (since this is not a pure virtual function, but completely defined inline here). I've added a comment naming the params; if that's not proper webkit style, do let me know.
The UNUSED_PARAM macro can help you solve this problem.
Adam Barth
Comment 55
2011-06-28 20:44:05 PDT
Comment on
attachment 99029
[details]
Addressed most of abarth's comments; fixed build errors View in context:
https://bugs.webkit.org/attachment.cgi?id=99029&action=review
Looks like we just have some const and Frame/Page nits to clean up. I'd like to give the whole patch one more read-through once we've got those sorted out.
> Source/WebKit/chromium/src/ChromeClientImpl.cpp:956 > + String logMessage = makeString("Blocked ", kDialogs[dialog], "('", dialogMessage, "') during ", kDismissals[dismissal], "."); > + const_cast<ChromeClientImpl*>(this)->addMessageToConsole(OtherMessageSource, LogMessageType, ErrorMessageLevel, logMessage, 0, String());
OMG, so much nicer. Thank you.
Sreeram Ramachandran
Comment 56
2011-06-29 11:33:01 PDT
(In reply to
comment #54
)
> Sure, that's fine. The point is that whether we can run a modal dialog is per-Page state, not per Frame state. That means you'll probably need to crawl the Frame tree to see if anyone is handling a page dismissal event.
Done.
> That code is wrong then. It's not sensible for Frame* to be const. Rather than spreading const to more places incorrectly, we should remove the offending consts.
Okay, but now I don't need to pass the Frame anymore, so I haven't touched this code. I think removing const-ness belongs logically in a different patch anyway. No need to combine it with this.
> The UNUSED_PARAM macro can help you solve this problem.
Done.
Sreeram Ramachandran
Comment 57
2011-06-29 11:33:37 PDT
Created
attachment 99116
[details]
Now checking all frames in the page
WebKit Review Bot
Comment 58
2011-06-29 13:05:48 PDT
Comment on
attachment 99116
[details]
Now checking all frames in the page
Attachment 99116
[details]
did not pass chromium-ews (chromium-xvfb): Output:
http://queues.webkit.org/results/8965132
New failing tests: fast/loader/page-dismissal-modal-dialogs.html
WebKit Review Bot
Comment 59
2011-06-29 13:05:55 PDT
Created
attachment 99133
[details]
Archive of layout-test-results from ec2-cr-linux-01 The attached test failures were seen while running run-webkit-tests on the chromium-ews. Bot: ec2-cr-linux-01 Port: Chromium Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Adam Barth
Comment 60
2011-06-29 14:03:48 PDT
Comment on
attachment 99116
[details]
Now checking all frames in the page Looks like your test doesn't pass.
Sreeram Ramachandran
Comment 61
2011-06-29 14:05:41 PDT
(In reply to
comment #60
)
> Looks like your test doesn't pass.
Yeah, I found that strange. It passed on my local machine. Perhaps I did something wrong. While I'm at it, I'll add a couple of more tests to test the frame vs page stuff.
Sreeram Ramachandran
Comment 62
2011-06-29 21:07:20 PDT
Created
attachment 99227
[details]
Updated test and expectations
Sreeram Ramachandran
Comment 63
2011-06-29 21:08:27 PDT
Created
attachment 99228
[details]
Diff of test expectations from current files to newly added chromium-specific files
Adam Barth
Comment 64
2011-06-29 22:42:57 PDT
Comment on
attachment 99227
[details]
Updated test and expectations View in context:
https://bugs.webkit.org/attachment.cgi?id=99227&action=review
Very nice. Thanks for iterating on the patch.
> Source/WebCore/page/Chrome.cpp:209 > +static bool canRunModalIfDuringPageDismissal(Page* page, ChromeClient* client, ChromeClient::DialogType dialog, const String& message)
This is fine, but ChromeClient can be reached from Page, so you could just pass Page, but whatever.
Sreeram Ramachandran
Comment 65
2011-06-30 07:30:23 PDT
Created
attachment 99298
[details]
Don't pass ChromeClient explicitly
Sreeram Ramachandran
Comment 66
2011-06-30 07:36:30 PDT
(In reply to
comment #64
)
> > Source/WebCore/page/Chrome.cpp:209 > > +static bool canRunModalIfDuringPageDismissal(Page* page, ChromeClient* client, ChromeClient::DialogType dialog, const String& message) > > This is fine, but ChromeClient can be reached from Page, so you could just pass Page, but whatever.
Done. Thanks for the review! The new patch only differs from the old patch in the above issue (passing ChromeClient), so it should be a quick one for you to review. Please also add cq+ (I'm not a committer). Aside: Is there a way to see the diff between two patches using the web interface?
Adam Barth
Comment 67
2011-06-30 09:45:00 PDT
> Aside: Is there a way to see the diff between two patches using the web interface?
There is, but it's super ugly and very few people use it.
Adam Barth
Comment 68
2011-06-30 09:45:32 PDT
Comment on
attachment 99298
[details]
Don't pass ChromeClient explicitly Ok. Let's rock and roll.
WebKit Review Bot
Comment 69
2011-06-30 10:09:41 PDT
Comment on
attachment 99298
[details]
Don't pass ChromeClient explicitly Rejecting
attachment 99298
[details]
from commit-queue. Failed to run "['./Tools/Scripts/webkit-patch', '--status-host=queues.webkit.org', '--bot-id=ec2-cq-01', '--port..." exit_code: 2 Last 500 characters of output: gPageDismissal(const WebCore::ChromeClient::DialogType&, const WTF::String&, WebCore::FrameLoader::PageDismissalType) const': Source/WebKit/chromium/src/ChromeClientImpl.cpp:953: error: comparison between signed and unsigned integer expressions Source/WebKit/chromium/src/ChromeClientImpl.cpp:957: error: comparison between signed and unsigned integer expressions make: *** [out/Debug/obj.target/webkit/Source/WebKit/chromium/src/ChromeClientImpl.o] Error 1 make: *** Waiting for unfinished jobs.... Full output:
http://queues.webkit.org/results/8957782
Sreeram Ramachandran
Comment 70
2011-06-30 11:14:55 PDT
Created
attachment 99337
[details]
Fix debug build
WebKit Review Bot
Comment 71
2011-06-30 14:47:51 PDT
Comment on
attachment 99337
[details]
Fix debug build Clearing flags on attachment: 99337 Committed
r90164
: <
http://trac.webkit.org/changeset/90164
>
WebKit Review Bot
Comment 72
2011-06-30 14:48:04 PDT
All reviewed patches have been landed. Closing bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug