Bug 747519 Implement permission interface for click-to-play plugins doorhangers by InvisibleSmiley r=Neil AURORA_BASE_20120424
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Tue, 24 Apr 2012 17:59:38 +0100
changeset 11721 8e416a0c96c266e4b646499e1abef6f74c834f06
parent 11720 7d36cb752e09156f2814d3837bd1db8e3fa4dbb3
child 11722 402f17689f0338210d97bf7e7a5b9f5eca7a55da
push idunknown
push userunknown
push dateunknown
reviewersNeil
bugs747519
Bug 747519 Implement permission interface for click-to-play plugins doorhangers by InvisibleSmiley r=Neil Also including patch for notificationboxes for l10n changes pending r=IanN
suite/common/bindings/notification.xml
suite/locales/en-US/chrome/common/notification.properties
--- a/suite/common/bindings/notification.xml
+++ b/suite/common/bindings/notification.xml
@@ -978,26 +978,51 @@
           ]]>
         </body>
       </method>
 
       <method name="showPluginClickToPlayPrompt">
         <body>
           <![CDATA[
             this.clickToPlayPromptShown = true;
-            var messageString = this._stringBundle.GetStringFromName("activatePluginsMessage.message");
+
+            var checkbox = document.createElement("checkbox");
+            checkbox.className = "rememberChoice";
+            checkbox.setAttribute("label", this._stringBundle.GetStringFromName("activatepluginsMessage.remember"));
+
+            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.label"),
-              accessKey: this._stringBundle.GetStringFromName("activatePluginsMessage.accesskey"),
-              callback: this.activatePlugins.bind(this)
+              label: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.label"),
+              accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.accesskey"),
+              callback: (function () {
+                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);
+              }).bind(this)
             }];
-            this.appendNotification(messageString, "click-to-play-plugins",
-                                    "chrome://mozapps/skin/plugins/pluginGeneric.png",
-                                    this.PRIORITY_INFO_HIGH,
-                                    buttons);
+            var box = this.appendNotification(messageString,
+                                              "click-to-play-plugins",
+                                              "chrome://mozapps/skin/plugins/pluginGeneric.png",
+                                              this.PRIORITY_INFO_HIGH,
+                                              buttons);
+            // Force a style flush, so that we ensure the binding is attached.
+            box.clientTop;
+            box.appendChild(checkbox);
           ]]>
         </body>
       </method>
 
       <method name="showGeolocationPrompt">
         <parameter name="file"/>
         <parameter name="site"/>
         <parameter name="image"/>
@@ -1030,35 +1055,33 @@
                             .formatStringFromName(type + ".siteWantsToKnow",
                                                   [site], 1);
             else
               message = this._stringBundle
                             .formatStringFromName(type + ".fileWantsToKnow",
                                                   [file], 1);
             var box = this.appendNotification(message, type, image,
                                               this.PRIORITY_INFO_HIGH, buttons);
-            // Create the checkbox on a timeout to allow the XBL to bind first.
-            setTimeout(function(stringBundle, formatter) {
-              if (site) {
-                box.checkbox = document.createElement("checkbox");
-                box.checkbox.className = "rememberChoice";
-                box.checkbox.setAttribute("label", stringBundle.GetStringFromName(type + ".remember"));
-                box.appendChild(box.checkbox);
-              }
-              var link = document.createElement("label");
-              link.className = "text-link";
-              link.setAttribute("value", stringBundle.GetStringFromName(type + ".learnMore"));
-
-              link.setAttribute("href", formatter.formatURLPref("browser.geolocation.warning.infoURL"));
-
-              document.getAnonymousElementByAttribute(box, "anonid", "messageText").appendChild(link);
-            }, 0, this._stringBundle, this._urlFormatter);
+            // Force a style flush, so that we ensure the binding is attached.
+            box.clientTop;
 
             // Create a dummy checkbox so file requests don't try to remember.
             box.checkbox = { checked: false };
+            if (site) {
+              box.checkbox = document.createElement("checkbox");
+              box.checkbox.className = "rememberChoice";
+              box.checkbox.setAttribute("label", this._stringBundle.GetStringFromName(type + ".remember"));
+              box.appendChild(box.checkbox);
+            }
+
+            var link = document.createElement("label");
+            link.className = "text-link";
+            link.setAttribute("value", this._stringBundle.GetStringFromName(type + ".learnMore"));
+            link.setAttribute("href", this._urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"));
+            document.getAnonymousElementByAttribute(box, "anonid", "messageText").appendChild(link);
           ]]>
         </body>
       </method>
 
       <method name="promptIndexedDB">
         <parameter name="aRequestor"/>
         <parameter name="aWindow"/>
         <parameter name="aTopic"/>
