Backout bug 831737 / changeset a3767eefc685 due to permanent orange on Linux. CLOSED TREE
authorMark Banner <bugzilla@standard8.plus.com>
Mon, 04 Feb 2013 12:32:52 +0000
changeset 14785 0587280f759e00b4c54924d761ae157f793ff5f2
parent 14784 2482caee1e4fb9d9c89c66b28a5880046068ef49
child 14786 0317bb637a4842e5e4ef59d43c78db919937b313
push idunknown
push userunknown
push dateunknown
bugs831737
Backout bug 831737 / changeset a3767eefc685 due to permanent orange on Linux. CLOSED TREE
mail/app/profile/all-thunderbird.js
mail/base/content/newmailalert.js
mail/base/content/newmailalert.xul
mail/base/jar.mn
mail/themes/gnomestripe/mail/newmailalert.css
mail/themes/qute/mail/newmailalert.css
mailnews/base/content/newmailalert.css
mailnews/base/content/newmailalert.js
mailnews/base/content/newmailalert.xul
mailnews/jar.mn
mailnews/mailnews.js
suite/browser/browser-prefs.js
suite/mailnews/jar.mn
suite/mailnews/newmailalert.css
suite/mailnews/newmailalert.js
suite/mailnews/newmailalert.xul
--- a/mail/app/profile/all-thunderbird.js
+++ b/mail/app/profile/all-thunderbird.js
@@ -209,16 +209,21 @@ pref("general.smoothScroll", true);
 pref("general.autoScroll", false);
 #else
 pref("general.autoScroll", true);
 #endif
 
 pref("mail.shell.checkDefaultClient", true);
 pref("mail.spellcheck.inline", true);
 
+pref("mail.biff.alert.show_preview", true);
+pref("mail.biff.alert.show_subject", true);
+pref("mail.biff.alert.show_sender",  true);
+pref("mail.biff.alert.preview_length", 40);
+
 pref("mail.folder.views.version", 0);
 
 // target folder URI used for the last move or copy
 pref("mail.last_msg_movecopy_target_uri", "");
 // last move or copy operation was a move
 pref("mail.last_msg_movecopy_was_move", true);
 
 #ifdef XP_WIN
