diff options
Diffstat (limited to 'components/sessionstore/SessionStorage.jsm')
-rw-r--r-- | components/sessionstore/SessionStorage.jsm | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/components/sessionstore/SessionStorage.jsm b/components/sessionstore/SessionStorage.jsm new file mode 100644 index 0000000..64aef35 --- /dev/null +++ b/components/sessionstore/SessionStorage.jsm @@ -0,0 +1,165 @@ +/* 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 ssto_serialize(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 ssto_deserialize(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 DomStorage_read(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 DomStorage_write(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 DomStorage_readEntry(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 History_getPrincipalForEntry(aHistory, + aIndex, + aDocShell) { + try { + return Services.scriptSecurityManager.getDocShellCodebasePrincipal( + aHistory.getEntryAtIndex(aIndex, false).URI, aDocShell); + } catch (e) { + // This might throw for some reason. + } + }, +}; |