Bug 800018 - Part 2 - Move plugin fallback event handling entirely to the front end. r=jaws

This commit is contained in:
John Schoenick 2012-11-07 13:59:20 -08:00
Родитель d433e2d472
Коммит a1c0496fa5
5 изменённых файлов: 81 добавлений и 33 удалений

Просмотреть файл

@ -113,6 +113,34 @@ var gPluginHandler = {
true); 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) { handleEvent : function(event) {
let self = gPluginHandler; let self = gPluginHandler;
let plugin = event.target; let plugin = event.target;
@ -122,10 +150,26 @@ var gPluginHandler = {
if (!(plugin instanceof Ci.nsIObjectLoadingContent)) if (!(plugin instanceof Ci.nsIObjectLoadingContent))
return; return;
// Force a style flush, so that we ensure our binding is attached. let eventType = event.type;
plugin.clientTop; 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": case "PluginCrashed":
self.pluginInstanceCrashed(plugin, event); self.pluginInstanceCrashed(plugin, event);
break; break;
@ -151,7 +195,7 @@ var gPluginHandler = {
#ifdef XP_MACOSX #ifdef XP_MACOSX
case "npapi-carbon-event-model-failure": case "npapi-carbon-event-model-failure":
#endif #endif
self.pluginUnavailable(plugin, event.type); self.pluginUnavailable(plugin, eventType);
break; break;
case "PluginVulnerableUpdatable": case "PluginVulnerableUpdatable":
@ -167,9 +211,9 @@ var gPluginHandler = {
let messageString = gNavigatorBundle.getFormattedString("PluginClickToPlay", [pluginName]); let messageString = gNavigatorBundle.getFormattedString("PluginClickToPlay", [pluginName]);
let overlayText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay"); let overlayText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
overlayText.textContent = messageString; overlayText.textContent = messageString;
if (event.type == "PluginVulnerableUpdatable" || if (eventType == "PluginVulnerableUpdatable" ||
event.type == "PluginVulnerableNoUpdate") { eventType == "PluginVulnerableNoUpdate") {
let vulnerabilityString = gNavigatorBundle.getString(event.type); let vulnerabilityString = gNavigatorBundle.getString(eventType);
let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus"); let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
vulnerabilityText.textContent = vulnerabilityString; 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. // 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"); 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)) if (overlay != null && self.isTooSmall(plugin, overlay))
overlay.style.visibility = "hidden"; overlay.style.visibility = "hidden";
} }
@ -321,7 +364,6 @@ var gPluginHandler = {
return; return;
} }
// The overlay is null if the XBL binding is not attached (element is display:none).
if (overlay) { if (overlay) {
overlay.addEventListener("click", function(aEvent) { overlay.addEventListener("click", function(aEvent) {
// Have to check that the target is not the link to update the plugin // 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) { _handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) {
let doc = aPlugin.ownerDocument; let doc = aPlugin.ownerDocument;
let previewContent = doc.getAnonymousElementByAttribute(aPlugin, "class", "previewPluginContent"); 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]; let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
if (!iframe) { if (!iframe) {
// lazy initialization of the iframe // lazy initialization of the iframe
@ -754,6 +791,9 @@ var gPluginHandler = {
// //
// Configure the crashed-plugin placeholder. // Configure the crashed-plugin placeholder.
// //
// Force a layout flush so the binding is attached.
plugin.clientTop;
let doc = plugin.ownerDocument; let doc = plugin.ownerDocument;
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus"); let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");

Просмотреть файл

@ -1012,15 +1012,11 @@ var gBrowserInit = {
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false); gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
gBrowser.addEventListener("PluginNotFound", gPluginHandler, true); // Note that the XBL binding is untrusted
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true); gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
gBrowser.addEventListener("PluginBlocklisted", gPluginHandler, true); gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
gBrowser.addEventListener("PluginOutdated", 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);
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true); gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
#ifdef XP_MACOSX #ifdef XP_MACOSX
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true); gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);

Просмотреть файл

@ -64,20 +64,22 @@ function test() {
gBrowser.selectedTab = newTab; gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser; gTestBrowser = gBrowser.selectedBrowser;
gTestBrowser.addEventListener("load", pageLoad, true); gTestBrowser.addEventListener("load", pageLoad, true);
gTestBrowser.addEventListener("PluginClickToPlay", handlePluginClickToPlay, true); gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
prepareTest(test1, gTestRoot + "plugin_unknown.html"); prepareTest(test1, gTestRoot + "plugin_unknown.html");
} }
function finishTest() { function finishTest() {
gTestBrowser.removeEventListener("load", pageLoad, true); gTestBrowser.removeEventListener("load", pageLoad, true);
gTestBrowser.removeEventListener("PluginClickToPlay", handlePluginClickToPlay, true); gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
window.focus(); window.focus();
finish(); finish();
} }
function handlePluginClickToPlay() { function handleBindingAttached(evt) {
gClickToPlayPluginActualEvents++; evt.target instanceof Ci.nsIObjectLoadingContent;
if (evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY)
gClickToPlayPluginActualEvents++;
} }
function pageLoad() { function pageLoad() {
@ -734,7 +736,7 @@ function test19f() {
// "display: block" can be clicked to activate. // "display: block" can be clicked to activate.
function test20a() { function test20a() {
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); 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 doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("plugin"); var plugin = doc.getElementById("plugin");
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
@ -756,6 +758,8 @@ function test20a() {
} }
function test20b() { 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 doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("plugin"); var plugin = doc.getElementById("plugin");
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect(); var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();

Просмотреть файл

@ -145,7 +145,7 @@ function test() {
gBrowser.selectedTab = newTab; gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser; gTestBrowser = gBrowser.selectedBrowser;
gTestBrowser.addEventListener("load", pageLoad, true); gTestBrowser.addEventListener("load", pageLoad, true);
gTestBrowser.addEventListener("PluginPlayPreview", handlePluginPlayPreview, true); gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
registerPlayPreview('application/x-test', 'about:'); registerPlayPreview('application/x-test', 'about:');
prepareTest(test1a, gTestRoot + "plugin_test.html", 1); prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
@ -153,14 +153,16 @@ function test() {
function finishTest() { function finishTest() {
gTestBrowser.removeEventListener("load", pageLoad, true); gTestBrowser.removeEventListener("load", pageLoad, true);
gTestBrowser.removeEventListener("PluginPlayPreview", handlePluginPlayPreview, true); gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
window.focus(); window.focus();
finish(); finish();
} }
function handlePluginPlayPreview() { function handleBindingAttached(evt) {
gPlayPreviewPluginActualEvents++; if (evt.target instanceof Ci.nsIObjectLoadingContent &&
evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
gPlayPreviewPluginActualEvents++;
} }
function pageLoad() { function pageLoad() {

Просмотреть файл

@ -58,5 +58,11 @@
<html:div class="previewPluginContent"><!-- iframe and its src will be set at runtime --></html:div> <html:div class="previewPluginContent"><!-- iframe and its src will be set at runtime --></html:div>
<html:div style="display:none;"><children/></html:div> <html:div style="display:none;"><children/></html:div>
</content> </content>
<implementation>
<constructor>
// Notify browser-plugins.js that we were attached
this.dispatchEvent(new CustomEvent("PluginBindingAttached"));
</constructor>
</implementation>
</binding> </binding>
</bindings> </bindings>