Bug 1400243 - 1. Use universal DoorHanger in LoginManagerPrompter; r=esawin
authorJim Chen <nchen@mozilla.com>
Tue, 19 Sep 2017 15:57:19 -0400
changeset 433763 ef0402ba21c23c957c6ffb56671c10a2680f4005
parent 433762 26f9c5c3f434500adb3aa7e47c8eebdb9ed45c86
child 433764 f07a6fbba625da26526a24fe04bd01b1f40b1a1b
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1400243
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 1400243 - 1. Use universal DoorHanger in LoginManagerPrompter; r=esawin Use the universal DoorHanger API from Prompt.jsm to show the login doorhanger from any window. Also, refactor parts of LoginManagerPrompter to use Services.jsm if possible. MozReview-Commit-ID: 3cnzeT0RNgR
mobile/android/components/LoginManagerPrompter.js
--- a/mobile/android/components/LoginManagerPrompter.js
+++ b/mobile/android/components/LoginManagerPrompter.js
@@ -3,17 +3,21 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  DoorHanger: "resource://gre/modules/Prompt.jsm",
+  Services: "resource://gre/modules/Services.jsm",
+});
 
 /* Constants for password prompt telemetry.
 * Mirrored in nsLoginManagerPrompter.js */
 const PROMPT_DISPLAYED = 0;
 
 const PROMPT_ADD = 1;
 const PROMPT_NOTNOW = 2;
 const PROMPT_NEVER = 3;