@@ -390,17 +395,17 @@ pref("spellchecker.dictionaries.download
 
 // profile.force.migration can be used to bypass the migration wizard, forcing migration from a particular
 // mail application without any user intervention. Possible values are: 
 // seamonkey (mozilla suite), eudora, oexpress, outlook.
 pref("profile.force.migration", "");
 
 // prefs to control the mail alert notification
 pref("alerts.slideIncrementTime", 50);
-pref("alerts.totalOpenTime", 10000);
+pref("alerts.totalOpenTime", 3000);
 
 // analyze urls in mail messages for scams
 pref("mail.phishing.detection.enabled", true);
 // If phishing detection is enabled, allow fine grained control
 // of the local, static tests
 pref("mail.phishing.detection.ipaddresses", true); 
 pref("mail.phishing.detection.mismatched_hosts", true);
 
new file mode 100644
--- /dev/null
+++ b/mail/base/content/newmailalert.js
@@ -0,0 +1,190 @@
+/* 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/. */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+const HORIZONTAL = 1;
+const LEFT = 2;
+const TOP = 4;
+
+var gSlideTime = 50;
+var gNumNewMsgsToShowInAlert = 4; // the more messages we show in the alert, the larger it will be
+var gOpenTime = 3000; // total time the alert should stay up once we are done animating.
+var gAlertListener = null;
+var gPendingPreviewFetchRequests = 0;
+var gUserInitiated = false;
+var gFadeIncrement = .05;
+var gOrigin = 0;
+
+function prefillAlertInfo()
+{
+  // unwrap all the args....
+  // arguments[0] --> array of folders with new mail
+  // arguments[1] --> the observer to call back with notifications about the alert
+  // arguments[2] --> user initiated boolean. true if the user initiated opening the alert 
+  //                 (which means skip the fade effect and don't auto close the alert)
+  // arguments[3] --> the alert origin returned by the look and feel
+  var foldersWithNewMail = window.arguments[0];  
+  gAlertListener = window.arguments[1];
+  gUserInitiated = window.arguments[2];
+  gOrigin = window.arguments[3];
+
+  // For now just grab the first folder which should be a root folder
+  // for the account that has new mail. If we can't find a folder, just
+  // return to avoid the exception and empty dialog in upper left-hand corner.
+  let rootFolder;
+  if (foldersWithNewMail && foldersWithNewMail.Count() > 0)
+     rootFolder = foldersWithNewMail.GetElementAt(0)
+                    .QueryInterface(Components.interfaces.nsIWeakReference)
+                    .QueryReferent(Components.interfaces.nsIMsgFolder);
+  else
+   return;
+
+  // generate an account label string based on the root folder
+  var label = document.getElementById('alertTitle');
+  var totalNumNewMessages = rootFolder.getNumNewMessages(true);
+  label.value = document.getElementById('bundle_messenger').getFormattedString(totalNumNewMessages == 1 ? "newMailNotification_message" : "newMailNotification_messages", 
+                                                                                     [rootFolder.prettiestName, totalNumNewMessages]);
+
+  // this is really the root folder and we have to walk through the list to find the real folder that has new mail in it...:(
+  var allFolders = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
+  rootFolder.ListDescendents(allFolders);
+  var numFolders = allFolders.Count();
+  var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
+  folderSummaryInfoEl.mMaxMsgHdrsInPopup = gNumNewMsgsToShowInAlert;
+  for (var folderIndex = 0; folderIndex < numFolders; folderIndex++)
+  {
+    var folder = allFolders.GetElementAt(folderIndex).QueryInterface(Components.interfaces.nsIMsgFolder);
+    const nsMsgFolderFlags = Components.interfaces.nsMsgFolderFlags;
+    if (folder.hasNewMessages && !(folder.flags & nsMsgFolderFlags.Virtual))
+    {
+      var asyncFetch = {};
+      folderSummaryInfoEl.parseFolder(folder, new urlListener(folder), asyncFetch);
+      if (asyncFetch.value)
+        gPendingPreviewFetchRequests++;
+    }
+  }
+}
+
+function urlListener(aFolder)
+{
+  this.mFolder = aFolder;
+}
+
+urlListener.prototype = {
+  OnStartRunningUrl: function(aUrl)
+  {
+  },
+
+  OnStopRunningUrl: function(aUrl, aExitCode)
+  {
+    var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
+    var asyncFetch = {};
+    folderSummaryInfoEl.parseFolder(this.mFolder, null, asyncFetch);
+    gPendingPreviewFetchRequests--;
+
+    // when we are done running all of our urls for fetching the preview text,
+    // start the alert.
+    if (!gPendingPreviewFetchRequests)
+      showAlert();
+  }
+}
+
+function onAlertLoad()
+{
+  prefillAlertInfo();
+  // read out our initial settings from prefs.
+  try 
+  {
+    gSlideTime = Services.prefs.getIntPref("alerts.slideIncrementTime");
+    gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime");
+  } catch (ex) {}
+  
+  // bogus call to make sure the window is moved offscreen until we are ready for it.
+  resizeAlert(true);
+
+  // if we aren't waiting to fetch preview text, then go ahead and 
+  // start showing the alert.
+  if (!gPendingPreviewFetchRequests)
+    setTimeout(showAlert, 0); // let the JS thread unwind, to give layout 
+                              // a chance to recompute the styles and widths for our alert text.
+}
+
+// If the user initiated the alert, show it right away, otherwise start opening the alert with
+// the fade effect. 
+function showAlert()
+{
+  if (!gUserInitiated) // set the initial opacity before we resize the window
+    document.getElementById('alertContainer').style.opacity = 0;
+  
+  // resize the alert based on our current content  
+  resizeAlert(false);
+  
+  if (document.getElementById('folderSummaryInfo').hasMessages)
+  {
+    if (!gUserInitiated) // don't fade in if the user opened the alert
+      setTimeout(fadeOpen, gSlideTime);
+  }
+  else
+    closeAlert(); // no mail, so don't bother showing the alert...
+}
+
+function resizeAlert(aMoveOffScreen)
+{
+  // sizeToContent is not working. It isn't honoring the max widths we are attaching to our inner
+  // objects like the folder summary element. While the folder summary element is cropping, 
+  // sizeToContent ends up thinking the window needs to be much wider than it should be. 
+  // use resizeTo and make up our measurements...
+  //sizeToContent();
+  
+  // Use the wider of the alert groove and the folderSummaryInfo box, then 
+  // add on the width of alertImageBox + some small amount of fudge. For the height, 
+  // just use the size of the alertBox, that appears to be pretty accurate.
+  var windowWidth = Math.max (document.getBoxObjectFor(document.getElementById('alertGroove')).width,
+                              document.getBoxObjectFor(document.getElementById('folderSummaryInfo')).width);
+  resizeTo(windowWidth + document.getBoxObjectFor(document.getElementById('alertImageBox')).width + 30, 
+           document.getBoxObjectFor(document.getElementById('alertBox')).height + 10);                     
+  
+  // leftover hack to get the window properly hidden when we first open it
+  if (aMoveOffScreen)
+    window.outerHeight = 1;
+
+  // Determine position and move window
+  var x = gOrigin & LEFT ? screen.availLeft :
+          (screen.availLeft + screen.availWidth - window.outerWidth);
+  var y = gOrigin & TOP ? screen.availTop :
+          (screen.availTop + screen.availHeight - window.outerHeight);
+  window.moveTo(x, y);
+}
+
+function fadeOpen()
+{
+  var alertContainer = document.getElementById('alertContainer');
+  var newOpacity = parseFloat(window.getComputedStyle(alertContainer, "").opacity) + gFadeIncrement;
+  alertContainer.style.opacity = newOpacity;
+  
+  if (newOpacity < 1.0)    
+    setTimeout(fadeOpen, gSlideTime);
+  else // switch gears and start closing the alert
+    setTimeout(fadeClose, gOpenTime);  
+}
+
+function fadeClose()
+{
+  var alertContainer = document.getElementById('alertContainer');
+  var newOpacity = parseFloat(window.getComputedStyle(alertContainer, "").opacity) - gFadeIncrement;
+  alertContainer.style.opacity = newOpacity;
+  
+  if (newOpacity <= 0)
+    closeAlert();
+  else
+    setTimeout(fadeClose, gSlideTime);
+}
+
+function closeAlert()
+{
+  if (gAlertListener)
+    gAlertListener.observe(null, "alertfinished", ""); 
+  window.close(); 
+}
new file mode 100644
--- /dev/null
+++ b/mail/base/content/newmailalert.xul
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://messenger/skin/newmailalert.css" type="text/css"?>
+
+<window id="newMailAlertNotification"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        windowtype="alert:alert"
+        role="alert"
+        align="start"
+        onload="onAlertLoad()">
+
+  <stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
+  <script type="application/javascript" src="chrome://messenger/content/newmailalert.js"/>
+
+  <stack id="alertContainer" mousethrough="always">
+    <hbox id="alertBox">
+      <hbox id ="alertImageBox" align="center" valign="center">
+        <image id="alertImage"/>
+      </hbox>
+
+      <vbox id="alertTextBox">
+        <label id="alertTitle"/>
+        <separator id="alertGroove" class="groove"/>
+        <folderSummary id="folderSummaryInfo" mousethrough="never"/>
+      </vbox>
+    </hbox>
+
+    <hbox align="top">
+      <spacer flex="1"/>
+      <toolbarbutton id="closeButton" onclick="closeAlert();"/>
+    </hbox>
+  </stack>
+</window>
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -65,16 +65,18 @@ messenger.jar:
     content/messenger/searchBar.js                  (content/searchBar.js)
     content/messenger/phishingDetector.js           (content/phishingDetector.js)
     content/messenger/mail-offline.js               (content/mail-offline.js)
     content/messenger/aboutDialog.css               (content/aboutDialog.css)
     content/messenger/messenger.css                 (content/messenger.css)
     content/messenger/search.xml                    (content/search.xml)
     content/messenger/tabmail.xml                   (content/tabmail.xml)
     content/messenger/tabmail.css                   (content/tabmail.css)
+    content/messenger/newmailalert.xul              (content/newmailalert.xul)
+    content/messenger/newmailalert.js               (content/newmailalert.js)
     content/messenger/newTagDialog.xul              (content/newTagDialog.xul)
     content/messenger/newTagDialog.js               (content/newTagDialog.js)
 *   content/messenger/viewSourceOverlay.xul         (content/viewSourceOverlay.xul)
     content/messenger/configEditorOverlay.xul       (content/configEditorOverlay.xul)
     content/messenger/EdSpellCheckOverlay.xul       (content/EdSpellCheckOverlay.xul)
     content/messenger/EdSpellCheckOverlay.js        (content/EdSpellCheckOverlay.js)
     content/messenger/composerOverlay.css           (content/composerOverlay.css)
     content/messenger/threadPane.js                 (content/threadPane.js)
--- a/mail/themes/gnomestripe/mail/newmailalert.css
+++ b/mail/themes/gnomestripe/mail/newmailalert.css
@@ -6,37 +6,54 @@
 /* ===== alert.css =====================================================
   == Styles specific to the alerts dialog.
   ======================================================================= */
 
 @import url("chrome://messenger/skin/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
-#newMailAlertNotification {
-  -moz-appearance: none;
+/*
+ * See bug 332160. Apply these rules on #alertContainer instead of on
+ * #newMailAlertNotification like on windows.
+ */
+#alertContainer {
   min-height: 60px;
   border: ridge #5486DA 4px;
+  background-color: -moz-Dialog;
+  color: -moz-DialogText;
+}
+
+#newMailAlertNotification {
+  border: none; /* See bug 332160. */
 }
 
 #alertImage {
   list-style-image: url("chrome://branding/content/icon64.png");
 }
 
 #alertImageBox {
