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 idunknown
push userunknown
push dateunknown
reviewersjst, blocking
bugs611566
milestone2.0b8pre
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>