Backed out changeset 5e494cb0aff6 (bug 1901534)
Backed out changeset e8773eda97c1 (bug 1891854)
Backed out changeset 4b079909d830 (bug 1901520)
Backed out changeset 5509d1905d2c (bug 1901520)
Backed out changeset 6d98566735ad (bug 1901520)
155 lines
5.1 KiB
JavaScript
155 lines
5.1 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 https://mozilla.org/MPL/2.0/. */
|
|
|
|
import { BackupResource } from "resource:///modules/backup/BackupResource.sys.mjs";
|
|
|
|
const lazy = {};
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
ActivityStreamStorage:
|
|
"resource://activity-stream/lib/ActivityStreamStorage.sys.mjs",
|
|
ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
|
|
});
|
|
|
|
const SNIPPETS_TABLE_NAME = "snippets";
|
|
const FILES_FOR_BACKUP = [
|
|
"enumerate_devices.txt",
|
|
"protections.sqlite",
|
|
"SiteSecurityServiceState.bin",
|
|
];
|
|
|
|
/**
|
|
* Class representing miscellaneous files for telemetry, site storage,
|
|
* media device origin mapping, chrome privileged IndexedDB databases,
|
|
* and Mozilla Accounts within a user profile.
|
|
*/
|
|
export class MiscDataBackupResource extends BackupResource {
|
|
static get key() {
|
|
return "miscellaneous";
|
|
}
|
|
|
|
static get requiresEncryption() {
|
|
return false;
|
|
}
|
|
|
|
async backup(stagingPath, profilePath = PathUtils.profileDir) {
|
|
const files = ["enumerate_devices.txt", "SiteSecurityServiceState.bin"];
|
|
await BackupResource.copyFiles(profilePath, stagingPath, files);
|
|
|
|
const sqliteDatabases = ["protections.sqlite"];
|
|
await BackupResource.copySqliteDatabases(
|
|
profilePath,
|
|
stagingPath,
|
|
sqliteDatabases
|
|
);
|
|
|
|
// Bug 1890585 - we don't currently have the ability to copy the
|
|
// chrome-privileged IndexedDB databases under storage/permanent/chrome.
|
|
// Instead, we'll manually export any IndexedDB data we need to backup
|
|
// to a separate JSON file.
|
|
|
|
// The first IndexedDB database we want to back up is the ActivityStream
|
|
// one - specifically, the "snippets" table, as this contains information
|
|
// on ASRouter impressions, blocked messages, message group impressions,
|
|
// etc.
|
|
let storage = new lazy.ActivityStreamStorage({
|
|
storeNames: [SNIPPETS_TABLE_NAME],
|
|
});
|
|
let snippetsTable = await storage.getDbTable(SNIPPETS_TABLE_NAME);
|
|
let snippetsObj = {};
|
|
for (let key of await snippetsTable.getAllKeys()) {
|
|
snippetsObj[key] = await snippetsTable.get(key);
|
|
}
|
|
let snippetsBackupFile = PathUtils.join(
|
|
stagingPath,
|
|
"activity-stream-snippets.json"
|
|
);
|
|
await IOUtils.writeJSON(snippetsBackupFile, snippetsObj);
|
|
|
|
return null;
|
|
}
|
|
|
|
async recover(_manifestEntry, recoveryPath, destProfilePath) {
|
|
await BackupResource.copyFiles(
|
|
recoveryPath,
|
|
destProfilePath,
|
|
FILES_FOR_BACKUP
|
|
);
|
|
|
|
// The times.json file, the one that powers ProfileAge, works hand in hand
|
|
// with the Telemetry client ID. We don't want to accidentally _overwrite_
|
|
// a pre-existing times.json with data from a different profile, because
|
|
// then the client ID wouldn't match the times.json data anymore.
|
|
//
|
|
// The rule that we're following for backups and recoveries is that the
|
|
// recovered profile always inherits the client ID (and therefore the
|
|
// times.json) from the profile that _initiated recovery_.
|
|
//
|
|
// This means we want to copy the times.json file from the profile that's
|
|
// currently in use to the destProfilePath.
|
|
await BackupResource.copyFiles(PathUtils.profileDir, destProfilePath, [
|
|
"times.json",
|
|
]);
|
|
|
|
// We also want to write the recoveredFromBackup timestamp now.
|
|
let profileAge = await lazy.ProfileAge(destProfilePath);
|
|
await profileAge.recordRecoveredFromBackup();
|
|
|
|
// The activity-stream-snippets data will need to be written during the
|
|
// postRecovery phase, so we'll stash the path to the JSON file in the
|
|
// post recovery entry.
|
|
let snippetsBackupFile = PathUtils.join(
|
|
recoveryPath,
|
|
"activity-stream-snippets.json"
|
|
);
|
|
return { snippetsBackupFile };
|
|
}
|
|
|
|
async postRecovery(postRecoveryEntry) {
|
|
let { snippetsBackupFile } = postRecoveryEntry;
|
|
|
|
// If for some reason, the activity-stream-snippets data file has been
|
|
// removed already, there's nothing to do.
|
|
if (!IOUtils.exists(snippetsBackupFile)) {
|
|
return;
|
|
}
|
|
|
|
let snippetsData = await IOUtils.readJSON(snippetsBackupFile);
|
|
let storage = new lazy.ActivityStreamStorage({
|
|
storeNames: [SNIPPETS_TABLE_NAME],
|
|
});
|
|
let snippetsTable = await storage.getDbTable(SNIPPETS_TABLE_NAME);
|
|
for (let key in snippetsData) {
|
|
let value = snippetsData[key];
|
|
await snippetsTable.set(key, value);
|
|
}
|
|
}
|
|
|
|
async measure(profilePath = PathUtils.profileDir) {
|
|
let fullSize = 0;
|
|
|
|
for (let filePath of FILES_FOR_BACKUP) {
|
|
let resourcePath = PathUtils.join(profilePath, filePath);
|
|
let resourceSize = await BackupResource.getFileSize(resourcePath);
|
|
if (Number.isInteger(resourceSize)) {
|
|
fullSize += resourceSize;
|
|
}
|
|
}
|
|
|
|
let chromeIndexedDBDirPath = PathUtils.join(
|
|
profilePath,
|
|
"storage",
|
|
"permanent",
|
|
"chrome"
|
|
);
|
|
let chromeIndexedDBDirSize = await BackupResource.getDirectorySize(
|
|
chromeIndexedDBDirPath
|
|
);
|
|
if (Number.isInteger(chromeIndexedDBDirSize)) {
|
|
fullSize += chromeIndexedDBDirSize;
|
|
}
|
|
|
|
Glean.browserBackup.miscDataSize.set(fullSize);
|
|
}
|
|
}
|