You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.2 KiB
165 lines
5.2 KiB
/* 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. |
|
} |
|
}, |
|
};
|
|
|