Bug 1388238 - Implement waitForMasterPasswordDialog helper which handles open dialogs. r=MattN
☠☠ backed out by b676d5b34892 ☠ ☠
authorsteveck-chung <schung@mozilla.com>
Mon, 07 Aug 2017 20:43:02 -0700
changeset 373525 7b7aa4e9ae5a532854650ff665320d75563ee32c
parent 373524 0d1ee6f3b3f40d9e4bbc36403c68684a2038654e
child 373526 55f44886a83925ccda59d8ff4c70522bba6c5c63
push id48316
push usermozilla@noorenberghe.ca
push dateWed, 09 Aug 2017 02:45:31 +0000
treeherderautoland@55f44886a839 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN
bugs1388238
milestone57.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 1388238 - Implement waitForMasterPasswordDialog helper which handles open dialogs. r=MattN MozReview-Commit-ID: A8jx8s37f1k
browser/extensions/formautofill/MasterPassword.jsm
toolkit/components/prompts/src/CommonDialog.jsm
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/MasterPassword.jsm
@@ -0,0 +1,81 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Helpers for the Master Password Dialog.
+ * In the future the Master Password implementation may move here.
+ */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+  "MasterPassword",
+];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+
+this.MasterPassword = {
+  /**
+   * Resolve when master password dialogs are closed, immediately if none are open.
+   *
+   * An existing MP dialog will be focused and will request attention.
+   *
+   * @returns {Promise<bool>}
+   *          Resolves with whether the user is logged in to MP.
+   */
+  async waitForExistingDialog() {
+    if (!Services.logins.uiBusy) {
+      log.debug("waitForExistingDialog: Dialog isn't showing. isLoggedIn:",
+                Services.logins.isLoggedIn);
+      return Services.logins.isLoggedIn;
+    }
+
+    return new Promise((resolve) => {
+      log.debug("waitForExistingDialog: Observing the open dialog");
+      let observer = {
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                               Ci.nsISupportsWeakReference]),
+
+        observe(subject, topic, data) {
+          log.debug("waitForExistingDialog: Got notification:", topic);
+          // Only run observer once.
+          Services.obs.removeObserver(this, "passwordmgr-crypto-login");
+          Services.obs.removeObserver(this, "passwordmgr-crypto-loginCanceled");
+          if (topic == "passwordmgr-crypto-loginCanceled") {
+            resolve(false);
+            return;
+          }
+
+          resolve(true);
+        },
+      };
+
+      // Possible leak: it's possible that neither of these notifications
+      // will fire, and if that happens, we'll leak the observer (and
+      // never return). We should guarantee that at least one of these
+      // will fire.
+      // See bug XXX.
+      Services.obs.addObserver(observer, "passwordmgr-crypto-login");
+      Services.obs.addObserver(observer, "passwordmgr-crypto-loginCanceled");
+
+      // Focus and draw attention to the existing master password dialog for the
+      // occassions where it's not attached to the current window.
+      let promptWin = Services.wm.getMostRecentWindow("prompt:promptPassword");
+      promptWin.focus();
+      promptWin.getAttention();
+    });
+  },
+};
+
+XPCOMUtils.defineLazyGetter(this, "log", () => {
+  let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
+  return new ConsoleAPI({
+    maxLogLevelPref: "masterPassword.loglevel",
+    prefix: "Master Password",
+  });
+});
--- a/toolkit/components/prompts/src/CommonDialog.jsm
+++ b/toolkit/components/prompts/src/CommonDialog.jsm
@@ -86,16 +86,20 @@ CommonDialog.prototype = {
             // Clear the label, since the message presumably indicates its purpose.
             this.ui.password1Label.setAttribute("value", "");
             break;
           default:
             Cu.reportError("commonDialog opened for unknown type: " + this.args.promptType);
             throw "unknown dialog type";
         }
 
+        if (xulDialog) {
+            xulDialog.setAttribute("windowtype", "prompt:" + this.args.promptType);
+        }
+
         // set the document title
         let title = this.args.title;
         // OS X doesn't have a title on modal dialogs, this is hidden on other platforms.
         let infoTitle = this.ui.infoTitle;
         infoTitle.appendChild(infoTitle.ownerDocument.createTextNode(title));
         if (xulDialog)
             xulDialog.ownerDocument.title = title;