-  padding: 4px;
+  -moz-margin-start: 4px;
+  -moz-margin-end: 6px;
+  min-height: 46px;
 }
 
 #alertTitle {
   font-weight: bold;
+  text-align: center;
+  /* this right margin keeps us from overlapping with the
+     close button. It's value should be related to the width
+     of the closeButtonImage
+  */
+  -moz-margin-end: 16px;
 }
 
 #alertTextBox {
-  padding: 4px;
-  -moz-padding-end: 20px;
+  -moz-padding-end: 10px;
+  padding-top: 5px;
 }
 
 .folderSummary-message-row
 {
   /* This max width ends up dictating the overall width of the alert window
      because it controls how large the preview, subject and sender text can be
      before cropping kicks in */
   max-width: 450px;
@@ -60,17 +77,21 @@
   color: blue;
 }
 
 #closeButton {
   list-style-image: url("chrome://messenger/skin/icons/close-button.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
   -moz-appearance: none;
   border: none !important;
-  padding: 2px;
+  padding: 2px 0px 0px;
+}
+
+#closeButton > .toolbarbutton-icon {
+  -moz-margin-end: 0px; /* override toolkit's default value */
 }
 
 #closeButton:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #closeButton:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
--- a/mail/themes/qute/mail/newmailalert.css
+++ b/mail/themes/qute/mail/newmailalert.css
@@ -9,33 +9,43 @@
 
 @import url("chrome://messenger/skin/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 #newMailAlertNotification {
   min-height: 60px;
   border: ridge #5486DA 4px;
+  background-color: -moz-Dialog;
+  color: -moz-DialogText;
 }
 
 #alertImage {
   list-style-image: url("chrome://branding/content/icon64.png");
 }
 
 #alertImageBox {
