Bug 1167740 - Allow editing login from "Update login" doorhanger. r=margaret
authorChenxia Liu <liuche@mozilla.com>
Thu, 11 Jun 2015 18:06:58 -0700
changeset 266806 e4c461d6bea857645bcd020243fce6a79ca1e0c8
parent 266805 85d78dc233e87302a61376ffbcb07e67bfc92080
child 266807 94ff3be9a0294c02df3dd4ae6f5e23e8aec19625
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-esr52@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmargaret
bugs1167740
milestone41.0a1
Bug 1167740 - Allow editing login from "Update login" doorhanger. r=margaret
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/strings.xml.in
mobile/android/base/widget/LoginDoorHanger.java
mobile/android/components/LoginManagerPrompter.js
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -447,17 +447,16 @@ size. -->
 
 <!ENTITY button_ok "OK">
 <!ENTITY button_cancel "Cancel">
 <!ENTITY button_yes "Yes">
 <!ENTITY button_no "No">
 <!ENTITY button_clear_data "Clear data">
 <!ENTITY button_set "Set">
 <!ENTITY button_clear "Clear">
-<!ENTITY button_remember "Remember">
 <!ENTITY button_copy "Copy">
 
 <!ENTITY firstrun_panel_title_welcome "Welcome">
 
 <!ENTITY home_top_sites_title "Top Sites">
 <!-- Localization note (home_top_sites_add): This string is used as placeholder
      text underneath empty thumbnails in the Top Sites page on about:home. -->
 <!ENTITY home_top_sites_add "Add a site">
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -380,17 +380,16 @@
 
   <string name="button_ok">&button_ok;</string>
   <string name="button_cancel">&button_cancel;</string>
   <string name="button_clear_data">&button_clear_data;</string>
   <string name="button_set">&button_set;</string>
   <string name="button_clear">&button_clear;</string>
   <string name="button_yes">&button_yes;</string>
   <string name="button_no">&button_no;</string>
-  <string name="button_remember">&button_remember;</string>
   <string name="button_copy">&button_copy;</string>
 
   <string name="firstrun_panel_title_welcome">&firstrun_panel_title_welcome;</string>
 
   <string name="home_title">&home_title;</string>
   <string name="home_top_sites_title">&home_top_sites_title;</string>
   <string name="home_top_sites_add">&home_top_sites_add;</string>
   <string name="home_history_title">&home_history_title;</string>
--- a/mobile/android/base/widget/LoginDoorHanger.java
+++ b/mobile/android/base/widget/LoginDoorHanger.java
@@ -33,41 +33,42 @@ import org.mozilla.gecko.favicons.OnFavi
 
 public class LoginDoorHanger extends DoorHanger {
     private static final String LOGTAG = "LoginDoorHanger";
     private enum ActionType { EDIT, SELECT }
 
     private final TextView mTitle;
     private final TextView mMessage;
     private final TextView mLink;
-    private int mCallbackID;
+    private final DoorhangerConfig.ButtonConfig mButtonConfig;
 
     public LoginDoorHanger(Context context, DoorhangerConfig config) {
         super(context, config, Type.LOGIN);
 
         mTitle = (TextView) findViewById(R.id.doorhanger_title);
         mMessage = (TextView) findViewById(R.id.doorhanger_message);
         mLink = (TextView) findViewById(R.id.doorhanger_link);
         mIcon.setImageResource(R.drawable.icon_key);
         mIcon.setVisibility(View.VISIBLE);
 
+        mButtonConfig = config.getPositiveButtonConfig();
+
         loadConfig(config);
     }
 
     private void setMessage(String message) {
         Spanned markupMessage = Html.fromHtml(message);
         mMessage.setText(markupMessage);
     }
 
     @Override
     protected void loadConfig(DoorhangerConfig config) {
         setOptions(config.getOptions());
         setMessage(config.getMessage());
         // Store the positive callback id for nested dialogs that need the same callback id.
-        mCallbackID = config.getPositiveButtonConfig().callback;
         addButtonsToLayout(config);
     }
 
     @Override
     protected int getContentResource() {
         return R.layout.login_doorhanger;
     }
 
@@ -155,22 +156,22 @@ public class LoginDoorHanger extends Doo
                                 password.setTransformationMethod(null);
                             } else {
                                 password.setTransformationMethod(PasswordTransformationMethod.getInstance());
                             }
                         }
                     });
                     builder.setView(view);
 
