logins.length > 1) { return; } // If one login is stored and it's a fxa sync key, we update the backup to store the // key only. if ( logins.length && logins[0].hostname == lazy.FXA_PWDMGR_HOST && logins[0].httpRealm == lazy.FXA_PWDMGR_REALM ) { try { await IOUtils.copy(this.path, this._options.backupTo); // This notification is specifically sent out for a test. Services.obs.notifyObservers(null, "logins-backup-updated"); } catch (ex) { console.error(ex); } } else if (!logins.length) { // If no logins are stored anymore, delete backup. await IOUtils.remove(this._options.backupTo, { ignoreAbsent: true, }); } }; /** * 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 = []; } if (!data.potentiallyVulnerablePasswords) { data.potentiallyVulnerablePasswords = []; } if (!data.dismissedBreachAlertsByLoginGUID) { data.dismissedBreachAlertsByLoginGUID = {}; } // sanitize dates in logins if (!("version" in data) || data.version < 3) { let dateProperties = ["timeCreated", "timeLastUsed", "timePasswordChanged"]; let now = Date.now(); function getEarliestDate(login, defaultDate) { let earliestDate = dateProperties.reduce((earliest, pname) => { let ts = login[pname]; return !ts ? earliest : Math.min(ts, earliest); }, defaultDate); return earliestDate; } for (let login of data.logins) { for (let pname of dateProperties) { let earliestDate; if (!login[pname] || login[pname] > MAX_DATE_MS) { login[pname] = earliestDate || (earliestDate = getEarliestDate(login, now)); } } } } // Indicate that the current version of the code has touched the file. data.version = kDataVersion; return data; }; PK