Bug 615318 - Add a "not now" choice to all doorhanger notification split buttons. r=gavin, a=blocking-beta9
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Thu, 16 Dec 2010 09:53:24 -0800
changeset 59409 545fcdd02090d337f6a2a02a1b6fce0a7134aa9e
parent 59408 794e1e461d626e9e6422ab3fad8c45609f6afbe1
child 59410 18a8c936ce3338c39e15ead4a151470c9d10b774
push id17613
push usermargaret.leibovic@gmail.com
push dateThu, 16 Dec 2010 17:57:19 +0000
treeherdermozilla-central@18a8c936ce33 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, blocking-beta9
bugs615318
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 615318 - Add a "not now" choice to all doorhanger notification split buttons. r=gavin, a=blocking-beta9
browser/base/content/test/browser_popupNotification.js
browser/base/content/urlbarBindings.xml
toolkit/content/PopupNotifications.jsm
toolkit/content/widgets/notification.xml
toolkit/locales/en-US/chrome/global/notification.dtd
toolkit/themes/gnomestripe/global/notification.css
toolkit/themes/pinstripe/global/notification.css
toolkit/themes/winstripe/global/notification.css
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -522,16 +522,32 @@ var tests = [
       notifyObj.addOptions({neverShow: true});
       showNotification(notifyObj);
     },
     updateNotShowing: function() {
       isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
             "geo anchor should be visible");
     }
   },
