Bug 636905 - part 2: check for document interactivity state when prompting for beforeunload, r?bz
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -123,16 +123,17 @@ static const char sPrintOptionsContractI
#include "mozilla/dom/Element.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
using namespace mozilla::dom;
#define BEFOREUNLOAD_DISABLED_PREFNAME "dom.disable_beforeunload"
+#define BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME "dom.require_user_interaction_for_beforeunload"
//-----------------------------------------------------
// LOGGING
#include "LayoutLogging.h"
#include "mozilla/Logging.h"
#ifdef NS_PRINTING
static PRLogModuleInfo *
@@ -1069,22 +1070,25 @@ nsDocumentViewer::PermitUnloadInternal(b
if (!mDocument
|| mInPermitUnload
|| mCallerIsClosingWindow
|| mInPermitUnloadPrompt) {
return NS_OK;
}
static bool sIsBeforeUnloadDisabled;
- static bool sBeforeUnloadPrefCached = false;
-
- if (!sBeforeUnloadPrefCached ) {
- sBeforeUnloadPrefCached = true;
+ static bool sBeforeUnloadRequiresInteraction;
+ static bool sBeforeUnloadPrefsCached = false;
+
+ if (!sBeforeUnloadPrefsCached ) {
+ sBeforeUnloadPrefsCached = true;
Preferences::AddBoolVarCache(&sIsBeforeUnloadDisabled,
BEFOREUNLOAD_DISABLED_PREFNAME);
+ Preferences::AddBoolVarCache(&sBeforeUnloadRequiresInteraction,
+ BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME);
}
// First, get the script global object from the document...
nsPIDOMWindow *window = mDocument->GetWindow();
if (!window) {
// This is odd, but not fatal
NS_WARNING("window not set for document!");
@@ -1132,17 +1136,20 @@ nsDocumentViewer::PermitUnloadInternal(b
globalWindow->EnableDialogs();
}
}
nsCOMPtr<nsIDocShell> docShell(mContainer);
nsAutoString text;
beforeUnload->GetReturnValue(text);
- if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled &&
+ // NB: we nullcheck mDocument because it might now be dead as a result of
+ // the event being dispatched.
+ if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled && mDocument &&
+ (!sBeforeUnloadRequiresInteraction || mDocument->UserHasInteracted()) &&
(event->GetInternalNSEvent()->mFlags.mDefaultPrevented ||
!text.IsEmpty())) {
// Ask the user if it's ok to unload the current page
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell);
if (prompt) {
nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1031,16 +1031,18 @@ pref("dom.disable_window_open_feature.pe
pref("dom.disable_window_open_feature.menubar", false);
pref("dom.disable_window_open_feature.scrollbars", false);
pref("dom.disable_window_open_feature.resizable", true);
pref("dom.disable_window_open_feature.minimizable", false);
pref("dom.disable_window_open_feature.status", true);
pref("dom.allow_scripts_to_close_windows", false);
+pref("dom.require_user_interaction_for_beforeunload", true);
+
pref("dom.disable_open_during_load", false);
pref("dom.popup_maximum", 20);
pref("dom.popup_allowed_events", "change click dblclick mouseup notificationclick reset submit touchend");
pref("dom.disable_open_click_delay", 1000);
pref("dom.storage.enabled", true);
pref("dom.storage.default_quota", 5120);