Bug 967349 - PopupNotifications should support a "Learn More" link. r=mattn
authorJustin Dolske <dolske@mozilla.com>
Tue, 18 Feb 2014 19:05:34 -0800
changeset 169474 8ffd0d235aab4934949e8e95c64f47a4578387fc
parent 169473 a7f34b3d7fc885ccb6334d4f76c492d62e48cb9a
child 169475 187282aafac115b92dc4f3f74abfa014c4f28c46
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmattn
bugs967349
milestone30.0a1
Bug 967349 - PopupNotifications should support a "Learn More" link. r=mattn
browser/base/content/browser.js
browser/base/content/popup-notifications.inc
browser/components/nsBrowserGlue.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
browser/themes/linux/browser.css
browser/themes/osx/browser.css
browser/themes/windows/browser.css
mobile/android/locales/en-US/chrome/notification.dtd
toolkit/components/social/SocialService.jsm
toolkit/content/widgets/notification.xml
toolkit/locales/en-US/chrome/global/notification.dtd
toolkit/modules/PopupNotifications.jsm
toolkit/themes/linux/global/notification.css
toolkit/themes/osx/global/notification.css
toolkit/themes/windows/global/notification.css
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6498,16 +6498,17 @@ var gIdentityHandler = {
           histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
           // Reload the page with the content unblocked
           BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
         }
       }
     ];
     let options = {
       dismissed: true,
+      learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "mixed-content",
     };
     PopupNotifications.show(gBrowser.selectedBrowser, "mixed-content-blocked",
                             messageString, "mixed-content-blocked-notification-icon",
                             action, secondaryActions, options);
   },
 
   /**
    * Return the eTLD+1 version of the current hostname
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -30,39 +30,27 @@
     </popupnotification>
 
     <popupnotification id="webapps-install-progress-notification" hidden="true">
       <popupnotificationcontent id="webapps-install-progress-content" orient="vertical" align="start">
         <separator class="thin"/>
       </popupnotificationcontent>
     </popupnotification>
 
-    <popupnotification id="geolocation-notification" hidden="true">
-      <popupnotificationcontent orient="vertical" align="start">
-        <separator class="thin"/>
-        <label id="geolocation-learnmore-link" class="text-link"/>
-      </popupnotificationcontent>
-    </popupnotification>
-
     <popupnotification id="servicesInstall-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
-        <separator class="thin"/>
-        <label id="servicesInstall-learnmore-link" class="text-link"/>
+        <!-- XXX bug 974146, tests are looking for this, can't remove yet. -->
       </popupnotificationcontent>
     </popupnotification>
 
     <popupnotification id="pointerLock-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
         <separator class="thin"/>
         <label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
       </popupnotificationcontent>
     </popupnotification>
 
     <popupnotification id="mixed-content-blocked-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
         <separator/>
         <description id="mixed-content-blocked-moreinfo">&mixedContentBlocked.moreinfo;</description>
-        <separator/>
-        <label id="mixed-content-blocked-helplink" class="text-link"
-               onclick="openHelpLink('mixed-content');"
-               value="&mixedContentBlocked.helplink;"/>
       </popupnotificationcontent>
     </popupnotification>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1909,27 +1909,30 @@ ContentPermissionPrompt.prototype = {
       return;
     }
 
     let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
 
     if (perm.type == "pointerLock") {
       // If there's no mainAction, this is the autoAllow warning prompt.
       let autoAllow = !mainAction;
-      aOptions = {
-        removeOnDismissal: autoAllow,
-        eventCallback: type => {
-          if (type == "removed") {
-            browser.removeEventListener("mozfullscreenchange", onFullScreen, true);
-            if (autoAllow) {
-              aRequest.allow();
-            }
+
+      if (!aOptions)
+        aOptions = {};
+
+      aOptions.removeOnDismissal = autoAllow;
+      aOptions.eventCallback = type => {
+        if (type == "removed") {
+          browser.removeEventListener("mozfullscreenchange", onFullScreen, true);
+          if (autoAllow) {
+            aRequest.allow();
           }
-        },
-      };
+        }
+      }
+
     }
 
     var popup = chromeWin.PopupNotifications.show(browser, aNotificationId, aMessage, aAnchorId,
                                                   mainAction, secondaryActions, aOptions);
     if (perm.type == "pointerLock") {
       // pointerLock is automatically allowed in fullscreen mode (and revoked
       // upon exit), so if the page enters fullscreen mode after requesting
       // pointerLock (but before the user has granted permission), we should
@@ -1977,25 +1980,24 @@ ContentPermissionPrompt.prototype = {
         action: Ci.nsIPermissionManager.DENY_ACTION,
         expireType: null,
         callback: function() {
           secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_NEVER_SHARE);
         },
       });
     }
 
-    var chromeWin = this._getBrowserForRequest(aRequest).ownerDocument.defaultView;
-    var link = chromeWin.document.getElementById("geolocation-learnmore-link");
-    link.value = browserBundle.GetStringFromName("geolocation.learnMore");
-    link.href = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL");
+    var options = {
+                    learnMoreURL: Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"),
+                  };
 
     secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST);
 
     this._showPrompt(aRequest, message, "geo", actions, "geolocation",
-                     "geo-notification-icon", null);
+                     "geo-notification-icon", options);
   },
 
   _promptWebNotifications : function(aRequest) {
     var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
     var requestingURI = aRequest.principal.URI;
 
     var message = browserBundle.formatStringFromName("webNotifications.showFromSite",
                                                      [requestingURI.host], 1);
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -704,17 +704,16 @@ just addresses the organization to follo
 <!ENTITY getUserMedia.selectCamera.label "Camera to share:">
 <!ENTITY getUserMedia.selectCamera.accesskey "C">
 <!ENTITY getUserMedia.selectMicrophone.label "Microphone to share:">
 <!ENTITY getUserMedia.selectMicrophone.accesskey "M">
 
 <!ENTITY webrtcIndicatorButton.label "Camera / Microphone Access">
 <!ENTITY webrtcIndicatorButton.tooltip "Display sites you are currently sharing your camera or microphone with">
 
-<!ENTITY mixedContentBlocked.helplink "Learn more">
 <!ENTITY mixedContentBlocked.moreinfo "Most websites will still work properly even when this content is blocked.">
 
 <!ENTITY pointerLock.notification.message "Press ESC at any time to show it again.">
 
 <!ENTITY pluginNotification.showAll.label "Show All">
 <!ENTITY pluginNotification.showAll.accesskey "S">
 
 <!-- LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.properties -->
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -315,19 +315,16 @@ puAlertText=Click here for details
 geolocation.shareLocation=Share Location
 geolocation.shareLocation.accesskey=a
 geolocation.alwaysShareLocation=Always Share Location
 geolocation.alwaysShareLocation.accesskey=A
 geolocation.neverShareLocation=Never Share Location
 geolocation.neverShareLocation.accesskey=N
 geolocation.shareWithSite=Would you like to share your location with %S?
 geolocation.shareWithFile=Would you like to share your location with the file %S?
-# LOCALIZATION NOTE (geolocation.learnMore): Use the unicode ellipsis char, \u2026,
-# or use "..." if \u2026 doesn't suit traditions in your locale.
-geolocation.learnMore=Learn More…
 
 webNotifications.showForSession=Show for this session
 webNotifications.showForSession.accesskey=s
 webNotifications.alwaysShow=Always Show Notifications
 webNotifications.alwaysShow.accesskey=A
 webNotifications.neverShow=Always Block Notifications
 webNotifications.neverShow.accesskey=N
 webNotifications.showFromSite=Would you like to show notifications from %S?
@@ -439,17 +436,16 @@ fullscreenButton.tooltip=Display the win
 
 service.toolbarbutton.label=Services
 service.toolbarbutton.tooltiptext=Services
 
 # LOCALIZATION NOTE (social.install.description): %1$S is the hostname of the social provider, %2$S is brandShortName (e.g. Firefox)
 service.install.description=Would you like to enable services from %1$S to display in your %2$S toolbar and sidebar?
 service.install.ok.label=Enable Services
 service.install.ok.accesskey=E
-service.install.learnmore=Learn More…
 
 # LOCALIZATION NOTE (social.turnOff.label): %S is the name of the social provider
 social.turnOff.label=Turn off %S
 social.turnOff.accesskey=T
 # LOCALIZATION NOTE (social.turnOn.label): %S is the name of the social provider
 social.turnOn.label=Turn on %S
 social.turnOn.accesskey=T
 social.turnOffAll.label=Turn off all Services
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1918,18 +1918,17 @@ toolbar[iconsize="small"] .toolbarbutton
 }
 
 .popup-notification-icon[popupid="servicesInstall"] {
   list-style-image: url(chrome://browser/skin/social/services-64.png);
 }
 #servicesInstall-notification-icon {
   list-style-image: url(chrome://browser/skin/social/services-16.png);
 }
-#social-undoactivation-button,
-#servicesInstall-learnmore-link {
+#social-undoactivation-button {
   -moz-margin-start: 0; /* override default label margin to match description margin */
 }
 
 .social-activation-icon {
   width: auto;
   height: auto;
   max-height: 64px;
   max-width: 64px;
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3299,20 +3299,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 @media (min-resolution: 2dppx) {
   .geo-notification-icon,
   #geo-notification-icon {
     list-style-image: url(chrome://browser/skin/Geolocation-16@2x.png);
   }
 }
 
-#geolocation-learnmore-link {
-  -moz-margin-start: 0; /* override default label margin to match description margin */
-}
-
 .indexedDB-notification-icon,
 #indexedDB-notification-icon {
   list-style-image: url(chrome://global/skin/icons/question-16.png);
 }
 @media (min-resolution: 2dppx) {
   .indexedDB-notification-icon,
   #indexedDB-notification-icon {
     list-style-image: url(chrome://global/skin/icons/question-32.png);
@@ -3595,20 +3591,16 @@ toolbarbutton.chevron > .toolbarbutton-m
     list-style-image: url(chrome://browser/skin/pointerLock-64@2x.png);
   }
 }
 #pointerLock-cancel {
   margin: 0px;
 }
 
 
