diff options
Diffstat (limited to 'toolkit/components/passwordmgr/LoginStore.jsm')
-rw-r--r-- | toolkit/components/passwordmgr/LoginStore.jsm | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/LoginStore.jsm b/toolkit/components/passwordmgr/LoginStore.jsm new file mode 100644 index 000000000..9fa6e7dff --- /dev/null +++ b/toolkit/components/passwordmgr/LoginStore.jsm @@ -0,0 +1,136 @@ +/* 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/. */ + +/** + * Handles serialization of the data and persistence into a file. + * + * The file is stored in JSON format, without indentation, using UTF-8 encoding. + * With indentation applied, the file would look like this: + * + * { + * "logins": [ + * { + * "id": 2, + * "hostname": "http://www.example.com", + * "httpRealm": null, + * "formSubmitURL": "http://www.example.com/submit-url", + * "usernameField": "username_field", + * "passwordField": "password_field", + * "encryptedUsername": "...", + * "encryptedPassword": "...", + * "guid": "...", + * "encType": 1, + * "timeCreated": 1262304000000, + * "timeLastUsed": 1262304000000, + * "timePasswordChanged": 1262476800000, + * "timesUsed": 1 + * }, + * { + * "id": 4, + * (...) + * } + * ], + * "disabledHosts": [ + * "http://www.example.org", + * "http://www.example.net" + * ], + * "nextId": 10, + * "version": 1 + * } + */ + +"use strict"; + +this.EXPORTED_SYMBOLS = [ + "LoginStore", +]; + +// Globals + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "JSONFile", + "resource://gre/modules/JSONFile.jsm"); + +/** + * Current data version assigned by the code that last touched the data. + * + * This number should be updated only when it is important to understand whether + * an old version of the code has touched the data, for example to execute an + * update logic. In most cases, this number should not be changed, in + * particular when no special one-time update logic is needed. + * + * For example, this number should NOT be changed when a new optional field is + * added to a login entry. + */ +const kDataVersion = 2; + +// The permission type we store in the permission manager. +const PERMISSION_SAVE_LOGINS = "login-saving"; + +// LoginStore + +/** + * Inherits from JSONFile and handles serialization of login-related data and + * persistence into a file. + * + * @param aPath + * String containing the file path where data should be saved. + */ +function LoginStore(aPath) { + JSONFile.call(this, { + path: aPath, + dataPostProcessor: this._dataPostProcessor.bind(this) + }); +} + +LoginStore.prototype = Object.create(JSONFile.prototype); +LoginStore.prototype.constructor = LoginStore; + +/** + * Synchronously work on the data just loaded into memory. + */ +LoginStore.prototype._dataPostProcessor = function(data) { + if (data.nextId === undefined) { + data.nextId = 1; + } + + // Create any arrays that are not present in the saved file. + if (!data.logins) { + data.logins = []; + } + + // Stub needed for login imports before data has been migrated. + if (!data.disabledHosts) { + data.disabledHosts = []; + } + + if (data.version === 1) { + this._migrateDisabledHosts(data); + } + + // Indicate that the current version of the code has touched the file. + data.version = kDataVersion; + + return data; +}; + +/** + * Migrates disabled hosts to the permission manager. + */ +LoginStore.prototype._migrateDisabledHosts = function (data) { + for (let host of data.disabledHosts) { + try { + let uri = Services.io.newURI(host, null, null); + Services.perms.add(uri, PERMISSION_SAVE_LOGINS, Services.perms.DENY_ACTION); + } catch (e) { + Cu.reportError(e); + } + } + + delete data.disabledHosts; +}; |