Bug 1129040 - Add a blocklist shim in the content process and forward requests to the parent process. r=Mossop
authorJim Mathies <jmathies@mozilla.com>
Mon, 23 Mar 2015 08:40:08 -0500
changeset 264202 cee8f9d83b7ed50814febaab616eac574564ad56
parent 264201 99153c410bad53b7cfde09da3fd4162fc0998513
child 264203 8fcdeca7e5480bfe92cd4de4540c7977503fd848
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1129040
milestone39.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 1129040 - Add a blocklist shim in the content process and forward requests to the parent process. r=Mossop
toolkit/mozapps/extensions/extensions.manifest
toolkit/mozapps/extensions/moz.build
toolkit/mozapps/extensions/nsBlocklistService.js
toolkit/mozapps/extensions/nsBlocklistServiceContent.js
--- a/toolkit/mozapps/extensions/extensions.manifest
+++ b/toolkit/mozapps/extensions/extensions.manifest
@@ -1,11 +1,14 @@
-component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js
-contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e}
-category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1
+component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js process=main
+contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e} process=main
+category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1  process=main
+component {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} nsBlocklistServiceContent.js process=content
+contract @mozilla.org/extensions/blocklist;1 {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} process=content
+
 #ifndef MOZ_WIDGET_GONK
 category update-timer nsBlocklistService @mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400
 component {4399533d-08d1-458c-a87a-235f74451cfa} addonManager.js
 contract @mozilla.org/addons/integration;1 {4399533d-08d1-458c-a87a-235f74451cfa}
 category update-timer addonManager @mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400
 component {7beb3ba8-6ec3-41b4-b67c-da89b8518922} amContentHandler.js
 contract @mozilla.org/uriloader/content-handler;1?type=application/x-xpinstall {7beb3ba8-6ec3-41b4-b67c-da89b8518922}
 component {0f38e086-89a3-40a5-8ffc-9b694de1d04a} amWebInstallListener.js
--- a/toolkit/mozapps/extensions/moz.build
+++ b/toolkit/mozapps/extensions/moz.build
@@ -21,16 +21,17 @@ EXTRA_COMPONENTS += [
     'amContentHandler.js',
     'amInstallTrigger.js',
     'amWebInstallListener.js',
 ]
 
 EXTRA_PP_COMPONENTS += [
     'extensions.manifest',
     'nsBlocklistService.js',
+    'nsBlocklistServiceContent.js',
 ]
 
 EXTRA_JS_MODULES += [
     'ChromeManifestParser.jsm',
     'DeferredSave.jsm',
     'LightweightThemeManager.jsm',
 ]
 
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -292,16 +292,18 @@ function Blocklist() {
   Services.obs.addObserver(this, "sessionstore-windows-restored", false);
   gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false);
   gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true);
   gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
                                      MAX_BLOCK_LEVEL);
   gPref.addObserver("extensions.blocklist.", this, false);
   gPref.addObserver(PREF_EM_LOGGING_ENABLED, this, false);
   this.wrappedJSObject = this;
+  // requests from child processes come in here, see receiveMessage.
+  Services.ppmm.addMessageListener("Blocklist::getPluginBlocklistState", this);
 }
 
 Blocklist.prototype = {
   /**
    * Extension ID -> array of Version Ranges
    * Each value in the version range array is a JS Object that has the
    * following properties:
    *   "minVersion"  The minimum version in a version range (default = 0)
@@ -313,22 +315,27 @@ Blocklist.prototype = {
    *                   "minVersion"  The minimum version in a version range
    *                                 (default = 0)
    *                   "maxVersion"  The maximum version in a version range
    *                                 (default = *)
    */
   _addonEntries: null,
   _pluginEntries: null,
 
+  shutdown: function () {
+    Services.obs.removeObserver(this, "xpcom-shutdown");
+    Services.ppmm.removeMessageListener("Blocklist::getPluginBlocklistState", this);
+    gPref.removeObserver("extensions.blocklist.", this);
+    gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this);
+  },
+
   observe: function Blocklist_observe(aSubject, aTopic, aData) {
     switch (aTopic) {
     case "xpcom-shutdown":
-      Services.obs.removeObserver(this, "xpcom-shutdown");
-      gPref.removeObserver("extensions.blocklist.", this);
-      gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this);
+      this.shutdown();
       break;
     case "nsPref:changed":
       switch (aData) {
         case PREF_EM_LOGGING_ENABLED:
           gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false);
           break;
         case PREF_BLOCKLIST_ENABLED:
           gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true);
