Bug 695446 - Password manager/Form Fill [r=mbrubeck]
authorMark Finkle <mfinkle@mozilla.com>
Thu, 27 Oct 2011 00:29:46 -0400
changeset 83285 c775f204ec05c0488187e45e97188b0de7244135
parent 83284 adad73e2ee6f20d0a88839af079dbf70060766df
child 83286 075341ad34eebe75267b025d67d585c34e501761
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs695446
milestone10.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 695446 - Password manager/Form Fill [r=mbrubeck]
mobile/app/mobile.js
mobile/chrome/content/browser.js
mobile/components/LoginManager.js
mobile/components/LoginManagerPrompter.idl
mobile/components/LoginManagerPrompter.js
mobile/components/Makefile.in
mobile/components/MobileComponents.manifest
mobile/installer/package-manifest.in
mobile/locales/en-US/chrome/overrides/passwordmgr.properties
--- a/mobile/app/mobile.js
+++ b/mobile/app/mobile.js
@@ -175,16 +175,17 @@ pref("alerts.height", 50);
 
 /* download helper */
 pref("browser.helperApps.deleteTempFileOnExit", false);
 
 /* password manager */
 pref("signon.rememberSignons", true);
 pref("signon.expireMasterPassword", false);
 pref("signon.SignonFileName", "signons.txt");