-  padding: 4px;
+  -moz-margin-start: 4px;
+  -moz-margin-end: 6px;
+  min-height: 46px;
 }
 
 #alertTitle {
   font-weight: bold;
+  text-align: center;
+  /* this right margin keeps us from overlapping with the
+     close button. It's value should be related to the width
+     of the closeButtonImage
+  */
+  -moz-margin-end: 16px;
 }
 
 #alertTextBox {
-  padding: 4px;
-  -moz-padding-end: 20px;
+  -moz-padding-end: 10px;
+  padding-top: 5px;
 }
 
 .folderSummary-message-row
 {
   /* This max width ends up dictating the overall width of the alert window
      because it controls how large the preview, subject and sender text can be
      before cropping kicks in */
   max-width: 450px;
@@ -59,17 +69,21 @@
   color: blue;
 }
 
 #closeButton {
   list-style-image: url("chrome://messenger/skin/icons/close-button.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
   -moz-appearance: none;
   border: none !important;
-  padding: 2px;
+  padding: 2px 0px 0px;
+}
+
+#closeButton > .toolbarbutton-icon {
+  -moz-margin-end: 0px; /* override toolkit's default value */
 }
 
 #closeButton:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #closeButton:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
deleted file mode 100644
--- a/mailnews/base/content/newmailalert.css
+++ /dev/null
@@ -1,35 +0,0 @@
-/* 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/. */
-
-#alertContainer {
-  opacity: 0;
-}
-
-#alertContainer[noanimation] {
-  opacity: 1;
-}
-
-#alertContainer[fade-in] {
-  animation-timing-function: ease-out;
-  animation-duration: 2s;
-  animation-fill-mode: both;
-  animation-name: fade-in;
-}
-
-@keyframes fade-in {
-  from {opacity: 0;}
-  to {opacity: 1;}
-}
-
-#alertContainer[fade-out] {
-  animation-timing-function: ease-in;
-  animation-duration: 2s;
-  animation-fill-mode: both;
-  animation-name: fade-out;
-}
-
-@keyframes fade-out {
-  from {opacity: 1;}
-  to {opacity: 0;}
-}
deleted file mode 100644
--- a/mailnews/base/content/newmailalert.js
+++ /dev/null
@@ -1,191 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-// Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin
-const NS_ALERT_HORIZONTAL = 1;
-const NS_ALERT_LEFT = 2;
-const NS_ALERT_TOP = 4;
-
-var gNumNewMsgsToShowInAlert = 4; // the more messages we show in the alert, the larger it will be
-var gOpenTime = 4000; // total time the alert should stay up once we are done animating.
-
-var gAlertListener = null;
-var gPendingPreviewFetchRequests = 0;
-var gUserInitiated = false;
-var gOrigin = 0; // Default value: alert from bottom right.
-
-function prefillAlertInfo()
-{
-  // unwrap all the args....
-  // arguments[0] --> array of folders with new mail
-  // arguments[1] --> the observer to call back with notifications about the alert
-  // arguments[2] --> user initiated boolean. true if the user initiated opening the alert
-  //                 (which means skip the fade effect and don't auto close the alert)
-  // arguments[3] --> the alert origin returned by the look and feel
-  var foldersWithNewMail = window.arguments[0];
-  gAlertListener = window.arguments[1];
-  gUserInitiated = window.arguments[2];
-  gOrigin = window.arguments[3];
-
-  // For now just grab the first folder which should be a root folder
-  // for the account that has new mail. If we can't find a folder, just
-  // return to avoid the exception and empty dialog in upper left-hand corner.
-  var rootFolder;
-  if (!foldersWithNewMail || foldersWithNewMail.Count() < 1)
-    return;
-  rootFolder = foldersWithNewMail.GetElementAt(0)
-                                 .QueryInterface(Components.interfaces.nsIWeakReference)
-                                 .QueryReferent(Components.interfaces.nsIMsgFolder);
-
-  // Generate an account label string based on the root folder.
-  var label = document.getElementById('alertTitle');
-  var totalNumNewMessages = rootFolder.getNumNewMessages(true);
-  var message = totalNumNewMessages == 1 ? "newMailNotification_message"
-                                         : "newMailNotification_messages";
-  label.value = document.getElementById('bundle_messenger')
-                        .getFormattedString(message,
-                                            [rootFolder.prettiestName, totalNumNewMessages]);
-
-  // This is really the root folder and we have to walk through the list to
-  // find the real folder that has new mail in it...:(
-  var allFolders = Components.classes["@mozilla.org/supports-array;1"]
-                             .createInstance(Components.interfaces.nsISupportsArray);
-  rootFolder.ListDescendents(allFolders);
-  var numFolders = allFolders.Count();
-  var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
-  folderSummaryInfoEl.mMaxMsgHdrsInPopup = gNumNewMsgsToShowInAlert;
-  for (let folderIndex = 0; folderIndex < numFolders; folderIndex++)
-  {
-    var folder = allFolders.GetElementAt(folderIndex)
-                           .QueryInterface(Components.interfaces.nsIMsgFolder);
-    const nsMsgFolderFlags = Components.interfaces.nsMsgFolderFlags;
-    if (folder.hasNewMessages && !(folder.flags & nsMsgFolderFlags.Virtual))
-    {
-      var asyncFetch = {};
-      folderSummaryInfoEl.parseFolder(folder, new urlListener(folder), asyncFetch);
-      if (asyncFetch.value)
-        gPendingPreviewFetchRequests++;
-    }
-  }
-}
-
-function urlListener(aFolder)
-{
-  this.mFolder = aFolder;
-}
-
-urlListener.prototype =
-{
-  OnStartRunningUrl: function(aUrl)
-  {
-  },
-
-  OnStopRunningUrl: function(aUrl, aExitCode)
-  {
-    var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
-    folderSummaryInfoEl.parseFolder(this.mFolder, null, {});
-    gPendingPreviewFetchRequests--;
-
-    // when we are done running all of our urls for fetching the preview text,
-    // start the alert.
-    if (!gPendingPreviewFetchRequests)
-      showAlert();
-  }
-}
-
-function onAlertLoad()
-{
-  prefillAlertInfo();
-  // read out our initial settings from prefs.
-  try
-  {
-    gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime");
-  } catch (ex) {}
-
-  // bogus call to make sure the window is moved offscreen until we are ready for it.
-  resizeAlert(true);
-
-  // if we aren't waiting to fetch preview text, then go ahead and
-  // start showing the alert.
-  if (!gPendingPreviewFetchRequests)
-    setTimeout(showAlert, 0); // let the JS thread unwind, to give layout
-                              // a chance to recompute the styles and widths for our alert text.
-}
-
-// If the user initiated the alert, show it right away, otherwise start opening the alert with
-// the fade effect.
-function showAlert()
-{
-  if (!document.getElementById("folderSummaryInfo").hasMessages) {
-    closeAlert(); // no mail, so don't bother showing the alert...
-    return;
-  }
-
-  // resize the alert based on our current content
-  resizeAlert(false);
-
-  var alertContainer = document.getElementById("alertContainer");
-  // Don't fade in if the user opened the alert or the pref is true.
-  if (gUserInitiated ||
-      Services.prefs.getBoolPref("alerts.disableSlidingEffect")) {
-    alertContainer.setAttribute("noanimation", true);
-    setTimeout(closeAlert, gOpenTime);
-    return;
-  }
-
-  alertContainer.addEventListener("animationend", function hideAlert(event) {
-    if (event.animationName == "fade-in") {
-      alertContainer.removeEventListener("animationend", hideAlert, false);
-      let remaining = Math.max(Math.round(gOpenTime - event.elapsedTime * 1000), 0);
-      setTimeout(fadeOutAlert, remaining);
-    }
-  }, false);
-  alertContainer.setAttribute("fade-in", true);
-}
-
-function resizeAlert(aMoveOffScreen)
-{
-  var alertTextBox = document.getElementById("alertTextBox");
-  var alertImageBox = document.getElementById("alertImageBox");
-  alertImageBox.style.minHeight = alertTextBox.scrollHeight + "px";
-
-  sizeToContent();
-
-  // leftover hack to get the window properly hidden when we first open it
-  if (aMoveOffScreen)
-    window.outerHeight = 1;
-
-  // Determine position
-  var x = gOrigin & NS_ALERT_LEFT ? screen.availLeft :
-          screen.availLeft + screen.availWidth - window.outerWidth;
-  var y = gOrigin & NS_ALERT_TOP ? screen.availTop :
-          screen.availTop + screen.availHeight - window.outerHeight;
-
-  // Offset the alert by 10 pixels from the edge of the screen
-  y += gOrigin & NS_ALERT_TOP ? 10 : -10;
-  x += gOrigin & NS_ALERT_LEFT ? 10 : -10;
-
-  window.moveTo(x, y);
-}
-
-function fadeOutAlert()
-{
-  var alertContainer = document.getElementById("alertContainer");
-  alertContainer.addEventListener("animationend", function fadeOut(event) {
-    if (event.animationName == "fade-out") {
-      alertContainer.removeEventListener("animationend", fadeOut, false);
-      closeAlert();
-    }
-  }, false);
-  alertContainer.setAttribute("fade-out", true);
-}
-
-function closeAlert()
-{
-  if (gAlertListener)
-    gAlertListener.observe(null, "alertfinished", "");
-  window.close();
-}
deleted file mode 100644
--- a/mailnews/base/content/newmailalert.xul
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://messenger/content/newmailalert.css" type="text/css"?>
-<?xml-stylesheet href="chrome://messenger/skin/newmailalert.css" type="text/css"?>
-
-<window id="newMailAlertNotification"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        windowtype="alert:alert"
-        role="alert"
-        align="start"
-        onload="onAlertLoad()">
-
-  <stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
-  <script type="application/javascript" src="chrome://messenger/content/newmailalert.js"/>
-
-  <stack id="alertContainer" mousethrough="always">
-    <hbox id="alertBox">
-      <hbox id ="alertImageBox" align="center" pack="center">
-        <image id="alertImage"/>
-      </hbox>
-
-      <vbox id="alertTextBox">
-        <label id="alertTitle"/>
-        <separator id="alertGroove" class="groove"/>
-        <folderSummary id="folderSummaryInfo" mousethrough="never"/>
-      </vbox>
-    </hbox>
-
-    <toolbarbutton id="closeButton" top="0" right="0" onclick="closeAlert();"/>
-  </stack>
-</window>
--- a/mailnews/jar.mn
+++ b/mailnews/jar.mn
@@ -121,11 +121,8 @@ messenger.jar:
     content/messenger/fieldMapImport.js                                        (import/content/fieldMapImport.js)
     content/messenger/downloadheaders.js                                       (news/content/downloadheaders.js)
     content/messenger/downloadheaders.xul                                      (news/content/downloadheaders.xul)
     content/messenger/markByDate.js                                            (base/content/markByDate.js)
     content/messenger/markByDate.xul                                           (base/content/markByDate.xul)
     content/messenger/dateFormat.js                                            (base/content/dateFormat.js)
     content/messenger/shutdownWindow.xul                                       (base/content/shutdownWindow.xul)
     content/messenger/shutdownWindow.js                                        (base/content/shutdownWindow.js)
