Bug 1295082 - Minor fixups for experimental WebExtensions APIs draft
authorRob Wu <rob@robwu.nl>
Thu, 18 Aug 2016 13:58:30 -0700
changeset 402852 13aac7cebc1b0798039faaaf9e385a9c2dab2bb9
parent 402851 5cd13b548e7f59a03a842d351db35bb21ed7ba4d
child 528771 c9ca95ca95123414ec57f817c61f8d14e5f7e092
push id26766
push userbmo:rob@robwu.nl
push dateThu, 18 Aug 2016 20:59:39 +0000
bugs1295082
milestone51.0a1
Bug 1295082 - Minor fixups for experimental WebExtensions APIs - Remove unused registerAPI and registerPrivilegedAPI - Generate the APIs just once. - Fix typo in addon ID. MozReview-Commit-ID: rdiiIxHMsm
toolkit/components/extensions/Extension.jsm
toolkit/components/extensions/ExtensionAPI.jsm
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -115,17 +115,16 @@ const COMMENT_REGEXP = new RegExp(String
 var scriptScope = this;
 
 var ExtensionContext, GlobalManager;
 
 // This object loads the ext-*.js scripts that define the extension API.
 var Management = {
   initialized: null,
   scopes: [],
-  apis: [],
   schemaApis: [],
   emitter: new EventEmitter(),
 
   // Loads all the ext-*.js scripts currently registered.
   lazyInit() {
     if (this.initialized) {
       return this.initialized;
     }
@@ -157,37 +156,35 @@ var Management = {
       // Save the scope to avoid it being garbage collected.
       this.scopes.push(scope);
     }
 
     this.initialized = promise;
     return this.initialized;
   },
 
-  // Called by an ext-*.js script to register an API. The |api|
-  // parameter should be an object of the form:
-  // {
-  //   tabs: {
-  //     create: ...,
-  //     onCreated: ...
-  //   }
-  // }
-  // This registers tabs.create and tabs.onCreated as part of the API.
-  registerAPI(api) {
-    this.apis.push({api});
-  },
-
-  // Same as above, but only register the API is the add-on has the
-  // given permission.
-  registerPrivilegedAPI(permission, api) {
-    this.apis.push({api, permission});
-  },
-
-  registerSchemaAPI(namespace, api) {
-    this.schemaApis.push({namespace, api});
+  /**
+   * Called by an ext-*.js script to register an API.
+   *
+   * @param {string} namespace The API namespace.
+   *     Used to determine whether the API should be generated when the caller
+   *     requests a subset of the available APIs (e.g. in content scripts).
+   * @param {function(BaseContext)} getAPI A function that returns an object
+   *     that will be merged with |chrome| and |browser|. The next example adds
+   *     the create, update and remove methods to the tabs API.
+   *
+   *     registerSchemaAPI("tabs", (context) => ({
+   *       tabs: { create, update },
+   *     }));
+   *     registerSchemaAPI("tabs", (context) => ({
+   *       tabs: { remove },
+   *     }));
+   */
+  registerSchemaAPI(namespace, getAPI) {
+    this.schemaApis.push({namespace, getAPI});
   },
 
   // Mash together into a single object all the APIs registered by the
   // functions above. Return the merged object.
   generateAPIs(context, apis, namespaces = null) {
     let obj = {};
 
     // Recursively copy properties from source to dest.
@@ -210,24 +207,19 @@ var Management = {
         continue;
       }
       if (api.permission) {
         if (!context.extension.hasPermission(api.permission)) {
           continue;
         }
       }
 
-      api = api.api(context);
+      api = api.getAPI(context);
       copy(obj, api);
     }
-
-    for (let api of context.extension.apis) {
-      copy(obj, api.getAPI(context));
-    }
-
     return obj;
   },
 
   // The ext-*.js scripts can ask to be notified for certain hooks.
   on(hook, callback) {
     this.emitter.on(hook, callback);
   },
 
@@ -630,19 +622,16 @@ GlobalManager = {
     }
   },
 
   getExtension(extensionId) {
     return this.extensionMap.get(extensionId);
   },
 
   injectInObject(context, defaultCallback, dest, namespaces = null) {
-    let api = Management.generateAPIs(context, Management.apis, namespaces);
-    injectAPI(api, dest);
-
     let schemaApi = Management.generateAPIs(context, Management.schemaApis, namespaces);
 
     // Add in any extra API namespaces which do not have implementations
     // outside of their schema file.
     schemaApi.extensionTypes = {};
 
     let schemaWrapper = {
       get principal() {
@@ -704,16 +693,19 @@ GlobalManager = {
       removeListener(path, name, listener) {
         return findPathInObject(schemaApi, path)[name].removeListener.call(null, listener);
       },
       hasListener(path, name, listener) {
         return findPathInObject(schemaApi, path)[name].hasListener.call(null, listener);
       },
     };
     Schemas.inject(dest, schemaWrapper);
+
+    let experimentalApis = Management.generateAPIs(context, context.extension.apis, namespaces);
+    injectAPI(experimentalApis, dest);
   },
 
   observe(document, topic, data) {
     let contentWindow = document.defaultView;
     if (!contentWindow) {
       return;
     }
 
--- a/toolkit/components/extensions/ExtensionAPI.jsm
+++ b/toolkit/components/extensions/ExtensionAPI.jsm
@@ -43,17 +43,17 @@ var ExtensionAPIs = {
     let api = this.apis.get(apiName);
 
     if (api.loadPromise) {
       return api.loadPromise;
     }
 
     let {script, schema} = api;
 
-    let addonId = `${api}@experiments.addons.mozilla.org`;
+    let addonId = `${apiName}@experiments.addons.mozilla.org`;
     api.sandbox = Cu.Sandbox(global, {
       wantXrays: false,
       sandboxName: script,
       addonId,
       metadata: {addonID: addonId},
     });
 
     api.sandbox.ExtensionAPI = ExtensionAPI;