Bug 1287178 - Add a dismissed event for <xul:notification> when they're dismissed via the close button. r=Felipe
authorMike Conley <mconley@mozilla.com>
Fri, 02 Sep 2016 14:09:42 -0400
changeset 355121 1599a90dcf2a052cd6f5493548b6ba0b7848c8f5
parent 355120 58846175232c221d1d6eccfdd9e26c1d41044f98
child 355122 aa1dbdd224f63af213d89e13c489ccfef7e33e91
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe
bugs1287178
milestone51.0a1
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 1287178 - Add a dismissed event for <xul:notification> when they're dismissed via the close button. r=Felipe MozReview-Commit-ID: 4bTq0g5a33j
toolkit/content/tests/chrome/test_notificationbox.xul
toolkit/content/widgets/notification.xml
--- a/toolkit/content/tests/chrome/test_notificationbox.xul
+++ b/toolkit/content/tests/chrome/test_notificationbox.xul
@@ -43,32 +43,45 @@ function testtag_notificationbox(nb)
   SimpleTest.is(nb.removeAllNotifications(false), undefined, "initial removeAllNotifications");
   testtag_notificationbox_State(nb, "initial removeAllNotifications", null, 0);
   SimpleTest.is(nb.removeAllNotifications(true), undefined, "initial removeAllNotifications immediate");
   testtag_notificationbox_State(nb, "initial removeAllNotifications immediate", null, 0);
 
   runTimedTests(tests, -1, nb, null);
 }
 
-var notification_last_event, notification_last_event_item;
+var notification_last_events = [];
 function notification_eventCallback(event)
 {
-  notification_last_event = event;
-  notification_last_event_item = this;
+  notification_last_events.push({ actualEvent: event , item: this });
 }
 
-function testtag_notification_eventCallback(expectedEvent, ntf, testName)
+/**
+ * For any notifications that have the notification_eventCallback on
+ * them, we will have recorded instances of those callbacks firing
+ * and stored them. This checks to see that the expected event types
+ * are being fired in order, and targeting the right item.
+ *
+ * @param {Array<string>} expectedEvents
+ *        The list of event types, in order, that we expect to have been
+ *        fired on the item.
+ * @param {<xul:notification>} ntf
+ *        The notification we expect the callback to have been fired from.
+ * @param {string} testName
+ *        The name of the current test, for logging.
+ */
+function testtag_notification_eventCallback(expectedEvents, ntf, testName)
 {
-  SimpleTest.is(notification_last_event, expectedEvent,
-                testName + ": event name");
-  SimpleTest.is(notification_last_event_item, ntf,
-                testName + ": event item");
-
-  notification_last_event = null;
-  notification_last_event_item = null;
+  for (let i = 0; i < expectedEvents; ++i) {
+    let expected = expectedEvents[i];
+    let { actualEvent, item } = notification_last_events[i];
+    SimpleTest.is(actualEvent, expected, testName + ": event name");
+    SimpleTest.is(item, ntf, testName + ": event item");
+  }
+  notification_last_events = [];
 }
 
 var tests =
 [
   {
     test: function(nb, ntf) {
       // append a new notification
       var ntf = nb.appendNotification("Notification", "note", "happy.png",
@@ -128,17 +141,46 @@ var tests =
     test: function(nb, ntf) {
       nb.removeNotification(ntf);
       return ntf;
     },
     result: function(nb, ntf) {
       testtag_notificationbox_State(nb, "removeNotification with callback",
                                     null, 0);
 
-      testtag_notification_eventCallback("removed", ntf, "removeNotification()");
+      testtag_notification_eventCallback(["removed"], ntf, "removeNotification()");
+      return ntf;
+    }
+  },
+  {
+    test: function(nb, ntf) {
+      var ntf = nb.appendNotification("Notification", "note", "happy.png",
+                                      nb.PRIORITY_INFO_LOW,
+                                      testtag_notificationbox_buttons,
+                                      notification_eventCallback);
+      SimpleTest.is(ntf && ntf.localName == "notification", true, "append notification with callback");
+      return ntf;
+    },
+    result: function(nb, ntf) {
+      testtag_notificationbox_State(nb, "append with callback", ntf, 1);
+      return ntf;
+    }
+  },
+  {
+    test: function(rb, ntf) {
+      // Dismissing the notification instead of removing it should
+      // fire a dismissed "event" on the callback, followed by
+      // a removed "event".
+      ntf.dismiss();
+      return ntf;
+    },
+    result: function(nb, ntf) {
+      testtag_notificationbox_State(nb, "called dismiss()", null, 0);
+      testtag_notification_eventCallback(["dismissed", "removed"], ntf,
+                                         "dismiss()");
       return ntf;
     }
   },
   {
     test: function(nb, ntf) {
       // Create a popup to be used by a menu-button.
       var doc = nb.ownerDocument;
       var menuPopup = doc.createElementNS(NSXUL, "menupopup");
--- a/toolkit/content/widgets/notification.xml
+++ b/toolkit/content/widgets/notification.xml
@@ -390,17 +390,17 @@
           <xul:description anonid="messageText" class="messageText" flex="1" xbl:inherits="xbl:text=label"/>
           <xul:spacer flex="1"/>
           <children/>
         </xul:hbox>
         <xul:toolbarbutton ondblclick="event.stopPropagation();"
                            class="messageCloseButton close-icon tabbable"
                            xbl:inherits="hidden=hideclose"
                            tooltiptext="&closeNotification.tooltip;"
-                           oncommand="document.getBindingParent(this).close();"/>
+                           oncommand="document.getBindingParent(this).dismiss();"/>
       </xul:hbox>
     </content>
     <resources>
       <stylesheet src="chrome://global/skin/notification.css"/>
     </resources>
     <implementation>
       <property name="label" onset="this.setAttribute('label', val); return val;"
                              onget="return this.getAttribute('label');"/>
@@ -425,16 +425,31 @@
                 return parent;
               parent = parent.parentNode;
             }
             return null;
           ]]>
         </getter>
       </property>
 
+      <!-- This method should only be called when the user has
+           manually closed the notification. If you want to
+           programmatically close the notification, you should
+           call close() instead. -->
+      <method name="dismiss">
+        <body>
+          <![CDATA[
+            if (this.eventCallback) {
+              this.eventCallback("dismissed");
+            }
+            this.close();
+          ]]>
+        </body>
+      </method>
+
       <method name="close">
         <body>
           <![CDATA[
             var control = this.control;
             if (control)
               control.removeNotification(this);
             else
               this.hidden = true;