mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1271799 - implement undo functionality in automigration code, r=mak
MozReview-Commit-ID: 28yvZyVimOx --HG-- extra : rebase_source : 216da87f46d1bb7cde17507431b04b8bbc3367c3
This commit is contained in:
parent
5da90b343c
commit
a580940405
@ -8,13 +8,19 @@ this.EXPORTED_SYMBOLS = ["AutoMigrate"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
|
||||
const kAutoMigrateStartedPref = "browser.migrate.automigrate-started";
|
||||
const kAutoMigrateFinishedPref = "browser.migrate.automigrate-finished";
|
||||
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const AutoMigrate = {
|
||||
get resourceTypesToUse() {
|
||||
let {BOOKMARKS, HISTORY, FORMDATA, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
|
||||
return BOOKMARKS | HISTORY | FORMDATA | PASSWORDS;
|
||||
let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
|
||||
return BOOKMARKS | HISTORY | PASSWORDS;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -47,11 +53,13 @@ const AutoMigrate = {
|
||||
histogram.add(sawErrors ? "finished-with-errors" : "finished");
|
||||
Services.obs.removeObserver(migrationObserver, "Migration:Ended");
|
||||
Services.obs.removeObserver(migrationObserver, "Migration:ItemError");
|
||||
Services.prefs.setCharPref(kAutoMigrateFinishedPref, Date.now().toString());
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(migrationObserver, "Migration:Ended", false);
|
||||
Services.obs.addObserver(migrationObserver, "Migration:ItemError", false);
|
||||
Services.prefs.setCharPref(kAutoMigrateStartedPref, Date.now().toString());
|
||||
migrator.migrate(this.resourceTypesToUse, profileStartup, profileToMigrate);
|
||||
histogram.add("migrate-called-without-exceptions");
|
||||
},
|
||||
@ -109,5 +117,59 @@ const AutoMigrate = {
|
||||
}
|
||||
return profiles ? profiles[0].id : null;
|
||||
},
|
||||
|
||||
getUndoRange() {
|
||||
let start, finish;
|
||||
try {
|
||||
start = parseInt(Services.prefs.getCharPref(kAutoMigrateStartedPref), 10);
|
||||
finish = parseInt(Services.prefs.getCharPref(kAutoMigrateFinishedPref), 10);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
if (!finish || !start) {
|
||||
return null;
|
||||
}
|
||||
return [new Date(start), new Date(finish)];
|
||||
},
|
||||
|
||||
canUndo() {
|
||||
if (!this.getUndoRange()) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
// Return a promise resolving to false if we're signed into sync, resolve
|
||||
// to true otherwise.
|
||||
let {fxAccounts} = Cu.import("resource://gre/modules/FxAccounts.jsm", {});
|
||||
return fxAccounts.getSignedInUser().then(user => !user, () => Promise.resolve(true));
|
||||
},
|
||||
|
||||
undo: Task.async(function* () {
|
||||
if (!(yield this.canUndo())) {
|
||||
throw new Error("Can't undo!");
|
||||
}
|
||||
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// NB: we drop the start time of the migration for now. This is because
|
||||
// imported history will always end up being 'backdated' to the actual
|
||||
// visit time recorded by the browser from which we imported. As a result,
|
||||
// a lower bound on this item doesn't really make sense.
|
||||
// Note that for form data this could be different, but we currently don't
|
||||
// support form data import from any non-Firefox browser, so it isn't
|
||||
// imported from other browsers by the automigration code, nor do we
|
||||
// remove it here.
|
||||
let range = this.getUndoRange();
|
||||
yield PlacesUtils.history.removeVisitsByFilter({
|
||||
beginDate: new Date(0),
|
||||
endDate: range[1]
|
||||
});
|
||||
|
||||
try {
|
||||
Services.logins.removeAllLogins();
|
||||
} catch (ex) {
|
||||
// ignore failure.
|
||||
}
|
||||
Services.prefs.clearUserPref("browser.migrate.automigrate-started");
|
||||
Services.prefs.clearUserPref("browser.migrate.automigrate-finished");
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://testing-common/TestUtils.jsm");
|
||||
Cu.import("resource://testing-common/PlacesTestUtils.jsm");
|
||||
let AutoMigrateBackstage = Cu.import("resource:///modules/AutoMigrate.jsm");
|
||||
|
||||
let gShimmedMigratorKeyPicker = null;
|
||||
let gShimmedMigrator = null;
|
||||
|
||||
const kUsecPerMin = 60 * 1000000;
|
||||
|
||||
// This is really a proxy on MigrationUtils, but if we specify that directly,
|
||||
// we get in trouble because the object itself is frozen, and Proxies can't
|
||||
// return a different value to an object when directly proxying a frozen
|
||||
@ -112,8 +117,133 @@ add_task(function* checkIntegration() {
|
||||
Assert.strictEqual(gShimmedMigrator._getMigrateDataArgs, null,
|
||||
"getMigrateData called with 'null' as a profile");
|
||||
|
||||
let {BOOKMARKS, HISTORY, FORMDATA, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
|
||||
let expectedTypes = BOOKMARKS | HISTORY | FORMDATA | PASSWORDS;
|
||||
let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
|
||||
let expectedTypes = BOOKMARKS | HISTORY | PASSWORDS;
|
||||
Assert.deepEqual(gShimmedMigrator._migrateArgs, [expectedTypes, "startup", null],
|
||||
"getMigrateData called with 'null' as a profile");
|
||||
"migrate called with 'null' as a profile");
|
||||
});
|
||||
|
||||
/**
|
||||
* Test the undo preconditions and a no-op undo in the automigrator.
|
||||
*/
|
||||
add_task(function* checkUndoPreconditions() {
|
||||
gShimmedMigrator = {
|
||||
get sourceProfiles() {
|
||||
do_print("Read sourceProfiles");
|
||||
return null;
|
||||
},
|
||||
getMigrateData(profileToMigrate) {
|
||||
this._getMigrateDataArgs = profileToMigrate;
|
||||
return Ci.nsIBrowserProfileMigrator.BOOKMARKS;
|
||||
},
|
||||
migrate(types, startup, profileToMigrate) {
|
||||
this._migrateArgs = [types, startup, profileToMigrate];
|
||||
TestUtils.executeSoon(function() {
|
||||
Services.obs.notifyObservers(null, "Migration:Ended", undefined);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
gShimmedMigratorKeyPicker = function() {
|
||||
return "gobbledygook";
|
||||
};
|
||||
AutoMigrate.migrate("startup");
|
||||
let migrationFinishedPromise = TestUtils.topicObserved("Migration:Ended");
|
||||
Assert.strictEqual(gShimmedMigrator._getMigrateDataArgs, null,
|
||||
"getMigrateData called with 'null' as a profile");
|
||||
|
||||
let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
|
||||
let expectedTypes = BOOKMARKS | HISTORY | PASSWORDS;
|
||||
Assert.deepEqual(gShimmedMigrator._migrateArgs, [expectedTypes, "startup", null],
|
||||
"migrate called with 'null' as a profile");
|
||||
|
||||
yield migrationFinishedPromise;
|
||||
Assert.ok(Services.prefs.getPrefType("browser.migrate.automigrate-started"),
|
||||
"Should have set start time pref");
|
||||
Assert.ok(Services.prefs.getPrefType("browser.migrate.automigrate-finished"),
|
||||
"Should have set finish time pref");
|
||||
Assert.ok((yield AutoMigrate.canUndo()), "Should be able to undo migration");
|
||||
|
||||
let [beginRange, endRange] = AutoMigrate.getUndoRange();
|
||||
let stringRange = `beginRange: ${beginRange}; endRange: ${endRange}`;
|
||||
Assert.ok(beginRange <= endRange,
|
||||
"Migration should have started before or when it ended " + stringRange);
|
||||
|
||||
yield AutoMigrate.undo();
|
||||
Assert.ok(true, "Should be able to finish an undo cycle.");
|
||||
});
|
||||
|
||||
/**
|
||||
* Fake a migration and then try to undo it to verify all data gets removed.
|
||||
*/
|
||||
add_task(function* checkUndoRemoval() {
|
||||
let startTime = "" + Date.now();
|
||||
Services.prefs.setCharPref("browser.migrate.automigrate-started", startTime);
|
||||
|
||||
// Insert a login and check that that worked.
|
||||
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
login.init("www.mozilla.org", "http://www.mozilla.org", null, "user", "pass", "userEl", "passEl");
|
||||
Services.logins.addLogin(login);
|
||||
let storedLogins = Services.logins.findLogins({}, "www.mozilla.org",
|
||||
"http://www.mozilla.org", null);
|
||||
Assert.equal(storedLogins.length, 1, "Should have 1 login");
|
||||
|
||||
// Insert a bookmark and check that we have exactly 1 bookmark for that URI.
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
url: "http://www.example.org/",
|
||||
title: "Some example bookmark",
|
||||
});
|
||||
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch({url: "http://www.example.org/"});
|
||||
Assert.ok(bookmark, "Should have a bookmark before undo");
|
||||
Assert.equal(bookmark.title, "Some example bookmark", "Should have correct bookmark before undo.");
|
||||
|
||||
// Insert 2 history visits - one in the current migration time, one from before.
|
||||
let now_uSec = Date.now() * 1000;
|
||||
let visitedURI = Services.io.newURI("http://www.example.com/", null, null);
|
||||
yield PlacesTestUtils.addVisits([
|
||||
{uri: visitedURI, visitDate: now_uSec},
|
||||
{uri: visitedURI, visitDate: now_uSec - 100 * kUsecPerMin},
|
||||
]);
|
||||
|
||||
// Verify that both visits get reported.
|
||||
let opts = PlacesUtils.history.getNewQueryOptions();
|
||||
opts.resultType = opts.RESULTS_AS_VISIT;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.uri = visitedURI;
|
||||
let visits = PlacesUtils.history.executeQuery(query, opts);
|
||||
visits.root.containerOpen = true;
|
||||
Assert.equal(visits.root.childCount, 2, "Should have 2 visits");
|
||||
// Clean up:
|
||||
visits.root.containerOpen = false;
|
||||
|
||||
// Now set finished pref:
|
||||
let endTime = "" + Date.now();
|
||||
Services.prefs.setCharPref("browser.migrate.automigrate-finished", endTime);
|
||||
|
||||
// Verify that we can undo, then undo:
|
||||
Assert.ok(yield AutoMigrate.canUndo(), "Should be possible to undo migration");
|
||||
yield AutoMigrate.undo();
|
||||
|
||||
// Check that the undo removed the history visits:
|
||||
visits = PlacesUtils.history.executeQuery(query, opts);
|
||||
visits.root.containerOpen = true;
|
||||
Assert.equal(visits.root.childCount, 0, "Should have no more visits");
|
||||
visits.root.containerOpen = false;
|
||||
|
||||
// Check that the undo removed the bookmarks:
|
||||
bookmark = yield PlacesUtils.bookmarks.fetch({url: "http://www.example.org/"});
|
||||
Assert.ok(!bookmark, "Should have no bookmarks after undo");
|
||||
|
||||
// Check that the undo removed the passwords:
|
||||
storedLogins = Services.logins.findLogins({}, "www.mozilla.org",
|
||||
"http://www.mozilla.org", null);
|
||||
Assert.equal(storedLogins.length, 0, "Should have no logins");
|
||||
|
||||
// Finally check prefs got cleared:
|
||||
Assert.ok(!Services.prefs.getPrefType("browser.migrate.automigrate-started"),
|
||||
"Should no longer have pref for migration start time.");
|
||||
Assert.ok(!Services.prefs.getPrefType("browser.migrate.automigrate-finished"),
|
||||
"Should no longer have pref for migration finish time.");
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user