Bug 1068087: Switch about:plugins to run remotely. r=mconley
--- 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: {