Bug 1456051 - Make addon an ES module. r?maja_zf draft
authorAndreas Tolfsen <ato@sny.no>
Mon, 23 Apr 2018 08:12:30 +0100
changeset 786521 d8ead6865f09b9eb1300eefcbf88cddc563bd2a1
parent 786520 dde46c4dfec5cb17059d07006bb3ea2f1bcecd9f
child 786522 e909b443fda6535b62887eae62a1763b72e0f5a4
child 786576 1a1068207e544a6cb30ce70d2cefb021f2c645e9
push id107501
push userbmo:ato@sny.no
push dateMon, 23 Apr 2018 14:06:07 +0000
reviewersmaja_zf
bugs1456051
milestone61.0a1
Bug 1456051 - Make addon an ES module. r?maja_zf This does not really functionally change anything, but it prevents us from polluting the global space in testing/marionette/driver.js. MozReview-Commit-ID: Guwt3g0lS8q
testing/marionette/addon.js
testing/marionette/doc/internals/addon.rst
testing/marionette/driver.js
--- a/testing/marionette/addon.js
+++ b/testing/marionette/addon.js
@@ -4,20 +4,17 @@
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
 
 const {UnknownError} = ChromeUtils.import("chrome://marionette/content/error.js", {});
 
-this.EXPORTED_SYMBOLS = ["addon"];
-
-/** @namespace */
-this.addon = {};
+this.EXPORTED_SYMBOLS = ["Addon"];
 
 // from https://developer.mozilla.org/en-US/Add-ons/Add-on_Manager/AddonManager#AddonInstall_errors
 const ERRORS = {
   [-1]: "ERROR_NETWORK_FAILURE: A network error occured.",
   [-2]: "ERROR_INCORECT_HASH: The downloaded file did not match the expected hash.",
   [-3]: "ERROR_CORRUPT_FILE: The file appears to be corrupt.",
   [-4]: "ERROR_FILE_ACCESS: There was an error accessing the filesystem.",
   [-5]: "ERROR_SIGNEDSTATE_REQUIRED: The addon must be signed and isn't.",
@@ -55,94 +52,98 @@ async function installAddon(file) {
       onInstallEnded: success,
     };
 
     install.addListener(listener);
     install.install();
   });
 }
 
