Bug 1539757 - fix trying to initialize XBL bindings while the prompt is still hidden, r=bgrins a=pascalc
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 01 Apr 2019 13:37:49 +0000
changeset 525896 a3b5dd595e17ef9b32ec4c806560362ca2347526
parent 525895 39a03fc4bac62ce4def8cd2cdaffe350b3df2417
child 525897 d32f0c0ddb193cafc7ce89a1a4fe5000db4d6e38
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins, pascalc
bugs1539757
milestone67.0
Bug 1539757 - fix trying to initialize XBL bindings while the prompt is still hidden, r=bgrins a=pascalc 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
@@ -8350,16 +8350,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 || !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() {