browser/components/sessionstore/src/SessionMigration.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict";
michael@0 6
michael@0 7 this.EXPORTED_SYMBOLS = ["SessionMigration"];
michael@0 8
michael@0 9 const Cu = Components.utils;
michael@0 10 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
michael@0 11 Cu.import("resource://gre/modules/Task.jsm", this);
michael@0 12 Cu.import("resource://gre/modules/osfile.jsm", this);
michael@0 13
michael@0 14 // An encoder to UTF-8.
michael@0 15 XPCOMUtils.defineLazyGetter(this, "gEncoder", function () {
michael@0 16 return new TextEncoder();
michael@0 17 });
michael@0 18
michael@0 19 // A decoder.
michael@0 20 XPCOMUtils.defineLazyGetter(this, "gDecoder", function () {
michael@0 21 return new TextDecoder();
michael@0 22 });
michael@0 23
michael@0 24 let SessionMigrationInternal = {
michael@0 25 /**
michael@0 26 * Convert the original session restore state into a minimal state. It will
michael@0 27 * only contain:
michael@0 28 * - open windows
michael@0 29 * - with tabs
michael@0 30 * - with history entries with only title, url
michael@0 31 * - with pinned state
michael@0 32 * - with tab group info (hidden + group id)
michael@0 33 * - with selected tab info
michael@0 34 * - with selected window info
michael@0 35 * - with tabgroups info
michael@0 36 *
michael@0 37 * The complete state is then wrapped into the "about:welcomeback" page as
michael@0 38 * form field info to be restored when restoring the state.
michael@0 39 */
michael@0 40 convertState: function(aStateObj) {
michael@0 41 let state = {
michael@0 42 selectedWindow: aStateObj.selectedWindow,
michael@0 43 _closedWindows: []
michael@0 44 };
michael@0 45 state.windows = aStateObj.windows.map(function(oldWin) {
michael@0 46 var win = {extData: {}};
michael@0 47 win.tabs = oldWin.tabs.map(function(oldTab) {
michael@0 48 var tab = {};
michael@0 49 // Keep only titles and urls for history entries
michael@0 50 tab.entries = oldTab.entries.map(function(entry) {
michael@0 51 return {url: entry.url, title: entry.title};
michael@0 52 });
michael@0 53 tab.index = oldTab.index;
michael@0 54 tab.hidden = oldTab.hidden;
michael@0 55 tab.pinned = oldTab.pinned;
michael@0 56 // The tabgroup info is in the extData, so we need to get it out.
michael@0 57 if (oldTab.extData && "tabview-tab" in oldTab.extData) {
michael@0 58 tab.extData = {"tabview-tab": oldTab.extData["tabview-tab"]};
michael@0 59 }
michael@0 60 return tab;
michael@0 61 });
michael@0 62 // There are various tabgroup-related attributes that we need to get out
michael@0 63 // of the session restore data for the window, too.
michael@0 64 if (oldWin.extData) {
michael@0 65 for (let k of Object.keys(oldWin.extData)) {
michael@0 66 if (k.startsWith("tabview-")) {
michael@0 67 win.extData[k] = oldWin.extData[k];
michael@0 68 }
michael@0 69 }
michael@0 70 }
michael@0 71 win.selected = oldWin.selected;
michael@0 72 win._closedTabs = [];
michael@0 73 return win;
michael@0 74 });
michael@0 75 let wrappedState = {
michael@0 76 url: "about:welcomeback",
michael@0 77 formdata: {
michael@0 78 id: {"sessionData": state},
michael@0 79 xpath: {}
michael@0 80 }
michael@0 81 };
michael@0 82 return {windows: [{tabs: [{entries: [wrappedState]}]}]};
michael@0 83 },
michael@0 84 /**
michael@0 85 * Asynchronously read session restore state (JSON) from a path
michael@0 86 */
michael@0 87 readState: function(aPath) {
michael@0 88 return Task.spawn(function() {
michael@0 89 let bytes = yield OS.File.read(aPath);
michael@0 90 let text = gDecoder.decode(bytes);
michael@0 91 let state = JSON.parse(text);
michael@0 92 throw new Task.Result(state);
michael@0 93 });
michael@0 94 },
michael@0 95 /**
michael@0 96 * Asynchronously write session restore state as JSON to a path
michael@0 97 */
michael@0 98 writeState: function(aPath, aState) {
michael@0 99 let bytes = gEncoder.encode(JSON.stringify(aState));
michael@0 100 return OS.File.writeAtomic(aPath, bytes, {tmpPath: aPath + ".tmp"});
michael@0 101 }
michael@0 102 }
michael@0 103
michael@0 104 let SessionMigration = {
michael@0 105 /**
michael@0 106 * Migrate a limited set of session data from one path to another.
michael@0 107 */
michael@0 108 migrate: function(aFromPath, aToPath) {
michael@0 109 return Task.spawn(function() {
michael@0 110 let inState = yield SessionMigrationInternal.readState(aFromPath);
michael@0 111 let outState = SessionMigrationInternal.convertState(inState);
michael@0 112 // Unfortunately, we can't use SessionStore's own SessionFile to
michael@0 113 // write out the data because it has a dependency on the profile dir
michael@0 114 // being known. When the migration runs, there is no guarantee that
michael@0 115 // that's true.
michael@0 116 yield SessionMigrationInternal.writeState(aToPath, outState);
michael@0 117 });
michael@0 118 }
michael@0 119 };

mercurial