-/**
- * Install a Firefox addon.
- *
- * If the addon is restartless, it can be used right away.  Otherwise a
- * restart is required.
- *
- * Temporary addons will automatically be uninstalled on shutdown and
- * do not need to be signed, though they must be restartless.
- *
- * @param {string} path
- *     Full path to the extension package archive.
- * @param {boolean=} temporary
- *     True to install the addon temporarily, false (default) otherwise.
- *
- * @return {Promise.<string>}
- *     Addon ID.
- *
- * @throws {UnknownError}
- *     If there is a problem installing the addon.
- */
-addon.install = async function(path, temporary = false) {
-  let addon;
-  let file;
+/** Installs addons by path and uninstalls by ID. */
+class Addon {
+  /**
+   * Install a Firefox addon.
+   *
+   * If the addon is restartless, it can be used right away.  Otherwise a
+   * restart is required.
+   *
+   * Temporary addons will automatically be uninstalled on shutdown and
+   * do not need to be signed, though they must be restartless.
+   *
+   * @param {string} path
+   *     Full path to the extension package archive.
+   * @param {boolean=} temporary
+   *     True to install the addon temporarily, false (default) otherwise.
+   *
+   * @return {Promise.<string>}
+   *     Addon ID.
+   *
+   * @throws {UnknownError}
+   *     If there is a problem installing the addon.
+   */
+  static async install(path, temporary = false) {
+    let addon;
+    let file;
 
-  try {
-    file = new FileUtils.File(path);
-  } catch (e) {
-    throw new UnknownError(`Expected absolute path: ${e}`, e);
-  }
+    try {
+      file = new FileUtils.File(path);
+    } catch (e) {
+      throw new UnknownError(`Expected absolute path: ${e}`, e);
+    }
+
+    if (!file.exists()) {
+      throw new UnknownError(`No such file or directory: ${path}`);
+    }
 
-  if (!file.exists()) {
-    throw new UnknownError(`No such file or directory: ${path}`);
+    try {
+      if (temporary) {
+        addon = await AddonManager.installTemporaryAddon(file);
+      } else {
+        addon = await installAddon(file);
+      }
+    } catch (e) {
+      throw new UnknownError(
+          `Could not install add-on: ${path}: ${e.message}`, e);
+    }
+
+    return addon.id;
   }
 
-  try {
-    if (temporary) {
-      addon = await AddonManager.installTemporaryAddon(file);
-    } else {
-      addon = await installAddon(file);
-    }
-  } catch (e) {
-    throw new UnknownError(
-        `Could not install add-on: ${path}: ${e.message}`, e);
-  }
-
-  return addon.id;
-};
+  /**
+   * Uninstall a Firefox addon.
+   *
+   * If the addon is restartless it will be uninstalled right away.
+   * Otherwise, Firefox must be restarted for the change to take effect.
+   *
+   * @param {string} id
+   *     ID of the addon to uninstall.
+   *
+   * @return {Promise}
+   *
+   * @throws {UnknownError}
+   *     If there is a problem uninstalling the addon.
+   */
+  static async uninstall(id) {
+    let candidate = await AddonManager.getAddonByID(id);
 
-/**
- * Uninstall a Firefox addon.
- *
- * If the addon is restartless it will be uninstalled right away.
- * Otherwise, Firefox must be restarted for the change to take effect.
- *
- * @param {string} id
- *     ID of the addon to uninstall.
- *
- * @return {Promise}
- *
- * @throws {UnknownError}
- *     If there is a problem uninstalling the addon.
- */
-addon.uninstall = async function(id) {
-  let candidate = await AddonManager.getAddonByID(id);
+    return new Promise(resolve => {
+      let listener = {
+        onOperationCancelled: addon => {
+          if (addon.id === candidate.id) {
+            AddonManager.removeAddonListener(listener);
+            throw new UnknownError(`Uninstall of ${candidate.id} has been canceled`);
+          }
+        },
 
-  return new Promise(resolve => {
-    let listener = {
-      onOperationCancelled: addon => {
-        if (addon.id === candidate.id) {
-          AddonManager.removeAddonListener(listener);
-          throw new UnknownError(`Uninstall of ${candidate.id} has been canceled`);
-        }
-      },
+        onUninstalled: addon => {
+          if (addon.id === candidate.id) {
+            AddonManager.removeAddonListener(listener);
+            resolve();
+          }
+        },
+      };
 
-      onUninstalled: addon => {
-        if (addon.id === candidate.id) {
-          AddonManager.removeAddonListener(listener);
-          resolve();
-        }
-      },
-    };
-
-    AddonManager.addAddonListener(listener);
-    addon.uninstall();
-  });
-};
+      AddonManager.addAddonListener(listener);
+      candidate.uninstall();
+    });
+  }
+}
+this.Addon = Addon;
--- a/testing/marionette/doc/internals/addon.rst
+++ b/testing/marionette/doc/internals/addon.rst
@@ -1,4 +1,7 @@
 addon module
 ============
-.. js:autoclass:: addon
+
+Addon
+-----
+.. js:autoclass:: Addon
   :members:
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -6,17 +6,17 @@
 /* global XPCNativeWrapper */
 
 ChromeUtils.import("resource://gre/modules/Log.jsm");
 ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 ChromeUtils.import("chrome://marionette/content/accessibility.js");
-ChromeUtils.import("chrome://marionette/content/addon.js");
+const {Addon} = ChromeUtils.import("chrome://marionette/content/addon.js", {});
 ChromeUtils.import("chrome://marionette/content/assert.js");
 ChromeUtils.import("chrome://marionette/content/atom.js");
 const {
   browser,
   Context,
   WindowState,
 } = ChromeUtils.import("chrome://marionette/content/browser.js", {});
 ChromeUtils.import("chrome://marionette/content/capture.js");
@@ -3291,28 +3291,28 @@ GeckoDriver.prototype.installAddon = fun
 
   let path = cmd.parameters.path;
   let temp = cmd.parameters.temporary || false;
   if (typeof path == "undefined" || typeof path != "string" ||
       typeof temp != "boolean") {
     throw new InvalidArgumentError();
   }
 
-  return addon.install(path, temp);
+  return Addon.install(path, temp);
 };
 
 GeckoDriver.prototype.uninstallAddon = function(cmd) {
   assert.firefox();
 
   let id = cmd.parameters.id;
   if (typeof id == "undefined" || typeof id != "string") {
     throw new InvalidArgumentError();
   }
 
-  return addon.uninstall(id);
+  return Addon.uninstall(id);
 };
 
 /** Receives all messages from content messageManager. */
 /* eslint-disable consistent-return */
 GeckoDriver.prototype.receiveMessage = function(message) {
   switch (message.name) {
     case "Marionette:switchedToFrame":
       if (message.json.restorePrevious) {