Bug 773761 - Port |Bug 760625 - Use the blocklist to inform click-to-play plugins|, r=Neil, a=Callek SEAMONKEY_2_14b5_BUILD1 SEAMONKEY_2_14b5_RELEASE
authorFrank Wein <mcsmurf@mcsmurf.de>
Wed, 14 Nov 2012 00:23:49 +0100
changeset 13556 588b5b98f12c088fef1e2d85f40e184de24ee383
parent 13553 9e078e25d4751c4e7b5e15dab42bff6c0015b327
child 13557 61f51e822a0c0fe777d321f2207db5c69015cb84
child 13559 fa9b8a2819c0b49b3869d4a67dcee85b9ae1e580
push id3
push userbugzilla@standard8.plus.com
push dateFri, 16 Nov 2012 10:54:06 +0000
reviewersNeil, Callek
bugs773761, 760625
Bug 773761 - Port |Bug 760625 - Use the blocklist to inform click-to-play plugins|, r=Neil, a=Callek
suite/common/bindings/notification.xml
suite/themes/modern/mozapps/plugins/pluginProblem.css
--- a/suite/common/bindings/notification.xml
+++ b/suite/common/bindings/notification.xml
@@ -550,42 +550,48 @@
       </method>
 
       <method name="addLinkClickCallback">
         <parameter name="linkNode"/>
         <parameter name="callback"/>
         <body>
           <![CDATA[
             // XXX just doing (callback)(arg) was giving a same-origin error. bug?
+
+            /* We use event bubbling for the event listeners so that inside a
+               click-to-play plugin we don't activate the plugin when the user
+               clicks on a link in the click-to-play UI (e.g. to check for
+               plugin updates)
+             */
             let callbackArgs = Array.slice(arguments, 2);
             linkNode.addEventListener("click",
                                       function(aEvent) {
                                         if (!aEvent.isTrusted)
                                           return;
                                         aEvent.preventDefault();
                                         aEvent.stopPropagation();
                                         if (callbackArgs.length == 0)
                                           callbackArgs = [ aEvent ];
                                         callback.apply(this, callbackArgs);
                                       }.bind(this),
-                                      true);
+                                      false);
 
             linkNode.addEventListener("keydown",
                                       function(aEvent) {
                                         if (!aEvent.isTrusted)
                                           return;
                                         if (aEvent.keyCode != aEvent.DOM_VK_RETURN)
                                           return;
                                         aEvent.preventDefault();
                                         aEvent.stopPropagation();
                                         if (callbackArgs.length == 0)
                                           callbackArgs = [ aEvent ];
                                         callback.apply(this, callbackArgs);
                                       }.bind(this),
-                                      true);
+                                      false);
           ]]>
         </body>
       </method>
 
       <!-- Callback for user clicking "submit a report" link -->
       <method name="submitReport">
         <parameter name="pluginDumpID"/>
         <parameter name="browserDumpID"/>
@@ -1015,20 +1021,26 @@
             const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
             var pm = Components.classes["@mozilla.org/permissionmanager;1"]
                                .getService(nsIPermissionManager);
             var messageString = this._stringBundle.GetStringFromName("activatepluginsMessage.title");
             var buttons = [{
               label: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.label"),
               accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.accesskey"),
               callback: (function () {
+                // bug 796039/797043: setting the plugin permission to "ALLOW"
+                // causes the "activated" property on an nsIObjectLoadingContent
+                // to return true for plugins that have not actually been
+                // activated. Thus, activate all applicable plugins before
+                // setting the permission.
+                this.activatePlugins();
+
                 if (checkbox.checked)
                   pm.add(this.activeBrowser.currentURI, "plugins",
                          nsIPermissionManager.ALLOW_ACTION);
-                this.activatePlugins();
               }).bind(this)
             }, {
               label: this._stringBundle.GetStringFromName("activatepluginsMessage.dismiss.label"),
               accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.dismiss.accesskey"),
               callback: (function () {
                 if (checkbox.checked)
                   pm.add(this.activeBrowser.currentURI, "plugins",
                          nsIPermissionManager.DENY_ACTION);
@@ -1041,16 +1053,52 @@
                                               buttons);
             // Force a style flush, so that we ensure the binding is attached.
             box.clientTop;
             box.appendChild(checkbox);
           ]]>
         </body>
       </method>
 
+      <method name="setupPluginClickToPlay">
+        <parameter name="pluginElement"/>
+        <body>
+          <![CDATA[
+            if (this.clickToPlayPluginsActivated) {
+              let objLoadingContent = pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent);
+              objLoadingContent.playPlugin();
+              return;
+            }
+
+            // Force a style flush, so that we ensure our binding is attached.
+            pluginElement.clientTop;
+            var doc = pluginElement.ownerDocument;
+            var overlay = doc.getAnonymousElementByAttribute(pluginElement, "class", "mainBox");
+
+            const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
+            var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                               .getService(nsIPermissionManager);
+            var pluginPermission = pm.testPermission(this.activeBrowser.currentURI, "plugins");
+            if (pluginPermission == nsIPermissionManager.DENY_ACTION) {
+              overlay.style.visibility = "hidden";
+              return;
+            }
+
+            this.addLinkClickCallback(overlay, this.activateSinglePlugin, pluginElement);
+
+            if (!this.clickToPlayPromptShown)
+              this.showPluginClickToPlayPrompt();
+
+            let overlay = doc.getAnonymousElementByAttribute(pluginElement, "class", "mainBox");
+            if (this.isTooSmall(pluginElement, overlay))
+              overlay.style.visibility = "hidden";
+          ]]>
+        </body>
+      </method>
+
       <method name="showGeolocationPrompt">
         <parameter name="file"/>
         <parameter name="site"/>
         <parameter name="allowCallback"/>
         <parameter name="cancelCallback"/>
         <body>
           <![CDATA[
             var type = "geolocation";
@@ -1827,16 +1875,34 @@
             popup: null,
             callback: this.installMissingPlugins.bind(this)
           }];
 
           this.pluginUnavailable(event, "blocked-plugins", messageString, buttons);
         ]]>
       </handler>
 
