Bug 1890591 - Add some utilities to BackupResource for copying files and Sqlite databases. r=backup-reviewers,kpatenio
Differential Revision: https://phabricator.services.mozilla.com/D207155
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
* 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/. */
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
|
||||
});
|
||||
|
||||
// Convert from bytes to kilobytes (not kibibytes).
|
||||
export const BYTES_IN_KB = 1000;
|
||||
|
||||
@@ -129,6 +135,65 @@ export class BackupResource {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a set of SQLite databases safely from a source directory to a
|
||||
* destination directory. A new read-only connection is opened for each
|
||||
* database, and then a backup is created.
|
||||
*
|
||||
* @param {string} sourcePath
|
||||
* Path to the source directory of the SQLite databases.
|
||||
* @param {string} destPath
|
||||
* Path to the destination directory where the SQLite databases should be
|
||||
* copied to.
|
||||
* @param {Array<string>} sqliteDatabases
|
||||
* An array of filenames of the SQLite databases to copy.
|
||||
* @returns {Promise<undefined>}
|
||||
*/
|
||||
static async copySqliteDatabases(sourcePath, destPath, sqliteDatabases) {
|
||||
for (let fileName of sqliteDatabases) {
|
||||
let sourceFilePath = PathUtils.join(sourcePath, fileName);
|
||||
let destFilePath = PathUtils.join(destPath, fileName);
|
||||
let connection;
|
||||
|
||||
try {
|
||||
connection = await lazy.Sqlite.openConnection({
|
||||
path: sourceFilePath,
|
||||
readOnly: true,
|
||||
});
|
||||
|
||||
await connection.backup(destFilePath);
|
||||
} finally {
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to copy a set of files from a source directory to a
|
||||
* destination directory. Callers should ensure that the source files can be
|
||||
* copied safely before invoking this function. Files that do not exist will
|
||||
* be ignored. Callers that wish to copy SQLite databases should use
|
||||
* copySqliteDatabases() instead.
|
||||
*
|
||||
* @param {string} sourcePath
|
||||
* Path to the source directory of the files to be copied.
|
||||
* @param {string} destPath
|
||||
* Path to the destination directory where the files should be
|
||||
* copied to.
|
||||
* @param {string[]} fileNames
|
||||
* An array of filenames of the files to copy.
|
||||
* @returns {Promise<undefined>}
|
||||
*/
|
||||
static async copyFiles(sourcePath, destPath, fileNames) {
|
||||
for (let fileName of fileNames) {
|
||||
let sourceFilePath = PathUtils.join(sourcePath, fileName);
|
||||
let destFilePath = PathUtils.join(destPath, fileName);
|
||||
if (await IOUtils.exists(sourceFilePath)) {
|
||||
await IOUtils.copy(sourceFilePath, destFilePath, { recursive: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
|
||||
import { BackupResource } from "resource:///modules/backup/BackupResource.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
|
||||
});
|
||||
|
||||
/**
|
||||
* Class representing miscellaneous files for telemetry, site storage,
|
||||
* media device origin mapping, chrome privileged IndexedDB databases,
|
||||
@@ -30,33 +24,14 @@ export class MiscDataBackupResource extends BackupResource {
|
||||
"enumerate_devices.txt",
|
||||
"SiteSecurityServiceState.bin",
|
||||
];
|
||||
|
||||
for (let fileName of files) {
|
||||
let sourcePath = PathUtils.join(profilePath, fileName);
|
||||
let destPath = PathUtils.join(stagingPath, fileName);
|
||||
if (await IOUtils.exists(sourcePath)) {
|
||||
await IOUtils.copy(sourcePath, destPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
await BackupResource.copyFiles(profilePath, stagingPath, files);
|
||||
|
||||
const sqliteDatabases = ["protections.sqlite"];
|
||||
|
||||
for (let fileName of sqliteDatabases) {
|
||||
let sourcePath = PathUtils.join(profilePath, fileName);
|
||||
let destPath = PathUtils.join(stagingPath, fileName);
|
||||
let connection;
|
||||
|
||||
try {
|
||||
connection = await lazy.Sqlite.openConnection({
|
||||
path: sourcePath,
|
||||
readOnly: true,
|
||||
});
|
||||
|
||||
await connection.backup(destPath);
|
||||
} finally {
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
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, so
|
||||
|
||||
@@ -10,7 +10,6 @@ const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.sys.mjs",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
@@ -60,22 +59,12 @@ export class PlacesBackupResource extends BackupResource {
|
||||
return { bookmarksOnly: true };
|
||||
}
|
||||
|
||||
for (let fileName of sqliteDatabases) {
|
||||
let sourcePath = PathUtils.join(profilePath, fileName);
|
||||
let destPath = PathUtils.join(stagingPath, fileName);
|
||||
let connection;
|
||||
await BackupResource.copySqliteDatabases(
|
||||
profilePath,
|
||||
stagingPath,
|
||||
sqliteDatabases
|
||||
);
|
||||
|
||||
try {
|
||||
connection = await lazy.Sqlite.openConnection({
|
||||
path: sourcePath,
|
||||
readOnly: true,
|
||||
});
|
||||
|
||||
await connection.backup(destPath);
|
||||
} finally {
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { BackupResource } from "resource:///modules/backup/BackupResource.sys.mjs";
|
||||
import { Sqlite } from "resource://gre/modules/Sqlite.sys.mjs";
|
||||
|
||||
/**
|
||||
* Class representing files that modify preferences and permissions within a user profile.
|
||||
@@ -28,32 +27,14 @@ export class PreferencesBackupResource extends BackupResource {
|
||||
"user.js",
|
||||
"chrome",
|
||||
];
|
||||
|
||||
for (let fileName of simpleCopyFiles) {
|
||||
let sourcePath = PathUtils.join(profilePath, fileName);
|
||||
let destPath = PathUtils.join(stagingPath, fileName);
|
||||
if (await IOUtils.exists(sourcePath)) {
|
||||
await IOUtils.copy(sourcePath, destPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
await BackupResource.copyFiles(profilePath, stagingPath, simpleCopyFiles);
|
||||
|
||||
const sqliteDatabases = ["permissions.sqlite", "content-prefs.sqlite"];
|
||||
|
||||
for (let fileName of sqliteDatabases) {
|
||||
let sourcePath = PathUtils.join(profilePath, fileName);
|
||||
let destPath = PathUtils.join(stagingPath, fileName);
|
||||
let connection;
|
||||
|
||||
try {
|
||||
connection = await Sqlite.openConnection({
|
||||
path: sourcePath,
|
||||
});
|
||||
|
||||
await connection.backup(destPath);
|
||||
} finally {
|
||||
await connection.close();
|
||||
}
|
||||
}
|
||||
await BackupResource.copySqliteDatabases(
|
||||
profilePath,
|
||||
stagingPath,
|
||||
sqliteDatabases
|
||||
);
|
||||
|
||||
// prefs.js is a special case - we have a helper function to flush the
|
||||
// current prefs state to disk off of the main thread.
|
||||
|
||||
Reference in New Issue
Block a user