-                    builder.setPositiveButton(R.string.button_remember, new DialogInterface.OnClickListener() {
+                    builder.setPositiveButton(mButtonConfig.label, new DialogInterface.OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                             JSONObject response = new JSONObject();
                             try {
-                                response.put("callback", mCallbackID);
+                                response.put("callback", mButtonConfig.callback);
                                 final JSONObject inputs = new JSONObject();
                                 inputs.put("username", username.getText());
                                 inputs.put("password", password.getText());
                                 response.put("inputs", inputs);
                             } catch (JSONException e) {
                                 Log.e(LOGTAG, "Error creating doorhanger reply message");
                                 response = null;
                                 Toast.makeText(mContext, mResources.getString(R.string.doorhanger_login_edit_toast_error), Toast.LENGTH_SHORT).show();
@@ -209,17 +210,17 @@ public class LoginDoorHanger extends Doo
                             usernames[i] = user;
                             passwords[i] = login.getString("password");
                         }
                         builder.setItems(usernames, new DialogInterface.OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int which) {
                                 final JSONObject response = new JSONObject();
                                 try {
-                                    response.put("callback", mCallbackID);
+                                    response.put("callback", mButtonConfig.callback);
                                     response.put("password", passwords[which]);
                                 } catch (JSONException e) {
                                     Log.e(LOGTAG, "Error making login select dialog JSON", e);
                                 }
                                 mOnButtonClickListener.onButtonClick(response, LoginDoorHanger.this);
                             }
                         });
                         builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
--- a/mobile/android/components/LoginManagerPrompter.js
+++ b/mobile/android/components/LoginManagerPrompter.js
@@ -141,39 +141,46 @@ LoginManagerPrompter.prototype = {
      *
      * Displays a notification doorhanger.
      * @param aTitle
      *        Object with title and optional resource to display with the title, such as a favicon key
      * @param aBody
      *        String message to be displayed in the doorhanger
      * @param aButtons
      *        Buttons to display with the doorhanger
-     * @param aActionText
-     *        Object with text to be displayed as clickable, along with a bundle to create an action
-     *
+     * @param aUsername
+     *        Username string used in creating a doorhanger action
+     * @param aPassword
+     *        Password string used in creating a doorhanger action
      */
-    _showLoginNotification : function (aTitle, aBody, aButtons, aActionText) {
+    _showLoginNotification : function (aTitle, aBody, aButtons, aUsername, aPassword) {
         let notifyWin = this._window.top;
         let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
         let browser = chromeWin.BrowserApp.getBrowserForWindow(notifyWin);
         let tabID = chromeWin.BrowserApp.getTabForBrowser(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
         // across the first location change.
 
         // Sites like Gmail perform a funky redirect dance before you end up
         // at the post-authentication page. I don't see a good way to
         // 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,
             title: aTitle,
-            actionText: aActionText
+            actionText: actionText
         }
 
         var nativeWindow = this._getNativeWindow();
         if (nativeWindow)
             nativeWindow.doorhanger.show(aBody, "password", aButtons, tabID, options, "LOGIN");
     },
 
 
@@ -189,23 +196,16 @@ LoginManagerPrompter.prototype = {
         let brandShortName = this._strBundle.brand.GetStringFromName("brandShortName");
         let notificationText  = this._getLocalizedString("saveLogin", [brandShortName]);
 
         let displayHost = this._getShortDisplayHost(aLogin.hostname);
         let title = { text: displayHost, resource: aLogin.hostname };
 
         let username = aLogin.username ? this._sanitizeUsername(aLogin.username) : "";
 
-        let actionText = {
-            text: username,
-            type: "EDIT",
-            bundle: { username: username,
-                       password: aLogin.password }
-        };
-
         // 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 pwmgr = this._pwmgr;
         let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_REMEMBER_ACTION");
 
         var buttons = [
             {
@@ -225,17 +225,17 @@ LoginManagerPrompter.prototype = {
                     }
                     pwmgr.addLogin(aLogin);
                     promptHistogram.add(PROMPT_ADD);
                 },
                 positive: true
             }
         ];
 
-        this._showLoginNotification(title, notificationText, buttons, actionText);
+        this._showLoginNotification(title, notificationText, buttons, aLogin.username, aLogin.password);
     },
 
     /*
      * promptToChangePassword
      *
      * Called when we think we detect a password change for an existing
      * login, when the form being submitted contains multiple password
      * fields.
@@ -275,25 +275,27 @@ LoginManagerPrompter.prototype = {
                 label: this._getLocalizedString("dontUpdateButton"),
                 callback:  function() {
                     promptHistogram.add(PROMPT_NOTNOW);
                     // do nothing
                 }
             },
             {
                 label: this._getLocalizedString("updateButton"),
-                callback:  function() {
-                    self._updateLogin(aOldLogin, aNewPassword);
-                    promptHistogram.add(PROMPT_UPDATE);
+                callback:  function(checked, response) {
+                   let password = response ? response["password"] : aNewPassword;
+                   self._updateLogin(aOldLogin, password);
+
+                   promptHistogram.add(PROMPT_UPDATE);
                 },
                 positive: true
             }
         ];
 
-        this._showLoginNotification(title, notificationText, buttons);
+        this._showLoginNotification(title, notificationText, buttons, aOldLogin.username, aNewPassword);
     },
 
 
     /*
      * promptToChangePasswordWithUsernames
      *
      * Called when we detect a password change in a form submission, but we
      * don't know which existing login (username) it's for. Asks the user