[Centaury] Remove ExtensionStorage.jsm duplicate after re-import.
parent
9d107e0c8c
commit
2c2e50bc2c
|
@ -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();
|
|
@ -10,7 +10,6 @@ EXTRA_JS_MODULES += [
|
|||
'ExtensionCommon.jsm',
|
||||
'ExtensionContent.jsm',
|
||||
'ExtensionManagement.jsm',
|
||||
'ExtensionStorage.jsm',
|
||||
'LegacyExtensionsUtils.jsm',
|
||||
'MessageChannel.jsm',
|
||||
'Schemas.jsm',
|
||||
|
|
Loading…
Reference in New Issue