Bug 1315575: Part 1 - More cleanup. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Sun, 06 Nov 2016 17:28:16 -0800
changeset 348223 2e0180c345940fa1893ef4e26ac68effa024ef48
parent 348222 deb2dcbb0ec045561f1fa042957221466439240c
child 348224 f29c03c0682adebf120110a654d22eb5130d7bca
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1315575
milestone52.0a1
Bug 1315575: Part 1 - More cleanup. r=aswan MozReview-Commit-ID: KdAplJGH9Hy
toolkit/components/extensions/Extension.jsm
toolkit/components/extensions/ExtensionChild.jsm
toolkit/components/extensions/ExtensionUtils.jsm
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -78,23 +78,23 @@ let schemaURLs = new Set();
 
 if (!AppConstants.RELEASE_OR_BETA) {
   schemaURLs.add("chrome://extensions/content/schemas/experiments.json");
 }
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   BaseContext,
-  defineLazyGetter,
   EventEmitter,
-  SchemaAPIManager,
+  LocalAPIImplementation,
   LocaleData,
+  SchemaAPIManager,
+  defineLazyGetter,
+  flushJarCache,
   instanceOf,
-  LocalAPIImplementation,
-  flushJarCache,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole);
 
 const LOGGER_ID_BASE = "addons.webextension.";
 const UUID_MAP_PREF = "extensions.webextensions.uuids";
 const LEAVE_STORAGE_PREF = "extensions.webextensions.keepStorageOnUninstall";
 const LEAVE_UUID_PREF = "extensions.webextensions.keepUuidOnUninstall";
