Bug 1539757 - fix trying to initialize XBL bindings while the prompt is still hidden, r=bgrins
☠☠ backed out by 12fa4d0520ad ☠ ☠
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Fri, 29 Mar 2019 23:11:37 +0000
changeset 466877 de24b08ddc37fd7d3fd29c6b893713d5657269e6
parent 466876 f7937d3264db00771b46cb1fcba71640d8df05cb
child 466878 9eb7867c1dd431f6effdd99bfea5c8a003ebb730
push id112603
push usernerli@mozilla.com
push dateSat, 30 Mar 2019 09:35:57 +0000
treeherdermozilla-inbound@7c3183c56eb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1539757
milestone68.0a1
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 1539757 - fix trying to initialize XBL bindings while the prompt is still hidden, r=bgrins Differential Revision: https://phabricator.services.mozilla.com/D25390
browser/base/content/browser.js
browser/base/content/test/tabPrompts/browser_multiplePrompts.js
browser/modules/RemotePrompt.jsm
toolkit/components/prompts/src/CommonDialog.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8364,16 +8364,18 @@ TabModalPromptBox.prototype = {
     this.prompts.delete(aPrompt.element);
     let browser = this.browser;
     aPrompt.element.remove();
 
     let prompts = this.listPrompts();
     if (prompts.length) {
       let prompt = prompts[prompts.length - 1];
       prompt.element.hidden = false;
+      // Because we were hidden before, this won't have been possible, so do it now:
+      prompt.ensureXBLBindingAttached();
       prompt.Dialog.setDefaultFocus();
     } else {
       browser.removeAttribute("tabmodalPromptShowing");
       browser.focus();
     }
   },
 
   listPrompts(aPrompt) {
--- a/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
+++ b/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
@@ -3,30 +3,31 @@
 /*
  * This test triggers multiple alerts on one single tab, because it"s possible
  * for web content to do so. The behavior is described in bug 1266353.
  *
  * We assert the presentation of the multiple alerts, ensuring we show only
  * the oldest one.
  */
 add_task(async function() {
-  const PROMPTCOUNT = 5;
+  const PROMPTCOUNT = 9;
 
-  let contentScript = function() {
-    var i = 5; // contentScript has no access to PROMPTCOUNT.
+  let contentScript = function(MAX_PROMPT) {
+    var i = MAX_PROMPT;
+    let fns = ["alert", "prompt", "confirm"];
     window.addEventListener("message", function() {
       i--;
       if (i) {
         window.postMessage("ping", "*");
       }
-      alert("Alert countdown #" + i);
+      window[fns[i % 3]](fns[i % 3] + " countdown #" + i);
     });
     window.postMessage("ping", "*");
   };
-  let url = "data:text/html,<script>(" + encodeURIComponent(contentScript.toSource()) + ")();</script>";
+  let url = "data:text/html,<script>(" + encodeURIComponent(contentScript.toSource()) + ")(" + PROMPTCOUNT + ");</script>";
 
   let promptsOpenedPromise = new Promise(function(resolve) {
     let unopenedPromptCount = PROMPTCOUNT;
     Services.obs.addObserver(function observer() {
       unopenedPromptCount--;
       if (!unopenedPromptCount) {
         Services.obs.removeObserver(observer, "tabmodal-dialog-loaded");
         info("Prompts opened.");
@@ -43,17 +44,18 @@ add_task(async function() {
   let promptElementsCount = PROMPTCOUNT;
   while (promptElementsCount--) {
     let promptElements = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
     is(promptElements.length, promptElementsCount + 1, "There should be " + (promptElementsCount + 1) + " prompt(s).");
     // The oldest should be the first.
     let i = 0;
     for (let promptElement of promptElements) {
       let prompt = tab.linkedBrowser.tabModalPromptBox.prompts.get(promptElement);
-      is(prompt.Dialog.args.text, "Alert countdown #" + i, "The #" + i + " alert should be labelled as such.");
+      let expectedType = ["alert", "prompt", "confirm"][i % 3];
+      is(prompt.Dialog.args.text, expectedType + " countdown #" + i, "The #" + i + " alert should be labelled as such.");
       if (i !== promptElementsCount) {
         is(prompt.element.hidden, true, "This prompt should be hidden.");
         i++;
         continue;
       }
 
       is(prompt.element.hidden, false, "The last prompt should not be hidden.");
       prompt.onButtonClick(0);
--- a/browser/modules/RemotePrompt.jsm
+++ b/browser/modules/RemotePrompt.jsm
@@ -75,16 +75,17 @@ var RemotePrompt = {
       if (needRemove) {
         tabPrompt.removePrompt(newPrompt);
       }
 
       // TODO since we don't actually open a window, need to check if
       // there's other stuff in nsWindowWatcher::OpenWindowInternal
       // that we might need to do here as well.
     } catch (ex) {
+      Cu.reportError(ex);
       onPromptClose(true);
     }
   },
 
   openModalWindow(args, browser) {
     let window = browser.ownerGlobal;
     try {
       PromptUtils.fireDialogEvent(window, "DOMWillOpenModalDialog", browser);
--- a/toolkit/components/prompts/src/CommonDialog.jsm
+++ b/toolkit/components/prompts/src/CommonDialog.jsm
@@ -157,24 +157,26 @@ CommonDialog.prototype = {
         let b = (this.args.defaultButtonNum || 0);
         let button = this.ui["button" + b];
 
         if (xulDialog)
             xulDialog.defaultButton = ["accept", "cancel", "extra1", "extra2"][b];
         else
             button.setAttribute("default", "true");
 
-        // For tab prompts, we will need to ensure its content bindings are attached.
-        if (!xulDialog) {
-            this.ui.prompt.ensureXBLBindingAttached();
+        if (!this.ui.promptContainer.hidden) {
+            // For tab prompts, we will need to ensure its content bindings are attached.
+            if (!xulDialog) {
+                this.ui.prompt.ensureXBLBindingAttached();
+            }
+
+            // Set default focus / selection.
+            this.setDefaultFocus(true);
         }
 
-        // Set default focus / selection.
-        this.setDefaultFocus(true);
-
         if (this.args.enableDelay) {
             this.delayHelper = new EnableDelayHelper({
                 disableDialog: () => this.setButtonsEnabledState(false),
                 enableDialog: () => this.setButtonsEnabledState(true),
                 focusTarget: this.ui.focusTarget,
             });
         }
 
@@ -254,19 +256,19 @@ CommonDialog.prototype = {
         } else if (this.args.promptType == "promptPassword") {
             // When the prompt is initialized, focus and select the textbox
             // contents. Afterwards, only focus the textbox.
             if (isInitialLoad)
                 this.ui.password1Textbox.select();
             else
                 this.ui.password1Textbox.focus();
         } else if (isInitialLoad) {
-                this.ui.loginTextbox.select();
+            this.ui.loginTextbox.select();
         } else {
-                this.ui.loginTextbox.focus();
+            this.ui.loginTextbox.focus();
         }
     },
 
     onCheckbox() {
         this.args.checked = this.ui.checkbox.checked;
     },
 
     onButton0() {