Bug 611566 - Remove Enter/LeaveModalState calls from nsGlobalWindow alert/confirm/prompt. r=jst, a=blocking+
authorJustin Dolske <dolske@mozilla.com>
Wed, 17 Nov 2010 22:44:50 -0800
changeset 57846 579f6301792190d9e2291c15d12ab4471e42ef2f
parent 57845 c3c229aaf5310cfaf67188d1ae5f3e214d8cef99
child 57847 f6fec8c990b1587a61843fa032e52d7fbe3627cd
push id17039
push userjdolske@mozilla.com
push dateThu, 18 Nov 2010 06:49:17 +0000
treeherdermozilla-central@579f63017921 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst, blocking
bugs611566
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 611566 - Remove Enter/LeaveModalState calls from nsGlobalWindow alert/confirm/prompt. r=jst, a=blocking+
dom/base/nsGlobalWindow.cpp
dom/tests/mochitest/bugs/test_bug61098.html
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4476,34 +4476,30 @@ nsGlobalWindow::Alert(const nsAString& a
   nsAutoString final;
   nsContentUtils::StripNullChars(*str, final);
 
   nsresult rv;
   nsCOMPtr<nsIPromptService> promptSvc =
     do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  EnterModalState();
-
   if (shouldEnableDisableDialog) {
     PRBool disallowDialog = PR_FALSE;
     nsXPIDLString label;
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
 
     rv = promptSvc->AlertCheck(this, title.get(), final.get(), label.get(),
                                &disallowDialog);
     if (disallowDialog)
       PreventFurtherDialogs();
   } else {
     rv = promptSvc->Alert(this, title.get(), final.get());
   }
 
-  LeaveModalState();
-
   return rv;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn)
 {
   FORWARD_TO_OUTER(Confirm, (aString, aReturn), NS_ERROR_NOT_INITIALIZED);
 
@@ -4533,34 +4529,30 @@ nsGlobalWindow::Confirm(const nsAString&
   nsAutoString final;
   nsContentUtils::StripNullChars(aString, final);
 
   nsresult rv;
   nsCOMPtr<nsIPromptService> promptSvc =
     do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  EnterModalState();
-
   if (shouldEnableDisableDialog) {
     PRBool disallowDialog = PR_FALSE;
     nsXPIDLString label;
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
 
     rv = promptSvc->ConfirmCheck(this, title.get(), final.get(), label.get(),
                                  &disallowDialog, aReturn);
     if (disallowDialog)
       PreventFurtherDialogs();
   } else {
     rv = promptSvc->Confirm(this, title.get(), final.get(), aReturn);
   }
 
-  LeaveModalState();
-
   return rv;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
                        nsAString& aReturn)
 {
   SetDOMStringToNull(aReturn);
@@ -4600,24 +4592,20 @@ nsGlobalWindow::Prompt(const nsAString& 
   PRBool disallowDialog = PR_FALSE;
 
   nsXPIDLString label;
   if (shouldEnableDisableDialog) {
     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
                                        "ScriptDialogLabel", label);
   }
 
-  EnterModalState();
-
   PRBool ok;
   rv = promptSvc->Prompt(this, title.get(), fixedMessage.get(),
                          &inoutValue, label.get(), &disallowDialog, &ok);
 
-  LeaveModalState();
-
   if (disallowDialog) {
     PreventFurtherDialogs();
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAdoptingString outValue(inoutValue);
 
--- a/dom/tests/mochitest/bugs/test_bug61098.html
+++ b/dom/tests/mochitest/bugs/test_bug61098.html
@@ -20,125 +20,209 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 </pre>
 <script class="testbody" type="text/javascript">
 /** Test for Bug 61098 **/
 
 SimpleTest.waitForExplicitFinish();
 
-var mockPromptServiceRegisterer;
+var mockPromptServiceRegisterer, mockPromptFactoryRegisterer;
 
 var promptState;
 
 function registerMockPromptService()
 {
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-  // Override the prompt service with our own so that we can test
-  // modal dialogs
-
-  function MockPromptService()
-  {
+  function MockPrompt(aDOMWindow) {
+    this.domWindow = aDOMWindow;
   }
 
-  MockPromptService.prototype = {
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptService]),
+  MockPrompt.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrompt]),
+
+    domWindow : null,
 
-    alert: function(aParent, aDialogTitle, aText)
+    _toggleModalState: function()
     {
+      // The real prompt service puts the window into a modal state
+      // immediately before showing a modal prompt, and leaves the modal state
+      // when the prompt is dismissed by the user. This mock prompt doesn't
+      // show anything to the user, so we only need to enter and immediately
+      // leave the modal state -- this is done to trigger the necessary
+      // accounting for triggering the "stop showing more prompts" code for
+      // abusive pages.
+      var winUtils = this.domWindow
+                         .QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIDOMWindowUtils);
+      winUtils.enterModalState();
+      winUtils.leaveModalState();
+    },
+
+    alert: function(aDialogTitle, aText)
+    {
+      this._toggleModalState();
       promptState = {method: "alert",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText
       };
     },
 
-    alertCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState)
+    alertCheck: function(aDialogTitle, aText, aCheckMsg, aCheckState)
     {
+      this._toggleModalState();
       promptState = {method: "alertCheck",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       aCheckState.value = true;
     },
 
-    confirm: function(aParent, aDialogTitle, aText)
+    confirm: function(aDialogTitle, aText)
     {
+      this._toggleModalState();
       promptState = {method: "confirm",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText
       };
 
       return true;
     },
 
-    confirmCheck: function(aParent, aDialogTitle, aText, aCheckMsg,
-                           aCheckState)
+    confirmCheck: function(aDialogTitle, aText, aCheckMsg, aCheckState)
     {
+      this._toggleModalState();
       promptState = {method: "confirmCheck",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       aCheckState.value = true;
 
       return true;
     },
 
-    confirmEx: function(aParent, aDialogTitle, aText, aButtonFlags,
+    confirmEx: function(aDialogTitle, aText, aButtonFlags,
                         aButton0Title, aButton1Title, aButton2Title,
                         aCheckMsg, aCheckState)
     {
+      this._toggleModalState();
       promptState = {method: "confirmCheck",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       if (aCheckMsg != null)
         aCheckState.value = true;
 
       return 0;
     },
 
-    prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg,
+    prompt: function(aDialogTitle, aText, aValue, aCheckMsg,
                      aCheckState)
     {
+      this._toggleModalState();
       promptState = {method: "prompt",
-                     parent: aParent,
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       if (aCheckMsg != null)
         aCheckState.value = true;
 
       return true;
     },
   };
 
+
+  // Override the prompt service with our own so that we can test
+  // modal dialogs
+
+  function MockPromptService()
+  {
+  }
+
+  MockPromptService.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory, Ci.nsIPromptService]),
+
+    getPrompt: function(aDOMWindow, aIID)
+    {
+        return new MockPrompt(aDOMWindow);
+    },
+
+    alert: function(aParent, aDialogTitle, aText)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.alert(aDialogTitle, aText);
+    },
+
+    alertCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.alertCheck(aDialogTitle, aText, aCheckMsg, aCheckState);
+    },
+
+    confirm: function(aParent, aDialogTitle, aText)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.confirm(aDialogTitle, aText);
+    },
+
+    confirmCheck: function(aParent, aDialogTitle, aText, aCheckMsg,
+                           aCheckState)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.confirmCheck(aDialogTitle, aText, aCheckMsg, aCheckState);
+    },
+
+    confirmEx: function(aParent, aDialogTitle, aText, aButtonFlags,
+                        aButton0Title, aButton1Title, aButton2Title,
+                        aCheckMsg, aCheckState)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.confirmEx(aDialogTitle, aText, aButtonFlags,
+                        aButton0Title, aButton1Title, aButton2Title,
+                        aCheckMsg, aCheckState);
+    },
+
+    prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg,
+                     aCheckState)
+    {
+      var prompt = new MockPrompt(aParent);
+      return prompt.prompt(aDialogTitle, aText, aValue, aCheckMsg, aCheckState);
+    },
+
+  };
+
   mockPromptServiceRegisterer =
     new MockObjectRegisterer("@mozilla.org/embedcomp/prompt-service;1",
                              MockPromptService);
+  mockPromptFactoryRegisterer =
+    new MockObjectRegisterer("@mozilla.org/prompter;1",
+                             MockPromptService);
 
   mockPromptServiceRegisterer.register();
+  mockPromptFactoryRegisterer.register();
 };
 
 function enableDialogLoopBlocking()
 {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var prefs = Components.classes["@mozilla.org/preferences-service;1"].
     getService(Components.interfaces.nsIPrefBranch);
 
@@ -255,16 +339,18 @@ function runtests()
   is (promptState.parent, w, "Wrong confirm parent");
   is (promptState.msg, "Prevent this page from creating additional dialogs",
       "Wrong confirm message");
   promptState = void(0);
 
   w.close();
 
   resetDialogLoopBlocking();
+
+  mockPromptFactoryRegisterer.unregister();
   mockPromptServiceRegisterer.unregister();
 
   SimpleTest.finish();
 }
 
 </script>
 </body>
 </html>