166 lines
5.2 KiB
JavaScript
166 lines
5.2 KiB
JavaScript
/* 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/. */
|
|
|
|
this.EXPORTED_SYMBOLS = ["SessionStorage"];
|
|
|
|
const Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
|
"resource:///modules/sessionstore/SessionStore.jsm");
|
|
|
|
this.SessionStorage = {
|
|
/**
|
|
* Updates all sessionStorage "super cookies"
|
|
* @param aDocShell
|
|
* That tab's docshell (containing the sessionStorage)
|
|
* @param aFullData
|
|
* always return privacy sensitive data (use with care)
|
|
*/
|
|
serialize: function(aDocShell, aFullData) {
|
|
return DomStorage.read(aDocShell, aFullData);
|
|
},
|
|
|
|
/**
|
|
* Restores all sessionStorage "super cookies".
|
|
* @param aDocShell
|
|
* A tab's docshell (containing the sessionStorage)
|
|
* @param aStorageData
|
|
* Storage data to be restored
|
|
*/
|
|
deserialize: function(aDocShell, aStorageData) {
|
|
DomStorage.write(aDocShell, aStorageData);
|
|
}
|
|
};
|
|
|
|
Object.freeze(SessionStorage);
|
|
|
|
var 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(aDocShell, aFullData) {
|
|
let data = {};
|
|
let isPinned = aDocShell.isAppTab;
|
|
let shistory = aDocShell.sessionHistory;
|
|
|
|
for (let i = 0; i < shistory.count; i++) {
|
|
let principal = History.getPrincipalForEntry(shistory, i, aDocShell);
|
|
if (!principal)
|
|
continue;
|
|
|
|
// Check if we're allowed to store sessionStorage data.
|
|
let isHTTPS = principal.URI && principal.URI.schemeIs("https");
|
|
if (aFullData || SessionStore.checkPrivacyLevel(isHTTPS, isPinned)) {
|
|
let origin = principal.extendedOrigin;
|
|
|
|
// Don't read a host twice.
|
|
if (!(origin in data)) {
|
|
let originData = this._readEntry(principal, aDocShell);
|
|
if (Object.keys(originData).length) {
|
|
data[origin] = originData;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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(aDocShell, aStorageData) {
|
|
for (let [host, data] in Iterator(aStorageData)) {
|
|
let uri = Services.io.newURI(host, null, null);
|
|
let principal = Services.scriptSecurityManager.getDocShellCodebasePrincipal(uri, aDocShell);
|
|
let storageManager = aDocShell.QueryInterface(Components.interfaces.nsIDOMStorageManager);
|
|
let window = aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
.getInterface(Components.interfaces.nsIDOMWindow);
|
|
|
|
// There is no need to pass documentURI, it's only used to fill documentURI property of
|
|
// domstorage event, which in this case has no consumer. Prevention of events in case
|
|
// of missing documentURI will be solved in a followup bug to bug 600307.
|
|
try {
|
|
let storage = storageManager.createStorage(window, principal, "", aDocShell.usePrivateBrowsing);
|
|
} catch(e) {
|
|
Cu.reportError(e);
|
|
}
|
|
|
|
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(aPrincipal, aDocShell) {
|
|
let hostData = {};
|
|
let storage;
|
|
|
|
try {
|
|
let storageManager = aDocShell.QueryInterface(Components.interfaces.nsIDOMStorageManager);
|
|
storage = storageManager.getStorage(aPrincipal);
|
|
} 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;
|
|
}
|
|
};
|
|
|
|
var History = {
|
|
/**
|
|
* Returns a given history entry's URI.
|
|
* @param aHistory
|
|
* That tab's session history
|
|
* @param aIndex
|
|
* The history entry's index
|
|
* @param aDocShell
|
|
* That tab's docshell
|
|
*/
|
|
getPrincipalForEntry: function(aHistory,
|
|
aIndex,
|
|
aDocShell) {
|
|
try {
|
|
return Services.scriptSecurityManager.getDocShellCodebasePrincipal(
|
|
aHistory.getEntryAtIndex(aIndex, false).URI, aDocShell);
|
|
} catch (e) {
|
|
// This might throw for some reason.
|
|
}
|
|
},
|
|
};
|