Bug 882858 - Add a "showing" notification to PopupNotifications, r=jaws sr=gavin
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 19 Jun 2013 13:29:05 -0400
changeset 135654 d7a1b18447fec42c393aa5e7091b3c9854b21618
parent 135653 a72d816724daddc2dc1cea8a96f100d07e377505
child 135655 61b6312cfab23a38dc75c4ce24570f9f9c881760
push id24847
push userkwierso@gmail.com
push dateWed, 19 Jun 2013 23:38:15 +0000
treeherdermozilla-central@8ea92aeab783 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, gavin
bugs882858
milestone24.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 882858 - Add a "showing" notification to PopupNotifications, r=jaws sr=gavin
browser/base/content/test/browser_CTP_drag_drop.js
browser/base/content/test/browser_pluginnotification.js
browser/base/content/test/browser_plugins_added_dynamically.js
browser/base/content/test/browser_popupNotification.js
toolkit/modules/PopupNotifications.jsm
--- a/browser/base/content/test/browser_CTP_drag_drop.js
+++ b/browser/base/content/test/browser_CTP_drag_drop.js
@@ -127,17 +127,20 @@ function part11() {
   // we have to actually show the panel to get the bindings to instantiate
   notification.options.eventCallback = part12;
   // this scripts the plugin, triggering the popup notification
   try {
     gNewWindow.gBrowser.selectedBrowser.contentDocument.getElementById("test").wrappedJSObject.getObjectValue();
   } catch (e) {}
 }
 