+  // Test notification "Not Now" menu item
+  { // Test #17
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      this.notification = showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      triggerSecondaryCommand(popup, 1);
+    },
+    onHidden: function (popup) {
+      ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
+      this.notification.remove();
+      ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
+    }
+  },
 ];
 
 function showNotification(notifyObj) {
   return PopupNotifications.show(notifyObj.browser,
                                  notifyObj.id,
                                  notifyObj.message,
                                  notifyObj.anchorID,
                                  notifyObj.mainAction,
@@ -553,17 +569,23 @@ function checkPopup(popup, notificationO
   is(notification.getAttribute("label"), notificationObj.message, "message matches");
   is(notification.id, notificationObj.id + "-notification", "id matches");
   if (notificationObj.mainAction) {
     is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
     is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
   }
   let actualSecondaryActions = notification.childNodes;
   let secondaryActions = notificationObj.secondaryActions || [];
-  is(actualSecondaryActions.length, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
+  let actualSecondaryActionsCount = actualSecondaryActions.length;
+  if (secondaryActions.length) {
+    let lastChild = actualSecondaryActions.item(actualSecondaryActions.length - 1);
+    is(lastChild.tagName, "menuseparator", "menuseparator exists");
+    actualSecondaryActionsCount--;
+  }
+  is(actualSecondaryActionsCount, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
   secondaryActions.forEach(function (a, i) {
     is(actualSecondaryActions[i].getAttribute("label"), a.label, "label for secondary action " + i + " matches");
     is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey, "accessKey for secondary action " + i + " matches");
   });
 }
 
 function triggerMainCommand(popup) {
   info("[Test #" + gTestIndex + "] triggering main command");
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -34,16 +34,21 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
+<!DOCTYPE bindings [
+<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
+%notificationDTD;
+]>
+
 <bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
           xmlns:html="http://www.w3.org/1999/xhtml"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
 
     <content sizetopopup="pref">
@@ -1040,21 +1045,25 @@
       <xul:vbox flex="1">
         <xul:description class="popup-notification-description"
                          xbl:inherits="xbl:text=label"/>
         <xul:spacer flex="1"/>
         <xul:hbox pack="end">
           <xul:label anonid="learnmore" class="text-link geolocation-text-link"/>
           <xul:spacer flex="1"/>
           <xul:button anonid="button"
+                      type="menu-button"
                       class="popup-notification-menubutton"
-                      xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey,type=buttontype">
+                      xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
             <xul:menupopup anonid="menupopup"
                            xbl:inherits="oncommand=menucommand">
               <children/>
+              <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
+                            label="&closeNotificationItem.label;"
+                            xbl:inherits="oncommand=closeitemcommand"/>
             </xul:menupopup>
           </xul:button>
         </xul:hbox>
       </xul:vbox>
     </content>
     <implementation>  
       <constructor><![CDATA[
         let link = document.getAnonymousElementByAttribute(this, "anonid", "learnmore");
--- a/toolkit/content/PopupNotifications.jsm
+++ b/toolkit/content/PopupNotifications.jsm
@@ -334,16 +334,23 @@ PopupNotifications.prototype = {
     var index = notifications.indexOf(notification);
     if (index == -1)
       return;
 
     // remove the notification
     notifications.splice(index, 1);
     this._fireCallback(notification, "removed");
   },
+  
+  /**
+   * Dismisses the notification without removing it.
+   */
+  _dismiss: function PopupNotifications_dismiss() {
+    this.panel.hidePopup();
+  },
 
   /**
    * Hides the notification popup.
    */
   _hidePanel: function PopupNotifications_hide() {
     this._ignoreDismissal = true;
     this.panel.hidePopup();
     this._ignoreDismissal = false;
@@ -365,36 +372,39 @@ PopupNotifications.prototype = {
       // Append "-notification" to the ID to try to avoid ID conflicts with other stuff
       // in the document.
       popupnotification.setAttribute("id", n.id + "-notification");
       popupnotification.setAttribute("popupid", n.id);
       if (n.mainAction) {
         popupnotification.setAttribute("buttonlabel", n.mainAction.label);
         popupnotification.setAttribute("buttonaccesskey", n.mainAction.accessKey);
         popupnotification.setAttribute("buttoncommand", "PopupNotifications._onButtonCommand(event);");
-        if (n.secondaryActions.length) {
-          popupnotification.setAttribute("buttontype", "menu-button");
-          popupnotification.setAttribute("menucommand", "PopupNotifications._onMenuCommand(event);");
-        }
+        popupnotification.setAttribute("menucommand", "PopupNotifications._onMenuCommand(event);");
+        popupnotification.setAttribute("closeitemcommand", "PopupNotifications._dismiss();event.stopPropagation();");
       }
       popupnotification.notification = n;
 
-      this.panel.appendChild(popupnotification);
-
       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;
           item.action = a;
 
           popupnotification.appendChild(item);
         }, this);
+  
+        if (n.secondaryActions.length) {
+          let closeItemSeparator = doc.createElementNS(XUL_NS, "menuseparator");
+          popupnotification.appendChild(closeItemSeparator);
+        }
       }
+
+      this.panel.appendChild(popupnotification);
     }, this);
   },
 
   _showPanel: function PopupNotifications_showPanel(notificationsToShow, anchorElement) {
     this.panel.hidden = false;
 
     this._refreshPanel(notificationsToShow);
 
--- a/toolkit/content/widgets/notification.xml
+++ b/toolkit/content/widgets/notification.xml
@@ -424,20 +424,24 @@
                  xbl:inherits="popupid"/>
       <xul:vbox flex="1">
         <xul:description class="popup-notification-description"
                          xbl:inherits="xbl:text=label"/>
         <xul:spacer flex="1"/>
         <xul:hbox pack="end">
           <xul:button anonid="button"
                       class="popup-notification-menubutton"
-                      xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey,type=buttontype">
+                      type="menu-button"
+                      xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
             <xul:menupopup anonid="menupopup"
                            xbl:inherits="oncommand=menucommand">
               <children/>
+              <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
+                            label="&closeNotificationItem.label;"
+                            xbl:inherits="oncommand=closeitemcommand"/>
             </xul:menupopup>
           </xul:button>
         </xul:hbox>
       </xul:vbox>
     </content>
     <resources>
       <stylesheet src="chrome://global/skin/notification.css"/>
     </resources>
--- a/toolkit/locales/en-US/chrome/global/notification.dtd
+++ b/toolkit/locales/en-US/chrome/global/notification.dtd
@@ -1,1 +1,3 @@
-<!ENTITY closeNotification.tooltip "Close this message"> 
+<!ENTITY closeNotification.tooltip "Close this message">
+
+<!ENTITY closeNotificationItem.label "Not Now">
--- a/toolkit/themes/gnomestripe/global/notification.css
+++ b/toolkit/themes/gnomestripe/global/notification.css
@@ -53,8 +53,12 @@ notification[type="critical"] .messageIm
   margin-bottom: 0;
 }
 
 /* Popup notification */
 
 .popup-notification-description {
   max-width: 248px;
 }
+
+.popup-notification-closeitem {
+  list-style-image: url("moz-icon://stock/gtk-close?size=menu");
+}
--- a/toolkit/themes/pinstripe/global/notification.css
+++ b/toolkit/themes/pinstripe/global/notification.css
@@ -149,8 +149,12 @@ notification[type="critical"] .messageIm
 .popup-notification-menubutton:not([type="menu-button"]):hover:active,
 .popup-notification-menubutton > .button-menubutton-button:hover:active,
 .popup-notification-menubutton[open="true"] > .button-menubutton-dropmarker {
   background: -moz-linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9));
   box-shadow: inset 0 0 3px rgba(0,0,0,.2),
               inset 0 1px 7px rgba(0,0,0,.4),
               0 1px 0 rgba(255,255,255,.1);
 }
+
+.popup-notification-closeitem > .menu-iconic-left {
+  display: none;
+}
--- a/toolkit/themes/winstripe/global/notification.css
+++ b/toolkit/themes/winstripe/global/notification.css
@@ -146,8 +146,13 @@ notification[type="critical"] .messageIm
     background-image: -moz-linear-gradient(top, rgba(250,250,250,.9), rgba(200,200,200,.6) 49%, rgba(0,0,0,.23) 51%, rgba(0,0,0,.17) 60%, rgba(0,0,0,.05));
 %else
     background-color: rgba(0,0,0,.05);
 %endif
     box-shadow: 0 0 2px rgba(0,0,0,.65) inset;
   }
 }
 %endif
+
+.popup-notification-closeitem {
+  list-style-image: url("chrome://global/skin/icons/close.png");
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}