Bug 636905 - part 2: check for document interactivity state when prompting for beforeunload, r?bz draft
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 24 Sep 2015 12:11:07 +0100
changeset 296582 49bb57b9162bfa365e3c07589d107fd764e788a7
parent 296581 34dfcd3a8d5ff64cf9e3e5ae4d1af94b9ab0806b
child 296583 79dc038c605adc5a0877e22b05c824556c36b04b
push id5861
push usergijskruitbosch@gmail.com
push dateSat, 26 Sep 2015 14:11:25 +0000
reviewersbz
bugs636905
milestone44.0a1
Bug 636905 - part 2: check for document interactivity state when prompting for beforeunload, r?bz
layout/base/nsDocumentViewer.cpp
modules/libpref/init/all.js
--- 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);