@@ -344,16 +351,28 @@ Blocklist.prototype = {
       break;
     case "sessionstore-windows-restored":
       Services.obs.removeObserver(this, "sessionstore-windows-restored");
       this._preloadBlocklist();
       break;
     }
   },
 
+  // Message manager message handlers
+  receiveMessage: function (aMsg) {
+    switch (aMsg.name) {
+      case "Blocklist::getPluginBlocklistState":
+        return this.getPluginBlocklistState(aMsg.data.addonData,
+                                            aMsg.data.appVersion,
+                                            aMsg.data.toolkitVersion);
+      default:
+        throw new Error("Unknown blocklist message received from content: " + aMsg.name);
+    }
+  },
+
   /* See nsIBlocklistService */
   isAddonBlocklisted: function Blocklist_isAddonBlocklisted(addon, appVersion, toolkitVersion) {
     return this.getAddonBlocklistState(addon, appVersion, toolkitVersion) ==
                    Ci.nsIBlocklistService.STATE_BLOCKED;
   },
 
   /* See nsIBlocklistService */
   getAddonBlocklistState: function Blocklist_getAddonBlocklistState(addon, appVersion, toolkitVersion) {
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/nsBlocklistServiceContent.js
@@ -0,0 +1,80 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+const kMissingAPIMessage = "Unsupported blocklist call in the child process."
+
+/*
+ * A lightweight blocklist proxy for the content process that traps plugin
+ * related blocklist checks and forwards them to the parent. This interface is
+ * primarily designed to insure overlays work.. it does not control plugin
+ * or addon loading.
+ */
+
+function Blocklist() {
+}
+
+Blocklist.prototype = {
+  classID: Components.ID("{e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIBlocklistService]),
+
+  /*
+    * A helper that queries key data from a plugin or addon object
+    * and generates a simple data wrapper suitable for ipc. We hand
+    * these directly to the nsBlockListService in the parent which
+    * doesn't query for much.. allowing us to get away with this.
+    */
+  flattenObject: function (aTag) {
+    // Based on debugging the nsBlocklistService, these are the props the
+    // parent side will check on our objects.
+    let props = ["name", "description", "filename", "version"];
+    let dataWrapper = {};
+    for (let prop of props) {
+      dataWrapper[prop] = aTag[prop];
+    }
+    return dataWrapper;
+  },
+
+  // We support the addon methods here for completeness, but content currently
+  // only calls getPluginBlocklistState.
+
+  isAddonBlocklisted: function (aAddon, aAppVersion, aToolkitVersion) {
+    throw new Error(kMissingAPIMessage);
+  },
+
+  getAddonBlocklistState: function (aAddon, aAppVersion, aToolkitVersion) {
+    throw new Error(kMissingAPIMessage);
+  },
+
+  getPluginBlocklistState: function (aPluginTag, aAppVersion, aToolkitVersion) {
+    return Services.cpmm.sendSyncMessage("Blocklist::getPluginBlocklistState", {
+      addonData: this.flattenObject(aPluginTag),
+      appVersion: aAppVersion,
+      toolkitVersion: aToolkitVersion
+    })[0];
+  },
+
+  getAddonBlocklistURL: function (aAddon, aAppVersion, aToolkitVersion) {
+    throw new Error(kMissingAPIMessage);
+  },
+
+  getPluginBlocklistURL: function (aPluginTag) {
+    throw new Error(kMissingAPIMessage);
+  },
+
+  getPluginInfoURL: function (aPluginTag) {
+    throw new Error(kMissingAPIMessage);
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Blocklist]);