1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * A cache for tabs data.
8 * This cache implements a weak map from tabs (as XUL elements)
9 * to tab data (as objects).
11 * Note that we should never cache private data, as:
12 * - that data is used very seldom by SessionStore;
13 * - caching private data in addition to public data is memory consuming.
15 export var TabStateCache = Object.freeze({
17 * Retrieves cached data for a given |tab| or associated |browser|.
19 * @param permanentKey (object)
20 * The tab or browser to retrieve cached data for.
22 * The cached data stored for the given |tab|
23 * or associated |browser|.
26 return TabStateCacheInternal.get(permanentKey);
30 * Updates cached data for a given |tab| or associated |browser|.
32 * @param permanentKey (object)
33 * The tab or browser belonging to the given tab data.
34 * @param newData (object)
35 * The new data to be stored for the given |tab|
36 * or associated |browser|.
38 update(permanentKey, newData) {
39 TabStateCacheInternal.update(permanentKey, newData);
43 var TabStateCacheInternal = {
47 * Retrieves cached data for a given |tab| or associated |browser|.
49 * @param permanentKey (object)
50 * The tab or browser to retrieve cached data for.
52 * The cached data stored for the given |tab|
53 * or associated |browser|.
56 return this._data.get(permanentKey);
60 * Helper function used by update (see below). For message size
61 * optimization sometimes we don't update the whole session storage
62 * only the values that have been changed.
64 * @param data (object)
65 * The cached data where we want to update the changes.
66 * @param change (object)
67 * The actual changed values per domain.
69 updatePartialStorageChange(data, change) {
74 let storage = data.storage;
75 for (let domain of Object.keys(change)) {
76 if (!change[domain]) {
77 // We were sent null in place of the change object, which means
78 // we should delete session storage entirely for this domain.
79 delete storage[domain];
81 for (let key of Object.keys(change[domain])) {
82 let value = change[domain][key];
84 if (storage[domain] && storage[domain][key]) {
85 delete storage[domain][key];
88 if (!storage[domain]) {
91 storage[domain][key] = value;
99 * Helper function used by update (see below). For message size
100 * optimization sometimes we don't update the whole browser history
101 * only the current index and the tail of the history from a certain
102 * index (specified by change.fromIdx)
104 * @param data (object)
105 * The cached data where we want to update the changes.
106 * @param change (object)
107 * Object containing the tail of the history array, and
108 * some additional metadata.
110 updatePartialHistoryChange(data, change) {
111 const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
114 data.history = { entries: [] };
117 let history = data.history;
118 for (let key of Object.keys(change)) {
119 if (key == "entries") {
120 if (change.fromIdx != kLastIndex) {
121 let start = change.fromIdx + 1;
122 history.entries.splice(start, Infinity, ...change.entries);
124 } else if (key != "fromIdx") {
125 history[key] = change[key];
131 * Updates cached data for a given |tab| or associated |browser|.
133 * @param permanentKey (object)
134 * The tab or browser belonging to the given tab data.
135 * @param newData (object)
136 * The new data to be stored for the given |tab|
137 * or associated |browser|.
139 update(permanentKey, newData) {
140 let data = this._data.get(permanentKey) || {};
142 for (let key of Object.keys(newData)) {
143 if (key == "storagechange") {
144 this.updatePartialStorageChange(data, newData.storagechange);
148 if (key == "historychange") {
149 this.updatePartialHistoryChange(data, newData.historychange);
153 let value = newData[key];
154 if (value === null) {
161 this._data.set(permanentKey, data);