+      <handler event="PluginVulnerableNoUpdate" phase="capturing">
+        <![CDATA[
+          this.setupPluginClickToPlay(event.target);
+        ]]>
+      </handler>
+
+      <handler event="PluginVulnerableUpdatable" phase="capturing">
+        <![CDATA[
+          var plugin = event.target;
+          var doc = plugin.ownerDocument;
+
+          var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
+          this.addLinkClickCallback(updateLink, this.openURLPref, "plugins.update.url");
+
+          this.setupPluginClickToPlay(plugin);
+        ]]>
+      </handler>
+
       <handler event="PluginDisabled" phase="capturing">
         <![CDATA[
           var plugin = event.target;
           // Since we are expecting also untrusted events, make sure
           // that the target is a plugin
           if (plugin instanceof Components.interfaces.nsIObjectLoadingContent &&
               "toEM" in window) {
             // Force a style flush, so that we ensure our binding is attached.
@@ -1845,42 +1911,17 @@
             var manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
             this.addLinkClickCallback(manageLink, window.toEM, "addons://list/plugin");
           }
         ]]>
       </handler>
 
       <handler event="PluginClickToPlay" phase="capturing">
         <![CDATA[
-          var plugin = event.target;
-
-          if (this.clickToPlayPluginsActivated) {
-            let objLoadingContent = plugin.QueryInterface(Components.interfaces.nsIObjectLoadingContent);
-            objLoadingContent.playPlugin();
-            return;
-          }
-
-          // Force a style flush, so that we ensure our binding is attached.
-          plugin.clientTop;
-          var doc = plugin.ownerDocument;
-          var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
-
-          const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
-          var pm = Components.classes["@mozilla.org/permissionmanager;1"]
-                             .getService(nsIPermissionManager);
-          var pluginPermission = pm.testPermission(this.activeBrowser.currentURI, "plugins");
-          if (pluginPermission == nsIPermissionManager.DENY_ACTION) {
-            overlay.style.visibility = "hidden";
-            return;
-          }
-
-          this.addLinkClickCallback(overlay, this.activateSinglePlugin, plugin);
-
-          if (!this.clickToPlayPromptShown)
-            this.showPluginClickToPlayPrompt();
+          this.setupPluginClickToPlay(event.target);
         ]]>
       </handler>
 
       <handler event="NewPluginInstalled" phase="capturing">
         <![CDATA[
           this.missingPlugins = {};
 
           // clean up the UI after a new plugin has been installed.
@@ -2042,19 +2083,24 @@
               label: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.label"),
               accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.accesskey"),
               callback: this.activatePlugins.bind(this)
             };
             var secondaryActions = [{
               label: this._stringBundle.GetStringFromName("activatepluginsMessage.always.label"),
               accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.always.accesskey"),
               callback: (function () {
+                // bug 796039/797043: setting the plugin permission to "ALLOW"
+                // causes the "activated" property on an nsIObjectLoadingContent
+                // to return true for plugins that have not actually been
+                // activated. Thus, activate all applicable plugins before
+                // setting the permission.
+                this.activatePlugins();
                 pm.add(this.activeBrowser.currentURI, "plugins",
                        nsIPermissionManager.ALLOW_ACTION);
-                this.activatePlugins();
               }).bind(this)
             }, {
               label: this._stringBundle.GetStringFromName("activatepluginsMessage.never.label"),
               accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.never.accesskey"),
               callback: (function () {
                 pm.add(this.activeBrowser.currentURI, "plugins",
                        nsIPermissionManager.DENY_ACTION);
                 var notification = PopupNotifications.getNotification("click-to-play-plugins",
--- a/suite/themes/modern/mozapps/plugins/pluginProblem.css
+++ b/suite/themes/modern/mozapps/plugins/pluginProblem.css
@@ -36,17 +36,19 @@ html|a {
   background-repeat: no-repeat;
 }
 :-moz-type-unsupported .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginMissing.png);
 }
 :-moz-type-unsupported .icon[status="ready"] {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDownload.png);
 }
-:-moz-handler-clicktoplay .icon {
+:-moz-handler-clicktoplay .icon,
+:-moz-handler-vulnerable-updatable .icon,
+:-moz-handler-vulnerable-no-update .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginClickToPlay.png);
 }
 :-moz-handler-disabled .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDisabled.png);
 }
 :-moz-handler-blocked .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginBlocked.png);
 }
@@ -62,18 +64,19 @@ html|a {
 
 .msg {
   font: message-box;
   font-size: 12px;
   cursor: default;
   text-shadow: rgba(0,0,0,0.8) 0 0 3.5px;
 }
 
-:-moz-handler-clicktoplay,
-.msgClickToPlay {
+:-moz-handler-clicktoplay .msgClickToPlay,
+:-moz-handler-vulnerable-updatable .msgClickToPlay,
+:-moz-handler-vulnerable-no-update .msgClickToPlay {
   cursor: pointer;
 }
 
 :-moz-handler-clicktoplay .msgTapToPlay {
   display: none;
 }
 
 .submitStatus div {