Bug 1213990 Convert getExtensionUUID to UUIDMap r?kmag
MozReview-Commit-ID: 9VVNa0pjx8g
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -83,16 +83,17 @@ var {
LocaleData,
Messenger,
injectAPI,
instanceOf,
flushJarCache,
} = ExtensionUtils;
const LOGGER_ID_BASE = "addons.webextension.";
+const UUID_MAP_PREF = "extensions.webextensions.uuids";
const COMMENT_REGEXP = new RegExp(String.raw`
^
(
(?:
[^"] |
" (?:[^"\\] | \\.)* "
)*?
@@ -470,16 +471,70 @@ let ParentAPIManager = {
let ref = data.path.concat(data.name).join(".");
let listener = context.listenerProxies.get(ref);
findPathInObject(context.apiObj, data.path)[data.name].removeListener(listener);
},
};
ParentAPIManager.init();
+// All moz-extension URIs use a machine-specific UUID rather than the
+// extension's own ID in the host component. This makes it more
+// difficult for web pages to detect whether a user has a given add-on
+// installed (by trying to load a moz-extension URI referring to a
+// web_accessible_resource from the extension). UUIDMap.get()
+// returns the UUID for a given add-on ID.
+var UUIDMap = {
+ _read() {
+ let pref = Preferences.get(UUID_MAP_PREF, "{}");
+ try {
+ return JSON.parse(pref);
+ } catch (e) {
+ Cu.reportError(`Error parsing ${UUID_MAP_PREF}.`);
+ return {};
+ }
+ },
+
+ _write(map) {
+ Preferences.set(UUID_MAP_PREF, JSON.stringify(map));
+ },
+
+ get(id, create = true) {
+ let map = this._read();
+
+ if (id in map) {
+ return map[id];
+ }
+
+ let uuid = null;
+ if (create) {
+ let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+ uuid = uuidGenerator.generateUUID().number;
+ uuid = uuid.slice(1, -1); // Strip { and } off the UUID.
+
+ map[id] = uuid;
+ this._write(map);
+ }
+ return uuid;
+ },
+
+ remove(id) {
+ let map = this._read();
+ delete map[id];
+ this._write(map);
+ },
+};
+
+// This is the old interface that UUIDMap replaced, to be removed when
+// the references listed in bug 1291399 are updated.
+/* exported getExtensionUUID */
+function getExtensionUUID(id) {
+ return UUIDMap.get(id, true);
+}
+
// For extensions that have called setUninstallURL(), send an event
// so the browser can display the URL.
var UninstallObserver = {
initialized: false,
init: function() {
if (!this.initialized) {
AddonManager.addAddonListener(this);
@@ -703,46 +758,16 @@ GlobalManager = {
}
contentWindow.console.log(text);
};
Cu.exportFunction(alertOverwrite, contentWindow, {defineAs: "alert"});
},
};
-// All moz-extension URIs use a machine-specific UUID rather than the
-// extension's own ID in the host component. This makes it more
-// difficult for web pages to detect whether a user has a given add-on
-// installed (by trying to load a moz-extension URI referring to a
-// web_accessible_resource from the extension). getExtensionUUID
-// returns the UUID for a given add-on ID.
-function getExtensionUUID(id) {
- const PREF_NAME = "extensions.webextensions.uuids";
-
- let pref = Preferences.get(PREF_NAME, "{}");
- let map = {};
- try {
- map = JSON.parse(pref);
- } catch (e) {
- Cu.reportError(`Error parsing ${PREF_NAME}.`);
- }
-
- if (id in map) {
- return map[id];
- }
-
- let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
- let uuid = uuidGenerator.generateUUID().number;
- uuid = uuid.slice(1, -1); // Strip { and } off the UUID.
-
- map[id] = uuid;
- Preferences.set(PREF_NAME, JSON.stringify(map));
- return uuid;
-}
-
// Represents the data contained in an extension, contained either
// in a directory or a zip file, which may or may not be installed.
// This class implements the functionality of the Extension class,
// primarily related to manifest parsing and localization, which is
// useful prior to extension installation or initialization.
//
// No functionality of this class is guaranteed to work before
// |readManifest| has been called, and completed.
@@ -793,17 +818,17 @@ this.ExtensionData = class {
* @param {string} path The path portion of the URL.
* @returns {string}
*/
getURL(path = "") {
if (!(this.id || this.uuid)) {
throw new Error("getURL may not be called before an `id` or `uuid` has been set");
}
if (!this.uuid) {
- this.uuid = getExtensionUUID(this.id);
+ this.uuid = UUIDMap.get(this.id);
}
return `moz-extension://${this.uuid}/${path}`;
}
readDirectory(path) {
return Task.spawn(function* () {
if (this.rootURI instanceof Ci.nsIFileURL) {
let uri = NetUtil.newURI(this.rootURI.resolve("./" + path));
@@ -1184,17 +1209,17 @@ class MockExtension {
}
// We create one instance of this class per extension. |addonData|
// comes directly from bootstrap.js when initializing.
this.Extension = class extends ExtensionData {
constructor(addonData) {
super(addonData.resourceURI);
- this.uuid = getExtensionUUID(addonData.id);
+ this.uuid = UUIDMap.get(addonData.id);
if (addonData.cleanupFile) {
Services.obs.addObserver(this, "xpcom-shutdown", false);
this.cleanupFile = addonData.cleanupFile || null;
delete addonData.cleanupFile;
}
this.addonData = addonData;