Bug 1287010 - Use schema-generated extension, split ext-extension.js r=billm
authorRob Wu <rob@robwu.nl>
Thu, 18 Aug 2016 19:19:40 -0700
changeset 311151 598895fae31d
parent 311150 2427f8eb4e83
child 311152 becfa1ce1bad
push id30602
push userkwierso@gmail.com
push date2016-08-25 23:53 +0000
treeherdermozilla-central@cd4ed9909dc9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1287010
milestone51.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 1287010 - Use schema-generated extension, split ext-extension.js r=billm - This was the last non-schema-generated API in content scripts. MozReview-Commit-ID: FaIOCHoircf
toolkit/components/extensions/Extension.jsm
toolkit/components/extensions/ExtensionContent.jsm
toolkit/components/extensions/ext-c-extension.js
toolkit/components/extensions/ext-extension.js
toolkit/components/extensions/extensions-toolkit.manifest
toolkit/components/extensions/jar.mn
toolkit/components/extensions/schemas/extension.json
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -174,27 +174,25 @@ var Management = new class extends Schem
 // (type="background"), popups (type="popup"), and any extension
 // content loaded into browser tabs (type="tab").
 //
 // |params| is an object with the following properties:
 // |type| is one of "background", "popup", or "tab".
 // |contentWindow| is the DOM window the content runs in.
 // |uri| is the URI of the content (optional).
 // |docShell| is the docshell the content runs in (optional).
-// |incognito| is the content running in a private context (default: false).
 ExtensionContext = class extends BaseContext {
   constructor(extension, params) {
     // TODO(robwu): This should be addon_child once all ext- files are split.
     // There should be a new ProxyContext instance with the "addon_parent" type.
     super("addon_parent", extension);
 
     let {type, uri} = params;
     this.type = type;
     this.uri = uri || extension.baseURI;
-    this.incognito = params.incognito || false;
 
     if (params.contentWindow) {
       this.setContentWindow(params.contentWindow);
     }
 
     // This is the MessageSender property passed to extension.
     // It can be augmented by the "page-open" hook.
     let sender = {id: extension.uuid};
@@ -697,19 +695,18 @@ GlobalManager = {
       // Options pages are currently displayed inline, but in Chrome
       // and in our UI mock-ups for a later milestone, they're
       // pop-ups.
       type = "popup";
     }
 
     let extension = this.extensionMap.get(id);
     let uri = document.documentURIObject;
-    let incognito = PrivateBrowsingUtils.isContentWindowPrivate(contentWindow);
 
-    let context = new ExtensionContext(extension, {type, contentWindow, uri, docShell, incognito});
+    let context = new ExtensionContext(extension, {type, contentWindow, uri, docShell});
     inject(context);
     if (type == "background") {
       this._initializeBackgroundPage(contentWindow);
     }
 
     let innerWindowID = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
 
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -28,32 +28,29 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
                                   "resource:///modules/translation/LanguageDetector.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
                                   "resource://gre/modules/MatchPattern.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MatchGlobs",
                                   "resource://gre/modules/MatchPattern.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
                                   "resource://gre/modules/MessageChannel.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
-                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
                                   "resource://gre/modules/WebNavigationFrames.jsm");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   runSafeSyncWithoutClone,
   BaseContext,
   LocaleData,
   Messenger,
-  injectAPI,
   flushJarCache,
   getInnerWindowID,
   promiseDocumentReady,
   ChildAPIManager,
   SchemaAPIManager,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole);
@@ -85,35 +82,16 @@ var apiManager = new class extends Schem
 
   registerSchemaAPI(namespace, envType, getAPI) {
     if (envType == "content_child") {
       super.registerSchemaAPI(namespace, envType, getAPI);
     }
   }
 };
 