-#mixed-content-blocked-helplink {
-  margin: 0px;
-}
-
 .popup-notification-icon[popupid="webRTC-sharingDevices"],
 .popup-notification-icon[popupid="webRTC-shareDevices"] {
   list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
 }
 @media (min-resolution: 2dppx) {
   .popup-notification-icon[popupid="webRTC-sharingDevices"],
   .popup-notification-icon[popupid="webRTC-shareDevices"] {
     list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64@2x.png);
@@ -3965,18 +3957,17 @@ toolbar[mode="icons"] > *|* > .toolbarbu
   .popup-notification-icon[popupid="servicesInstall"] {
     list-style-image: url(chrome://browser/skin/social/services-64@2x.png);
   }
   #servicesInstall-notification-icon {
     list-style-image: url(chrome://browser/skin/social/services-16@2x.png);
   }
 }
 
-#social-undoactivation-button,
-#servicesInstall-learnmore-link {
+#social-undoactivation-button {
   -moz-margin-start: 0; /* override default label margin to match description margin */
 }
 
 .social-activation-icon {
   width: auto;
   height: auto;
   max-height: 64px;
   max-width: 64px;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2380,18 +2380,17 @@ toolbarpaletteitem[place="palette"] > #s
 }
 
 .popup-notification-icon[popupid="servicesInstall"] {
   list-style-image: url(chrome://browser/skin/social/services-64.png);
 }
 #servicesInstall-notification-icon {
   list-style-image: url(chrome://browser/skin/social/services-16.png);
 }
-#social-undoactivation-button,
-#servicesInstall-learnmore-link {
+#social-undoactivation-button {
   -moz-margin-start: 0; /* override default label margin to match description margin */
 }
 
 #socialActivatedNotification .popup-notification-button-container {
   margin-left: 6px;
 }
 
 .social-activation-icon {
--- a/mobile/android/locales/en-US/chrome/notification.dtd
+++ b/mobile/android/locales/en-US/chrome/notification.dtd
@@ -1,12 +1,3 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- 
-     LOCALIZATION NOTE (geolocation.learnMore): Use the
-     unicode ellipsis char, \u2026,
-     or use "..." unless \u2026 doesn't suit traditions in your
-     locale.
--->
-<!ENTITY geolocation.learnMore         "Learn More…">
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -569,24 +569,23 @@ this.SocialService = {
     let action = {
       label: browserBundle.GetStringFromName("service.install.ok.label"),
       accessKey: browserBundle.GetStringFromName("service.install.ok.accesskey"),
       callback: function() {
         aAddonInstaller.install();
       },
     };
 
-    let link = chromeWin.document.getElementById("servicesInstall-learnmore-link");
-    link.value = browserBundle.GetStringFromName("service.install.learnmore");
-    link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api";
-
+    let options = {
+                    learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api",
+                  };
     let anchor = "servicesInstall-notification-icon";
     let notificationid = "servicesInstall";
     chromeWin.PopupNotifications.show(browser, notificationid, message, anchor,
-                                      action, [], {});
+                                      action, [], options);
   },
 
   installProvider: function(aDOMDocument, data, installCallback) {
     let manifest;
     let installOrigin = aDOMDocument.nodePrincipal.origin;
 
     if (data) {
       let installType = getOriginActivationType(installOrigin);
--- a/toolkit/content/widgets/notification.xml
+++ b/toolkit/content/widgets/notification.xml
@@ -451,16 +451,18 @@
   <binding id="popup-notification">
     <content align="start">
       <xul:image class="popup-notification-icon"
                  xbl:inherits="popupid,src=icon"/>
       <xul:vbox flex="1">
         <xul:description class="popup-notification-description"
                          xbl:inherits="xbl:text=label"/>
         <children includes="popupnotificationcontent"/>
+        <xul:label class="text-link popup-notification-learnmore-link"
+               xbl:inherits="href=learnmoreurl">&learnMore;</xul:label>
         <xul:spacer flex="1"/>
         <xul:hbox class="popup-notification-button-container"
                   pack="end" align="center">
           <xul:button anonid="button"
                       class="popup-notification-menubutton"
                       type="menu-button"
                       xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
             <xul:menupopup anonid="menupopup"
--- a/toolkit/locales/en-US/chrome/global/notification.dtd
+++ b/toolkit/locales/en-US/chrome/global/notification.dtd
@@ -2,8 +2,10 @@
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!ENTITY closeNotification.tooltip "Close this message">
 
 <!ENTITY closeNotificationItem.label "Not Now">
 
 <!ENTITY checkForUpdates "Check for updates…">
+
+<!ENTITY learnMore "Learn more…">
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -255,16 +255,20 @@ PopupNotifications.prototype = {
    *                     not be shown. If 'Not Now' is hidden, it needs to be
    *                     replaced by another 'do nothing' item, so providing at
    *                     least one secondary action is required; and one of the
    *                     actions needs to have the 'dismiss' property set to true.
    *        popupIconURL:
    *                     A string. URL of the image to be displayed in the popup.
    *                     Normally specified in CSS using list-style-image and the
    *                     .popup-notification-icon[popupid=...] selector.
+   *        learnMoreURL:
+   *                     A string URL. Setting this property will make the
+   *                     prompt display a "Learn More" link that, when clicked,
+   *                     opens the URL in a new tab.
    * @returns the Notification object corresponding to the added notification.
    */
   show: function PopupNotifications_show(browser, id, message, anchorID,
                                          mainAction, secondaryActions, options) {
     function isInvalidAction(a) {
       return !a || !(typeof(a.callback) == "function") || !a.label || !a.accessKey;
     }
 
@@ -542,16 +546,21 @@ PopupNotifications.prototype = {
         popupnotification.removeAttribute("buttonaccesskey");
         popupnotification.removeAttribute("buttoncommand");
         popupnotification.removeAttribute("menucommand");
         popupnotification.removeAttribute("closeitemcommand");
       }
 
       if (n.options.popupIconURL)
         popupnotification.setAttribute("icon", n.options.popupIconURL);
+      if (n.options.learnMoreURL)
+        popupnotification.setAttribute("learnmoreurl", n.options.learnMoreURL);
+      else
+        popupnotification.removeAttribute("learnmoreurl");
+
       popupnotification.notification = n;
 
       if (n.secondaryActions) {
         n.secondaryActions.forEach(function (a) {
           let item = doc.createElementNS(XUL_NS, "menuitem");
           item.setAttribute("label", a.label);
           item.setAttribute("accesskey", a.accessKey);
           item.notification = n;
--- a/toolkit/themes/linux/global/notification.css
+++ b/toolkit/themes/linux/global/notification.css
@@ -58,15 +58,23 @@ notification[type="critical"] {
 }
 
 /* Popup notification */
 
 .popup-notification-description {
   max-width: 24em;
 }
 
+.popup-notification-learnmore-link {
+  margin-top: 1em !important;
+}
+
+.popup-notification-learnmore-link:not([href]) {
+  display: none;
+}
+
 .popup-notification-button-container {
   margin-top: 17px;
 }
 
 .popup-notification-closeitem {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
--- a/toolkit/themes/osx/global/notification.css
+++ b/toolkit/themes/osx/global/notification.css
@@ -85,16 +85,25 @@ notification[type="critical"] {
 }
 
 /* Popup notification */
 
 .popup-notification-description {
   max-width: 24em;
 }
 
+.popup-notification-learnmore-link {
+  margin-top: 1em !important;
+  -moz-margin-start: 0 !important; /* override default label margin to match description margin */
+}
+
+.popup-notification-learnmore-link:not([href]) {
+  display: none;
+}
+
 .popup-notification-button-container {
   margin-top: 17px;
 }
 
 .popup-notification-menubutton {
   -moz-appearance: none;
 }
 
--- a/toolkit/themes/windows/global/notification.css
+++ b/toolkit/themes/windows/global/notification.css
@@ -52,16 +52,24 @@ notification[type="critical"] {
 }
 
 /* Popup notification */
 
 .popup-notification-description {
   max-width: 24em;
 }
 
+.popup-notification-learnmore-link {
+  margin-top: 1em !important;
+}
+
+.popup-notification-learnmore-link:not([href]) {
+  display: none;
+}
+
 .popup-notification-button-container {
   margin-top: 17px;
 }
 
 %ifdef XP_WIN
 /*
 XXX: apply styles to all themes until bug 509642 is fixed
 @media (-moz-windows-default-theme) {