+pref("signon.debug", false);
 
 /* form helper */
 // 0 = disabled, 1 = enabled, 2 = dynamic depending on screen size
 pref("formhelper.mode", 2);
 pref("formhelper.autozoom", true);
 pref("formhelper.autozoom.caret", true);
 pref("formhelper.restore", false);
 
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -132,28 +132,30 @@ var BrowserApp = {
     Services.obs.addObserver(this, "Preferences:Get", false);
     Services.obs.addObserver(this, "Preferences:Set", false);
     Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
 
     Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
     Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
 
     NativeWindow.init();
+    Downloads.init();
+
+    // Init LoginManager
+    Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
 
     let uri = "about:support";
     if ("arguments" in window && window.arguments[0])
       uri = window.arguments[0];
 
     // XXX maybe we don't do this if the launch was kicked off from external
     Services.io.offline = false;
     let newTab = this.addTab(uri);
     newTab.active = true;
 
-    Downloads.init();
-
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
 
     // notify java that gecko has loaded
     sendMessageToJava({
       gecko: {
deleted file mode 100644
--- a/mobile/components/LoginManager.js
+++ /dev/null
@@ -1,719 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Justin Dolske <dolske@mozilla.com> (original author)
- *  Ehsan Akhgari <ehsan.akhgari@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function LoginManager() {
-    this.init();
-}
-
-LoginManager.prototype = {
-
-    classID: Components.ID("{f9a0edde-2a8d-4bfd-a08c-3f9333213a85}"),
-    QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManager,
-                                            Ci.nsIObserver,
-                                            Ci.nsISupportsWeakReference]),
-
-
-    /* ---------- private members ---------- */
-
-
-    __storage : null, // Storage component which contains the saved logins
-    get _storage() {
-        if (!this.__storage) {
-
-            var contractID = "@mozilla.org/login-manager/storage/mozStorage;1";
-            try {
-                var catMan = Cc["@mozilla.org/categorymanager;1"].
-                             getService(Ci.nsICategoryManager);
-                contractID = catMan.getCategoryEntry("login-manager-storage",
-                                                     "nsILoginManagerStorage");
-                this.log("Found alternate nsILoginManagerStorage with " +
-                         "contract ID: " + contractID);
-            } catch (e) {
-                this.log("No alternate nsILoginManagerStorage registered");
-            }
-
-            this.__storage = Cc[contractID].
-                             createInstance(Ci.nsILoginManagerStorage);
-            try {
-                this.__storage.init();
-            } catch (e) {
-                this.log("Initialization of storage component failed: " + e);
-                this.__storage = null;
-            }
-        }
-
-        return this.__storage;
-    },
-
-
-    _nsLoginInfo : null, // Constructor for nsILoginInfo implementation
-    _debug    : false, // mirrors signon.debug
-    _remember : true,  // mirrors signon.rememberSignons preference
-
-
-    /*
-     * init
-     *
-     * Initialize the Login Manager. Automatically called when service
-     * is created.
-     *
-     * Note: Service created in /browser/base/content/browser.js,
-     *       delayedStartup()
-     */
-    init : function () {
-        // Add content listener.
-        var messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                             getService(Ci.nsIChromeFrameMessageManager);
-        messageManager.loadFrameScript("chrome://browser/content/LoginManagerChild.js", true);
-        messageManager.addMessageListener("PasswordMgr:FormSubmitted", this);
-        messageManager.addMessageListener("PasswordMgr:GetPasswords", this);
-
-        // Get constructor for nsILoginInfo
-        this._nsLoginInfo = new Components.Constructor(
-            "@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
-
-        // Preferences. Add observer so we get notified of changes.
-        Services.prefs.addObserver("signon.", this, false);
-
-        // Get current preference values.
-        this._debug = Services.prefs.getBoolPref("signon.debug");
-        this._remember = Services.prefs.getBoolPref("signon.rememberSignons");
-
-        // Listen for shutdown to clean up
-        Services.obs.addObserver(this, "xpcom-shutdown", false);
-    },
-
-    /*
-     * log
-     *
-     * Internal function for logging debug messages to the Error Console window
-     */
-    log : function (message) {
-        if (!this._debug)
-            return;
-        dump("PasswordUtils: " + message + "\n");
-        Services.console.logStringMessage("PasswordUtils: " + message);
-    },
-
-    /*
-     * observe
-     *
-     * Implements nsIObserver for preferences and shutdown.
-     */
-    observe : function (subject, topic, data) {
-        if (topic == "nsPref:changed") {
-            this._pwmgr._debug    = Services.prefs.getBoolPref("signon.debug");
-            this._pwmgr._remember = Services.prefs.getBoolPref("signon.rememberSignons");
-        } else if (topic == "xpcom-shutdown") {
-            // Circular reference forms when we mark an input field as managed
-            // by the password manager
-            this._formFillService = null;
-        } else {
-            this._pwmgr.log("Oops! Unexpected notification: " + topic);
-        }
-    },
-
-    /*
-     * receiveMessage
-     *
-     * Receives messages from content process.
-     */
-    receiveMessage: function (message) {
-        // local helper function
-        function getPrompter(aBrowser) {
-            var prompterSvc = Cc["@mozilla.org/login-manager/prompter;1"].
-                              createInstance(Ci.nsILoginManagerPrompter);
-            prompterSvc.init(aBrowser);
-            return prompterSvc;
-        }
-
-        switch (message.name) {
-            case "PasswordMgr:GetPasswords":
-                // If there are no logins for this site, bail out now.
-                if (!this.countLogins(message.json.formOrigin, "", null))
-                    return { foundLogins: {} };
-
-                var foundLogins = {};
-
-                if (!this.uiBusy) {
-                    for (var i = 0; i < message.json.actionOrigins.length; i++) {
-                        var actionOrigin = message.json.actionOrigins[i];
-                        var logins = this.findLogins({}, message.json.formOrigin, actionOrigin, null);
-                        if (logins.length) {
-                            foundLogins[actionOrigin] = logins;
-                        }
-                    }
-                }
-
-                return {
-                    uiBusy: this.uiBusy,
-                    foundLogins: foundLogins
-                };
-
-            case "PasswordMgr:FormSubmitted":
-                var json = message.json;
-                var hostname = json.hostname;
-                var formSubmitURL = json.formSubmitURL;
-
-                if (!this.getLoginSavingEnabled(hostname)) {
-                    this.log("(form submission ignored -- saving is " +
-                             "disabled for: " + hostname + ")");
-                    return {};
-                }
-
-                var browser = message.target;
-
-                var formLogin = new this._nsLoginInfo();
-
-                formLogin.init(hostname, formSubmitURL, null,
-                            json.usernameValue,
-                            json.passwordValue,
-                            json.usernameField,
-                            json.passwordField);
-
-                // If we didn't find a username field, but seem to be changing a
-                // password, allow the user to select from a list of applicable
-                // logins to update the password for.
-                if (!json.usernameField && json.hasOldPasswordField) {
-
-                    var logins = this.findLogins({}, hostname, formSubmitURL, null);
-
-                    if (logins.length == 0) {
-                        // Could prompt to save this as a new password-only login.
-                        // This seems uncommon, and might be wrong, so ignore.
-                        this.log("(no logins for this host -- pwchange ignored)");
-                        return {};
-                    }
-
-                    var prompter = getPrompter(browser);
-
-                    if (logins.length == 1) {
-                        var oldLogin = logins[0];
-                        formLogin.username      = oldLogin.username;
-                        formLogin.usernameField = oldLogin.usernameField;
-
-                        prompter.promptToChangePassword(oldLogin, formLogin);
-                    } else {
-                        prompter.promptToChangePasswordWithUsernames(
-                                            logins, logins.length, formLogin);
-                    }
-
-                } else {
-
-                    // Look for an existing login that matches the form login.
-                    var existingLogin = null;
-                    var logins = this.findLogins({}, hostname, formSubmitURL, null);
-
-                    for (var i = 0; i < logins.length; i++) {
-                        var same, login = logins[i];
-
-                        // If one login has a username but the other doesn't, ignore
-                        // the username when comparing and only match if they have the
-                        // same password. Otherwise, compare the logins and match even
-                        // if the passwords differ.
-                        if (!login.username && formLogin.username) {
-                            var restoreMe = formLogin.username;
-                            formLogin.username = ""; 
-                            same = formLogin.matches(login, false);
-                            formLogin.username = restoreMe;
-                        } else if (!formLogin.username && login.username) {
-                            formLogin.username = login.username;
-                            same = formLogin.matches(login, false);
-                            formLogin.username = ""; // we know it's always blank.
-                        } else {
-                            same = formLogin.matches(login, true);
-                        }
-
-                        if (same) {
-                            existingLogin = login;
-                            break;
-                        }
-                    }
-
-                    if (existingLogin) {
-                        this.log("Found an existing login matching this form submission");
-
-                        // Change password if needed.
-                        if (existingLogin.password != formLogin.password) {
-                            this.log("...passwords differ, prompting to change.");
-                            prompter = getPrompter(browser);
-                            prompter.promptToChangePassword(existingLogin, formLogin);
-                        } else {
-                            // Update the lastUsed timestamp.
-                            var propBag = Cc["@mozilla.org/hash-property-bag;1"].
-                                          createInstance(Ci.nsIWritablePropertyBag);
-                            propBag.setProperty("timeLastUsed", Date.now());
-                            propBag.setProperty("timesUsedIncrement", 1);
-                            this.modifyLogin(existingLogin, propBag);
-                        }
-
-                        return {};
-                    }
-
-
-                    // Prompt user to save login (via dialog or notification bar)
-                    prompter = getPrompter(browser);
-                    prompter.promptToSavePassword(formLogin);
-                }
-                return {};
-
-            default:
-                throw "Unexpected message " + message.name;
-        }
-    },
-
-
-    /*
-     * _getPasswordOrigin
-     *
-     * Get the parts of the URL we want for identification.
-     */
-    _getPasswordOrigin : function (uriString, allowJS) {
-        var realm = "";
-        try {
-            var uri = Services.io.newURI(uriString, null, null);
-
-            if (allowJS && uri.scheme == "javascript")
-                return "javascript:"
-
-            realm = uri.scheme + "://" + uri.host;
-
-            // If the URI explicitly specified a port, only include it when
-            // it's not the default. (We never want "http://foo.com:80")
-            var port = uri.port;
-            if (port != -1) {
-                var handler = Services.io.getProtocolHandler(uri.scheme);
-                if (port != handler.defaultPort)
-                    realm += ":" + port;
-            }
-
-        } catch (e) {
-            // bug 159484 - disallow url types that don't support a hostPort.
-            // (although we handle "javascript:..." as a special case above.)
-            this.log("Couldn't parse origin for " + uriString);
-            realm = null;
-        }
-
-        return realm;
-    },
-
-
-    _getActionOrigin : function (form) {
-        var uriString = form.action;
-
-        // A blank or mission action submits to where it came from.
-        if (uriString == "")
-            uriString = form.baseURI; // ala bug 297761
-
-        return this._getPasswordOrigin(uriString, true);
-    },
-
-
-    /* ---------- Primary Public interfaces ---------- */
-
-
-    /*
-     * fillForm
-     *
-     * Fill the form with login information if we can find it.
-     */
-    fillForm : function (form) {
-        // XXX figure out what to do about fillForm
-        return false;
-    },
-
-
-    /*
-     * addLogin
-     *
-     * Add a new login to login storage.
-     */
-    addLogin : function (login) {
-        // Sanity check the login
-        if (login.hostname == null || login.hostname.length == 0)
-            throw "Can't add a login with a null or empty hostname.";
-
-        // For logins w/o a username, set to "", not null.
-        if (login.username == null)
-            throw "Can't add a login with a null username.";
-
-        if (login.password == null || login.password.length == 0)
-            throw "Can't add a login with a null or empty password.";
-
-        if (login.formSubmitURL || login.formSubmitURL == "") {
-            // We have a form submit URL. Can't have a HTTP realm.
-            if (login.httpRealm != null)
-                throw "Can't add a login with both a httpRealm and formSubmitURL.";
-        } else if (login.httpRealm) {
-            // We have a HTTP realm. Can't have a form submit URL.
-            if (login.formSubmitURL != null)
-                throw "Can't add a login with both a httpRealm and formSubmitURL.";
-        } else {
-            // Need one or the other!
-            throw "Can't add a login without a httpRealm or formSubmitURL.";
-        }
-
-
-        // Look for an existing entry.
-        var logins = this.findLogins({}, login.hostname, login.formSubmitURL,
-                                     login.httpRealm);
-
-        if (logins.some(function(l) login.matches(l, true)))
-            throw "This login already exists.";
-
-        this.log("Adding login: " + login);
-        return this._storage.addLogin(login);
-    },
-
-
-    /*
-     * removeLogin
-     *
-     * Remove the specified login from the stored logins.
-     */
-    removeLogin : function (login) {
-        this.log("Removing login: " + login);
-        return this._storage.removeLogin(login);
-    },
-
-
-    /*
-     * modifyLogin
-     *
-     * Change the specified login to match the new login.
-     */
-    modifyLogin : function (oldLogin, newLogin) {
-        this.log("Modifying oldLogin: " + oldLogin + " newLogin: " + newLogin);
-        return this._storage.modifyLogin(oldLogin, newLogin);
-    },
-
-
-    /*
-     * getAllLogins
-     *
-     * Get a dump of all stored logins. Used by the login manager UI.
-     *
-     * |count| is only needed for XPCOM.
-     *
-     * Returns an array of logins. If there are no logins, the array is empty.
-     */
-    getAllLogins : function (count) {
-        this.log("Getting a list of all logins");
-        return this._storage.getAllLogins(count);
-    },
-
-
-    /*
-     * removeAllLogins
-     *
-     * Remove all stored logins.
-     */
-    removeAllLogins : function () {
-        this.log("Removing all logins");
-        this._storage.removeAllLogins();
-    },
-
-    /*
-     * getAllDisabledHosts
-     *
-     * Get a list of all hosts for which logins are disabled.
-     *
-     * |count| is only needed for XPCOM.
-     *
-     * Returns an array of disabled logins. If there are no disabled logins,
-     * the array is empty.
-     */
-    getAllDisabledHosts : function (count) {
-        this.log("Getting a list of all disabled hosts");
-        return this._storage.getAllDisabledHosts(count);
-    },
-
-
-    /*
-     * findLogins
-     *
-     * Search for the known logins for entries matching the specified criteria.
-     */
-    findLogins : function (count, hostname, formSubmitURL, httpRealm) {
-        this.log("Searching for logins matching host: " + hostname +
-            ", formSubmitURL: " + formSubmitURL + ", httpRealm: " + httpRealm);
-
-        return this._storage.findLogins(count, hostname, formSubmitURL,
-                                        httpRealm);
-    },
-
-
-    /*
-     * searchLogins
-     *
-     * Public wrapper around _searchLogins to convert the nsIPropertyBag to a
-     * JavaScript object and decrypt the results.
-     *
-     * Returns an array of decrypted nsILoginInfo.
-     */
-    searchLogins : function(count, matchData) {
-       this.log("Searching for logins");
-
-        return this._storage.searchLogins(count, matchData);
-    },
-
-
-    /*
-     * countLogins
-     *
-     * Search for the known logins for entries matching the specified criteria,
-     * returns only the count.
-     */
-    countLogins : function (hostname, formSubmitURL, httpRealm) {
-        this.log("Counting logins matching host: " + hostname +
-            ", formSubmitURL: " + formSubmitURL + ", httpRealm: " + httpRealm);
-
-        return this._storage.countLogins(hostname, formSubmitURL, httpRealm);
-    },
-
-
-    /*
-     * uiBusy
-     */
-    get uiBusy() {
-        return this._storage.uiBusy;
-    },
-
-
-    /*
-     * getLoginSavingEnabled
-     *
-     * Check to see if user has disabled saving logins for the host.
-     */
-    getLoginSavingEnabled : function (host) {
-        this.log("Checking if logins to " + host + " can be saved.");
-        if (!this._remember)
-            return false;
-
-        return this._storage.getLoginSavingEnabled(host);
-    },
-
-
-    /*
-     * setLoginSavingEnabled
-     *
-     * Enable or disable storing logins for the specified host.
-     */
-    setLoginSavingEnabled : function (hostname, enabled) {
-        // Nulls won't round-trip with getAllDisabledHosts().
-        if (hostname.indexOf("\0") != -1)
-            throw "Invalid hostname";
-
-        this.log("Saving logins for " + hostname + " enabled? " + enabled);
-        return this._storage.setLoginSavingEnabled(hostname, enabled);
-    },
-
-
-    /*
-     * autoCompleteSearch
-     *
-     * Yuck. This is called directly by satchel:
-     * nsFormFillController::StartSearch()
-     * [toolkit/components/satchel/src/nsFormFillController.cpp]
-     *
-     * We really ought to have a simple way for code to register an
-     * auto-complete provider, and not have satchel calling pwmgr directly.
-     */
-    autoCompleteSearch : function (aSearchString, aPreviousResult, aElement) {
-        // aPreviousResult & aResult are nsIAutoCompleteResult,
-        // aElement is nsIDOMHTMLInputElement
-
-        if (!this._remember)
-            return null;
-
-        this.log("AutoCompleteSearch invoked. Search is: " + aSearchString);
-
-        var result = null;
-
-        if (aPreviousResult &&
-                aSearchString.substr(0, aPreviousResult.searchString.length) == aPreviousResult.searchString) {
-            this.log("Using previous autocomplete result");
-            result = aPreviousResult;
-            result.wrappedJSObject.searchString = aSearchString;
-
-            // We have a list of results for a shorter search string, so just
-            // filter them further based on the new search string.
-            // Count backwards, because result.matchCount is decremented
-            // when we remove an entry.
-            for (var i = result.matchCount - 1; i >= 0; i--) {
-                var match = result.getValueAt(i);
-
-                // Remove results that are too short, or have different prefix.
-                if (aSearchString.length > match.length ||
-                    aSearchString.toLowerCase() !=
-                        match.substr(0, aSearchString.length).toLowerCase())
-                {
-                    this.log("Removing autocomplete entry '" + match + "'");
-                    result.removeValueAt(i, false);
-                }
-            }
-        } else {
-            this.log("Creating new autocomplete search result.");
-
-            var doc = aElement.ownerDocument;
-            var origin = this._getPasswordOrigin(doc.documentURI);
-            var actionOrigin = this._getActionOrigin(aElement.form);
-
-            // This shouldn't trigger a master password prompt, because we
-            // don't attach to the input until after we successfully obtain
-            // logins for the form.
-            var logins = this.findLogins({}, origin, actionOrigin, null);
-            var matchingLogins = [];
-
-            // Filter out logins that don't match the search prefix. Also
-            // filter logins without a username, since that's confusing to see
-            // in the dropdown and we can't autocomplete them anyway.
-            for (i = 0; i < logins.length; i++) {
-                var username = logins[i].username.toLowerCase();
-                if (username &&
-                    aSearchString.length <= username.length &&
-                    aSearchString.toLowerCase() ==
-                        username.substr(0, aSearchString.length))
-                {
-                    matchingLogins.push(logins[i]);
-                }
-            }
-            this.log(matchingLogins.length + " autocomplete logins avail.");
-            result = new UserAutoCompleteResult(aSearchString, matchingLogins);
-        }
-
-        return result;
-    }
-}; // end of LoginManager implementation
-
-
-
-
-// nsIAutoCompleteResult implementation
-function UserAutoCompleteResult (aSearchString, matchingLogins) {
-    function loginSort(a,b) {
-        var userA = a.username.toLowerCase();
-        var userB = b.username.toLowerCase();
-
-        if (userA < userB)
-            return -1;
-
-        if (userB > userA)
-            return  1;
-
-        return 0;
-    };
-
-    this.searchString = aSearchString;
-    this.logins = matchingLogins.sort(loginSort);
-    this.matchCount = matchingLogins.length;
-
-    if (this.matchCount > 0) {
-        this.searchResult = Ci.nsIAutoCompleteResult.RESULT_SUCCESS;
-        this.defaultIndex = 0;
-    }
-}
-
-UserAutoCompleteResult.prototype = {
-    QueryInterface : XPCOMUtils.generateQI([Ci.nsIAutoCompleteResult,
-                                            Ci.nsISupportsWeakReference]),
-
-    // private
-    logins : null,
-
-    // Allow autoCompleteSearch to get at the JS object so it can
-    // modify some readonly properties for internal use.
-    get wrappedJSObject() {
-        return this;
-    },
-
-    // Interfaces from idl...
-    searchString : null,
-    searchResult : Ci.nsIAutoCompleteResult.RESULT_NOMATCH,
-    defaultIndex : -1,
-    errorDescription : "",
-    matchCount : 0,
-
-    getValueAt : function (index) {
-        if (index < 0 || index >= this.logins.length)
-            throw "Index out of range.";
-
-        return this.logins[index].username;
-    },
-
-    getLabelAt : function (index) {
-      return this.getValueAt(index);
-    },
-
-    getCommentAt : function (index) {
-        return "";
-    },
-
-    getStyleAt : function (index) {
-        return "";
-    },
-
-    getImageAt : function (index) {
-        return "";
-    },
-
-    removeValueAt : function (index, removeFromDB) {
-        if (index < 0 || index >= this.logins.length)
-            throw "Index out of range.";
-
-        var [removedLogin] = this.logins.splice(index, 1);
-
-        this.matchCount--;
-        if (this.defaultIndex > this.logins.length)
-            this.defaultIndex--;
-
-        if (removeFromDB) {
-            var pwmgr = Cc["@mozilla.org/login-manager;1"].
-                        getService(Ci.nsILoginManager);
-            pwmgr.removeLogin(removedLogin);
-        }
-    }
-};
-
-var NSGetFactory = XPCOMUtils.generateNSGetFactory([LoginManager]);
deleted file mode 100644
--- a/mobile/components/LoginManagerPrompter.idl
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Justin Dolske <dolske@mozilla.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-#include "nsISupports.idl"
-
-interface nsILoginInfo;
-interface nsIFrameLoaderOwner;
-
-[scriptable, uuid(3f385080-aef5-11df-94e2-0800200c9a66)]
-
-interface nsILoginManagerPrompter : nsISupports {
-    /**
-     * Initialize the prompter. Must be called before using other interfaces.
-     *
-     * @param aBrowser
-     *        A browser element in which the user is doing some
-     *        login-related action in need to prompt them for something.
-     *        The prompt will be associated with browser.
-     */
-    void init(in nsIFrameLoaderOwner aBrowser);
-
-    /**
-     * Ask the user if they want to save a login (Yes, Never, Not Now)
-     *
-     * @param aLogin
-     *        The login to be saved.
-     */
-    void promptToSavePassword(in nsILoginInfo aLogin);
-
-    /**
-     * Ask the user if they want to change a login's password. If the
-     * user consents, modifyLogin() will be called.
-     *
-     * @param aOldLogin
-     *        The existing login (with the old password).
-     * @param aNewLogin
-     *        The new login.
-     */
-    void promptToChangePassword(in nsILoginInfo aOldLogin,
-                                in nsILoginInfo aNewLogin);
-
-    /**
-     * Ask the user if they want to change the password for one of
-     * multiple logins, when the caller can't determine exactly which
-     * login should be changed. If the user consents, modifyLogin() will
-     * be called.
-     *
-     * @param logins
-     *        An array of existing logins.
-     * @param count
-     *        (length of the array)
-     * @param aNewLogin
-     *        The new login. 
-     *
-     * Note: Because the caller does not know the username of the login
-     *       to be changed, aNewLogin.username and aNewLogin.usernameField
-     *       will be set (using the user's selection) before modifyLogin()
-     *       is called.
-     */
-    void promptToChangePasswordWithUsernames(
-            [array, size_is(count)] in nsILoginInfo logins,
-            in PRUint32 count,
-            in nsILoginInfo aNewLogin);
-};
-
--- a/mobile/components/LoginManagerPrompter.js
+++ b/mobile/components/LoginManagerPrompter.js
@@ -313,21 +313,21 @@ LoginManagerPrompter.prototype = {
         } else {
             dialogText = this._getLocalizedString(
                                  "saveLoginTextNoUsername",
                                  [brandShortName, displayHost]);
         }
         var dialogTitle        = this._getLocalizedString(
                                         "savePasswordTitle");
         var neverButtonText    = this._getLocalizedString(
-                                        "neverForSiteButtonText");
+                                        "promptNeverForSiteButtonText");
         var rememberButtonText = this._getLocalizedString(
-                                        "rememberButtonText");
+                                        "promptRememberButtonText");
         var notNowButtonText   = this._getLocalizedString(
-                                        "notNowButtonText");
+                                        "promptNotNowButtonText");
 
         this.log("Prompting user to save/ignore login");
         var userChoice = this._promptService.confirmEx(null,
                                             dialogTitle, dialogText,
                                             buttonFlags, rememberButtonText,
                                             notNowButtonText, neverButtonText,
                                             null, {});
         //  Returns:
