mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 1221050 - part 1: set up migration infrastructure, r=ttaubert
--HG-- extra : commitid : 8nKMm2oklw9 extra : rebase_source : 6957bbc0b47accf8161476d97b1c20e775e814fb
This commit is contained in:
parent
845fd1cf6f
commit
218769e24f
@ -93,6 +93,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
"resource:///modules/RecentWindow.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TabGroupsMigrator",
|
||||
"resource:///modules/TabGroupsMigrator.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
@ -1390,6 +1393,14 @@ BrowserGlue.prototype = {
|
||||
},
|
||||
#endif
|
||||
|
||||
_maybeMigrateTabGroups() {
|
||||
let migrationObserver = (stateAsSupportsString, topic) => {
|
||||
Services.obs.removeObserver(migrationObserver, "sessionstore-state-read");
|
||||
TabGroupsMigrator.migrate(stateAsSupportsString);
|
||||
};
|
||||
Services.obs.addObserver(migrationObserver, "sessionstore-state-read", false);
|
||||
},
|
||||
|
||||
_onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
|
||||
// If user has already dismissed quit request, then do nothing
|
||||
if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
|
||||
@ -1897,7 +1908,7 @@ BrowserGlue.prototype = {
|
||||
},
|
||||
|
||||
_migrateUI: function BG__migrateUI() {
|
||||
const UI_VERSION = 34;
|
||||
const UI_VERSION = 35;
|
||||
const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
|
||||
let currentUIVersion = 0;
|
||||
try {
|
||||
@ -2242,6 +2253,9 @@ BrowserGlue.prototype = {
|
||||
this._notifyNotificationsUpgrade().catch(Cu.reportError);
|
||||
}
|
||||
|
||||
if (currentUIVersion < 35) {
|
||||
this._maybeMigrateTabGroups();
|
||||
}
|
||||
|
||||
// Update the migration version.
|
||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||
|
@ -803,3 +803,8 @@ weakCryptoOverriding.message = %S recommends that you don't enter your password,
|
||||
revokeOverride.label = Don't Trust This Website
|
||||
revokeOverride.accesskey = D
|
||||
|
||||
# LOCALIZATION NOTE (tabgroups.migration.anonGroup):
|
||||
# %S is the group number/ID
|
||||
tabgroups.migration.anonGroup = Group %S
|
||||
tabgroups.migration.tabGroupBookmarkFolderName = Bookmarked Tab Groups
|
||||
|
||||
|
144
browser/modules/TabGroupsMigrator.jsm
Normal file
144
browser/modules/TabGroupsMigrator.jsm
Normal file
@ -0,0 +1,144 @@
|
||||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TabGroupsMigrator"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown", "resource://gre/modules/AsyncShutdown.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
|
||||
return Services.strings.createBundle('chrome://browser/locale/browser.properties');
|
||||
});
|
||||
|
||||
|
||||
this.TabGroupsMigrator = {
|
||||
/**
|
||||
* If this state contains tab groups, migrate the user's data. This means:
|
||||
* - make a backup of the user's data.
|
||||
* - create bookmarks of all the user's tab groups in a single folder
|
||||
* - append a tab to the active window that lets the user restore background
|
||||
* groups.
|
||||
* - remove all the tabs hidden through tab groups from the state data.
|
||||
*/
|
||||
migrate(stateAsSupportsString) {
|
||||
stateAsSupportsString.QueryInterface(Ci.nsISupportsString);
|
||||
let stateStr = stateAsSupportsString.data;
|
||||
let state;
|
||||
try {
|
||||
state = JSON.parse(stateStr);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Failed to parse sessionstore state JSON to migrate tab groups: " + ex);
|
||||
return; // can't recover from invalid JSON
|
||||
}
|
||||
|
||||
let groupData = this._gatherGroupData(state);
|
||||
|
||||
// This strips out the hidden tab groups and puts them in a different object.
|
||||
// It also removes all tabview metadata.
|
||||
// We always do this, and always reassign the new state back into the
|
||||
// nsISupportsString for use by sessionstore, in order to tidy up the state
|
||||
// object.
|
||||
let hiddenTabState = this._removeHiddenTabGroupsFromState(state, groupData);
|
||||
|
||||
// However, we will only create a backup file, bookmarks and a new tab to
|
||||
// restore hidden tabs if tabs were actually removed from |state| by
|
||||
// _removeHiddenTabGroupsFromState.
|
||||
if (hiddenTabState.windows.length) {
|
||||
// We create the backup with the original string, from before all our
|
||||
// changes:
|
||||
this._createBackup(stateStr);
|
||||
|
||||
this._createBackgroundTabGroupRestorationPage(state, hiddenTabState);
|
||||
|
||||
// Bookmark creation is async. We need to return synchronously,
|
||||
// so we purposefully don't wait for this to be finished here. We do
|
||||
// store the promise it creates and use that in the session restore page
|
||||
// to be able to link to the bookmarks folder...
|
||||
let bookmarksFinishedPromise = this._bookmarkAllGroupsFromState(groupData);
|
||||
// ... and we make sure we finish before shutting down:
|
||||
AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
"Tab groups migration bookmarks",
|
||||
bookmarksFinishedPromise
|
||||
);
|
||||
}
|
||||
|
||||
stateAsSupportsString.data = JSON.stringify(state);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a Map from window state objects to per-window group data.
|
||||
* Specifically, the values in the Map are themselves Maps from group IDs to
|
||||
* JS Objects which have these properties:
|
||||
* - title: the title of the group (or empty string)
|
||||
* - tabs: an array of the tabs objects in this group.
|
||||
*/
|
||||
_gatherGroupData(state) {
|
||||
let allGroupData = new Map();
|
||||
let globalAnonGroupID = 0;
|
||||
for (let win of state.windows) {
|
||||
if (win.extData && win.extData["tabview-group"]) {
|
||||
let groupInfo = {};
|
||||
try {
|
||||
groupInfo = JSON.parse(win.extData["tabview-group"]);
|
||||
} catch (ex) {
|
||||
// This is annoying, but we'll try to deal with this.
|
||||
}
|
||||
|
||||
let windowGroupData = new Map();
|
||||
for (let tab of win.tabs) {
|
||||
let group;
|
||||
// Get a string group ID:
|
||||
try {
|
||||
group = tab.extData && tab.extData["tabview-tab"] &&
|
||||
(JSON.parse(tab.extData["tabview-tab"]).groupID + "");
|
||||
} catch (ex) {
|
||||
// Ignore tabs with no group info
|
||||
continue;
|
||||
}
|
||||
let groupData = windowGroupData.get(group);
|
||||
if (!groupData) {
|
||||
let title = (groupInfo[group] && groupInfo[group].title) || "";
|
||||
groupData = {
|
||||
tabs: [],
|
||||
title,
|
||||
};
|
||||
if (!title) {
|
||||
groupData.anonGroupID = ++globalAnonGroupID;
|
||||
}
|
||||
windowGroupData.set(group, groupData);
|
||||
}
|
||||
groupData.tabs.push(tab);
|
||||
}
|
||||
|
||||
allGroupData.set(win, windowGroupData);
|
||||
}
|
||||
}
|
||||
return allGroupData;
|
||||
},
|
||||
|
||||
_createBackup(stateStr) {
|
||||
// TODO
|
||||
},
|
||||
|
||||
_bookmarkAllGroupsFromState: Task.async(function*(groupData) {
|
||||
// TODO
|
||||
}),
|
||||
|
||||
_removeHiddenTabGroupsFromState(state, groupData) {
|
||||
// TODO
|
||||
},
|
||||
|
||||
_createBackgroundTabGroupRestorationPage(state, backgroundData) {
|
||||
// TODO
|
||||
},
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ EXTRA_JS_MODULES += [
|
||||
'SelfSupportBackend.jsm',
|
||||
'SitePermissions.jsm',
|
||||
'Social.jsm',
|
||||
'TabGroupsMigrator.jsm',
|
||||
'TransientPrefs.jsm',
|
||||
'WebappManager.jsm',
|
||||
'webrtcUI.jsm',
|
||||
|
Loading…
Reference in New Issue
Block a user