summaryrefslogtreecommitdiffstats
path: root/application/basilisk/components/sessionstore/SessionHistory.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'application/basilisk/components/sessionstore/SessionHistory.jsm')
-rw-r--r--application/basilisk/components/sessionstore/SessionHistory.jsm473
1 files changed, 0 insertions, 473 deletions
diff --git a/application/basilisk/components/sessionstore/SessionHistory.jsm b/application/basilisk/components/sessionstore/SessionHistory.jsm
deleted file mode 100644
index f53246d52..000000000
--- a/application/basilisk/components/sessionstore/SessionHistory.jsm
+++ /dev/null
@@ -1,473 +0,0 @@
-/* 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 = ["SessionHistory"];
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Utils",
- "resource://gre/modules/sessionstore/Utils.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "uuidGenerator",
- "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
-
-function debug(msg) {
- Services.console.logStringMessage("SessionHistory: " + msg);
-}
-
-/**
- * The external API exported by this module.
- */
-this.SessionHistory = Object.freeze({
- isEmpty: function (docShell) {
- return SessionHistoryInternal.isEmpty(docShell);
- },
-
- collect: function (docShell, aFromIdx = -1) {
- return SessionHistoryInternal.collect(docShell, aFromIdx);
- },
-
- restore: function (docShell, tabData) {
- SessionHistoryInternal.restore(docShell, tabData);
- }
-});
-
-/**
- * The internal API for the SessionHistory module.
- */
-var SessionHistoryInternal = {
- /**
- * Mapping from legacy docshellIDs to docshellUUIDs.
- */
- _docshellUUIDMap: new Map(),
-
- /**
- * Returns whether the given docShell's session history is empty.
- *
- * @param docShell
- * The docShell that owns the session history.
- */
- isEmpty: function (docShell) {
- let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
- let history = webNavigation.sessionHistory;
- if (!webNavigation.currentURI) {
- return true;
- }
- let uri = webNavigation.currentURI.spec;
- return uri == "about:blank" && history.count == 0;
- },
-
- /**
- * Collects session history data for a given docShell.
- *
- * @param docShell
- * The docShell that owns the session history.
- * @param aFromIdx
- * The starting local index to collect the history from.
- * @return An object reprereseting a partial global history update.
- */
- collect: function (docShell, aFromIdx = -1) {
- let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
- let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
- let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
- let ihistory = history.QueryInterface(Ci.nsISHistory);
-
- let data = {entries: [], userContextId: loadContext.originAttributes.userContextId };
-
- if (history && history.count > 0) {
- // Loop over the transaction linked list directly so we can get the
- // persist property for each transaction.
- for (let txn = history.rootTransaction; txn; txn = txn.next) {
- let entry = this.serializeEntry(txn.sHEntry);
- entry.persist = txn.persist;
- data.entries.push(entry);
- }
-
- // Ensure the index isn't out of bounds if an exception was thrown above.
- data.index = Math.min(history.index + 1, data.entries.length);
- }
-
- // If either the session history isn't available yet or doesn't have any
- // valid entries, make sure we at least include the current page.
- if (data.entries.length == 0) {
- let uri = webNavigation.currentURI.spec;
- let body = webNavigation.document.body;
- // We landed here because the history is inaccessible or there are no
- // history entries. In that case we should at least record the docShell's
- // current URL as a single history entry. If the URL is not about:blank
- // or it's a blank tab that was modified (like a custom newtab page),
- // record it. For about:blank we explicitly want an empty array without
- // an 'index' property to denote that there are no history entries.
- if (uri != "about:blank" || (body && body.hasChildNodes())) {
- data.entries.push({
- url: uri,
- triggeringPrincipal_base64: Utils.SERIALIZED_SYSTEMPRINCIPAL
- });
- data.index = 1;
- }
- }
-
- // Check if we should discard some of the entries which didn't change
- if (aFromIdx > -1) {
- data.entries.splice(0, aFromIdx + 1);
- }
-
- // Transform the entries from local to global index space.
- data.index += ihistory.globalIndexOffset;
- data.fromIdx = aFromIdx + ihistory.globalIndexOffset;
-
- // If we are not the most recent partialSHistory in our groupedSHistory, we
- // need to make certain that we don't replace the entries from the following
- // SHistories - so we replace only the number of entries which our SHistory
- // takes up.
- if (ihistory.globalIndexOffset + ihistory.count < ihistory.globalCount) {
- data.toIdx = data.fromIdx + ihistory.count;
- }
-
- return data;
- },
-
- /**
- * Get an object that is a serialized representation of a History entry.
- *
- * @param shEntry
- * nsISHEntry instance
- * @return object
- */
- serializeEntry: function (shEntry) {
- let entry = { url: shEntry.URI.spec };
-
- // Save some bytes and don't include the title property
- // if that's identical to the current entry's URL.
- if (shEntry.title && shEntry.title != entry.url) {
- entry.title = shEntry.title;
- }
- if (shEntry.isSubFrame) {
- entry.subframe = true;
- }
-
- entry.charset = shEntry.URI.originCharset;
-
- let cacheKey = shEntry.cacheKey;
- if (cacheKey && cacheKey instanceof Ci.nsISupportsPRUint32 &&
- cacheKey.data != 0) {
- // XXXbz would be better to have cache keys implement
- // nsISerializable or something.
- entry.cacheKey = cacheKey.data;
- }
- entry.ID = shEntry.ID;
- entry.docshellUUID = shEntry.docshellID.toString();
-
- // We will include the property only if it's truthy to save a couple of
- // bytes when the resulting object is stringified and saved to disk.
- if (shEntry.referrerURI) {
- entry.referrer = shEntry.referrerURI.spec;
- entry.referrerPolicy = shEntry.referrerPolicy;
- }
-
- if (shEntry.originalURI) {
- entry.originalURI = shEntry.originalURI.spec;
- }
-
- if (shEntry.loadReplace) {
- entry.loadReplace = shEntry.loadReplace;
- }
-
- if (shEntry.srcdocData)
- entry.srcdocData = shEntry.srcdocData;
-
- if (shEntry.isSrcdocEntry)
- entry.isSrcdocEntry = shEntry.isSrcdocEntry;
-
- if (shEntry.baseURI)
- entry.baseURI = shEntry.baseURI.spec;
-
- if (shEntry.contentType)
- entry.contentType = shEntry.contentType;
-
- if (shEntry.scrollRestorationIsManual) {
- entry.scrollRestorationIsManual = true;
- } else {
- let x = {}, y = {};
- shEntry.getScrollPosition(x, y);
- if (x.value != 0 || y.value != 0)
- entry.scroll = x.value + "," + y.value;
- }
-
- // Collect triggeringPrincipal data for the current history entry.
- // Please note that before Bug 1297338 there was no concept of a
- // principalToInherit. To remain backward/forward compatible we
- // serialize the principalToInherit as triggeringPrincipal_b64.
- // Once principalToInherit is well established (within FF55)
- // we can update this code, remove triggeringPrincipal_b64 and
- // just keep triggeringPrincipal_base64 as well as
- // principalToInherit_base64; see Bug 1301666.
- if (shEntry.principalToInherit) {
- try {
- let principalToInherit = Utils.serializePrincipal(shEntry.principalToInherit);
- if (principalToInherit) {
- entry.triggeringPrincipal_b64 = principalToInherit;
- entry.principalToInherit_base64 = principalToInherit;
- }
- } catch (e) {
- debug(e);
- }
- }
-
- if (shEntry.triggeringPrincipal) {
- try {
- let triggeringPrincipal = Utils.serializePrincipal(shEntry.triggeringPrincipal);
- if (triggeringPrincipal) {
- entry.triggeringPrincipal_base64 = triggeringPrincipal;
- }
- } catch (e) {
- debug(e);
- }
- }
-
- entry.docIdentifier = shEntry.BFCacheEntry.ID;
-
- if (shEntry.stateData != null) {
- entry.structuredCloneState = shEntry.stateData.getDataAsBase64();
- entry.structuredCloneVersion = shEntry.stateData.formatVersion;
- }
-
- if (!(shEntry instanceof Ci.nsISHContainer)) {
- return entry;
- }
-
- if (shEntry.childCount > 0 && !shEntry.hasDynamicallyAddedChild()) {
- let children = [];
- for (let i = 0; i < shEntry.childCount; i++) {
- let child = shEntry.GetChildAt(i);
-
- if (child) {
- // Don't try to restore framesets containing wyciwyg URLs.
- // (cf. bug 424689 and bug 450595)
- if (child.URI.schemeIs("wyciwyg")) {
- children.length = 0;
- break;
- }
-
- children.push(this.serializeEntry(child));
- }
- }
-
- if (children.length) {
- entry.children = children;
- }
- }
-
- return entry;
- },
-
- /**
- * Restores session history data for a given docShell.
- *
- * @param docShell
- * The docShell that owns the session history.
- * @param tabData
- * The tabdata including all history entries.
- */
- restore: function (docShell, tabData) {
- let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
- let history = webNavigation.sessionHistory;
- if (history.count > 0) {
- history.PurgeHistory(history.count);
- }
- history.QueryInterface(Ci.nsISHistoryInternal);
-
- let idMap = { used: {} };
- let docIdentMap = {};
- for (let i = 0; i < tabData.entries.length; i++) {
- let entry = tabData.entries[i];
- //XXXzpao Wallpaper patch for bug 514751
- if (!entry.url)
- continue;
- let persist = "persist" in entry ? entry.persist : true;
- history.addEntry(this.deserializeEntry(entry, idMap, docIdentMap), persist);
- }
-
- // Select the right history entry.
- let index = tabData.index - 1;
- if (index < history.count && history.index != index) {
- history.getEntryAtIndex(index, true);
- }
- },
-
- /**
- * Expands serialized history data into a session-history-entry instance.
- *
- * @param entry
- * Object containing serialized history data for a URL
- * @param idMap
- * Hash for ensuring unique frame IDs
- * @param docIdentMap
- * Hash to ensure reuse of BFCache entries
- * @returns nsISHEntry
- */
- deserializeEntry: function (entry, idMap, docIdentMap) {
-
- var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
- createInstance(Ci.nsISHEntry);
-
- shEntry.setURI(Utils.makeURI(entry.url, entry.charset));
- shEntry.setTitle(entry.title || entry.url);
- if (entry.subframe)
- shEntry.setIsSubFrame(entry.subframe || false);
- shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
- if (entry.contentType)
- shEntry.contentType = entry.contentType;
- if (entry.referrer) {
- shEntry.referrerURI = Utils.makeURI(entry.referrer);
- shEntry.referrerPolicy = entry.referrerPolicy;
- }
- if (entry.originalURI) {
- shEntry.originalURI = Utils.makeURI(entry.originalURI);
- }
- if (entry.loadReplace) {
- shEntry.loadReplace = entry.loadReplace;
- }
- if (entry.isSrcdocEntry)
- shEntry.srcdocData = entry.srcdocData;
- if (entry.baseURI)
- shEntry.baseURI = Utils.makeURI(entry.baseURI);
-
- if (entry.cacheKey) {
- var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
- createInstance(Ci.nsISupportsPRUint32);
- cacheKey.data = entry.cacheKey;
- shEntry.cacheKey = cacheKey;
- }
-
- if (entry.ID) {
- // get a new unique ID for this frame (since the one from the last
- // start might already be in use)
- var id = idMap[entry.ID] || 0;
- if (!id) {
- for (id = Date.now(); id in idMap.used; id++);
- idMap[entry.ID] = id;
- idMap.used[id] = true;
- }
- shEntry.ID = id;
- }
-
- // If we have the legacy docshellID on our entry, upgrade it to a
- // docshellUUID by going through the mapping.
- if (entry.docshellID) {
- if (!this._docshellUUIDMap.has(entry.docshellID)) {
- // Convert the nsID to a string so that the docshellUUID property
- // is correctly stored as a string.
- this._docshellUUIDMap.set(entry.docshellID,
- uuidGenerator.generateUUID().toString());
- }
- entry.docshellUUID = this._docshellUUIDMap.get(entry.docshellID);
- delete entry.docshellID;
- }
-
- if (entry.docshellUUID) {
- shEntry.docshellID = Components.ID(entry.docshellUUID);
- }
-
- if (entry.structuredCloneState && entry.structuredCloneVersion) {
- shEntry.stateData =
- Cc["@mozilla.org/docshell/structured-clone-container;1"].
- createInstance(Ci.nsIStructuredCloneContainer);
-
- shEntry.stateData.initFromBase64(entry.structuredCloneState,
- entry.structuredCloneVersion);
- }
-
- if (entry.scrollRestorationIsManual) {
- shEntry.scrollRestorationIsManual = true;
- } else if (entry.scroll) {
- var scrollPos = (entry.scroll || "0,0").split(",");
- scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
- shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
- }
-
- let childDocIdents = {};
- if (entry.docIdentifier) {
- // If we have a serialized document identifier, try to find an SHEntry
- // which matches that doc identifier and adopt that SHEntry's
- // BFCacheEntry. If we don't find a match, insert shEntry as the match
- // for the document identifier.
- let matchingEntry = docIdentMap[entry.docIdentifier];
- if (!matchingEntry) {
- matchingEntry = {shEntry: shEntry, childDocIdents: childDocIdents};
- docIdentMap[entry.docIdentifier] = matchingEntry;
- }
- else {
- shEntry.adoptBFCacheEntry(matchingEntry.shEntry);
- childDocIdents = matchingEntry.childDocIdents;
- }
- }
-
- // The field entry.owner_b64 got renamed to entry.triggeringPricipal_b64 in
- // Bug 1286472. To remain backward compatible we still have to support that
- // field for a few cycles before we can remove it within Bug 1289785.
- if (entry.owner_b64) {
- entry.triggeringPricipal_b64 = entry.owner_b64;
- delete entry.owner_b64;
- }
-
- // Before introducing the concept of principalToInherit we only had
- // a triggeringPrincipal within every entry which basically is the
- // equivalent of the new principalToInherit. To avoid compatibility
- // issues, we first check if the entry has entries for
- // triggeringPrincipal_base64 and principalToInherit_base64. If not
- // we fall back to using the principalToInherit (which is stored
- // as triggeringPrincipal_b64) as the triggeringPrincipal and
- // the principalToInherit.
- // FF55 will remove the triggeringPrincipal_b64, see Bug 1301666.
- if (entry.triggeringPrincipal_base64 || entry.principalToInherit_base64) {
- if (entry.triggeringPrincipal_base64) {
- shEntry.triggeringPrincipal =
- Utils.deserializePrincipal(entry.triggeringPrincipal_base64);
- }
- if (entry.principalToInherit_base64) {
- shEntry.principalToInherit =
- Utils.deserializePrincipal(entry.principalToInherit_base64);
- }
- } else if (entry.triggeringPrincipal_b64) {
- shEntry.triggeringPrincipal = Utils.deserializePrincipal(entry.triggeringPrincipal_b64);
- shEntry.principalToInherit = shEntry.triggeringPrincipal;
- }
-
- if (entry.children && shEntry instanceof Ci.nsISHContainer) {
- for (var i = 0; i < entry.children.length; i++) {
- //XXXzpao Wallpaper patch for bug 514751
- if (!entry.children[i].url)
- continue;
-
- // We're getting sessionrestore.js files with a cycle in the
- // doc-identifier graph, likely due to bug 698656. (That is, we have
- // an entry where doc identifier A is an ancestor of doc identifier B,
- // and another entry where doc identifier B is an ancestor of A.)
- //
- // If we were to respect these doc identifiers, we'd create a cycle in
- // the SHEntries themselves, which causes the docshell to loop forever
- // when it looks for the root SHEntry.
- //
- // So as a hack to fix this, we restrict the scope of a doc identifier
- // to be a node's siblings and cousins, and pass childDocIdents, not
- // aDocIdents, to _deserializeHistoryEntry. That is, we say that two
- // SHEntries with the same doc identifier have the same document iff
- // they have the same parent or their parents have the same document.
-
- shEntry.AddChild(this.deserializeEntry(entry.children[i], idMap,
- childDocIdents), i);
- }
- }
-
- return shEntry;
- },
-
-};