--- a/mobile/components/Makefile.in
+++ b/mobile/components/Makefile.in
@@ -43,17 +43,16 @@ VPATH      = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = MobileComponents
 XPIDL_MODULE = MobileComponents
 
 XPIDLSRCS = \
         SessionStore.idl \
-        LoginManagerPrompter.idl \
         $(NULL)
 
 EXTRA_PP_COMPONENTS = \
         MobileComponents.manifest \
         AboutRedirector.js \
         BrowserCLH.js \
         BrowserStartup.js \
         DirectoryProvider.js\
@@ -67,17 +66,16 @@ EXTRA_COMPONENTS = \
         ContentPermissionPrompt.js \
         XPIDialogService.js \
         DownloadManagerUI.js \
         PromptService.js \
         ContentDispatchChooser.js \
         AutoCompleteCache.js \
         AddonUpdateService.js \
         FormAutoComplete.js \
-        LoginManager.js \
         LoginManagerPrompter.js \
         BlocklistPrompt.js \
         CapturePicker.js \
         $(NULL)
 
 ifdef MOZ_SAFE_BROWSING
 EXTRA_COMPONENTS += SafeBrowsing.js
 endif
--- a/mobile/components/MobileComponents.manifest
+++ b/mobile/components/MobileComponents.manifest
@@ -91,20 +91,16 @@ category bookmark-observers BrowserBookm
 component {93c8824c-9b87-45ae-bc90-5b82a1e4d877} AddonUpdateService.js
 contract @mozilla.org/browser/addon-update-service;1 {93c8824c-9b87-45ae-bc90-5b82a1e4d877}
 category update-timer AddonUpdateService @mozilla.org/browser/addon-update-service;1,getService,auto-addon-background-update-timer,extensions.autoupdate.interval,86400
 
 # FormAutoComplete.js
 component {cccd414c-3ec2-4cc5-9dc4-36c87cc3c4fe} FormAutoComplete.js
 contract @mozilla.org/satchel/form-autocomplete;1 {cccd414c-3ec2-4cc5-9dc4-36c87cc3c4fe}
 