@@ -35,32 +39,16 @@ function LoginManagerPrompter() {
 LoginManagerPrompter.prototype = {
   classID: Components.ID("97d12931-abe2-11df-94e2-0800200c9a66"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsILoginManagerPrompter]),
 
   _factory: null,
   _window: null,
   _debug: false, // mirrors signon.debug
 
-  __pwmgr: null, // Password Manager service
-  get _pwmgr() {
-    if (!this.__pwmgr)
-      this.__pwmgr = Cc["@mozilla.org/login-manager;1"].
-                     getService(Ci.nsILoginManager);
-    return this.__pwmgr;
-  },
-
-  __promptService: null, // Prompt service for user interaction
-  get _promptService() {
-    if (!this.__promptService)
-      this.__promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
-                             getService(Ci.nsIPromptService2);
-    return this.__promptService;
-  },
-
   __strBundle: null, // String bundle for L10N
   get _strBundle() {
     if (!this.__strBundle) {
       let bunService = Cc["@mozilla.org/intl/stringbundle;1"].
                        getService(Ci.nsIStringBundleService);
       this.__strBundle = {
         pwmgr: bunService.createBundle("chrome://browser/locale/passwordmgr.properties"),
         brand: bunService.createBundle("chrome://branding/locale/brand.properties")
@@ -100,17 +88,17 @@ LoginManagerPrompter.prototype = {
 
   /* ---------- nsILoginManagerPrompter prompts ---------- */
 
   /*
    * init
    *
    */
   init: function(aWindow, aFactory) {
-    this._chromeWindow = this._getChromeWindow(aWindow).wrappedJSObject;
+    this._window = aWindow;
     this._factory = aFactory || null;
     this._browser = null;
 
     var prefBranch = Services.prefs.getBranch("signon.");
     this._debug = prefBranch.getBoolPref("debug");
     this.log("===== initialized =====");
   },
 
@@ -141,18 +129,16 @@ LoginManagerPrompter.prototype = {
    * @param aButtons
    *        Buttons to display with the doorhanger
    * @param aUsername
    *        Username string used in creating a doorhanger action
    * @param aPassword
    *        Password string used in creating a doorhanger action
    */
   _showLoginNotification: function(aBody, aButtons, aUsername, aPassword) {
-    let tabID = this._chromeWindow.BrowserApp.getTabForBrowser(this._browser).id;
-
     let actionText = {
       text: aUsername,
       type: "EDIT",
       bundle: { username: aUsername,
       password: aPassword }
     };
 
     // The page we're going to hasn't loaded yet, so we want to persist
@@ -163,19 +149,18 @@ LoginManagerPrompter.prototype = {
     // heuristically determine when to ignore such location changes, so
     // we'll try ignoring location changes based on a time interval.
     let options = {
       persistWhileVisible: true,
       timeout: Date.now() + 10000,
       actionText: actionText
     }
 
-    var nativeWindow = this._getNativeWindow();
-    if (nativeWindow)
-      nativeWindow.doorhanger.show(aBody, "password", aButtons, tabID, options, "LOGIN");
+    let win = (this._browser && this._browser.contentWindow) || this._window;
+    DoorHanger.show(win, aBody, "password", aButtons, options, "LOGIN");
   },
 
   /*
    * _showSaveLoginNotification
    *
    * Displays a notification doorhanger (rather than a popup), to allow the user to
    * save the specified login. This allows the user to see the results of
    * their login, and only save a login which they know worked.
@@ -183,19 +168,19 @@ LoginManagerPrompter.prototype = {
    */
   _showSaveLoginNotification: function(aLogin) {
     let brandShortName = this._strBundle.brand.GetStringFromName("brandShortName");
     let notificationText  = this._getLocalizedString("saveLogin", [brandShortName]);
 
     let username = aLogin.username ? this._sanitizeUsername(aLogin.username) : "";
 
     // The callbacks in |buttons| have a closure to access the variables
-    // in scope here; set one to |this._pwmgr| so we can get back to pwmgr
+    // in scope here; set one to |Services.logins| so we can get back to pwmgr
     // without a getService() call.
-    var pwmgr = this._pwmgr;
+    var pwmgr = Services.logins;
     let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_REMEMBER_ACTION");
 
     var buttons = [
       {
         label: this._getLocalizedString("neverButton"),
         callback: function() {
           promptHistogram.add(PROMPT_NEVER);
           pwmgr.setLoginSavingEnabled(aLogin.hostname, false);
@@ -243,19 +228,16 @@ LoginManagerPrompter.prototype = {
     var notificationText;
     if (aOldLogin.username) {
       let displayUser = this._sanitizeUsername(aOldLogin.username);
       notificationText  = this._getLocalizedString("updatePassword", [displayUser]);
     } else {
       notificationText  = this._getLocalizedString("updatePasswordNoUser");
     }
 
-    // The callbacks in |buttons| have a closure to access the variables
-    // in scope here; set one to |this._pwmgr| so we can get back to pwmgr
-    // without a getService() call.
     var self = this;
     let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_UPDATE_ACTION");
 
     var buttons = [
       {
         label: this._getLocalizedString("dontUpdateButton"),
         callback:  function() {
           promptHistogram.add(PROMPT_NOTNOW);
@@ -295,17 +277,17 @@ LoginManagerPrompter.prototype = {
 
     var usernames = logins.map(l => l.username);
     var dialogText  = this._getLocalizedString("userSelectText2");
     var dialogTitle = this._getLocalizedString("passwordChangeTitle");
     var selectedIndex = { value: null };
 
     // If user selects ok, outparam.value is set to the index
     // of the selected username.
-    var ok = this._promptService.select(null,
+    var ok = Services.prompt.select(null,
       dialogTitle, dialogText,
       usernames.length, usernames,
       selectedIndex);
     if (ok) {
       // Now that we know which login to use, modify its password.
       let selectedLogin = logins[selectedIndex.value];
       this.log("Updating password for user " + selectedLogin.username);
       this._updateLogin(selectedLogin, aNewLogin.password);
@@ -325,55 +307,17 @@ LoginManagerPrompter.prototype = {
       propBag.setProperty("password", newPassword);
       // Explicitly set the password change time here (even though it would
       // be changed automatically), to ensure that it's exactly the same
       // value as timeLastUsed.
       propBag.setProperty("timePasswordChanged", now);
     }
     propBag.setProperty("timeLastUsed", now);
     propBag.setProperty("timesUsedIncrement", 1);
-    this._pwmgr.modifyLogin(login, propBag);
-  },
-
-  /*
-   * _getChromeWindow
-   *
-   * Given a content DOM window, returns the chrome window it's in.
-   */
-  _getChromeWindow: function(aWindow) {
-    if (aWindow instanceof Ci.nsIDOMChromeWindow)
-      return aWindow;
-    var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIWebNavigation)
-      .QueryInterface(Ci.nsIDocShell)
-      .chromeEventHandler.ownerGlobal;
-    return chromeWin;
-  },
-
-  /*
-   * _getNativeWindow
-   *
-   * Returns the NativeWindow to this prompter, or null if there isn't
-   * a NativeWindow available (w/ error sent to logcat).
-   */
-  _getNativeWindow: function() {
-    let nativeWindow = null;
-    try {
-      let chromeWin = this._chromeWindow;
-      if (chromeWin.NativeWindow) {
-        nativeWindow = chromeWin.NativeWindow;
-      } else {
-        Cu.reportError("NativeWindow not available on window");
-      }
-
-    } catch (e) {
-      // If any errors happen, just assume no native window helper.
-      Cu.reportError("No NativeWindow available: " + e);
-    }
-    return nativeWindow;
+    Services.logins.modifyLogin(login, propBag);
   },
 
   /*
    * _getLocalizedString
    *
    * Can be called as:
    *   _getLocalizedString("key1");
    *   _getLocalizedString("key2", ["arg1"]);