diff --git a/toolkit/components/passwordmgr/LoginManager.sys.mjs b/toolkit/components/passwordmgr/LoginManager.sys.mjs --- a/toolkit/components/passwordmgr/LoginManager.sys.mjs +++ b/toolkit/components/passwordmgr/LoginManager.sys.mjs @@ -301,10 +301,11 @@ */ initializationPromise: null, /** * Add a new login to login storage. + * @deprecated: use `addLoginAsync` instead. */ addLogin(login) { this._checkLogin(login); // Look for an existing entry. @@ -316,12 +317,44 @@ let matchingLogin = logins.find(l => login.matches(l, true)); if (matchingLogin) { throw lazy.LoginHelper.createLoginAlreadyExistsError(matchingLogin.guid); } + lazy.log.debug("addLogin is DEPRECATED, please use addLoginAsync instead."); + return this._storage.addLogin(login); + }, + + /** + * Add a new login to login storage. + */ + async addLoginAsync(login) { + this._checkLogin(login); + + const { origin, formActionOrigin, httpRealm } = login; + const existingLogins = this.findLogins(origin, formActionOrigin, httpRealm); + const matchingLogin = existingLogins.find(l => login.matches(l, true)); + if (matchingLogin) { + throw lazy.LoginHelper.createLoginAlreadyExistsError(matchingLogin.guid); + } + + const crypto = Cc["@mozilla.org/login-manager/crypto/SDR;1"].getService( + Ci.nsILoginManagerCrypto + ); + const plaintexts = [login.username, login.password]; + const [username, password] = await crypto.encryptMany(plaintexts); + + const { username: plaintextUsername, password: plaintextPassword } = login; + login.username = username; + login.password = password; + lazy.log.debug("Adding login"); - return this._storage.addLogin(login); + return this._storage.addLogin( + login, + true, + plaintextUsername, + plaintextPassword + ); }, async addLogins(logins) { if (logins.length === 0) { return logins; diff --git a/toolkit/components/passwordmgr/nsILoginManager.idl b/toolkit/components/passwordmgr/nsILoginManager.idl --- a/toolkit/components/passwordmgr/nsILoginManager.idl +++ b/toolkit/components/passwordmgr/nsILoginManager.idl @@ -43,10 +43,23 @@ * be used instead. */ nsILoginInfo addLogin(in nsILoginInfo aLogin); /** + * Like addLogin, but asynchronous. + * + * @param aLogin + * The login to be added. + * @return A promise which resolves with a cloned login with the guid set. + * + * Default values for each login's nsILoginMetaInfo properties will be + * created. However, if the caller specifies non-default values, they will + * be used instead. + */ + Promise addLoginAsync(in nsILoginInfo aLogin); + + /** * Like addLogin, but asynchronous and for many logins. * * @param aLogins * A JS Array of nsILoginInfos to add. * @return A promise which resolves with a JS Array of cloned logins with