-# LoginManager.js
-component {f9a0edde-2a8d-4bfd-a08c-3f9333213a85} LoginManager.js
-contract @mozilla.org/login-manager;1 {f9a0edde-2a8d-4bfd-a08c-3f9333213a85}
-
 # LoginManagerPrompter.js
 component {97d12931-abe2-11df-94e2-0800200c9a66} LoginManagerPrompter.js
 contract @mozilla.org/login-manager/prompter;1 {97d12931-abe2-11df-94e2-0800200c9a66}
 
 # BlocklistPrompt.js
 component {4e6ea350-b09a-11df-94e2-0800200c9a66} BlocklistPrompt.js
 contract @mozilla.org/addons/blocklist-prompt;1 {4e6ea350-b09a-11df-94e2-0800200c9a66}
 
--- a/mobile/installer/package-manifest.in
+++ b/mobile/installer/package-manifest.in
@@ -599,17 +599,16 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/BrowserCLH.js
 @BINPATH@/components/BrowserStartup.js
 @BINPATH@/components/ContentDispatchChooser.js
 @BINPATH@/components/ContentPermissionPrompt.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/DownloadManagerUI.js
 @BINPATH@/components/FormAutoComplete.js
 @BINPATH@/components/HelperAppDialog.js
-@BINPATH@/components/LoginManager.js
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
 @BINPATH@/components/MobileComponents.xpt
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/Sidebar.js
 @BINPATH@/components/OpenWebapps.js
 #ifdef MOZ_SAFE_BROWSING