@@ -1806,16 +1829,26 @@
             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.activatePlugins);
 
           if (!this.clickToPlayPromptShown)
             this.showPluginClickToPlayPrompt();
         ]]>
       </handler>
 
       <handler event="NewPluginInstalled">
@@ -1850,17 +1883,28 @@
       <handler event="pageshow">
         <![CDATA[
           // The PluginClickToPlay events are not fired when navigating using the
           // BF cache. |event.persisted| is true when the page is loaded from the
           // BF cache, so this code reshows the notification if necessary.
           if (!event.persisted || !this._prefs.getBoolPref("plugins.click_to_play"))
             return;
 
-          if (this.contentWindowUtils.plugins.length)
+          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)
+            return;
+
+          var pluginNeedsActivation = this.contentWindowUtils.plugins.some(function(aPlugin) {
+            var objLoadingContent = aPlugin.QueryInterface(Components.interfaces.nsIObjectLoadingContent);
+            return !objLoadingContent.activated;
+          });
+          if (pluginNeedsActivation)
             this.showPluginClickToPlayPrompt();
         ]]>
       </handler>
     </handlers>
   </binding>
 
   <binding id="popup-notification"
            extends="chrome://communicator/content/bindings/notification.xml#browser-notificationbox">
@@ -1957,26 +2001,51 @@
           ]]>
         </body>
       </method>
 
       <method name="showPluginClickToPlayPrompt">
         <body>
           <![CDATA[
             this.clickToPlayPromptShown = true;
-            var messageString = this._stringBundle.GetStringFromName("activatePluginsMessage.message");
-            var action = {
-              label: this._stringBundle.GetStringFromName("activatePluginsMessage.label"),
-              accessKey: this._stringBundle.GetStringFromName("activatePluginsMessage.accesskey"),
+            const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
+            var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                               .getService(nsIPermissionManager);
+            var messageString = this._stringBundle.GetStringFromName("activatepluginsMessage.title");
+            var mainAction = {
+              label: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.label"),
+              accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.activate.accesskey"),
               callback: this.activatePlugins.bind(this)
             };
-            let options = { dismissed: true };
+            var secondaryActions = [{
+              label: this._stringBundle.GetStringFromName("activatepluginsMessage.always.label"),
+              accessKey: this._stringBundle.GetStringFromName("activatepluginsMessage.always.accesskey"),
+              callback: (function () {
+                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",
+                                                                      this.activeBrowser);
+                if (notification)
+                  notification.remove();
+              }).bind(this)
+            }];
+            var options = {
+              dismissed: true
+            };
             PopupNotifications.show(this.activeBrowser, "click-to-play-plugins",
                                     messageString, "plugins-notification-icon",
-                                    action, null, options);
+                                    mainAction, secondaryActions, options);
            ]]>
         </body>
       </method>
 
       <method name="showGeolocationPrompt">
         <parameter name="file"/>
         <parameter name="site"/>
         <parameter name="image"/>
--- a/suite/locales/en-US/chrome/common/notification.properties
+++ b/suite/locales/en-US/chrome/common/notification.properties
@@ -23,19 +23,26 @@ blockedpluginsMessage.searchButton.acces
 
 crashedpluginsMessage.title=The %S plugin has crashed.
 crashedpluginsMessage.reloadButton.label=Reload page
 crashedpluginsMessage.reloadButton.accesskey=R
 crashedpluginsMessage.submitButton.label=Submit a crash report
 crashedpluginsMessage.submitButton.accesskey=S
 crashedpluginsMessage.learnMore=Learn Moreā€¦
 
-activatePluginsMessage.message=Would you like to activate the plugins on this page?
-activatePluginsMessage.label=Activate plugins
-activatePluginsMessage.accesskey=A
+activatepluginsMessage.title=Would you like to activate the plugins on this page?
+activatepluginsMessage.activate.label=Activate plugins
+activatepluginsMessage.activate.accesskey=A
+activatepluginsMessage.dismiss.label=Don't activate
+activatepluginsMessage.dismiss.accesskey=D
+activatepluginsMessage.remember=Remember for this website
+activatepluginsMessage.always.label=Always activate plugins for this site
+activatepluginsMessage.always.accesskey=c
+activatepluginsMessage.never.label=Never activate plugins for this site
+activatepluginsMessage.never.accesskey=N
 
 popupWarning=%S prevented this website from opening a popup window.
 popupWarningMultiple=%S prevented this website from opening %S popup windows.
 popupWarningButton=Preferences
 popupWarningButton.accesskey=P
 
 xpinstallHostNotAvailable=unknown host
 xpinstallPromptWarning=%S prevented this website (%S) from asking you to install software on your computer.