Bug 1460047 - 1. Assign module resource to phases; r?esawin draft
authorJim Chen <nchen@mozilla.com>
Fri, 11 May 2018 14:59:50 -0400
changeset 794353 f4a79a066cfea022dc5138c7cda2bec361bbad4f
parent 794352 704cf5e7a7a597071b11b182c96caf66008f49b2
child 794354 68084e111f7f1651a44b3914995bf8124985c5e8
push id109650
push userbmo:nchen@mozilla.com
push dateFri, 11 May 2018 19:02:41 +0000
reviewersesawin
bugs1460047
milestone62.0a1
Bug 1460047 - 1. Assign module resource to phases; r?esawin Assign a module's .jsm resource to either the init phase or the enable phase, so that it's possible to delay loading the module resource until it is enabled. MozReview-Commit-ID: 4k8djPyG9Pq
mobile/android/chrome/geckoview/geckoview.js
--- a/mobile/android/chrome/geckoview/geckoview.js
+++ b/mobile/android/chrome/geckoview/geckoview.js
@@ -12,21 +12,22 @@ XPCOMUtils.defineLazyModuleGetters(this,
   Services: "resource://gre/modules/Services.jsm",
 });
 
 XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher",
   () => EventDispatcher.for(window));
 
 /**
  * ModuleManager creates and manages GeckoView modules. Each GeckoView module
- * normally consists of a JSM file with an optional frame script file. The JSM
- * file contains a class that extends GeckoViewModule. A module usually pairs
- * with a particular GeckoSessionHandler or delegate on the Java side, and
- * automatically receives module lifetime events such as initialization, change
- * in enabled state, and change in settings.
+ * normally consists of a JSM module file with an optional content module file.
+ * The module file contains a class that extends GeckoViewModule, and the
+ * content module file contains a class that extends GeckoViewContentModule. A
+ * module usually pairs with a particular GeckoSessionHandler or delegate on the
+ * Java side, and automatically receives module lifetime events such as
+ * initialization, change in enabled state, and change in settings.
  */
 var ModuleManager = {
   get _initData() {
     return window.arguments[0].QueryInterface(Ci.nsIAndroidView).initData;
   },
 
   init(aBrowser, aModules) {
     const initData = this._initData;
@@ -128,36 +129,63 @@ var ModuleManager = {
 
 /**
  * ModuleInfo is the structure used by ModuleManager to represent individual
  * modules. It is responsible for loading the module JSM file if necessary,
  * and it acts as the intermediary between ModuleManager and the module
  * object that extends GeckoViewModule.
  */
 class ModuleInfo {
-  constructor({enabled, manager, name, resource}) {
+  /**
+   * Create a ModuleInfo instance. See _loadPhase for phase object description.
+   *
+   * @param manager the ModuleManager instance.
+   * @param name Name of the module.
+   * @param enabled Enabled state of the module at startup.
+   * @param onInit Phase object for the init phase, when the window is created.
+   * @param onEnable Phase object for the enable phase, when the module is first
+   *                 enabled by setting a delegate in Java.
+   */
+  constructor({manager, name, enabled, onInit, onEnable}) {
     this._manager = manager;
     this._name = name;
 
-    const scope = {};
-    const global = ChromeUtils.import(resource, scope);
-    const tag = name.replace("GeckoView", "GeckoView.");
-    GeckoViewUtils.initLogging(tag, global);
-
-    this._impl = new scope[name](this);
+    this._impl = null;
     this._enabled = false;
     // Only enable once we performed initialization.
     this._enabledOnInit = enabled;
+
+    this._loadPhase(onInit);
+    this._onEnablePhase = onEnable;
   }
 
   onInit() {
     this._impl.onInit();
     this.enabled = this._enabledOnInit;
   }
 
+  /**
+   * Load resources according to a phase object that contains possible keys,
+   *
+   * "resource": specify the JSM resource to load for this module.
+   */
+  _loadPhase(aPhase) {
+    if (!aPhase) {
+      return;
+    }
+
+    if (aPhase.resource && !this._impl) {
+      const scope = {};
+      const global = ChromeUtils.import(aPhase.resource, scope);
+      const tag = this._name.replace("GeckoView", "GeckoView.");
+      GeckoViewUtils.initLogging(tag, global);
+      this._impl = new scope[this._name](this);
+    }
+  }
+
   get manager() {
     return this._manager;
   }
 
   get name() {
     return this._name;
   }
 
@@ -176,16 +204,18 @@ class ModuleInfo {
 
     if (!aEnabled) {
       this._impl.onDisable();
     }
 
     this._enabled = aEnabled;
 
     if (aEnabled) {
+      this._loadPhase(this._onEnablePhase);
+      this._onEnablePhase = null;
       this._impl.onEnable();
       this._impl.onSettingsUpdate();
     }
 
     this._manager.messageManager.sendAsyncMessage("GeckoView:UpdateModuleState", {
       module: this._name,
       enabled: aEnabled,
       settings: aEnabled ? this._manager.settings : null,
@@ -202,41 +232,59 @@ function createBrowser() {
 }
 
 function startup() {
   GeckoViewUtils.initLogging("GeckoView.XUL", window);
 
   const browser = createBrowser();
   ModuleManager.init(browser, [{
     name: "GeckoViewAccessibility",
-    resource: "resource://gre/modules/GeckoViewAccessibility.jsm",
+    onInit: {
+      resource: "resource://gre/modules/GeckoViewAccessibility.jsm",
+    },
   }, {
     name: "GeckoViewContent",
-    resource: "resource://gre/modules/GeckoViewContent.jsm",
+    onInit: {
+      resource: "resource://gre/modules/GeckoViewContent.jsm",
+    },
   }, {
     name: "GeckoViewNavigation",
-    resource: "resource://gre/modules/GeckoViewNavigation.jsm",
+    onInit: {
+      resource: "resource://gre/modules/GeckoViewNavigation.jsm",
+    },
   }, {
     name: "GeckoViewProgress",
-    resource: "resource://gre/modules/GeckoViewProgress.jsm",
+    onEnable: {
+      resource: "resource://gre/modules/GeckoViewProgress.jsm",
+    },
   }, {
     name: "GeckoViewScroll",
-    resource: "resource://gre/modules/GeckoViewScroll.jsm",
+    onEnable: {
+      resource: "resource://gre/modules/GeckoViewScroll.jsm",
+    },
   }, {
     name: "GeckoViewSelectionAction",
-    resource: "resource://gre/modules/GeckoViewSelectionAction.jsm",
+    onEnable: {
+      resource: "resource://gre/modules/GeckoViewSelectionAction.jsm",
+    },
   }, {
     name: "GeckoViewSettings",
-    resource: "resource://gre/modules/GeckoViewSettings.jsm",
+    onInit: {
+      resource: "resource://gre/modules/GeckoViewSettings.jsm",
+    },
   }, {
     name: "GeckoViewTab",
-    resource: "resource://gre/modules/GeckoViewTab.jsm",
+    onInit: {
+      resource: "resource://gre/modules/GeckoViewTab.jsm",
+    },
   }, {
     name: "GeckoViewTrackingProtection",
-    resource: "resource://gre/modules/GeckoViewTrackingProtection.jsm",
+    onEnable: {
+      resource: "resource://gre/modules/GeckoViewTrackingProtection.jsm",
+    },
   }]);
 
   window.document.documentElement.appendChild(browser);
 
   ModuleManager.forEach(module => {
     module.onInit();
   });