-function part12() {
+function part12(type) {
+  if (type != "shown") {
+    return;
+  }
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser);
   notification.options.eventCallback = null;
   let centerAction = null;
   for (let action of notification.options.centerActions) {
     if (action.message == "Test") {
       centerAction = action;
       break;
     }
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -713,16 +713,19 @@ function test18e() {
 function test18f() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 18f, Should have a click-to-play notification");
   ok(notification.dismissed, "Test 18f, notification should start dismissed");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 18f, Plugin should not be activated");
 
+  // XXXBAD: this code doesn't do what you think it does! it is actually
+  // observing the "removed" event of the old notification, since we create
+  // a *new* one when the plugin is clicked.
   notification.options.eventCallback = function() { executeSoon(test18g); };
   EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
 }
 
 function test18g() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 18g, Should have a click-to-play notification");
   ok(!notification.dismissed, "Test 18g, notification should be open");
@@ -874,17 +877,20 @@ function test21a() {
     ok(!objLoadingContent.activated, "Test 21a, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   // we have to actually show the panel to get the bindings to instantiate
   notification.options.eventCallback = test21b;
   notification.reshow();
 }
 
-function test21b() {
+function test21b(type) {
+  if (type != "shown") {
+    return;
+  }
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   notification.options.eventCallback = null;
   var centerAction = null;
   for (var action of notification.options.centerActions) {
     if (action.message == "Test") {
       centerAction = action;
       break;
     }
@@ -933,17 +939,20 @@ function test21c() {
     ok(!objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   // we have to actually show the panel to get the bindings to instantiate
   notification.options.eventCallback = test21d;
   notification.reshow();
 }
 
-function test21d() {
+function test21d(type) {
+  if (type != "shown") {
+    return;
+  }
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   notification.options.eventCallback = null;
 
   var centerAction = null;
   for (var action of notification.options.centerActions) {
     if (action.message == "Second Test") {
       centerAction = action;
       break;
--- a/browser/base/content/test/browser_plugins_added_dynamically.js
+++ b/browser/base/content/test/browser_plugins_added_dynamically.js
@@ -106,17 +106,20 @@ function testActivateAddSameTypePart2() 
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "testActivateAddSameTypePart2: should have a click-to-play notification");
 
   // we have to actually show the panel to get the bindings to instantiate
   popupNotification.options.eventCallback = testActivateAddSameTypePart3;
   popupNotification.reshow();
 }
 
-function testActivateAddSameTypePart3() {
+function testActivateAddSameTypePart3(type) {
+  if (type != "shown") {
+    return;
+  }
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   popupNotification.options.eventCallback = null;
   let centerAction = null;
   for (let action of popupNotification.options.centerActions) {
     if (action.message == "Test") {
       centerAction = action;
       break;
     }
@@ -184,17 +187,20 @@ function testActivateAddDifferentTypePar
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "testActivateAddDifferentTypePart2: should have a click-to-play notification");
 
   // we have to actually show the panel to get the bindings to instantiate
   popupNotification.options.eventCallback = testActivateAddDifferentTypePart3;
   popupNotification.reshow();
 }
 
-function testActivateAddDifferentTypePart3() {
+function testActivateAddDifferentTypePart3(type) {
+  if (type != "shown") {
+    return;
+  }
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   popupNotification.options.eventCallback = null;
   let centerAction = null;
   for (let action of popupNotification.options.centerActions) {
     if (action.message == "Test") {
       centerAction = action;
       break;
     }
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -132,16 +132,19 @@ function basicNotification() {
     }
   ];
   this.options = {
     eventCallback: function (eventName) {
       switch (eventName) {
         case "dismissed":
           self.dismissalCallbackTriggered = true;
           break;
+        case "showing":
+          self.showingCallbackTriggered = true;
+          break;
         case "shown":
           self.shownCallbackTriggered = true;
           break;
         case "removed":
           self.removedCallbackTriggered = true;
           break;
       }
     }
@@ -853,32 +856,54 @@ var tests = [
          "notification2 anchor should be visible");
 
       dismissNotification(popup);
     },
     onHidden: function(popup) {
       this.notification1.remove();
       this.notification2.remove();
     }
+  },
+  { // Test #30 - Showing should be able to modify the popup data
+    run: function() {
+      this.notifyObj = new basicNotification();
+      var normalCallback = this.notifyObj.options.eventCallback;
+      this.notifyObj.options.eventCallback = function (eventName) {
+        if (eventName == "showing") {
+          this.mainAction.label = "Alternate Label";
+        }
+        normalCallback.call(this, eventName);
+      };
+      showNotification(this.notifyObj);
+    },
+    onShown: function(popup) {
+      // checkPopup checks for the matching label. Note that this assumes that
+      // this.notifyObj.mainAction is the same as notification.mainAction,
+      // which could be a problem if we ever decided to deep-copy.
+      checkPopup(popup, this.notifyObj);
+      triggerMainCommand(popup);
+    },
+    onHidden: function() { }
   }
 ];
 
 function showNotification(notifyObj) {
   return PopupNotifications.show(notifyObj.browser,
                                  notifyObj.id,
                                  notifyObj.message,
                                  notifyObj.anchorID,
                                  notifyObj.mainAction,
                                  notifyObj.secondaryActions,
                                  notifyObj.options);
 }
 
 function checkPopup(popup, notificationObj) {
   info("[Test #" + gTestIndex + "] checking popup");
 
+  ok(notificationObj.showingCallbackTriggered, "showing callback was triggered");
   ok(notificationObj.shownCallbackTriggered, "shown callback was triggered");
 
   let notifications = popup.childNodes;
   is(notifications.length, 1, "one notification displayed");
   let notification = notifications[0];
   if (!notification)
     return;
   let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -5,16 +5,17 @@
 this.EXPORTED_SYMBOLS = ["PopupNotifications"];
 
 var Cc = Components.classes, Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 const NOTIFICATION_EVENT_DISMISSED = "dismissed";
 const NOTIFICATION_EVENT_REMOVED = "removed";
+const NOTIFICATION_EVENT_SHOWING = "showing";
 const NOTIFICATION_EVENT_SHOWN = "shown";
 
 const ICON_SELECTOR = ".notification-anchor-icon";
 const ICON_ATTRIBUTE_SHOWING = "showing";
 
 const PREF_SECURITY_DELAY = "security.notification_enable_delay";
 
 let popupNotificationsMap = new WeakMap();
@@ -516,16 +517,19 @@ PopupNotifications.prototype = {
       // document rather than creating it ad hoc.
       popupnotification.hidden = false;
     }, this);
   },
 
   _showPanel: function PopupNotifications_showPanel(notificationsToShow, anchorElement) {
     this.panel.hidden = false;
 
+    notificationsToShow.forEach(function (n) {
+      this._fireCallback(n, NOTIFICATION_EVENT_SHOWING);
+    }, this);
     this._refreshPanel(notificationsToShow);
 
     if (this.isPanelOpen && this._currentAnchorElement == anchorElement)
       return;
 
     // If the panel is already open but we're changing anchors, we need to hide
     // it first.  Otherwise it can appear in the wrong spot.  (_hidePanel is
     // safe to call even if the panel is already hidden.)