-// This is the fairly simple API that we inject into content
-// scripts.
-var api = context => {
-  return {
-
-    extension: {
-      getURL: function(url) {
-        return context.extension.baseURI.resolve(url);
-      },
-
-      get lastError() {
-        return context.lastError;
-      },
-
-      inIncognitoContext: PrivateBrowsingUtils.isContentWindowPrivate(context.contentWindow),
-    },
-  };
-};
-
 // Represents a content script.
 function Script(extension, options, deferred = PromiseUtils.defer()) {
   this.extension = extension;
   this.options = options;
   this.run_at = this.options.run_at;
   this.js = this.options.js || [];
   this.css = this.options.css || [];
   this.remove_css = this.options.remove_css;
@@ -361,29 +339,25 @@ class ExtensionContext extends BaseConte
     this.messenger = new Messenger(this, [mm], sender, filter, delegate);
 
     this.chromeObj = Cu.createObjectIn(this.sandbox, {defineAs: "browser"});
 
     // Sandboxes don't get Xrays for some weird compatibility
     // reason. However, we waive here anyway in case that changes.
     Cu.waiveXrays(this.sandbox).chrome = this.chromeObj;
 
-    let incognito = PrivateBrowsingUtils.isContentWindowPrivate(this.contentWindow);
     let localApis = {};
     apiManager.generateAPIs(this, localApis);
     this.childManager = new ChildAPIManager(this, mm, localApis, {
       type: "content_script",
       url,
-      incognito,
     });
 
     Schemas.inject(this.chromeObj, this.childManager);
 
-    injectAPI(api(this), this.chromeObj);
-
     // This is an iframe with content script API enabled. (See Bug 1214658 for rationale)
     if (isExtensionPage) {
       Cu.waiveXrays(this.contentWindow).chrome = this.chromeObj;
       Cu.waiveXrays(this.contentWindow).browser = this.chromeObj;
     }
   }
 
   get cloneScope() {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/ext-c-extension.js
@@ -0,0 +1,25 @@
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
+
+function extensionApiFactory(context) {
+  return {
+    extension: {
+      getURL(url) {
+        return context.extension.baseURI.resolve(url);
+      },
+
+      get lastError() {
+        return context.lastError;
+      },
+
+      get inIncognitoContext() {
+        return PrivateBrowsingUtils.isContentWindowPrivate(context.contentWindow);
+      },
+    },
+  };
+}
+
+extensions.registerSchemaAPI("extension", "addon_child", extensionApiFactory);
+extensions.registerSchemaAPI("extension", "content_child", extensionApiFactory);
--- a/toolkit/components/extensions/ext-extension.js
+++ b/toolkit/components/extensions/ext-extension.js
@@ -1,18 +1,14 @@
 "use strict";
 
 extensions.registerSchemaAPI("extension", "addon_parent", context => {
   let {extension} = context;
   return {
     extension: {
-      getURL: function(url) {
-        return extension.baseURI.resolve(url);
-      },
-
       getViews: function(fetchProperties) {
         let result = Cu.cloneInto([], context.cloneScope);
 
         for (let view of extension.views) {
           if (!view.active) {
             continue;
           }
           if (fetchProperties !== null) {
@@ -27,23 +23,20 @@ extensions.registerSchemaAPI("extension"
 
           result.push(view.contentWindow);
         }
 
         return result;
       },
 
       get lastError() {
+        // TODO(robwu): See comment about lastError in ext-runtime.js
         return context.lastError;
       },
 
-      get inIncognitoContext() {
-        return context.incognito;
-      },
-
       isAllowedIncognitoAccess() {
         return Promise.resolve(true);
       },
 
       isAllowedFileSchemeAccess() {
         return Promise.resolve(false);
       },
     },
--- a/toolkit/components/extensions/extensions-toolkit.manifest
+++ b/toolkit/components/extensions/extensions-toolkit.manifest
@@ -10,16 +10,17 @@ category webextension-scripts idle chrom
 category webextension-scripts webRequest chrome://extensions/content/ext-webRequest.js
 category webextension-scripts webNavigation chrome://extensions/content/ext-webNavigation.js
 category webextension-scripts runtime chrome://extensions/content/ext-runtime.js
 category webextension-scripts extension chrome://extensions/content/ext-extension.js
 category webextension-scripts storage chrome://extensions/content/ext-storage.js
 category webextension-scripts test chrome://extensions/content/ext-test.js
 
 # scripts specific for content process.
+category webextension-scripts-content extension chrome://extensions/content/ext-c-extension.js
 category webextension-scripts-content i18n chrome://extensions/content/ext-i18n.js
 category webextension-scripts-content runtime chrome://extensions/content/ext-c-runtime.js
 
 # schemas
 category webextension-schemas alarms chrome://extensions/content/schemas/alarms.json
 category webextension-schemas cookies chrome://extensions/content/schemas/cookies.json
 category webextension-schemas downloads chrome://extensions/content/schemas/downloads.json
 category webextension-schemas events chrome://extensions/content/schemas/events.json
--- a/toolkit/components/extensions/jar.mn
+++ b/toolkit/components/extensions/jar.mn
@@ -13,9 +13,10 @@ toolkit.jar:
     content/extensions/ext-i18n.js
     content/extensions/ext-idle.js
     content/extensions/ext-webRequest.js
     content/extensions/ext-webNavigation.js
     content/extensions/ext-runtime.js
     content/extensions/ext-extension.js
     content/extensions/ext-storage.js
     content/extensions/ext-test.js
+    content/extensions/ext-c-extension.js
     content/extensions/ext-c-runtime.js
--- a/toolkit/components/extensions/schemas/extension.json
+++ b/toolkit/components/extensions/schemas/extension.json
@@ -1,46 +1,50 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 [
   {
     "namespace": "extension",
+    "restrictions": ["content"],
     "description": "The <code>browser.extension</code> API has utilities that can be used by any extension page. It includes support for exchanging messages between an extension and its content scripts or between extensions, as described in detail in $(topic:messaging)[Message Passing].",
     "properties": {
       "lastError": {
         "type": "object",
         "optional": true,
+        "restrictions": ["content"],
         "description": "Set for the lifetime of a callback if an ansychronous extension api has resulted in an error. If no error has occured lastError will be <var>undefined</var>.",
         "properties": {
           "message": { "type": "string", "description": "Description of the error that has taken place." }
         },
         "additionalProperties": {
           "type": "any"
         }
       },
       "inIncognitoContext": {
         "type": "boolean",
         "optional": true,
+        "restrictions": ["content"],
         "description": "True for content scripts running inside incognito tabs, and for extension pages running inside an incognito process. The latter only applies to extensions with 'split' incognito_behavior."
       }
     },
     "types": [
       {
         "id": "ViewType",
         "type": "string",
         "enum": ["tab", "notification", "popup"],
         "description": "The type of extension view."
       }
     ],
     "functions": [
       {
         "name": "getURL",
         "type": "function",
+        "restrictions": ["content"],
         "description": "Converts a relative path within an extension install directory to a fully-qualified URL.",
         "parameters": [
           {
             "type": "string",
             "name": "path",
             "description": "A path to a resource within an extension expressed relative to its install directory."
           }
         ],