Bug 1389861: Remove needless overhead from same-process policy initialization. r?zombie draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 12 Aug 2017 17:21:27 -0700
changeset 645487 1d214d1e82b73e28905303292fab47706a7c5aea
parent 645486 5d2a0f2ddf46608e61a16f016524c3dd6243cd06
child 725906 d3785c7612fdad3d47d18b5306cfc766114e7660
push id73764
push usermaglione.k@gmail.com
push dateSun, 13 Aug 2017 00:21:48 +0000
reviewerszombie
bugs1389861
milestone57.0a1
Bug 1389861: Remove needless overhead from same-process policy initialization. r?zombie MozReview-Commit-ID: 3E7hnNnk46D
toolkit/components/extensions/Extension.jsm
toolkit/components/extensions/ExtensionChild.jsm
toolkit/components/extensions/extension-process-script.js
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -287,16 +287,17 @@ UninstallObserver.init();
 // 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 {
   constructor(rootURI) {
     this.rootURI = rootURI;
+    this.resourceURL = rootURI.spec;
 
     this.manifest = null;
     this.id = null;
     this.uuid = null;
     this.localeData = null;
     this._promiseLocales = null;
 
     this.apiNames = new Set();
@@ -1004,28 +1005,32 @@ this.Extension = class extends Extension
   // processes. This should include anything the content process might
   // need.
   serialize() {
     return {
       id: this.id,
       uuid: this.uuid,
       instanceId: this.instanceId,
       manifest: this.manifest,
-      resourceURL: this.addonData.resourceURI.spec,
+      resourceURL: this.resourceURL,
       baseURL: this.baseURI.spec,
-      content_scripts: this.manifest.content_scripts || [],  // eslint-disable-line camelcase
+      contentScripts: this.contentScripts,
       webAccessibleResources: this.webAccessibleResources.map(res => res.glob),
       whiteListedHosts: this.whiteListedHosts.patterns.map(pat => pat.pattern),
       localeData: this.localeData.serialize(),
       permissions: this.permissions,
       principal: this.principal,
       optionalPermissions: this.manifest.optional_permissions,
     };
   }
 
+  get contentScripts() {
+    return this.manifest.content_scripts || [];
+  }
+
   broadcast(msg, data) {
     return new Promise(resolve => {
       let {ppmm} = Services;
       let children = new Set();
       for (let i = 0; i < ppmm.childCount; i++) {
         children.add(ppmm.getChildAt(i));
       }
 
@@ -1192,17 +1197,17 @@ this.Extension = class extends Extension
 
       if (this.hasShutdown) {
         return;
       }
 
       GlobalManager.init(this);
 
       this.policy.active = false;
-      this.policy = processScript.initExtension(this.serialize(), this);
+      this.policy = processScript.initExtension(this);
 
       this.updatePermissions(this.startupReason);
 
       // The "startup" Management event sent on the extension instance itself
       // is emitted just before the Management "startup" event,
       // and it is used to run code that needs to be executed before
       // any of the "startup" listeners.
       this.emit("startup", this);
--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -494,17 +494,17 @@ class BrowserExtensionContent extends Ev
     this.id = data.id;
     this.uuid = data.uuid;
     this.instanceId = data.instanceId;
 
     this.MESSAGE_EMIT_EVENT = `Extension:EmitEvent:${this.instanceId}`;
     Services.cpmm.addMessageListener(this.MESSAGE_EMIT_EVENT, this);
 
     defineLazyGetter(this, "scripts", () => {
-      return data.content_scripts.map(scriptData => new ExtensionContent.Script(this, scriptData));
+      return data.contentScripts.map(scriptData => new ExtensionContent.Script(this, scriptData));
     });
 
     this.webAccessibleResources = data.webAccessibleResources.map(res => new MatchGlob(res));
     this.whiteListedHosts = new MatchPatternSet(data.whiteListedHosts, {ignorePath: true});
     this.permissions = data.permissions;
     this.optionalPermissions = data.optionalPermissions;
     this.principal = data.principal;
 
--- a/toolkit/components/extensions/extension-process-script.js
+++ b/toolkit/components/extensions/extension-process-script.js
@@ -49,17 +49,22 @@ function parseScriptOptions(options) {
     excludeGlobs: options.exclude_globs && options.exclude_globs.map(glob => new MatchGlob(glob)),
 
     jsPaths: options.js || [],
     cssPaths: options.css || [],
   };
 }
 
 var extensions = new DefaultWeakMap(policy => {
-  let extension = new ExtensionChild.BrowserExtensionContent(policy.initData);
+  let data = policy.initData;
+  if (data.serialize) {
+    data = data.serialize();
+  }
+
+  let extension = new ExtensionChild.BrowserExtensionContent(data);
   extension.policy = policy;
   return extension;
 });
 
 var contentScripts = new DefaultWeakMap(matcher => {
   return new ExtensionContent.Script(extensions.get(matcher.extension),
                                      matcher);
 });
@@ -285,44 +290,53 @@ ExtensionManager = {
         procData["Extension:Schemas"] = new Map();
       }
       this.schemaJSON = procData["Extension:Schemas"];
 
       Services.cpmm.addMessageListener("Schema:Add", this);
     }
   },
 
-  initExtensionPolicy(data, extension) {
-    let policy = WebExtensionPolicy.getByID(data.id);
+  initExtensionPolicy(extension) {
+    let policy = WebExtensionPolicy.getByID(extension.id);
     if (!policy) {
-      let localizeCallback = (
-        extension ? extension.localize.bind(extension)
-                  : str => extensions.get(policy).localize(str));
+      let localizeCallback, allowedOrigins, webAccessibleResources;
+      if (extension.localize) {
+        // We have a real Extension object.
+        localizeCallback = extension.localize.bind(extension);
+        allowedOrigins = extension.whiteListedHosts;
+        webAccessibleResources = extension.webAccessibleResources;
+      } else {
+        // We have serialized extension data;
+        localizeCallback = str => extensions.get(policy).localize(str);
+        allowedOrigins = new MatchPatternSet(extension.whiteListedHosts);
+        webAccessibleResources = extension.webAccessibleResources.map(host => new MatchGlob(host));
+      }
 
       policy = new WebExtensionPolicy({
-        id: data.id,
-        mozExtensionHostname: data.uuid,
-        baseURL: data.resourceURL,
+        id: extension.id,
+        mozExtensionHostname: extension.uuid,
+        baseURL: extension.resourceURL,
 
-        permissions: Array.from(data.permissions),
-        allowedOrigins: new MatchPatternSet(data.whiteListedHosts),
-        webAccessibleResources: data.webAccessibleResources.map(host => new MatchGlob(host)),
+        permissions: Array.from(extension.permissions),
+        allowedOrigins,
+        webAccessibleResources,
 
-        contentSecurityPolicy: data.manifest.content_security_policy,
+        contentSecurityPolicy: extension.manifest.content_security_policy,
 
         localizeCallback,
 
-        backgroundScripts: (data.manifest.background &&
-                            data.manifest.background.scripts),
+        backgroundScripts: (extension.manifest.background &&
+                            extension.manifest.background.scripts),
 
-        contentScripts: (data.manifest.content_scripts || []).map(parseScriptOptions),
+        contentScripts: extension.contentScripts.map(parseScriptOptions),
       });
 
       policy.active = true;
-      policy.initData = data;
+      policy.initData = extension;
     }
     return policy;
   },
 
   initExtension(data) {
     let policy = this.initExtensionPolicy(data);
 
     DocumentManager.initExtension(policy);
@@ -382,18 +396,18 @@ ExtensionProcessScript.prototype = {
 
   get wrappedJSObject() { return this; },
 
   getFrameData(global, force) {
     let extGlobal = DocumentManager.globals.get(global);
     return extGlobal && extGlobal.getFrameData(force);
   },
 
-  initExtension(data, extension) {
-    return ExtensionManager.initExtensionPolicy(data, extension);
+  initExtension(extension) {
+    return ExtensionManager.initExtensionPolicy(extension);
   },
 
   initExtensionDocument(policy, doc) {
     if (DocumentManager.globals.has(getMessageManager(doc.defaultView))) {
       DocumentManager.loadInto(policy, doc.defaultView);
     }
   },