Mypal/toolkit/components/passwordmgr/LoginStore.jsm

137 lines
3.6 KiB
JavaScript

/* 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;
};