Bug 1315575: Part 1 - More cleanup. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Sun, 06 Nov 2016 17:28:16 -0800
changeset 366632 2e0180c345940fa1893ef4e26ac68effa024ef48
parent 366631 deb2dcbb0ec045561f1fa042957221466439240c
child 366633 f29c03c0682adebf120110a654d22eb5130d7bca
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1315575
milestone52.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 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.
   //