mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1063714 - migrate FHR related data to new profile on profile migration/reset. r=gps
This commit is contained in:
parent
788ae8894c
commit
551b3bc5c4
@ -20,8 +20,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
|
||||
"resource://gre/modules/PlacesBackups.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionMigration",
|
||||
"resource:///modules/sessionstore/SessionMigration.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
function FirefoxProfileMigrator() { }
|
||||
|
||||
function FirefoxProfileMigrator() {
|
||||
this.wrappedJSObject = this; // for testing...
|
||||
}
|
||||
|
||||
FirefoxProfileMigrator.prototype = Object.create(MigratorPrototype);
|
||||
|
||||
@ -58,6 +65,10 @@ FirefoxProfileMigrator.prototype.getResources = function() {
|
||||
if (sourceProfileDir.equals(currentProfileDir))
|
||||
return null;
|
||||
|
||||
return this._getResourcesInternal(sourceProfileDir, currentProfileDir);
|
||||
}
|
||||
|
||||
FirefoxProfileMigrator.prototype._getResourcesInternal = function(sourceProfileDir, currentProfileDir) {
|
||||
let getFileResource = function(aMigrationType, aFileNames) {
|
||||
let files = [];
|
||||
for (let fileName of aFileNames) {
|
||||
@ -120,8 +131,72 @@ FirefoxProfileMigrator.prototype.getResources = function() {
|
||||
}
|
||||
}
|
||||
|
||||
// FHR related migrations.
|
||||
let times = getFileResource(types.OTHERDATA, ["times.json"]);
|
||||
let healthReporter = {
|
||||
name: "healthreporter", // name is used only by tests...
|
||||
type: types.OTHERDATA,
|
||||
migrate: aCallback => {
|
||||
// the health-reporter can't have been initialized yet so it's safe to
|
||||
// copy the SQL file.
|
||||
|
||||
// We only support the default database name - copied from healthreporter.jsm
|
||||
const DEFAULT_DATABASE_NAME = "healthreport.sqlite";
|
||||
let path = OS.Path.join(sourceProfileDir.path, DEFAULT_DATABASE_NAME);
|
||||
let sqliteFile = FileUtils.File(path);
|
||||
if (sqliteFile.exists()) {
|
||||
sqliteFile.copyTo(currentProfileDir, "");
|
||||
}
|
||||
// In unusual cases there may be 2 additional files - a "write ahead log"
|
||||
// (-wal) file and a "shared memory file" (-shm). The wal file contains
|
||||
// data that will be replayed when the DB is next opened, while the shm
|
||||
// file is ignored in that case - the replay happens using only the wal.
|
||||
// So we *do* copy a wal if it exists, but not a shm.
|
||||
// See https://www.sqlite.org/tempfiles.html for more.
|
||||
// (Note also we attempt these copies even if we can't find the DB, and
|
||||
// rely on FHR itself to do the right thing if it can)
|
||||
path = OS.Path.join(sourceProfileDir.path, DEFAULT_DATABASE_NAME + "-wal");
|
||||
let sqliteWal = FileUtils.File(path);
|
||||
if (sqliteWal.exists()) {
|
||||
sqliteWal.copyTo(currentProfileDir, "");
|
||||
}
|
||||
|
||||
// If the 'healthreport' directory exists we copy everything from it.
|
||||
let subdir = this._getFileObject(sourceProfileDir, "healthreport");
|
||||
if (subdir && subdir.isDirectory()) {
|
||||
// Copy all regular files.
|
||||
let dest = currentProfileDir.clone();
|
||||
dest.append("healthreport");
|
||||
dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,
|
||||
FileUtils.PERMS_DIRECTORY);
|
||||
let enumerator = subdir.directoryEntries;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let file = enumerator.getNext().QueryInterface(Components.interfaces.nsIFile);
|
||||
if (file.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
file.copyTo(dest, "");
|
||||
}
|
||||
}
|
||||
// If the 'datareporting' directory exists we copy just state.json
|
||||
subdir = this._getFileObject(sourceProfileDir, "datareporting");
|
||||
if (subdir && subdir.isDirectory()) {
|
||||
let stateFile = this._getFileObject(subdir, "state.json");
|
||||
if (stateFile) {
|
||||
let dest = currentProfileDir.clone();
|
||||
dest.append("datareporting");
|
||||
dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,
|
||||
FileUtils.PERMS_DIRECTORY);
|
||||
stateFile.copyTo(dest, "");
|
||||
}
|
||||
}
|
||||
aCallback(true);
|
||||
}
|
||||
}
|
||||
|
||||
return [r for each (r in [places, cookies, passwords, formData,
|
||||
dictionary, bookmarksBackups, session]) if (r)];
|
||||
dictionary, bookmarksBackups, session,
|
||||
times, healthReporter]) if (r)];
|
||||
}
|
||||
|
||||
Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", {
|
||||
|
228
browser/components/migration/tests/unit/test_fx_fhr.js
Normal file
228
browser/components/migration/tests/unit/test_fx_fhr.js
Normal file
@ -0,0 +1,228 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function checkDirectoryContains(dir, files) {
|
||||
print("checking " + dir.path + " - should contain " + Object.keys(files));
|
||||
let seen = new Set();
|
||||
let enumerator = dir.directoryEntries;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
|
||||
print("found file: " + file.path);
|
||||
Assert.ok(file.leafName in files, file.leafName + " exists, but shouldn't");
|
||||
|
||||
let expectedContents = files[file.leafName];
|
||||
if (typeof expectedContents != "string") {
|
||||
// it's a subdir - recurse!
|
||||
Assert.ok(file.isDirectory(), "should be a subdir");
|
||||
let newDir = dir.clone();
|
||||
newDir.append(file.leafName);
|
||||
checkDirectoryContains(newDir, expectedContents);
|
||||
} else {
|
||||
Assert.ok(!file.isDirectory(), "should be a regular file");
|
||||
let stream = Cc['@mozilla.org/network/file-input-stream;1']
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
stream.init(file, -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||
|
||||
let sis = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
sis.init(stream);
|
||||
let contents = sis.read(file.fileSize);
|
||||
sis.close();
|
||||
|
||||
Assert.equal(contents, expectedContents);
|
||||
}
|
||||
seen.add(file.leafName);
|
||||
}
|
||||
let missing = [x for (x in files) if (!seen.has(x))];
|
||||
Assert.deepEqual(missing, [], "no missing files in " + dir.path);
|
||||
}
|
||||
|
||||
function getTestDirs() {
|
||||
// we make a directory structure in a temp dir which mirrors what we are
|
||||
// testing.
|
||||
let tempDir = do_get_tempdir();
|
||||
let srcDir = tempDir.clone();
|
||||
srcDir.append("test_source_dir");
|
||||
srcDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
let targetDir = tempDir.clone();
|
||||
targetDir.append("test_target_dir");
|
||||
targetDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
// no need to cleanup these dirs - the xpcshell harness will do it for us.
|
||||
return [srcDir, targetDir];
|
||||
}
|
||||
|
||||
function writeToFile(dir, leafName, contents) {
|
||||
let file = dir.clone();
|
||||
file.append(leafName);
|
||||
|
||||
let outputStream = FileUtils.openFileOutputStream(file);
|
||||
outputStream.write(contents, contents.length);
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
function promiseFHRMigrator(srcDir, targetDir) {
|
||||
let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=firefox"]
|
||||
.createInstance(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
let migrators = migrator._getResourcesInternal(srcDir, targetDir);
|
||||
for (let m of migrators) {
|
||||
if (m.name == "healthreporter") {
|
||||
return new Promise((resolve, reject) => {
|
||||
m.migrate(resolve);
|
||||
});
|
||||
}
|
||||
}
|
||||
throw new Error("failed to find the fhr migrator");
|
||||
}
|
||||
|
||||
add_task(function* test_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with empty directories");
|
||||
// check both are empty
|
||||
checkDirectoryContains(srcDir, {});
|
||||
checkDirectoryContains(targetDir, {});
|
||||
});
|
||||
|
||||
add_task(function* test_just_sqlite() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with sqlite file copied");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_extras() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents_sqlite = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents_sqlite);
|
||||
|
||||
let contents_wal = "this is the wal\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite-wal", contents_wal);
|
||||
|
||||
// and the -shm - this should *not* be copied.
|
||||
writeToFile(srcDir, "healthreport.sqlite-shm", "whatever");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with sqlite file copied");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents_sqlite,
|
||||
"healthreport.sqlite-wal": contents_wal,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_not_dir() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
writeToFile(srcDir, "healthreport", "I'm a file but should be a directory");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true even though the directory was a file");
|
||||
// We should have only the sqlite file
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
// create an empty 'healthreport' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("healthreport");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with the .sqlite file and an empty subdir in the target.
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
"healthreport": {},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_contents() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
// create an empty 'healthreport' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("healthreport");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
writeToFile(subDir, "file1", "this is file 1");
|
||||
writeToFile(subDir, "file2", "this is file 2");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with the .sqlite file and an empty subdir in the target.
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
"healthreport": {
|
||||
"file1": "this is file 1",
|
||||
"file2": "this is file 2",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_datareporting_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// create an empty 'datareporting' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("datareporting");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with nothing at all in the destination - state.json was
|
||||
// missing so we didn't even create the target dir.
|
||||
checkDirectoryContains(targetDir, {});
|
||||
});
|
||||
|
||||
add_task(function* test_datareporting_many() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// create an empty 'datareporting' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("datareporting");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
writeToFile(subDir, "state.json", "should be copied");
|
||||
writeToFile(subDir, "something.else", "should not");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"datareporting" : {
|
||||
"state.json": "should be copied",
|
||||
}
|
||||
});
|
||||
});
|
@ -6,3 +6,5 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
|
||||
[test_IE_bookmarks.js]
|
||||
skip-if = os != "win"
|
||||
|
||||
[test_fx_fhr.js]
|
||||
|
Loading…
Reference in New Issue
Block a user