Bug 1423425 Make some extensions comments jsdoc-compatible
MozReview-Commit-ID: 3mUKR9IuEKA
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -274,25 +274,27 @@ var UninstallObserver = {
// Clear the entry in the UUID map
UUIDMap.remove(addon.id);
}
},
};
UninstallObserver.init();
-// 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
-// |loadManifest| has been called, and completed.
-this.ExtensionData = class {
+/**
+ * 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
+ * `loadManifest` has been called, and completed.
+ */
+class ExtensionData {
constructor(rootURI) {
this.rootURI = rootURI;
this.resourceURL = rootURI.spec;
this.manifest = null;
this.type = null;
this.id = null;
this.uuid = null;
@@ -313,21 +315,28 @@ this.ExtensionData = class {
return null;
}
get logger() {
let id = this.id || "<unknown>";
return Log.repository.getLogger(LOGGER_ID_BASE + id);
}
- // Report an error about the extension's manifest file.
+ /**
+ * Report an error about the extension's manifest file.
+ * @param {string} message The error message
+ */
manifestError(message) {
this.packagingError(`Reading manifest: ${message}`);
}
+ /**
+ * Report a warning about the extension's manifest file.
+ * @param {string} message The warning message
+ */
manifestWarning(message) {
this.packagingWarning(`Reading manifest: ${message}`);
}
// Report an error about the extension's general packaging.
packagingError(message) {
this.errors.push(message);
this.logError(message);
@@ -955,33 +964,34 @@ this.ExtensionData = class {
if (haveAccessKeys) {
result.acceptKey = bundle.GetStringFromName("webextPerms.optionalPermsAllow.accessKey");
result.cancelKey = bundle.GetStringFromName("webextPerms.optionalPermsDeny.accessKey");
}
}
return result;
}
-};
+}
const PROXIED_EVENTS = new Set(["test-harness-message", "add-permissions", "remove-permissions"]);
const shutdownPromises = new Map();
class BootstrapScope {
install(data, reason) {}
uninstall(data, reason) {
Management.emit("uninstall", {id: data.id});
}
update(data, reason) {
Management.emit("update", {id: data.id, resourceURI: data.resourceURI});
}
startup(data, reason) {
+ // eslint-disable-next-line no-use-before-define
this.extension = new Extension(data, this.BOOTSTRAP_REASON_TO_STRING_MAP[reason]);
return this.extension.startup();
}
shutdown(data, reason) {
this.extension.shutdown(this.BOOTSTRAP_REASON_TO_STRING_MAP[reason]);
this.extension = null;
}
@@ -1002,29 +1012,33 @@ XPCOMUtils.defineLazyGetter(BootstrapSco
});
});
class LangpackBootstrapScope {
install(data, reason) {}
uninstall(data, reason) {}
startup(data, reason) {
+ // eslint-disable-next-line no-use-before-define
this.langpack = new Langpack(data);
return this.langpack.startup();
}
shutdown(data, reason) {
this.langpack.shutdown();
this.langpack = null;
}
}
-// We create one instance of this class per extension. |addonData|
-// comes directly from bootstrap.js when initializing.
-this.Extension = class extends ExtensionData {
+/**
+ * This class is the main representation of an active WebExtension
+ * in the main process.
+ * @extends ExtensionData
+ */
+class Extension extends ExtensionData {
constructor(addonData, startupReason) {
super(addonData.resourceURI);
this.uuid = UUIDMap.get(addonData.id);
this.instanceId = getUniqueId();
this.MESSAGE_EMIT_EVENT = `Extension:EmitEvent:${this.instanceId}`;
Services.ppmm.addMessageListener(this.MESSAGE_EMIT_EVENT, this);
@@ -1107,16 +1121,23 @@ this.Extension = class extends Extension
this.policy.permissions = Array.from(this.permissions);
this.policy.allowedOrigins = this.whiteListedHosts;
this.cachePermissions();
});
/* eslint-enable mozilla/balanced-listeners */
}
+ // Some helpful properties added elsewhere:
+ /**
+ * An object used to map between extension-visible tab ids and
+ * native Tab object
+ * @property {TabManager} tabManager
+ */
+
static getBootstrapScope(id, file) {
return new BootstrapScope();
}
get groupFrameLoader() {
let frameLoader = this._backgroundPageFrameLoader;
for (let view of this.views) {
if (view.viewType === "background" && view.xulBrowser) {
@@ -1346,16 +1367,25 @@ this.Extension = class extends Extension
data["Extension:Extensions"].push(serial);
return this.broadcast("Extension:Startup", serial).then(() => {
return Promise.all(promises);
});
}
+ /**
+ * Call the close() method on the given object when this extension
+ * is shut down. This can happen during browser shutdown, or when
+ * an extension is manually disabled or uninstalled.
+ *
+ * @param {object} obj
+ * An object on which to call the close() method when this
+ * extension is shut down.
+ */
callOnClose(obj) {
this.onShutdown.add(obj);
}
forgetOnClose(obj) {
this.onShutdown.delete(obj);
}
@@ -1645,19 +1675,19 @@ this.Extension = class extends Extension
get optionalOrigins() {
if (this._optionalOrigins == null) {
let origins = this.manifest.optional_permissions.filter(perm => classifyPermission(perm).origin);
this._optionalOrigins = new MatchPatternSet(origins, {ignorePath: true});
}
return this._optionalOrigins;
}
-};
+}
-this.Langpack = class extends ExtensionData {
+class Langpack extends ExtensionData {
constructor(addonData, startupReason) {
super(addonData.resourceURI);
this.startupData = addonData.startupData;
this.manifestCacheKey = [addonData.id, addonData.version];
}
static getBootstrapScope(id, file) {
return new LangpackBootstrapScope();
@@ -1748,9 +1778,9 @@ this.Langpack = class extends ExtensionD
}
if (this.chromeRegistryHandle) {
this.chromeRegistryHandle.destruct();
this.chromeRegistryHandle = null;
}
resourceProtocol.setSubstitution(this.langpackId, null);
}
-};
+}
--- a/toolkit/components/extensions/ExtensionCommon.jsm
+++ b/toolkit/components/extensions/ExtensionCommon.jsm
@@ -78,16 +78,21 @@ class NoCloneSpreadArgs {
this.unwrappedValues = args;
}
[Symbol.iterator]() {
return this.unwrappedValues[Symbol.iterator]();
}
}
+/**
+ * Base class for WebExtension APIs. Each API creates a new class
+ * that inherits from this class, the derived class is instantiated
+ * once for each extension that uses the API.
+ */
class ExtensionAPI extends ExtensionUtils.EventEmitter {
constructor(extension) {
super();
this.extension = extension;
extension.once("shutdown", () => {
if (this.onShutdown) {
@@ -170,16 +175,23 @@ var ExtensionAPIs = {
if (!this.apis.has(namespace)) {
throw new Error(`API namespace does not exist: ${namespace}`);
}
this.apis.delete(namespace);
},
};
+/**
+ * This class contains the information we have about an individual
+ * extension. It is never instantiated directly, instead subclasses
+ * for each type of process extend this class and add members that are
+ * relevant for that process.
+ * @abstract
+ */
class BaseContext {
constructor(envType, extension) {
this.envType = envType;
this.onClose = new Set();
this.checkedLastError = false;
this._lastError = null;
this.contextId = getUniqueId();
this.unloaded = false;
@@ -1513,37 +1525,48 @@ LocaleData.prototype = {
},
};
defineLazyGetter(LocaleData.prototype, "availableLocales", function() {
return new Set([this.BUILTIN, this.selectedLocale, this.defaultLocale]
.filter(locale => this.messages.has(locale)));
});
-// This is a generic class for managing event listeners. Example usage:
-//
-// new EventManager(context, "api.subAPI", fire => {
-// let listener = (...) => {
-// // Fire any listeners registered with addListener.
-// fire.async(arg1, arg2);
-// };
-// // Register the listener.
-// SomehowRegisterListener(listener);
-// return () => {
-// // Return a way to unregister the listener.
-// SomehowUnregisterListener(listener);
-// };
-// }).api()
-//
-// The result is an object with addListener, removeListener, and
-// hasListener methods. |context| is an add-on scope (either an
-// ExtensionContext in the chrome process or ExtensionContext in a
-// content process). |name| is for debugging. |register| is a function
-// to register the listener. |register| should return an
-// unregister function that will unregister the listener.
+/**
+* This is a generic class for managing event listeners.
+ *
+ * @example
+ * new EventManager(context, "api.subAPI", fire => {
+ * let listener = (...) => {
+ * // Fire any listeners registered with addListener.
+ * fire.async(arg1, arg2);
+ * };
+ * // Register the listener.
+ * SomehowRegisterListener(listener);
+ * return () => {
+ * // Return a way to unregister the listener.
+ * SomehowUnregisterListener(listener);
+ * };
+ * }).api()
+ *
+ * The result is an object with addListener, removeListener, and
+ * hasListener methods. `context` is an add-on scope (either an
+ * ExtensionContext in the chrome process or ExtensionContext in a
+ * content process). `name` is for debugging. `register` is a function
+ * to register the listener. `register` should return an
+ * unregister function that will unregister the listener.
+ * @constructor
+ *
+ * @param {BaseContext} context
+ * An object representing the extension instance using this event.
+ * @param {string} name
+ * A name used only for debugging.
+ * @param {functon} register
+ * A function called whenever a new listener is added.
+ */
function EventManager(context, name, register) {
this.context = context;
this.name = name;
this.register = register;
this.unregister = new Map();
this.inputHandling = false;
}