@@ -237,18 +237,17 @@ let ProxyMessenger = {
       let tab = Management.global.TabManager.getTab(tabId, null, null);
       return tab && tab.linkedBrowser.messageManager;
     }
 
     // runtime.sendMessage / runtime.connect
     if (extensionId) {
       // TODO(robwu): map the extensionId to the addon parent process's message
       // manager when they run in a separate process.
-      let pipmm = Services.ppmm.getChildAt(0);
-      return pipmm;
+      return Services.ppmm.getChildAt(0);
     }
 
     return null;
   },
 };
 
 class BrowserDocshellFollower {
   /**
@@ -285,18 +284,18 @@ class ProxyContext extends BaseContext {
 
     this.incognito = params.incognito;
 
     // This message manager is used by ParentAPIManager to send messages and to
     // close the ProxyContext if the underlying message manager closes. This
     // message manager object may change when `xulBrowser` swaps docshells, e.g.
     // when a tab is moved to a different window.
     this.currentMessageManager = xulBrowser.messageManager;
-    this._docShellTracker = new BrowserDocshellFollower(xulBrowser,
-        this.onBrowserChange.bind(this));
+    this._docShellTracker = new BrowserDocshellFollower(
+      xulBrowser, this.onBrowserChange.bind(this));
 
     Object.defineProperty(this, "principal", {
       value: principal, enumerable: true, configurable: true,
     });
 
     this.listenerProxies = new Map();
 
     Management.emit("proxy-context-load", this);
@@ -454,40 +453,37 @@ ParentAPIManager = {
         this.removeListener(data);
         break;
     }
   },
 
   createProxyContext(data, target) {
     let {envType, extensionId, childId, principal} = data;
     if (this.proxyContexts.has(childId)) {
-      Cu.reportError("A WebExtension context with the given ID already exists!");
-      return;
+      throw new Error("A WebExtension context with the given ID already exists!");
     }
+
     let extension = GlobalManager.getExtension(extensionId);
     if (!extension) {
-      Cu.reportError(`No WebExtension found with ID ${extensionId}`);
-      return;
+      throw new Error(`No WebExtension found with ID ${extensionId}`);
     }
 
     let context;
     if (envType == "addon_parent") {
       // Privileged addon contexts can only be loaded in documents whose main
       // frame is also the same addon.
       if (principal.URI.prePath != extension.baseURI.prePath ||
           !target.contentPrincipal.subsumes(principal)) {
-        Cu.reportError(`Refused to create privileged WebExtension context for ${principal.URI.spec}`);
-        return;
+        throw new Error(`Refused to create privileged WebExtension context for ${principal.URI.spec}`);
       }
       context = new ExtensionChildProxyContext(envType, extension, data, target);
     } else if (envType == "content_parent") {
       context = new ProxyContext(envType, extension, data, target, principal);
     } else {
-      Cu.reportError(`Invalid WebExtension context envType: ${envType}`);
-      return;
+      throw new Error(`Invalid WebExtension context envType: ${envType}`);
     }
     this.proxyContexts.set(childId, context);
   },
 
   closeProxyContext(childId) {
     let context = this.proxyContexts.get(childId);
     if (!context) {
       return;
--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -71,24 +71,25 @@ var apiManager = new class extends Schem
   }
 }();
 
 // A class that behaves identical to a ChildAPIManager, except
 // 1) creation of the ProxyContext in the parent is synchronous, and
 // 2) APIs without a local implementation and marked as incompatible with the
 //    out-of-process model fall back to directly invoking the parent methods.
 // TODO(robwu): Remove this when all APIs have migrated.
-class WannabeChildAPIManager extends ChildAPIManager {
-  createProxyContextInConstructor(data) {
+class PseudoChildAPIManager extends ChildAPIManager {
+  createProxyContextInConstructor(originalData) {
     // Create a structured clone to simulate IPC.
-    data = Object.assign({}, data);
-    let {principal} = data;  // Not structurally cloneable.
-    delete data.principal;
+    let data = Object.assign({}, originalData, {principal: null});
     data = Cu.cloneInto(data, {});
-    data.principal = principal;
+    // Principals can be structured cloned by message managers, but not
+    // by cloneInto.
+    data.principal = originalData.principal;
+
     let name = "API:CreateProxyContext";
     // The <browser> that receives messages from `this.messageManager`.
     let target = this.context.contentWindow
       .QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIDocShell)
       .chromeEventHandler;
     ParentAPIManager.receiveMessage({name, data, target});
 
@@ -100,17 +101,17 @@ class WannabeChildAPIManager extends Chi
     // arrives locally, the object is cloned into the local clone scope).
     // If all calls are direct, then the parent cloneScope does matter, because
     // the objects are not cloned again.
     Object.defineProperty(proxyContext, "cloneScope", {
       get: () => this.cloneScope,
     });
 
     // Synchronously unload the ProxyContext because we synchronously create it.
-    this.context.callOnClose({close: proxyContext.unload.bind(proxyContext)});
+    this.context.callOnClose(proxyContext);
   }
 
   getFallbackImplementation(namespace, name) {
     // This is gross and should be removed ASAP.
     let shouldSynchronouslyUseParentAPI = false;
     // Incompatible APIs are listed here.
     if (namespace == "webNavigation" || // ChildAPIManager is oblivious to filters.
         namespace == "webRequest") { // Incompatible by design (synchronous).
@@ -243,17 +244,17 @@ defineLazyGetter(ExtensionContext.protot
 defineLazyGetter(ExtensionContext.prototype, "childManager", function() {
   let localApis = {};
   apiManager.generateAPIs(this, localApis);
 
   if (this.viewType == "background") {
     apiManager.global.initializeBackgroundPage(this.contentWindow);
   }
 
-  let childManager = new WannabeChildAPIManager(this, this.messageManager, localApis, {
+  let childManager = new PseudoChildAPIManager(this, this.messageManager, localApis, {
     envType: "addon_parent",
     viewType: this.viewType,
     url: this.uri.spec,
     incognito: this.incognito,
   });
 
   this.callOnClose(childManager);
 
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -497,16 +497,23 @@ class BaseContext {
       extensionId: this.extension.id,
       contextId: this.contextId,
     });
 
     for (let obj of this.onClose) {
       obj.close();
     }
   }
+
+  /**
+   * A simple proxy for unload(), for use with callOnClose().
+   */
+  close() {
+    this.unload();
+  }
 }
 
 // Manages icon details for toolbar buttons in the |pageAction| and
 // |browserAction| APIs.
 let IconDetails = {
   // Normalizes the various acceptable input formats into an object
   // with icon size as key and icon URL as value.
   //