--- a/mobile/locales/en-US/chrome/overrides/passwordmgr.properties
+++ b/mobile/locales/en-US/chrome/overrides/passwordmgr.properties
@@ -39,23 +39,23 @@
 rememberValue = Use Password Manager to remember this value.
 rememberPassword = Use Password Manager to remember this password.
 savePasswordTitle = Confirm
 # 1st string is product name, 2nd is the username for the login, 3rd is the
 #   login's hostname. Note that long usernames may be truncated.
 saveLoginText = Do you want %1$S to remember the password for "%2$S" on %3$S?
 # 1st string is product name, 2nd is the login's hostname
 saveLoginTextNoUsername = Do you want %1$S to remember this password on %2$S?
-notNowButtonText = &Not Now
+promptNotNowButtonText = Not Now
 notifyBarNotNowButtonText = Not Now
 notifyBarNotNowButtonAccessKey =
-neverForSiteButtonText = Ne&ver for This Site
+promptNeverForSiteButtonText = Never
 notifyBarNeverForSiteButtonText = Never
 notifyBarNeverForSiteButtonAccessKey =
-rememberButtonText = &Remember
+promptRememberButtonText = Remember
 notifyBarRememberButtonText = Remember
 notifyBarRememberButtonAccessKey =
 passwordChangeTitle = Confirm Password Change
 passwordChangeText = Would you like to change the stored password for %S?
 passwordChangeTextNoUser = Would you like to change the stored password for this login?
 notifyBarChangeButtonText = Change
 notifyBarChangeButtonAccessKey =
 notifyBarDontChangeButtonText = Don't Change