summaryrefslogtreecommitdiffstats
path: root/components/sessionstore/SessionStorage.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'components/sessionstore/SessionStorage.jsm')
-rw-r--r--components/sessionstore/SessionStorage.jsm165
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.
+ }
+ },
+};