Bug 813622 Port some of the work from bug 800018 (Click-to-play is broken on various websites like cnn.com or latimes.com) to fix plugins and their mozmill tests. r+a=Standard8 GECKO1701_2013010313_RELBRANCH
authorMike Conley <mconley@mozilla.com>
Wed, 21 Nov 2012 09:58:04 +0000
branchGECKO1701_2013010313_RELBRANCH
changeset 30916 cbd1e04cce5e9458810eb0725028c96346b87072
parent 30915 fa8340d66cf56e2bfae03d5392d73adc4ccd396d
child 30917 1225d8c122c4962f84222a8bd0a84f93e16e3f68
push id1
push userclokep@gmail.com
push dateMon, 07 May 2018 22:45:56 +0000
treeherdercomm-esr60@57eacde5ef40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs813622, 800018
Bug 813622 Port some of the work from bug 800018 (Click-to-play is broken on various websites like cnn.com or latimes.com) to fix plugins and their mozmill tests. r+a=Standard8
mail/base/content/plugins.js
--- a/mail/base/content/plugins.js
+++ b/mail/base/content/plugins.js
@@ -57,30 +57,27 @@ function getPluginInfo(pluginElement)
  */
 function formatURL(aFormat, aIsPref) {
   var formatter = Services.urlFormatter;
   return aIsPref ? formatter.formatURLPref(aFormat) : formatter.formatURL(aFormat);
 }
 
 var gPluginHandler = {
   addEventListeners: function ph_addEventListeners(browser) {
-    browser.addEventListener("PluginNotFound", gPluginHandler, true);
-    browser.addEventListener("PluginCrashed", gPluginHandler, true);
-    browser.addEventListener("PluginBlocklisted", gPluginHandler, true);
-    browser.addEventListener("PluginOutdated", gPluginHandler, true);
-    browser.addEventListener("PluginDisabled", gPluginHandler, true);
-    browser.addEventListener("NewPluginInstalled", gPluginHandler, true);
+    // Note that the XBL binding is untrusted
+    browser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
+    browser.addEventListener("PluginCrashed",         gPluginHandler, true);
+    browser.addEventListener("PluginOutdated",        gPluginHandler, true);
+    browser.addEventListener("NewPluginInstalled",    gPluginHandler, true);
   },
 
   removeEventListeners: function ph_removeEventListeners(browser) {
-    browser.removeEventListener("PluginNotFound", gPluginHandler);
+    browser.removeEventListener("PluginBindingAttached", gPluginHandler);
     browser.removeEventListener("PluginCrashed", gPluginHandler);
-    browser.removeEventListener("PluginBlocklisted", gPluginHandler);
     browser.removeEventListener("PluginOutdated", gPluginHandler);
-    browser.removeEventListener("PluginDisabled", gPluginHandler);
     browser.removeEventListener("NewPluginInstalled", gPluginHandler);
   },
 
   get CrashSubmit() {
     delete this.CrashSubmit;
     Components.utils.import("resource://gre/modules/CrashSubmit.jsm", this);
     return this.CrashSubmit;
   },
@@ -130,29 +127,75 @@ var gPluginHandler = {
                                     callbackArgs = [ evt ];
                                   evt.preventDefault();
                                   (self[callbackName]).apply(self, callbackArgs);
                                 }
                               },
                               true);
   },
 
+  // Helper to get the binding handler type from a plugin object
+  _getBindingType : function(plugin) {
+    let Ci = Components.interfaces;
+
+    if (!(plugin instanceof Ci.nsIObjectLoadingContent))
+      return null;
+
+    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 null;
+    }
+  },
+
   handleEvent : function ph_handleEvent(event) {
     let self = gPluginHandler;
     let plugin = event.target;
     let doc = plugin.ownerDocument;
 
     // We're expecting the target to be a plugin.
     if (!(plugin instanceof Components.interfaces.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;
 
       case "PluginNotFound":
         // For non-object plugin tags, register a click handler to install the
         // plugin. Object tags can, and often do, deal with that themselves,
         // so don't stomp on the page developers toes.
@@ -168,27 +211,27 @@ var gPluginHandler = {
         }
         /* FALLTHRU */
 
       case "PluginBlocklisted":
       case "PluginOutdated":
 #ifdef XP_MACOSX
       case "npapi-carbon-event-model-failure":
 #endif
-        self.pluginUnavailable(plugin, event.type);
+        self.pluginUnavailable(plugin, eventType);
         break;
 
       case "PluginDisabled":
         let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
         self.addLinkClickCallback(manageLink, "managePlugins");
         break;
     }
 
     // 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");
       if (self.isTooSmall(plugin, overlay))
           overlay.style.visibility = "hidden";
     }
   },
 
   newPluginInstalled : function ph_newPluginInstalled(event) {
     // browser elements are anonymous so we can't just use target.
@@ -473,16 +516,20 @@ var gPluginHandler = {
     // Remap the plugin name to a more user-presentable form.
     pluginName = this.makeNicePluginName(pluginName, pluginFilename);
 
     let messageString = messengerBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]);
 
     //
     // 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");
 #ifdef MOZ_CRASHREPORTER
     let status;
 
     // Determine which message to show regarding crash reports.
     if (submittedReport) { // submitReports && !doPrompt, handled in observer