Bug 1423425 Make some extensions comments jsdoc-compatible r=kmag
☠☠ backed out by bb75be81efa6 ☠ ☠
authorAndrew Swan <aswan@mozilla.com>
Tue, 05 Dec 2017 18:53:15 -0800
changeset 448347 d64fd69a4b8866c93f67690d0357ccdda6a9ccdd
parent 448346 04017639642aeda22eeee2034deeca3a10de0653
child 448348 c3ac950b0b8a71e4e5fbb478cdceb6a2777d66c0
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1423425
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1423425 Make some extensions comments jsdoc-compatible r=kmag MozReview-Commit-ID: 3mUKR9IuEKA
toolkit/components/extensions/Extension.jsm
toolkit/components/extensions/ExtensionCommon.jsm
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -275,25 +275,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;
@@ -314,21 +316,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);
@@ -956,33 +965,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;
   }
@@ -1003,29 +1013,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);
@@ -1108,16 +1122,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) {
@@ -1347,16 +1368,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);
   }
 
@@ -1646,19 +1676,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();
@@ -1749,9 +1779,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
@@ -80,16 +80,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) {
@@ -172,16 +177,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;
@@ -1515,37 +1527,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;
 }