зеркало из https://github.com/mozilla/gecko-dev.git
Bug 742047 - Part 2 - Refactor SessionStorage.jsm and its API; r=zpao
This commit is contained in:
Родитель
2f19669713
Коммит
a36b34a473
|
@ -15,95 +15,158 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
|||
let SessionStorage = {
|
||||
/**
|
||||
* Updates all sessionStorage "super cookies"
|
||||
* @param aTabData
|
||||
* The data object for a specific tab
|
||||
* @param aHistory
|
||||
* That tab's session history
|
||||
* @param aDocShell
|
||||
* That tab's docshell (containing the sessionStorage)
|
||||
* @param aFullData
|
||||
* always return privacy sensitive data (use with care)
|
||||
* @param aIsPinned
|
||||
* the tab is pinned and should be treated differently for privacy
|
||||
*/
|
||||
serialize: function ssto_serialize(aTabData, aHistory, aDocShell, aFullData,
|
||||
aIsPinned) {
|
||||
let storageData = {};
|
||||
let hasContent = false;
|
||||
|
||||
for (let i = 0; i < aHistory.count; i++) {
|
||||
let uri;
|
||||
try {
|
||||
uri = aHistory.getEntryAtIndex(i, false).URI;
|
||||
}
|
||||
catch (ex) {
|
||||
// Chances are that this is getEntryAtIndex throwing, as seen in bug 669196.
|
||||
// We've already asserted in _collectTabData, so we won't show that again.
|
||||
continue;
|
||||
}
|
||||
// sessionStorage is saved per origin (cf. nsDocShell::GetSessionStorageForURI)
|
||||
let domain = uri.spec;
|
||||
try {
|
||||
if (uri.host)
|
||||
domain = uri.prePath;
|
||||
}
|
||||
catch (ex) { /* this throws for host-less URIs (such as about: or jar:) */ }
|
||||
if (storageData[domain] ||
|
||||
!(aFullData || SessionStore.checkPrivacyLevel(uri.schemeIs("https"), aIsPinned)))
|
||||
continue;
|
||||
|
||||
let storage, storageItemCount = 0;
|
||||
try {
|
||||
var principal = Services.scriptSecurityManager.getCodebasePrincipal(uri);
|
||||
|
||||
// Using getSessionStorageForPrincipal instead of getSessionStorageForURI
|
||||
// just to be able to pass aCreate = false, that avoids creation of the
|
||||
// sessionStorage object for the page earlier than the page really
|
||||
// requires it. It was causing problems while accessing a storage when
|
||||
// a page later changed its domain.
|
||||
storage = aDocShell.getSessionStorageForPrincipal(principal, "", false);
|
||||
if (storage)
|
||||
storageItemCount = storage.length;
|
||||
}
|
||||
catch (ex) { /* sessionStorage might throw if it's turned off, see bug 458954 */ }
|
||||
if (storageItemCount == 0)
|
||||
continue;
|
||||
|
||||
let data = storageData[domain] = {};
|
||||
for (let j = 0; j < storageItemCount; j++) {
|
||||
try {
|
||||
let key = storage.key(j);
|
||||
let item = storage.getItem(key);
|
||||
data[key] = item;
|
||||
}
|
||||
catch (ex) { /* this currently throws for secured items (cf. bug 442048) */ }
|
||||
}
|
||||
hasContent = true;
|
||||
}
|
||||
|
||||
if (hasContent)
|
||||
aTabData.storage = storageData;
|
||||
serialize: function ssto_serialize(aDocShell, aFullData) {
|
||||
return DomStorage.read(aDocShell, aFullData);
|
||||
},
|
||||
|
||||
/**
|
||||
* restores all sessionStorage "super cookies"
|
||||
* @param aStorageData
|
||||
* Storage data to be restored
|
||||
* Restores all sessionStorage "super cookies".
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
* @param aStorageData
|
||||
* Storage data to be restored
|
||||
*/
|
||||
deserialize: function ssto_deserialize(aStorageData, aDocShell) {
|
||||
for (let url in aStorageData) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
let storage = aDocShell.getSessionStorageForURI(uri, "");
|
||||
for (let key in aStorageData[url]) {
|
||||
try {
|
||||
storage.setItem(key, aStorageData[url][key]);
|
||||
}
|
||||
catch (ex) { Cu.reportError(ex); } // throws e.g. for URIs that can't have sessionStorage
|
||||
}
|
||||
}
|
||||
deserialize: function ssto_deserialize(aDocShell, aStorageData) {
|
||||
DomStorage.write(aDocShell, aStorageData);
|
||||
}
|
||||
};
|
||||
|
||||
Object.freeze(SessionStorage);
|
||||
|
||||
let DomStorage = {
|
||||
/**
|
||||
* Reads all session storage data from the given docShell.
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
* @param aFullData
|
||||
* Always return privacy sensitive data (use with care)
|
||||
*/
|
||||
read: function DomStorage_read(aDocShell, aFullData) {
|
||||
let data = {};
|
||||
let isPinned = aDocShell.isAppTab;
|
||||
let shistory = aDocShell.sessionHistory;
|
||||
|
||||
for (let i = 0; i < shistory.count; i++) {
|
||||
let uri = History.getUriForEntry(shistory, i);
|
||||
|
||||
if (uri) {
|
||||
// Check if we're allowed to store sessionStorage data.
|
||||
let isHTTPS = uri.schemeIs("https");
|
||||
if (aFullData || SessionStore.checkPrivacyLevel(isHTTPS, isPinned)) {
|
||||
let host = History.getHostForURI(uri);
|
||||
|
||||
// Don't read a host twice.
|
||||
if (!(host in data)) {
|
||||
let hostData = this._readEntry(uri, aDocShell);
|
||||
if (Object.keys(hostData).length) {
|
||||
data[host] = hostData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes session storage data to the given tab.
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
* @param aStorageData
|
||||
* Storage data to be restored
|
||||
*/
|
||||
write: function DomStorage_write(aDocShell, aStorageData) {
|
||||
for (let [host, data] in Iterator(aStorageData)) {
|
||||
let uri = Services.io.newURI(host, null, null);
|
||||
let storage = aDocShell.getSessionStorageForURI(uri, "");
|
||||
|
||||
for (let [key, value] in Iterator(data)) {
|
||||
try {
|
||||
storage.setItem(key, value);
|
||||
} catch (e) {
|
||||
// throws e.g. for URIs that can't have sessionStorage
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads an entry in the session storage data contained in a tab's history.
|
||||
* @param aURI
|
||||
* That history entry uri
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
*/
|
||||
_readEntry: function DomStorage_readEntry(aURI, aDocShell) {
|
||||
let hostData = {};
|
||||
let storage;
|
||||
|
||||
try {
|
||||
let principal = Services.scriptSecurityManager.getCodebasePrincipal(aURI);
|
||||
|
||||
// Using getSessionStorageForPrincipal instead of
|
||||
// getSessionStorageForURI just to be able to pass aCreate = false,
|
||||
// that avoids creation of the sessionStorage object for the page
|
||||
// earlier than the page really requires it. It was causing problems
|
||||
// while accessing a storage when a page later changed its domain.
|
||||
storage = aDocShell.getSessionStorageForPrincipal(principal, "", false);
|
||||
} catch (e) {
|
||||
// sessionStorage might throw if it's turned off, see bug 458954
|
||||
}
|
||||
|
||||
if (storage && storage.length) {
|
||||
for (let i = 0; i < storage.length; i++) {
|
||||
try {
|
||||
let key = storage.key(i);
|
||||
hostData[key] = storage.getItem(key);
|
||||
} catch (e) {
|
||||
// This currently throws for secured items (cf. bug 442048).
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hostData;
|
||||
}
|
||||
};
|
||||
|
||||
let History = {
|
||||
/**
|
||||
* Returns a given history entry's URI.
|
||||
* @param aHistory
|
||||
* That tab's session history
|
||||
* @param aIndex
|
||||
* The history entry's index
|
||||
*/
|
||||
getUriForEntry: function History_getUriForEntry(aHistory, aIndex) {
|
||||
try {
|
||||
return aHistory.getEntryAtIndex(aIndex, false).URI;
|
||||
} catch (e) {
|
||||
// This might throw for some reason.
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the host of a given URI.
|
||||
* @param aURI
|
||||
* The URI for which to return the host
|
||||
*/
|
||||
getHostForURI: function History_getHostForURI(aURI) {
|
||||
let host = aURI.spec;
|
||||
|
||||
try {
|
||||
if (aURI.host)
|
||||
host = aURI.prePath;
|
||||
} catch (e) {
|
||||
// This throws for host-less URIs (such as about: or jar:).
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -87,7 +87,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
|
||||
"resource:///modules/sessionstore/DocumentUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
|
||||
"resource:///modules/sessionstore/SessionStorage.jsm");
|
||||
"resource:///modules/sessionstore/SessionStorage.jsm");
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
|
||||
|
@ -1993,9 +1993,11 @@ let SessionStoreInternal = {
|
|||
else if (tabData.extData)
|
||||
delete tabData.extData;
|
||||
|
||||
if (history && browser.docShell instanceof Ci.nsIDocShell)
|
||||
SessionStorage.serialize(tabData, history, browser.docShell, aFullData,
|
||||
aTab.pinned);
|
||||
if (history && browser.docShell instanceof Ci.nsIDocShell) {
|
||||
let storageData = SessionStorage.serialize(browser.docShell, aFullData)
|
||||
if (Object.keys(storageData).length)
|
||||
tabData.storage = storageData;
|
||||
}
|
||||
|
||||
return tabData;
|
||||
},
|
||||
|
@ -3061,7 +3063,7 @@ let SessionStoreInternal = {
|
|||
tab.setAttribute(name, tabData.attributes[name]);
|
||||
|
||||
if (tabData.storage && browser.docShell instanceof Ci.nsIDocShell)
|
||||
SessionStorage.deserialize(tabData.storage, browser.docShell);
|
||||
SessionStorage.deserialize(browser.docShell, tabData.storage);
|
||||
|
||||
// notify the tabbrowser that the tab chrome has been restored
|
||||
var event = aWindow.document.createEvent("Events");
|
||||
|
|
Загрузка…
Ссылка в новой задаче