summaryrefslogtreecommitdiffstats
path: root/toolkit/components/webextensions/ExtensionStorage.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/webextensions/ExtensionStorage.jsm')
-rw-r--r--toolkit/components/webextensions/ExtensionStorage.jsm241
1 files changed, 0 insertions, 241 deletions
diff --git a/toolkit/components/webextensions/ExtensionStorage.jsm b/toolkit/components/webextensions/ExtensionStorage.jsm
deleted file mode 100644
index 0b0ffb000..000000000
--- a/toolkit/components/webextensions/ExtensionStorage.jsm
+++ /dev/null
@@ -1,241 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["ExtensionStorage"];
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
- "resource://gre/modules/AsyncShutdown.jsm");
-
-function jsonReplacer(key, value) {
- switch (typeof(value)) {
- // Serialize primitive types as-is.
- case "string":
- case "number":
- case "boolean":
- return value;
-
- case "object":
- if (value === null) {
- return value;
- }
-
- switch (Cu.getClassName(value, true)) {
- // Serialize arrays and ordinary objects as-is.
- case "Array":
- case "Object":
- return value;
-
- // Serialize Date objects and regular expressions as their
- // string representations.
- case "Date":
- case "RegExp":
- return String(value);
- }
- break;
- }
-
- if (!key) {
- // If this is the root object, and we can't serialize it, serialize
- // the value to an empty object.
- return {};
- }
-
- // Everything else, omit entirely.
- return undefined;
-}
-
-this.ExtensionStorage = {
- cache: new Map(),
- listeners: new Map(),
-
- /**
- * Sanitizes the given value, and returns a JSON-compatible
- * representation of it, based on the privileges of the given global.
- *
- * @param {value} value
- * The value to sanitize.
- * @param {Context} context
- * The extension context in which to sanitize the value
- * @returns {value}
- * The sanitized value.
- */
- sanitize(value, context) {
- let json = context.jsonStringify(value, jsonReplacer);
- return JSON.parse(json);
- },
-
- getExtensionDir(extensionId) {
- return OS.Path.join(this.extensionDir, extensionId);
- },
-
- getStorageFile(extensionId) {
- return OS.Path.join(this.extensionDir, extensionId, "storage.js");
- },
-
- read(extensionId) {
- if (this.cache.has(extensionId)) {
- return this.cache.get(extensionId);
- }
-
- let path = this.getStorageFile(extensionId);
- let decoder = new TextDecoder();
- let promise = OS.File.read(path);
- promise = promise.then(array => {
- return JSON.parse(decoder.decode(array));
- }).catch((error) => {
- if (!error.becauseNoSuchFile) {
- Cu.reportError("Unable to parse JSON data for extension storage.");
- }
- return {};
- });
- this.cache.set(extensionId, promise);
- return promise;
- },
-
- write(extensionId) {
- let promise = this.read(extensionId).then(extData => {
- let encoder = new TextEncoder();
- let array = encoder.encode(JSON.stringify(extData));
- let path = this.getStorageFile(extensionId);
- OS.File.makeDir(this.getExtensionDir(extensionId), {
- ignoreExisting: true,
- from: OS.Constants.Path.profileDir,
- });
- let promise = OS.File.writeAtomic(path, array);
- return promise;
- }).catch(() => {
- // Make sure this promise is never rejected.
- Cu.reportError("Unable to write JSON data for extension storage.");
- });
-
- AsyncShutdown.profileBeforeChange.addBlocker(
- "ExtensionStorage: Finish writing extension data",
- promise);
-
- return promise.then(() => {
- AsyncShutdown.profileBeforeChange.removeBlocker(promise);
- });
- },
-
- set(extensionId, items, context) {
- return this.read(extensionId).then(extData => {
- let changes = {};
- for (let prop in items) {
- let item = this.sanitize(items[prop], context);
- changes[prop] = {oldValue: extData[prop], newValue: item};
- extData[prop] = item;
- }
-
- this.notifyListeners(extensionId, changes);
-
- return this.write(extensionId);
- });
- },
-
- remove(extensionId, items) {
- return this.read(extensionId).then(extData => {
- let changes = {};
- for (let prop of [].concat(items)) {
- changes[prop] = {oldValue: extData[prop]};
- delete extData[prop];
- }
-
- this.notifyListeners(extensionId, changes);
-
- return this.write(extensionId);
- });
- },
-
- clear(extensionId) {
- return this.read(extensionId).then(extData => {
- let changes = {};
- for (let prop of Object.keys(extData)) {
- changes[prop] = {oldValue: extData[prop]};
- delete extData[prop];
- }
-
- this.notifyListeners(extensionId, changes);
-
- return this.write(extensionId);
- });
- },
-
- get(extensionId, keys) {
- return this.read(extensionId).then(extData => {
- let result = {};
- if (keys === null) {
- Object.assign(result, extData);
- } else if (typeof(keys) == "object" && !Array.isArray(keys)) {
- for (let prop in keys) {
- if (prop in extData) {
- result[prop] = extData[prop];
- } else {
- result[prop] = keys[prop];
- }
- }
- } else {
- for (let prop of [].concat(keys)) {
- if (prop in extData) {
- result[prop] = extData[prop];
- }
- }
- }
-
- return result;
- });
- },
-
- addOnChangedListener(extensionId, listener) {
- let listeners = this.listeners.get(extensionId) || new Set();
- listeners.add(listener);
- this.listeners.set(extensionId, listeners);
- },
-
- removeOnChangedListener(extensionId, listener) {
- let listeners = this.listeners.get(extensionId);
- listeners.delete(listener);
- },
-
- notifyListeners(extensionId, changes) {
- let listeners = this.listeners.get(extensionId);
- if (listeners) {
- for (let listener of listeners) {
- listener(changes);
- }
- }
- },
-
- init() {
- if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
- return;
- }
- Services.obs.addObserver(this, "extension-invalidate-storage-cache", false);
- Services.obs.addObserver(this, "xpcom-shutdown", false);
- },
-
- observe(subject, topic, data) {
- if (topic == "xpcom-shutdown") {
- Services.obs.removeObserver(this, "extension-invalidate-storage-cache");
- Services.obs.removeObserver(this, "xpcom-shutdown");
- } else if (topic == "extension-invalidate-storage-cache") {
- this.cache.clear();
- }
- },
-};
-
-XPCOMUtils.defineLazyGetter(ExtensionStorage, "extensionDir",
- () => OS.Path.join(OS.Constants.Path.profileDir, "browser-extension-data"));
-
-ExtensionStorage.init();