-    content/messenger/newmailalert.css                                         (base/content/newmailalert.css)
-    content/messenger/newmailalert.js                                          (base/content/newmailalert.js)
-    content/messenger/newmailalert.xul                                         (base/content/newmailalert.xul)
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -603,21 +603,16 @@ pref("mail.imap.confirm_emptyTrashFolder
 pref("mailnews.append_preconfig_accounts.version", 1);
 
 // Pref controlling the updates on the pre-configured smtp servers.
 // In order to add new pre-configured smtp servers (after a version),
 // increase the following version number besides updating the
 // pref mail.smtpservers.appendsmtpservers
 pref("mail.append_preconfig_smtpservers.version", 1);
 
-pref("mail.biff.alert.show_preview", true);
-pref("mail.biff.alert.show_subject", true);
-pref("mail.biff.alert.show_sender",  true);
-pref("mail.biff.alert.preview_length", 40);
-
 pref("mail.biff.play_sound", true);
 // 0 == default system sound, 1 == user specified wav
 pref("mail.biff.play_sound.type", 0);
 // _moz_mailbeep is a magic key, for the default sound.
 // otherwise, this needs to be a file url
 pref("mail.biff.play_sound.url", "");
 pref("mail.biff.show_alert", true);
 pref("mail.biff.show_tray_icon", true); // currently Windows-only
--- a/suite/browser/browser-prefs.js
+++ b/suite/browser/browser-prefs.js
@@ -320,16 +320,20 @@ pref("javascript.options.showInConsole",
 pref("offline.startup_state",            0);
 pref("offline.send.unsent_messages",            0);
 pref("offline.download.download_messages",  0);
 
 pref("browser.offline-apps.notify", true);
 
 pref("browser.formfill.expire_days",        180);
 
+pref("mail.biff.alert.show_preview", true);
+pref("mail.biff.alert.show_subject", true);
+pref("mail.biff.alert.show_sender",  true);
+pref("mail.biff.alert.preview_length", 40);
 pref("mail.biff.show_new_alert",     true);
 
 pref("mailnews.ui.deleteMarksRead", true);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bugs 746055 and 768015.)
 pref("image.mem.max_decoded_image_kb", 256000);
@@ -660,17 +664,17 @@ pref("sidebar.customize.directory.url", 
 pref("sidebar.customize.more_panels.url", "http://dmoz.org/Netscape/Sidebar/");
 pref("sidebar.num_tabs_in_view", 8);
 
 pref("browser.throbber.url","chrome://navigator-region/locale/region.properties");
 
 // pref to control the alert notification 
 pref("alerts.slideIncrement", 1);
 pref("alerts.slideIncrementTime", 10);
-pref("alerts.totalOpenTime", 10000);
+pref("alerts.totalOpenTime", 4000);
 
 // 0 opens the download manager
 // 1 opens a progress dialog
 // 2 and other values, no download manager, no progress dialog. 
 pref("browser.download.manager.behavior", 0);
 
 pref("privacy.popups.sound_enabled",              false);
 pref("privacy.popups.sound_type",                 1);
--- a/suite/mailnews/jar.mn
+++ b/suite/mailnews/jar.mn
@@ -53,16 +53,19 @@ messenger.jar:
     content/messenger/mailEditorOverlay.xul
     content/messenger/mailKeysOverlay.xul
     content/messenger/phishingDetector.js
     content/messenger/mailOverlay.xul
     content/messenger/mailOverlay.js
     content/messenger/mail-offline.js
     content/messenger/mailContextMenus.js
     content/messenger/msgFolderPickerOverlay.xul
+    content/messenger/newmailalert.css
+    content/messenger/newmailalert.js
+    content/messenger/newmailalert.xul
     content/messenger/start.xhtml
     content/messenger/messengerdnd.js
     content/messenger/mailPrefsOverlay.xul                                     (prefs/mailPrefsOverlay.xul)
     content/messenger/pref-mailnews.xul                                        (prefs/pref-mailnews.xul)
     content/messenger/pref-mailnews.js                                         (prefs/pref-mailnews.js)
     content/messenger/pref-notifications.xul                                   (prefs/pref-notifications.xul)
     content/messenger/pref-notifications.js                                    (prefs/pref-notifications.js)
     content/messenger/pref-junk.xul                                            (prefs/pref-junk.xul)
new file mode 100644
--- /dev/null
+++ b/suite/mailnews/newmailalert.css
@@ -0,0 +1,23 @@
+/* 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/. */
+
+#alertContainer {
+  opacity: 0;
+}
+
+#alertContainer[noanimation] {
+  opacity: 1;
+}
+
+#alertContainer[animate] {
+  animation-timing-function: ease-out;
+  animation-duration: 4s;
+  animation-fill-mode: both;
+  animation-name: alert-animation;
+}
+
+@keyframes alert-animation {
+  from {opacity: 0;}
+  to {opacity: 1;}
+}
new file mode 100644
--- /dev/null
+++ b/suite/mailnews/newmailalert.js
@@ -0,0 +1,181 @@
+/* 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/. */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+// Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin
+const NS_ALERT_HORIZONTAL = 1;
+const NS_ALERT_LEFT = 2;
+const NS_ALERT_TOP = 4;
+
+var gNumNewMsgsToShowInAlert = 4; // the more messages we show in the alert, the larger it will be
+var gOpenTime = 4000; // total time the alert should stay up once we are done animating.
+
+var gAlertListener = null;
+var gPendingPreviewFetchRequests = 0;
+var gUserInitiated = false;
+var gOrigin = 0; // Default value: alert from bottom right.
+
+function prefillAlertInfo()
+{
+  // unwrap all the args....
+  // arguments[0] --> array of folders with new mail
+  // arguments[1] --> the observer to call back with notifications about the alert
+  // arguments[2] --> user initiated boolean. true if the user initiated opening the alert 
+  //                 (which means skip the fade effect and don't auto close the alert)
+  // arguments[3] --> the alert origin returned by the look and feel
+  var foldersWithNewMail = window.arguments[0];  
+  gAlertListener = window.arguments[1];
+  gUserInitiated = window.arguments[2];
+  gOrigin = window.arguments[3];
+
+  // For now just grab the first folder which should be a root folder
+  // for the account that has new mail. If we can't find a folder, just
+  // return to avoid the exception and empty dialog in upper left-hand corner.
+  var rootFolder;
+  if (!foldersWithNewMail || foldersWithNewMail.Count() < 1)
+    return;
+  rootFolder = foldersWithNewMail.GetElementAt(0)
+                                 .QueryInterface(Components.interfaces.nsIWeakReference)
+                                 .QueryReferent(Components.interfaces.nsIMsgFolder);
+
+  // Generate an account label string based on the root folder.
+  var label = document.getElementById('alertTitle');
+  var totalNumNewMessages = rootFolder.getNumNewMessages(true);
+  var message = totalNumNewMessages == 1 ? "newMailNotification_message"
+                                         : "newMailNotification_messages";
+  label.value = document.getElementById('bundle_messenger')
+                        .getFormattedString(message, 
+                                            [rootFolder.prettiestName, totalNumNewMessages]);
+
+  // This is really the root folder and we have to walk through the list to
+  // find the real folder that has new mail in it...:(
+  var allFolders = Components.classes["@mozilla.org/supports-array;1"]
+                             .createInstance(Components.interfaces.nsISupportsArray);
+  rootFolder.ListDescendents(allFolders);
+  var numFolders = allFolders.Count();
+  var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
+  folderSummaryInfoEl.mMaxMsgHdrsInPopup = gNumNewMsgsToShowInAlert;
+  for (let folderIndex = 0; folderIndex < numFolders; folderIndex++)
+  {
+    var folder = allFolders.GetElementAt(folderIndex)
+                           .QueryInterface(Components.interfaces.nsIMsgFolder);
+    const nsMsgFolderFlags = Components.interfaces.nsMsgFolderFlags;
+    if (folder.hasNewMessages && !(folder.flags & nsMsgFolderFlags.Virtual))
+    {
+      var asyncFetch = {};
+      folderSummaryInfoEl.parseFolder(folder, new urlListener(folder), asyncFetch);
+      if (asyncFetch.value)
+        gPendingPreviewFetchRequests++;
+    }
+  }
+}
+
+function urlListener(aFolder)
+{
+  this.mFolder = aFolder;
+}
+
+urlListener.prototype =
+{
+  OnStartRunningUrl: function(aUrl)
+  {
+  },
+
+  OnStopRunningUrl: function(aUrl, aExitCode)
+  {
+    var folderSummaryInfoEl = document.getElementById('folderSummaryInfo');
+    folderSummaryInfoEl.parseFolder(this.mFolder, null, {});
+    gPendingPreviewFetchRequests--;
+
+    // when we are done running all of our urls for fetching the preview text,
+    // start the alert.
+    if (!gPendingPreviewFetchRequests)
+      showAlert();
+  }
+}
+
+function onAlertLoad()
+{
+  prefillAlertInfo();
+  // read out our initial settings from prefs.
+  try 
+  {
+    gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime");
+  } catch (ex) {}
+  
+  // bogus call to make sure the window is moved offscreen until we are ready for it.
+  resizeAlert(true);
+
+  // if we aren't waiting to fetch preview text, then go ahead and 
+  // start showing the alert.
+  if (!gPendingPreviewFetchRequests)
+    setTimeout(showAlert, 0); // let the JS thread unwind, to give layout 
+                              // a chance to recompute the styles and widths for our alert text.
+}
+
+// If the user initiated the alert, show it right away, otherwise start opening the alert with
+// the fade effect. 
+function showAlert()
+{
+  // resize the alert based on our current content  
+  resizeAlert(false);
+  
+  var alertContainer = document.getElementById("alertContainer");
+  // Don't fade in if the user opened the alert or the pref is true.
+  if (gUserInitiated ||
+      Services.prefs.getBoolPref("alerts.disableSlidingEffect")) {
+    alertContainer.setAttribute("noanimation", true);
+    setTimeout(closeAlert, gOpenTime);
+    return;
+  }
+  
+  if (document.getElementById('folderSummaryInfo').hasMessages)
+  {
+    alertContainer.addEventListener("animationend", function hideAlert(event) {
+      if (event.animationName == "alert-animation") {
+        alertContainer.removeEventListener("animationend", hideAlert, false);
+        let remaining = Math.max(Math.round(gOpenTime - event.elapsedTime * 1000), 0);
+        setTimeout(closeAlert, remaining);
+      }
+    }, false);
+    alertContainer.setAttribute("animate", true);
+  }
+  else
+  {
+    closeAlert(); // no mail, so don't bother showing the alert...
+  }
+}
+
+function resizeAlert(aMoveOffScreen)
+{
+  var alertTextBox = document.getElementById("alertTextBox");
+  var alertImageBox = document.getElementById("alertImageBox");
+  alertImageBox.style.minHeight = alertTextBox.scrollHeight + "px";
+
+  sizeToContent();
+  
+  // leftover hack to get the window properly hidden when we first open it
+  if (aMoveOffScreen)
+    window.outerHeight = 1;
+
+  // Determine position
+  var x = gOrigin & NS_ALERT_LEFT ? screen.availLeft :
+          screen.availLeft + screen.availWidth - window.outerWidth;
+  var y = gOrigin & NS_ALERT_TOP ? screen.availTop :
+          screen.availTop + screen.availHeight - window.outerHeight;
+
+  // Offset the alert by 10 pixels from the edge of the screen
+  y += gOrigin & NS_ALERT_TOP ? 10 : -10;
+  x += gOrigin & NS_ALERT_LEFT ? 10 : -10;
+
+  window.moveTo(x, y);
+}
+
+function closeAlert()
+{
+  if (gAlertListener)
+    gAlertListener.observe(null, "alertfinished", ""); 
+  window.close(); 
+}
new file mode 100644
--- /dev/null
+++ b/suite/mailnews/newmailalert.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://messenger/content/newmailalert.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/newmailalert.css" type="text/css"?>
+
+<window id="newMailAlertNotification"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        windowtype="alert:alert"
+        role="alert"
+        align="start"
+        onload="onAlertLoad()">
+
+  <stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
+  <script type="application/javascript" src="chrome://messenger/content/newmailalert.js"/>
+
+  <stack id="alertContainer" mousethrough="always">
+    <hbox id="alertBox">
+      <hbox id ="alertImageBox" align="center" pack="center">
+        <image id="alertImage"/>
+      </hbox>
+
+      <vbox id="alertTextBox">
+        <label id="alertTitle"/>
+        <separator id="alertGroove" class="groove"/>
+        <folderSummary id="folderSummaryInfo" mousethrough="never"/>
+      </vbox>
+    </hbox>
+
+    <toolbarbutton id="closeButton" top="0" right="0" onclick="closeAlert();"/>
+  </stack>
+</window>