Bug 1265818 - Part 3 - Store and restore the LayoutHistoryState through SessionHistoy.jsm. r?mikedeboer
Since a LayoutHistoryState is basically just a collection of PresStates, we just save each PresState we can find and then later restore it.
MozReview-Commit-ID: A6WpdelseHn
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -321,30 +321,34 @@ var SessionHistoryListener = {
this.collect();
},
onFrameTreeReset() {
this.collect();
},
OnHistoryNewEntry(newURI, oldIndex) {
+ // We ought to collect the previously current entry as well, see bug 1350567.
this.collectFrom(oldIndex);
},
OnHistoryGoBack(backURI) {
+ // We ought to collect the previously current entry as well, see bug 1350567.
this.collectFrom(kLastIndex);
return true;
},
OnHistoryGoForward(forwardURI) {
+ // We ought to collect the previously current entry as well, see bug 1350567.
this.collectFrom(kLastIndex);
return true;
},
OnHistoryGotoIndex(index, gotoURI) {
+ // We ought to collect the previously current entry as well, see bug 1350567.
this.collectFrom(kLastIndex);
return true;
},
OnHistoryPurge(numEntries) {
this.collect();
return true;
},
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -196,18 +196,31 @@ var SessionHistoryInternal = {
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)
+ if (x.value !== 0 || y.value !== 0) {
entry.scroll = x.value + "," + y.value;
+ }
+
+ let layoutHistoryState = shEntry.layoutHistoryState;
+ if (layoutHistoryState && layoutHistoryState.hasStates) {
+ let presStates = layoutHistoryState.getKeys().map(key =>
+ this._getSerializablePresState(layoutHistoryState, key)).filter(presState =>
+ // Only keep presState entries that contain more than the key itself.
+ Object.getOwnPropertyNames(presState).length > 1);
+
+ if (presStates.length > 0) {
+ entry.presState = presStates;
+ }
+ }
}
// Collect triggeringPrincipal data for the current history entry.
if (shEntry.principalToInherit) {
try {
let principalToInherit = Utils.serializePrincipal(shEntry.principalToInherit);
if (principalToInherit) {
entry.principalToInherit_base64 = principalToInherit;
@@ -260,16 +273,46 @@ var SessionHistoryInternal = {
entry.children = children;
}
}
return entry;
},
/**
+ * Get an object that is a serializable representation of a PresState.
+ *
+ * @param layoutHistoryState
+ * nsILayoutHistoryState instance
+ * @param stateKey
+ * The state key of the presState to be retrieved.
+ * @return object
+ */
+ _getSerializablePresState(layoutHistoryState, stateKey) {
+ let presState = { stateKey };
+ let x = {}, y = {}, scrollOriginDowngrade = {}, res = {}, scaleToRes = {};
+
+ layoutHistoryState.getPresState(stateKey, x, y, scrollOriginDowngrade, res, scaleToRes);
+ if (x.value !== 0 || y.value !== 0) {
+ presState.scroll = x.value + "," + y.value;
+ }
+ if (scrollOriginDowngrade.value === false) {
+ presState.scrollOriginDowngrade = scrollOriginDowngrade.value;
+ }
+ if (res.value != 1.0) {
+ presState.res = res.value;
+ }
+ if (scaleToRes.value === true) {
+ presState.scaleToRes = scaleToRes.value;
+ }
+
+ return presState;
+ },
+
+ /**
* 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.
* @return A reference to the docShell's nsISHistoryInternal interface.
*/
@@ -380,20 +423,28 @@ var SessionHistoryInternal = {
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]);
+ } else {
+ if (entry.scroll) {
+ shEntry.setScrollPosition(...this._deserializeScrollPosition(entry.scroll));
+ }
+
+ if (entry.presState) {
+ let layoutHistoryState = shEntry.initLayoutHistoryState();
+
+ for (let presState of entry.presState) {
+ this._deserializePresState(layoutHistoryState, presState);
+ }
+ }
}
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.
@@ -438,9 +489,40 @@ var SessionHistoryInternal = {
shEntry.AddChild(this.deserializeEntry(entry.children[i], idMap,
childDocIdents), i);
}
}
return shEntry;
},
+ /**
+ * Expands serialized PresState data and adds it to the given nsILayoutHistoryState.
+ *
+ * @param layoutHistoryState
+ * nsILayoutHistoryState instance
+ * @param presState
+ * Object containing serialized PresState data.
+ */
+ _deserializePresState(layoutHistoryState, presState) {
+ let stateKey = presState.stateKey;
+ let scrollOriginDowngrade =
+ typeof presState.scrollOriginDowngrade == "boolean" ? presState.scrollOriginDowngrade : true;
+ let res = presState.res || 1.0;
+ let scaleToRes = presState.scaleToRes || false;
+
+ layoutHistoryState.addNewPresState(stateKey, ...this._deserializeScrollPosition(presState.scroll),
+ scrollOriginDowngrade, res, scaleToRes);
+ },
+
+ /**
+ * Expands serialized scroll position data into an array containing the x and y coordinates,
+ * defaulting to 0,0 if no scroll position was found.
+ *
+ * @param scroll
+ * Object containing serialized scroll position data.
+ * @return An array containing the scroll position's x and y coordinates.
+ */
+ _deserializeScrollPosition(scroll = "0,0") {
+ return scroll.split(",").map(pos => parseInt(pos, 10) || 0);
+ },
+
};