Bug 1068087: Switch about:plugins to run remotely. r=mconley
authorDave Townsend <dtownsend@oxymoronical.com>
Thu, 08 Jan 2015 12:40:14 -0800
changeset 233749 9393c7434d4e
parent 233748 1b3657fee5a8
child 233750 dab6b12a0ff6
push id28423
push userphilringnalda@gmail.com
push date2015-03-16 02:35 +0000
treeherdermozilla-central@436686833af0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1068087
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 1068087: Switch about:plugins to run remotely. r=mconley
docshell/base/nsAboutRedirector.cpp
toolkit/content/plugins.html
toolkit/mozapps/extensions/AddonManager.jsm
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -38,17 +38,20 @@ static RedirEntry kRedirMap[] = {
   {
     "credits", "http://www.mozilla.org/credits/",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
   },
   {
     "mozilla", "chrome://global/content/mozilla.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
   },
-  { "plugins", "chrome://global/content/plugins.html", 0 },
+  {
+    "plugins", "chrome://global/content/plugins.html",
+    nsIAboutModule::URI_MUST_LOAD_IN_CHILD
+  },
   { "config", "chrome://global/content/config.xul", 0 },
 #ifdef MOZ_CRASHREPORTER
   { "crashes", "chrome://global/content/crashes.xhtml", 0 },
 #endif
   {
     "logo", "chrome://branding/content/about.png",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
   },
--- a/toolkit/content/plugins.html
+++ b/toolkit/content/plugins.html
@@ -4,18 +4,16 @@
    - 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/. -->
 
 <html>
 <head>
 <script type="application/javascript">
   "use strict";
 
-  Components.utils.import("resource://gre/modules/AddonManager.jsm");
-
   var Ci = Components.interfaces;
   var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
   var pluginsbundle = strBundleService.createBundle("chrome://global/locale/plugins.properties");
   var regionbundle = strBundleService.createBundle("chrome://global-region/locale/region.properties");
 
   document.writeln("<title>" + pluginsbundle.GetStringFromName("title_label") + "<\/title>");
 </script>
 <link rel="stylesheet" type="text/css" href="chrome://global/content/plugins.css">
@@ -53,17 +51,17 @@
 
    * First, refresh plugins in case anything has been changed recently in
    * prefs: (The "false" argument tells refresh not to reload or activate
    * any plug-ins that would be active otherwise.  In contrast, one would
    * use "true" in the case of ASD instead of restarting)
    */
   navigator.plugins.refresh(false);
 
-  AddonManager.getAddonsByTypes(["plugin"], function (aPlugins) {
+  addMessageListener("PluginList", function({ data: aPlugins }) {
     var fragment = document.createDocumentFragment();
 
     // "Installed plugins"
     var id, label;
     if (aPlugins.length > 0) {
       id = "plugs";
       label = "installedplugins_label";
     } else {
@@ -210,12 +208,14 @@
             mimetypeRow.appendChild(suffixes);
           }
         }
       }
     }
 
     document.getElementById("outside").appendChild(fragment);
   });
+
+  sendAsyncMessage("RequestPlugins");
 </script>
 </div>
 </body>
 </html>
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -503,16 +503,17 @@ var gStrictCompatibility = true;
 var gCheckUpdateSecurityDefault = true;
 var gCheckUpdateSecurity = gCheckUpdateSecurityDefault;
 var gUpdateEnabled = true;
 var gAutoUpdateDefault = true;
 var gHotfixID = null;
 var gShutdownBarrier = null;
 var gRepoShutdownState = "";
 var gShutdownInProgress = false;
+var gPluginPageListener = null;
 
 /**
  * This is the real manager, kept here rather than in AddonManager to keep its
  * contents hidden from API users.
  */
 var AddonManagerInternal = {
   managerListeners: [],
   installListeners: [],
@@ -843,16 +844,23 @@ var AddonManagerInternal = {
       }
 
       // If this is a new profile just pretend that there were no changes
       if (appChanged === undefined) {
         for (let type in this.startupChanges)
           delete this.startupChanges[type];
       }
 
+      // Support for remote about:plugins. Note that this module isn't loaded
+      // at the top because Services.appinfo is defined late in tests.
+      Cu.import("resource://gre/modules/RemotePageManager.jsm");
+
+      gPluginPageListener = new RemotePages("about:plugins");
+      gPluginPageListener.addMessageListener("RequestPlugins", this.requestPlugins);
+
       gStartupComplete = true;
       this.recordTimestamp("AMI_startup_end");
     }
     catch (e) {
       logger.error("startup failed", e);
       AddonManagerPrivate.recordException("AMI", "startup failed", e);
     }
 
@@ -1054,16 +1062,18 @@ var AddonManagerInternal = {
     gShutdownInProgress = true;
     // Clean up listeners
     Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
     Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this);
     Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this);
     Services.prefs.removeObserver(PREF_EM_UPDATE_ENABLED, this);
     Services.prefs.removeObserver(PREF_EM_AUTOUPDATE_DEFAULT, this);
     Services.prefs.removeObserver(PREF_EM_HOTFIX_ID, this);
+    gPluginPageListener.destroy();
+    gPluginPageListener = null;
 
     let savedError = null;
     // Only shut down providers if they've been started.
     if (gStarted) {
       try {
         yield gShutdownBarrier.wait();
       }
       catch(err) {
@@ -1097,16 +1107,34 @@ var AddonManagerInternal = {
     gStartupComplete = false;
     gShutdownBarrier = null;
     gShutdownInProgress = false;
     if (savedError) {
       throw savedError;
     }
   }),
 
+  requestPlugins: function({ target: port }) {
+    // Lists all the properties that plugins.html needs
+    const NEEDED_PROPS = ["name", "pluginLibraries", "pluginFullpath", "version",
+                          "isActive", "blocklistState", "description",
+                          "pluginMimeTypes"];
+    function filterProperties(plugin) {
+      let filtered = {};
+      for (let prop of NEEDED_PROPS) {
+        filtered[prop] = plugin[prop];
+      }
+      return filtered;
+    }
+
+    AddonManager.getAddonsByTypes(["plugin"], function (aPlugins) {
+      port.sendAsyncMessage("PluginList", [filterProperties(p) for (p of aPlugins)]);
+    });
+  },
+
   /**
    * Notified when a preference we're interested in has changed.
    *
    * @see nsIObserver
    */
   observe: function AMI_observe(aSubject, aTopic, aData) {
     switch (aData) {
       case PREF_EM_CHECK_COMPATIBILITY: {