/* 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. } }, };