diff --git a/browser/base/content/browser-plugins.js b/browser/base/content/browser-plugins.js
index c05ddada5afa..bbcee11b0a85 100644
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -113,6 +113,34 @@ var gPluginHandler = {
true);
},
+ // Helper to get the binding handler type from a plugin object
+ _getBindingType : function(plugin) {
+ if (!(plugin instanceof Ci.nsIObjectLoadingContent))
+ return;
+
+ switch (plugin.pluginFallbackType) {
+ case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
+ return "PluginNotFound";
+ case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED:
+ return "PluginDisabled";
+ case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED:
+ return "PluginBlocklisted";
+ case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
+ return "PluginOutdated";
+ case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
+ return "PluginClickToPlay";
+ case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
+ return "PluginVulnerableUpdatable";
+ case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
+ return "PluginVulnerableNoUpdate";
+ case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
+ return "PluginPlayPreview";
+ default:
+ // Not all states map to a handler
+ return;
+ }
+ },
+
handleEvent : function(event) {
let self = gPluginHandler;
let plugin = event.target;
@@ -122,10 +150,26 @@ var gPluginHandler = {
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
return;
- // Force a style flush, so that we ensure our binding is attached.
- plugin.clientTop;
+ let eventType = event.type;
+ if (eventType == "PluginBindingAttached") {
+ // The plugin binding fires this event when it is created.
+ // As an untrusted event, ensure that this object actually has a binding
+ // and make sure we don't handle it twice
+ let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
+ if (!overlay || overlay._bindingHandled) {
+ return;
+ }
+ overlay._bindingHandled = true;
- switch (event.type) {
+ // Lookup the handler for this binding
+ eventType = self._getBindingType(plugin);
+ if (!eventType) {
+ // Not all bindings have handlers
+ return;
+ }
+ }
+
+ switch (eventType) {
case "PluginCrashed":
self.pluginInstanceCrashed(plugin, event);
break;
@@ -151,7 +195,7 @@ var gPluginHandler = {
#ifdef XP_MACOSX
case "npapi-carbon-event-model-failure":
#endif
- self.pluginUnavailable(plugin, event.type);
+ self.pluginUnavailable(plugin, eventType);
break;
case "PluginVulnerableUpdatable":
@@ -167,9 +211,9 @@ var gPluginHandler = {
let messageString = gNavigatorBundle.getFormattedString("PluginClickToPlay", [pluginName]);
let overlayText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
overlayText.textContent = messageString;
- if (event.type == "PluginVulnerableUpdatable" ||
- event.type == "PluginVulnerableNoUpdate") {
- let vulnerabilityString = gNavigatorBundle.getString(event.type);
+ if (eventType == "PluginVulnerableUpdatable" ||
+ eventType == "PluginVulnerableNoUpdate") {
+ let vulnerabilityString = gNavigatorBundle.getString(eventType);
let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
vulnerabilityText.textContent = vulnerabilityString;
}
@@ -186,9 +230,8 @@ var gPluginHandler = {
}
// Hide the in-content UI if it's too big. The crashed plugin handler already did this.
- if (event.type != "PluginCrashed") {
+ if (eventType != "PluginCrashed") {
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
- /* overlay might be null, so only operate on it if it exists */
if (overlay != null && self.isTooSmall(plugin, overlay))
overlay.style.visibility = "hidden";
}
@@ -321,7 +364,6 @@ var gPluginHandler = {
return;
}
- // The overlay is null if the XBL binding is not attached (element is display:none).
if (overlay) {
overlay.addEventListener("click", function(aEvent) {
// Have to check that the target is not the link to update the plugin
@@ -341,11 +383,6 @@ var gPluginHandler = {
_handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) {
let doc = aPlugin.ownerDocument;
let previewContent = doc.getAnonymousElementByAttribute(aPlugin, "class", "previewPluginContent");
- if (!previewContent) {
- // the XBL binding is not attached (element is display:none), fallback to click-to-play logic
- gPluginHandler.stopPlayPreview(aPlugin, false);
- return;
- }
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
if (!iframe) {
// lazy initialization of the iframe
@@ -754,6 +791,9 @@ var gPluginHandler = {
//
// Configure the crashed-plugin placeholder.
//
+
+ // Force a layout flush so the binding is attached.
+ plugin.clientTop;
let doc = plugin.ownerDocument;
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 7be4c20c6a0b..10e7b7c2554b 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1012,15 +1012,11 @@ var gBrowserInit = {
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
- gBrowser.addEventListener("PluginNotFound", gPluginHandler, true);
- gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
- gBrowser.addEventListener("PluginBlocklisted", gPluginHandler, true);
- gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
- gBrowser.addEventListener("PluginDisabled", gPluginHandler, true);
- gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true);
- gBrowser.addEventListener("PluginPlayPreview", gPluginHandler, true);
- gBrowser.addEventListener("PluginVulnerableUpdatable", gPluginHandler, true);
- gBrowser.addEventListener("PluginVulnerableNoUpdate", gPluginHandler, true);
+ // Note that the XBL binding is untrusted
+ gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
+ gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
+ gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
+
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
#ifdef XP_MACOSX
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);
diff --git a/browser/base/content/test/browser_pluginnotification.js b/browser/base/content/test/browser_pluginnotification.js
index 0d4fe9722512..deb5176ba7d7 100644
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -64,20 +64,22 @@ function test() {
gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser;
gTestBrowser.addEventListener("load", pageLoad, true);
- gTestBrowser.addEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
+ gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
prepareTest(test1, gTestRoot + "plugin_unknown.html");
}
function finishTest() {
gTestBrowser.removeEventListener("load", pageLoad, true);
- gTestBrowser.removeEventListener("PluginClickToPlay", handlePluginClickToPlay, true);
+ gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
gBrowser.removeCurrentTab();
window.focus();
finish();
}
-function handlePluginClickToPlay() {
- gClickToPlayPluginActualEvents++;
+function handleBindingAttached(evt) {
+ evt.target instanceof Ci.nsIObjectLoadingContent;
+ if (evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY)
+ gClickToPlayPluginActualEvents++;
}
function pageLoad() {
@@ -734,7 +736,7 @@ function test19f() {
// "display: block" can be clicked to activate.
function test20a() {
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
- ok(clickToPlayNotification, "Test 20a, Should have a click-to-play notification");
+ ok(!clickToPlayNotification, "Test 20a, Should not have a click-to-play notification");
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("plugin");
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
@@ -756,6 +758,8 @@ function test20a() {
}
function test20b() {
+ var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+ ok(clickToPlayNotification, "Test 20b, Should now have a click-to-play notification");
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("plugin");
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
diff --git a/browser/base/content/test/browser_pluginplaypreview.js b/browser/base/content/test/browser_pluginplaypreview.js
index b8462680b1b5..427d0aff6c53 100644
--- a/browser/base/content/test/browser_pluginplaypreview.js
+++ b/browser/base/content/test/browser_pluginplaypreview.js
@@ -145,7 +145,7 @@ function test() {
gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser;
gTestBrowser.addEventListener("load", pageLoad, true);
- gTestBrowser.addEventListener("PluginPlayPreview", handlePluginPlayPreview, true);
+ gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
registerPlayPreview('application/x-test', 'about:');
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
@@ -153,14 +153,16 @@ function test() {
function finishTest() {
gTestBrowser.removeEventListener("load", pageLoad, true);
- gTestBrowser.removeEventListener("PluginPlayPreview", handlePluginPlayPreview, true);
+ gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
gBrowser.removeCurrentTab();
window.focus();
finish();
}
-function handlePluginPlayPreview() {
- gPlayPreviewPluginActualEvents++;
+function handleBindingAttached(evt) {
+ if (evt.target instanceof Ci.nsIObjectLoadingContent &&
+ evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
+ gPlayPreviewPluginActualEvents++;
}
function pageLoad() {
diff --git a/toolkit/mozapps/plugins/content/pluginProblem.xml b/toolkit/mozapps/plugins/content/pluginProblem.xml
index 7e2bf2027e18..f61cb484807d 100644
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -58,5 +58,11 @@
+
+
+ // Notify browser-plugins.js that we were attached
+ this.dispatchEvent(new CustomEvent("PluginBindingAttached"));
+
+