Bug 1692021 - Order infobars by appearnce rather than priority r=Gijs
☠☠ backed out by e8ccb5d14184 ☠ ☠
authorMark Striemer <mstriemer@mozilla.com>
Thu, 15 Apr 2021 19:20:53 +0000
changeset 576287 b80da7156f2018ea3c9bc5fb00c847a6e1a0f38f
parent 576286 1271c319a2a15f8144e37a771864be1a8afd5026
child 576288 137846a0623352a4faaddbb6258bab4f1e779945
push id141209
push usermstriemer@mozilla.com
push dateThu, 15 Apr 2021 19:31:04 +0000
treeherderautoland@b80da7156f20 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1692021
milestone89.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 1692021 - Order infobars by appearnce rather than priority r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D112238
browser/base/content/browser.js
browser/base/content/moz.build
browser/base/content/test/notificationbox/.eslintrc.js
browser/base/content/test/notificationbox/browser.ini
browser/base/content/test/notificationbox/browser_notification_stacking.js
browser/base/content/test/notificationbox/browser_tabnotificationbox_switch_tabs.js
browser/base/content/test/tabnotificationbox/.eslintrc.js
browser/base/content/test/tabnotificationbox/browser.ini
browser/base/content/test/tabnotificationbox/browser_tabnotificationbox_switch_tabs.js
browser/base/moz.build
toolkit/content/widgets/notificationbox.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -392,16 +392,17 @@ XPCOMUtils.defineLazyGetter(this, "Refer
   )
 );
 
 // High priority notification bars shown at the top of the window.
 XPCOMUtils.defineLazyGetter(this, "gHighPriorityNotificationBox", () => {
   return new MozElements.NotificationBox(element => {
     element.classList.add("global-notificationbox");
     element.setAttribute("notificationside", "top");
+    element.toggleAttribute("prepend-notifications", gProton);
     if (gProton) {
       // With Proton enabled all notification boxes are at the top, built into the browser chrome.
       let tabNotifications = document.getElementById("tab-notification-deck");
       gNavToolbox.insertBefore(element, tabNotifications);
     } else {
       document.getElementById("appcontent").prepend(element);
     }
   });
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -89,17 +89,17 @@ with Files("test/statuspanel/**"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
 with Files("test/sync/**"):
     BUG_COMPONENT = ("Firefox", "Sync")
 
 with Files("test/tabdialogs/**"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
-with Files("test/tabnotificationbox/**"):
+with Files("test/notificationbox/**"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
 with Files("test/tabPrompts/**"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
 with Files("test/tabcrashed/**"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
rename from browser/base/content/test/tabnotificationbox/.eslintrc.js
rename to browser/base/content/test/notificationbox/.eslintrc.js
rename from browser/base/content/test/tabnotificationbox/browser.ini
rename to browser/base/content/test/notificationbox/browser.ini
--- a/browser/base/content/test/tabnotificationbox/browser.ini
+++ b/browser/base/content/test/notificationbox/browser.ini
@@ -1,1 +1,2 @@
+[browser_notification_stacking.js]
 [browser_tabnotificationbox_switch_tabs.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/notificationbox/browser_notification_stacking.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function addNotification(box, label, value, priorityName) {
+  let added = BrowserTestUtils.waitForNotificationInNotificationBox(box, value);
+  let priority =
+    gHighPriorityNotificationBox[`PRIORITY_${priorityName}_MEDIUM`];
+  let notification = box.appendNotification(label, value, null, priority);
+  await added;
+  return notification;
+}
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [["browser.proton.enabled", true]],
+  });
+});
+
+add_task(async function testStackingOrder() {
+  const tabNotificationBox = gBrowser.getNotificationBox();
+  ok(
+    gHighPriorityNotificationBox.stack.hasAttribute("prepend-notifications"),
+    "Browser stack will prepend"
+  );
+  ok(
+    !tabNotificationBox.stack.hasAttribute("prepend-notifications"),
+    "Tab stack will append"
+  );
+
+  let browserOne = await addNotification(
+    gHighPriorityNotificationBox,
+    "My first browser notification",
+    "browser-one",
+    "INFO"
+  );
+
+  let tabOne = await addNotification(
+    tabNotificationBox,
+    "My first tab notification",
+    "tab-one",
+    "CRITICAL"
+  );
+
+  let browserTwo = await addNotification(
+    gHighPriorityNotificationBox,
+    "My second browser notification",
+    "browser-two",
+    "CRITICAL"
+  );
+  let browserThree = await addNotification(
+    gHighPriorityNotificationBox,
+    "My third browser notification",
+    "browser-three",
+    "WARNING"
+  );
+
+  let tabTwo = await addNotification(
+    tabNotificationBox,
+    "My second tab notification",
+    "tab-two",
+    "INFO"
+  );
+  let tabThree = await addNotification(
+    tabNotificationBox,
+    "My third tab notification",
+    "tab-three",
+    "WARNING"
+  );
+
+  Assert.deepEqual(
+    [browserThree, browserTwo, browserOne],
+    [...gHighPriorityNotificationBox.stack.children],
+    "Browser notifications prepended"
+  );
+  Assert.deepEqual(
+    [tabOne, tabTwo, tabThree],
+    [...tabNotificationBox.stack.children],
+    "Tab notifications appended"
+  );
+
+  gHighPriorityNotificationBox.removeAllNotifications(true);
+  tabNotificationBox.removeAllNotifications(true);
+});
rename from browser/base/content/test/tabnotificationbox/browser_tabnotificationbox_switch_tabs.js
rename to browser/base/content/test/notificationbox/browser_tabnotificationbox_switch_tabs.js
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -27,16 +27,17 @@ BROWSER_CHROME_MANIFESTS += [
     "content/test/favicons/browser.ini",
     "content/test/forms/browser.ini",
     "content/test/fullscreen/browser.ini",
     "content/test/general/browser.ini",
     "content/test/historySwipeAnimation/browser.ini",
     "content/test/keyboard/browser.ini",
     "content/test/menubar/browser.ini",
     "content/test/metaTags/browser.ini",
+    "content/test/notificationbox/browser.ini",
     "content/test/outOfProcess/browser.ini",
     "content/test/pageActions-proton/browser.ini",
     "content/test/pageActions/browser.ini",
     "content/test/pageinfo/browser.ini",
     "content/test/pageStyle/browser.ini",
     "content/test/performance/browser.ini",
     "content/test/performance/hidpi/browser.ini",
     "content/test/performance/io/browser.ini",
@@ -52,17 +53,16 @@ BROWSER_CHROME_MANIFESTS += [
     "content/test/siteIdentity/browser.ini",
     "content/test/startup/browser.ini",
     "content/test/static/browser.ini",
     "content/test/statuspanel/browser.ini",
     "content/test/sync/browser.ini",
     "content/test/tabcrashed/browser.ini",
     "content/test/tabdialogs/browser.ini",
     "content/test/tabMediaIndicator/browser.ini",
-    "content/test/tabnotificationbox/browser.ini",
     "content/test/tabPrompts/browser.ini",
     "content/test/tabs/browser.ini",
     "content/test/touch/browser.ini",
     "content/test/webextensions/browser.ini",
     "content/test/webrtc/browser.ini",
     "content/test/webrtc/gracePeriod/browser.ini",
     "content/test/webrtc/legacyIndicator/browser.ini",
     "content/test/zoom/browser.ini",
--- a/toolkit/content/widgets/notificationbox.js
+++ b/toolkit/content/widgets/notificationbox.js
@@ -160,27 +160,16 @@
     ) {
       if (
         aPriority < this.PRIORITY_SYSTEM ||
         aPriority > this.PRIORITY_CRITICAL_HIGH
       ) {
         throw new Error("Invalid notification priority " + aPriority);
       }
 
-      // check for where the notification should be inserted according to
-      // priority. If two are equal, the existing one appears on top.
-      var notifications = this.allNotifications;
-      var insertPos = null;
-      for (var n = notifications.length - 1; n >= 0; n--) {
-        if (notifications[n].priority < aPriority) {
-          break;
-        }
-        insertPos = notifications[n];
-      }
-
       MozXULElement.insertFTLIfNeeded("toolkit/global/notification.ftl");
 
       // Create the Custom Element and connect it to the document immediately.
       var newitem;
       if (this.gProton && !aNotificationIs) {
         if (!customElements.get("notification-message")) {
           // There's some weird timing stuff when this element is created at
           // script load time, we don't need it until now anyway so be lazy.
@@ -189,17 +178,37 @@
         newitem = document.createElement("notification-message");
         newitem.setAttribute("message-bar-type", "infobar");
       } else {
         newitem = document.createXULElement(
           "notification",
           aNotificationIs ? { is: aNotificationIs } : {}
         );
       }
-      this.stack.insertBefore(newitem, insertPos);
+
+      if (this.gProton) {
+        // Append or prepend notification, based on stack preference.
+        if (this.stack.hasAttribute("prepend-notifications")) {
+          this.stack.prepend(newitem);
+        } else {
+          this.stack.append(newitem);
+        }
+      } else {
+        // check for where the notification should be inserted according to
+        // priority. If two are equal, the existing one appears on top.
+        var notifications = this.allNotifications;
+        var insertPos = null;
+        for (var n = notifications.length - 1; n >= 0; n--) {
+          if (notifications[n].priority < aPriority) {
+            break;
+          }
+          insertPos = notifications[n];
+        }
+        this.stack.insertBefore(newitem, insertPos);
+      }
 
       // Custom notification classes may not have the messageText property.
       if (newitem.messageText) {
         // Can't use instanceof in case this was created from a different document:
         if (
           aLabel &&
           typeof aLabel == "object" &&
           aLabel.nodeType &&
@@ -227,17 +236,20 @@
       } else if (aPriority >= this.PRIORITY_CRITICAL_LOW) {
         newitem.setAttribute("type", "critical");
       } else if (aPriority <= this.PRIORITY_INFO_HIGH) {
         newitem.setAttribute("type", "info");
       } else {
         newitem.setAttribute("type", "warning");
       }
 
-      if (!insertPos) {
+      // Animate the notification for proton (all notifications visible)
+      // or if this isn't proton and this is the visible notification (it
+      // was inserted at the top of the stack).
+      if (this.gProton || !insertPos) {
         newitem.style.display = "block";
         newitem.style.position = "fixed";
         newitem.style.top = "100%";
         newitem.style.marginTop = "-15px";
         newitem.style.opacity = "0";
         this._showNotification(newitem, true);
       }