summaryrefslogtreecommitdiffstats
path: root/mailnews/base/src/nsMessengerUnixIntegration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/base/src/nsMessengerUnixIntegration.cpp')
-rw-r--r--mailnews/base/src/nsMessengerUnixIntegration.cpp762
1 files changed, 762 insertions, 0 deletions
diff --git a/mailnews/base/src/nsMessengerUnixIntegration.cpp b/mailnews/base/src/nsMessengerUnixIntegration.cpp
new file mode 100644
index 000000000..0e4dd1405
--- /dev/null
+++ b/mailnews/base/src/nsMessengerUnixIntegration.cpp
@@ -0,0 +1,762 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "nsMessengerUnixIntegration.h"
+#include "nsIMsgAccountManager.h"
+#include "nsIMsgMailSession.h"
+#include "nsIMsgIncomingServer.h"
+#include "nsIMsgIdentity.h"
+#include "nsIMsgAccount.h"
+#include "nsIMsgFolder.h"
+#include "nsIMsgWindow.h"
+#include "nsCOMPtr.h"
+#include "nsMsgBaseCID.h"
+#include "nsMsgFolderFlags.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIDirectoryService.h"
+#include "nsIWindowWatcher.h"
+#include "nsIWindowMediator.h"
+#include "mozIDOMWindow.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDocShell.h"
+#include "nsIBaseWindow.h"
+#include "MailNewsTypes.h"
+#include "nsIMessengerWindowService.h"
+#include "prprf.h"
+#include "nsIWeakReference.h"
+#include "nsIStringBundle.h"
+#include "nsIAlertsService.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIMsgDatabase.h"
+#include "nsIMsgHdr.h"
+#include "nsAutoPtr.h"
+#include "prmem.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIWeakReferenceUtils.h"
+
+#include "nsNativeCharsetUtils.h"
+#include "nsToolkitCompsCID.h"
+#include "nsMsgUtils.h"
+#include "msgCore.h"
+#include "nsCOMArray.h"
+#include "nsIMutableArray.h"
+#include "nsArrayUtils.h"
+#include "nsMemory.h"
+#include "mozilla/Services.h"
+#include "mozilla/mailnews/MimeHeaderParser.h"
+
+#define ALERT_CHROME_URL "chrome://messenger/content/newmailalert.xul"
+#define NEW_MAIL_ALERT_ICON "chrome://messenger/skin/icons/new-mail-alert.png"
+#define SHOW_ALERT_PREF "mail.biff.show_alert"
+#define SHOW_ALERT_PREVIEW_LENGTH "mail.biff.alert.preview_length"
+#define SHOW_ALERT_PREVIEW_LENGTH_DEFAULT 40
+#define SHOW_ALERT_PREVIEW "mail.biff.alert.show_preview"
+#define SHOW_ALERT_SENDER "mail.biff.alert.show_sender"
+#define SHOW_ALERT_SUBJECT "mail.biff.alert.show_subject"
+#define SHOW_ALERT_SYSTEM "mail.biff.use_system_alert"
+
+using namespace mozilla::mailnews;
+
+static void openMailWindow(const nsACString& aFolderUri)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgMailSession> mailSession ( do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIMsgWindow> topMostMsgWindow;
+ rv = mailSession->GetTopmostMsgWindow(getter_AddRefs(topMostMsgWindow));
+ if (topMostMsgWindow)
+ {
+ if (!aFolderUri.IsEmpty())
+ {
+ nsCOMPtr<nsIMsgWindowCommands> windowCommands;
+ topMostMsgWindow->GetWindowCommands(getter_AddRefs(windowCommands));
+ if (windowCommands)
+ windowCommands->SelectFolder(aFolderUri);
+ }
+
+ nsCOMPtr<mozIDOMWindowProxy> domWindow;
+ topMostMsgWindow->GetDomWindow(getter_AddRefs(domWindow));
+ if (domWindow) {
+ nsCOMPtr<nsPIDOMWindowOuter> privateWindow = nsPIDOMWindowOuter::From(domWindow);
+ privateWindow->Focus();
+ }
+ }
+ else
+ {
+ // the user doesn't have a mail window open already so open one for them...
+ nsCOMPtr<nsIMessengerWindowService> messengerWindowService =
+ do_GetService(NS_MESSENGERWINDOWSERVICE_CONTRACTID);
+ // if we want to preselect the first account with new mail,
+ // here is where we would try to generate a uri to pass in
+ // (and add code to the messenger window service to make that work)
+ if (messengerWindowService)
+ messengerWindowService->OpenMessengerWindowWithUri(
+ "mail:3pane", nsCString(aFolderUri).get(), nsMsgKey_None);
+ }
+}
+
+nsMessengerUnixIntegration::nsMessengerUnixIntegration()
+{
+ mBiffStateAtom = MsgGetAtom("BiffState");
+ mNewMailReceivedAtom = MsgGetAtom("NewMailReceived");
+ mAlertInProgress = false;
+ mFoldersWithNewMail = do_CreateInstance(NS_ARRAY_CONTRACTID);
+}
+
+NS_IMPL_ISUPPORTS(nsMessengerUnixIntegration, nsIFolderListener, nsIObserver,
+ nsIMessengerOSIntegration, nsIUrlListener)
+
+nsresult
+nsMessengerUnixIntegration::Init()
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv,rv);
+ return mailSession->AddFolderListener(this, nsIFolderListener::intPropertyChanged);
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemPropertyChanged(nsIMsgFolder *, nsIAtom *, char const *, char const *)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemUnicharPropertyChanged(nsIMsgFolder *, nsIAtom *, const char16_t *, const char16_t *)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemRemoved(nsIMsgFolder *, nsISupports *)
+{
+ return NS_OK;
+}
+
+nsresult nsMessengerUnixIntegration::GetStringBundle(nsIStringBundle **aBundle)
+{
+ NS_ENSURE_ARG_POINTER(aBundle);
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::services::GetStringBundleService();
+ NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
+ nsCOMPtr<nsIStringBundle> bundle;
+ bundleService->CreateBundle("chrome://messenger/locale/messenger.properties",
+ getter_AddRefs(bundle));
+ bundle.swap(*aBundle);
+ return NS_OK;
+}
+
+bool
+nsMessengerUnixIntegration::BuildNotificationTitle(nsIMsgFolder *aFolder, nsIStringBundle *aBundle, nsString &aTitle)
+{
+ nsString accountName;
+ aFolder->GetPrettiestName(accountName);
+
+ int32_t numNewMessages = 0;
+ aFolder->GetNumNewMessages(true, &numNewMessages);
+
+ if (!numNewMessages)
+ return false;
+
+ nsAutoString numNewMsgsText;
+ numNewMsgsText.AppendInt(numNewMessages);
+
+ const char16_t *formatStrings[] =
+ {
+ accountName.get(), numNewMsgsText.get()
+ };
+
+ aBundle->FormatStringFromName(numNewMessages == 1 ?
+ u"newMailNotification_message" :
+ u"newMailNotification_messages",
+ formatStrings, 2, getter_Copies(aTitle));
+ return true;
+}
+
+/* This comparator lets us sort an nsCOMArray of nsIMsgDBHdr's by
+ * their dateInSeconds attributes in ascending order.
+ */
+static int
+nsMsgDbHdrTimestampComparator(nsIMsgDBHdr *aElement1,
+ nsIMsgDBHdr *aElement2,
+ void *aData)
+{
+ uint32_t aElement1Timestamp;
+ nsresult rv = aElement1->GetDateInSeconds(&aElement1Timestamp);
+ if (NS_FAILED(rv))
+ return 0;
+
+ uint32_t aElement2Timestamp;
+ rv = aElement2->GetDateInSeconds(&aElement2Timestamp);
+ if (NS_FAILED(rv))
+ return 0;
+
+ return aElement1Timestamp - aElement2Timestamp;
+}
+
+
+bool
+nsMessengerUnixIntegration::BuildNotificationBody(nsIMsgDBHdr *aHdr,
+ nsIStringBundle *aBundle,
+ nsString &aBody)
+{
+ nsAutoString alertBody;
+
+ bool showPreview = true;
+ bool showSubject = true;
+ bool showSender = true;
+ int32_t previewLength = SHOW_ALERT_PREVIEW_LENGTH_DEFAULT;
+
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (!prefBranch)
+ return false;
+
+ prefBranch->GetBoolPref(SHOW_ALERT_PREVIEW, &showPreview);
+ prefBranch->GetBoolPref(SHOW_ALERT_SENDER, &showSender);
+ prefBranch->GetBoolPref(SHOW_ALERT_SUBJECT, &showSubject);
+ prefBranch->GetIntPref(SHOW_ALERT_PREVIEW_LENGTH, &previewLength);
+
+ nsCOMPtr<nsIMsgFolder> folder;
+ aHdr->GetFolder(getter_AddRefs(folder));
+
+ if (!folder)
+ return false;
+
+ nsCString msgURI;
+ folder->GetUriForMsg(aHdr, msgURI);
+
+ bool localOnly;
+
+ size_t msgURIIndex = mFetchingURIs.IndexOf(msgURI);
+ if (msgURIIndex == mFetchingURIs.NoIndex)
+ {
+ localOnly = false;
+ mFetchingURIs.AppendElement(msgURI);
+ }
+ else
+ localOnly = true;
+
+ nsMsgKey messageKey;
+ if (NS_FAILED(aHdr->GetMessageKey(&messageKey)))
+ return false;
+
+ bool asyncResult = false;
+ nsresult rv = folder->FetchMsgPreviewText(&messageKey, 1,
+ localOnly, this,
+ &asyncResult);
+ // If we're still waiting on getting the message previews,
+ // bail early. We'll come back later when the async operation
+ // finishes.
+ if (NS_FAILED(rv) || asyncResult)
+ return false;
+
+ // If we got here, that means that we've retrieved the message preview,
+ // so we can stop tracking it with our mFetchingURIs array.
+ if (msgURIIndex != mFetchingURIs.NoIndex)
+ mFetchingURIs.RemoveElementAt(msgURIIndex);
+
+ nsCString utf8previewString;
+ if (showPreview &&
+ NS_FAILED(aHdr->GetStringProperty("preview", getter_Copies(utf8previewString))))
+ return false;
+
+ // need listener that mailbox is remote such as IMAP
+ // to generate preview message
+ nsString previewString;
+ CopyUTF8toUTF16(utf8previewString, previewString);
+
+ nsString subject;
+ if (showSubject && NS_FAILED(aHdr->GetMime2DecodedSubject(subject)))
+ return false;
+
+ nsString author;
+ if (showSender)
+ {
+ nsString fullHeader;
+ if (NS_FAILED(aHdr->GetMime2DecodedAuthor(fullHeader)))
+ return false;
+
+ ExtractName(DecodedHeader(fullHeader), author);
+ }
+
+ if (showSubject && showSender)
+ {
+ nsString msgTitle;
+ const char16_t *formatStrings[] =
+ {
+ subject.get(), author.get()
+ };
+ aBundle->FormatStringFromName(u"newMailNotification_messagetitle",
+ formatStrings, 2, getter_Copies(msgTitle));
+ alertBody.Append(msgTitle);
+ }
+ else if (showSubject)
+ alertBody.Append(subject);
+ else if (showSender)
+ alertBody.Append(author);
+
+ if (showPreview && (showSubject || showSender))
+ {
+ alertBody.AppendLiteral("\n");
+ }
+
+ if (showPreview)
+ alertBody.Append(StringHead(previewString, previewLength));
+
+ if (alertBody.IsEmpty())
+ return false;
+
+ aBody.Assign(alertBody);
+ return true;
+}
+
+nsresult nsMessengerUnixIntegration::ShowAlertMessage(const nsAString& aAlertTitle, const nsAString& aAlertText, const nsACString& aFolderURI)
+{
+ nsresult rv;
+ // if we are already in the process of showing an alert, don't try to show another....
+ if (mAlertInProgress)
+ return NS_OK;
+
+ mAlertInProgress = true;
+
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // determine if we should use libnotify or the built-in alert system
+ bool useSystemAlert = true;
+ prefBranch->GetBoolPref(SHOW_ALERT_SYSTEM, &useSystemAlert);
+
+ if (useSystemAlert) {
+ nsCOMPtr<nsIAlertsService> alertsService(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ rv = alertsService->ShowAlertNotification(NS_LITERAL_STRING(NEW_MAIL_ALERT_ICON),
+ aAlertTitle,
+ aAlertText,
+ false,
+ NS_ConvertASCIItoUTF16(aFolderURI),
+ this,
+ EmptyString(),
+ NS_LITERAL_STRING("auto"),
+ EmptyString(),
+ EmptyString(),
+ nullptr,
+ false,
+ false);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+ }
+ }
+ AlertFinished();
+ rv = ShowNewAlertNotification(false);
+
+ if (NS_FAILED(rv)) // go straight to showing the system tray icon.
+ AlertFinished();
+
+ return rv;
+}
+
+// Opening Thunderbird's new mail alert notification window for not supporting libnotify
+// aUserInitiated --> true if we are opening the alert notification in response to a user action
+// like clicking on the biff icon
+nsresult nsMessengerUnixIntegration::ShowNewAlertNotification(bool aUserInitiated)
+{
+
+ nsresult rv;
+
+ // if we are already in the process of showing an alert, don't try to show another....
+ if (mAlertInProgress)
+ return NS_OK;
+
+ nsCOMPtr<nsIMutableArray> argsArray = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ if (!argsArray)
+ return NS_ERROR_FAILURE;
+
+ // pass in the array of folders with unread messages
+ nsCOMPtr<nsISupportsInterfacePointer> ifptr = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ ifptr->SetData(mFoldersWithNewMail);
+ ifptr->SetDataIID(&NS_GET_IID(nsIArray));
+ argsArray->AppendElement(ifptr, false);
+
+ // pass in the observer
+ ifptr = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr <nsISupports> supports = do_QueryInterface(static_cast<nsIMessengerOSIntegration*>(this));
+ ifptr->SetData(supports);
+ ifptr->SetDataIID(&NS_GET_IID(nsIObserver));
+ argsArray->AppendElement(ifptr, false);
+
+ // pass in the animation flag
+ nsCOMPtr<nsISupportsPRBool> scriptableUserInitiated (do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ scriptableUserInitiated->SetData(aUserInitiated);
+ argsArray->AppendElement(scriptableUserInitiated, false);
+
+ nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
+ nsCOMPtr<mozIDOMWindowProxy> newWindow;
+
+ mAlertInProgress = true;
+ rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank",
+ "chrome,dialog=yes,titlebar=no,popup=yes", argsArray,
+ getter_AddRefs(newWindow));
+
+ if (NS_FAILED(rv))
+ AlertFinished();
+
+ return rv;
+}
+
+nsresult nsMessengerUnixIntegration::AlertFinished()
+{
+ mAlertInProgress = false;
+ return NS_OK;
+}
+
+nsresult nsMessengerUnixIntegration::AlertClicked()
+{
+ nsCString folderURI;
+ GetFirstFolderWithNewMail(folderURI);
+ openMailWindow(folderURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
+{
+ if (strcmp(aTopic, "alertfinished") == 0)
+ return AlertFinished();
+ if (strcmp(aTopic, "alertclickcallback") == 0)
+ return AlertClicked();
+
+ return NS_OK;
+}
+
+void nsMessengerUnixIntegration::FillToolTipInfo()
+{
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv,);
+
+ bool showAlert = true;
+ prefBranch->GetBoolPref(SHOW_ALERT_PREF, &showAlert);
+ if (!showAlert)
+ return;
+
+ nsCString folderUri;
+ GetFirstFolderWithNewMail(folderUri);
+
+ uint32_t count = 0;
+ NS_ENSURE_SUCCESS_VOID(mFoldersWithNewMail->GetLength(&count));
+
+ nsCOMPtr<nsIWeakReference> weakReference;
+ nsCOMPtr<nsIMsgFolder> folder = nullptr;
+ nsCOMPtr<nsIMsgFolder> folderWithNewMail = nullptr;
+
+ uint32_t i;
+ for (i = 0; i < count && !folderWithNewMail; i++)
+ {
+ weakReference = do_QueryElementAt(mFoldersWithNewMail, i);
+ folder = do_QueryReferent(weakReference);
+ folder->GetChildWithURI(folderUri, true, true,
+ getter_AddRefs(folderWithNewMail));
+ }
+
+ if (folder && folderWithNewMail)
+ {
+ nsCOMPtr<nsIStringBundle> bundle;
+ GetStringBundle(getter_AddRefs(bundle));
+
+ if (!bundle)
+ return;
+
+ // Create the notification title
+ nsString alertTitle;
+ if (!BuildNotificationTitle(folder, bundle, alertTitle))
+ return;
+
+ // Let's get the new mail for this folder
+ nsCOMPtr<nsIMsgDatabase> db;
+ if (NS_FAILED(folderWithNewMail->GetMsgDatabase(getter_AddRefs(db))))
+ return;
+
+ uint32_t numNewKeys = 0;
+ uint32_t *newMessageKeys;
+ db->GetNewList(&numNewKeys, &newMessageKeys);
+
+ // If we had new messages, we *should* have new keys, but we'll
+ // check just in case.
+ if (numNewKeys <= 0) {
+ NS_Free(newMessageKeys);
+ return;
+ }
+
+ // Find the rootFolder that folder belongs to, and find out
+ // what MRUTime it maps to. Assign this to lastMRUTime.
+ uint32_t lastMRUTime = 0;
+ if (NS_FAILED(GetMRUTimestampForFolder(folder, &lastMRUTime)))
+ lastMRUTime = 0;
+
+ // Next, add the new message headers to an nsCOMArray. We
+ // only add message headers that are newer than lastMRUTime.
+ nsCOMArray<nsIMsgDBHdr> newMsgHdrs;
+ for (unsigned int i = 0; i < numNewKeys; ++i) {
+ nsCOMPtr<nsIMsgDBHdr> hdr;
+ if (NS_FAILED(db->GetMsgHdrForKey(newMessageKeys[i], getter_AddRefs(hdr))))
+ continue;
+
+ uint32_t dateInSeconds = 0;
+ hdr->GetDateInSeconds(&dateInSeconds);
+
+ if (dateInSeconds > lastMRUTime)
+ newMsgHdrs.AppendObject(hdr);
+
+ }
+
+ // At this point, we don't need newMessageKeys any more,
+ // so let's free it.
+ NS_Free(newMessageKeys);
+
+ // If we didn't happen to add any message headers, bail out
+ if (!newMsgHdrs.Count())
+ return;
+
+ // Sort the message headers by dateInSeconds, in ascending
+ // order
+ newMsgHdrs.Sort(nsMsgDbHdrTimestampComparator, nullptr);
+
+ nsString alertBody;
+
+ // Build the body text of the notification.
+ if (!BuildNotificationBody(newMsgHdrs[0], bundle, alertBody))
+ return;
+
+ // Show the notification
+ ShowAlertMessage(alertTitle, alertBody, EmptyCString());
+
+ // Find the last, and therefore newest message header
+ // in our nsCOMArray
+ nsCOMPtr<nsIMsgDBHdr> lastMsgHdr = newMsgHdrs[newMsgHdrs.Count() - 1];
+
+ uint32_t dateInSeconds = 0;
+ if (NS_FAILED(lastMsgHdr->GetDateInSeconds(&dateInSeconds)))
+ return;
+
+ // Write the newest message timestamp to the appropriate
+ // mapping in our hashtable of MRUTime's.
+ PutMRUTimestampForFolder(folder, dateInSeconds);
+ } // if we got a folder
+}
+
+// Get the first top level folder which we know has new mail, then enumerate over
+// all the subfolders looking for the first real folder with new mail.
+// Return the folderURI for that folder.
+nsresult nsMessengerUnixIntegration::GetFirstFolderWithNewMail(nsACString& aFolderURI)
+{
+ NS_ENSURE_TRUE(mFoldersWithNewMail, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMsgFolder> folder;
+ nsCOMPtr<nsIWeakReference> weakReference;
+
+ uint32_t count = 0;
+ nsresult rv = mFoldersWithNewMail->GetLength(&count);
+ if (NS_FAILED(rv) || !count) // kick out if we don't have any folders with new mail
+ return NS_OK;
+
+ uint32_t i;
+ for(i = 0; i < count; i++)
+ {
+ weakReference = do_QueryElementAt(mFoldersWithNewMail, i);
+ folder = do_QueryReferent(weakReference);
+
+ // We only want to find folders which haven't been notified
+ // yet. This is specific to Thunderbird. In Seamonkey, we
+ // just return 0, and we don't care about timestamps anymore.
+ uint32_t lastMRUTime = 0;
+ rv = GetMRUTimestampForFolder(folder, &lastMRUTime);
+ if (NS_FAILED(rv))
+ lastMRUTime = 0;
+
+ if (!folder)
+ continue;
+ // enumerate over the folders under this root folder till we find one with new mail....
+ nsCOMPtr<nsIMsgFolder> msgFolder;
+ nsCOMPtr<nsIArray> allFolders;
+ rv = folder->GetDescendants(getter_AddRefs(allFolders));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t subfolderCount = 0;
+ allFolders->GetLength(&subfolderCount);
+ uint32_t j;
+ for (j = 0; j < subfolderCount; j++)
+ {
+ nsCOMPtr<nsIMsgFolder> msgFolder = do_QueryElementAt(allFolders, j);
+
+ if (!msgFolder)
+ continue;
+
+ uint32_t flags;
+ rv = msgFolder->GetFlags(&flags);
+
+ if (NS_FAILED(rv))
+ continue;
+
+ // Unless we're dealing with an Inbox, we don't care
+ // about Drafts, Queue, SentMail, Template, or Junk folders
+ if (!(flags & nsMsgFolderFlags::Inbox) &&
+ (flags & (nsMsgFolderFlags::SpecialUse & ~nsMsgFolderFlags::Inbox)))
+ continue;
+
+ nsCString folderURI;
+ msgFolder->GetURI(folderURI);
+ bool hasNew = false;
+ rv = msgFolder->GetHasNewMessages(&hasNew);
+
+ if (NS_FAILED(rv))
+ continue;
+
+ // Grab the MRUTime property from the folder
+ nsCString dateStr;
+ msgFolder->GetStringProperty(MRU_TIME_PROPERTY, dateStr);
+ uint32_t MRUTime = (uint32_t) dateStr.ToInteger(&rv, 10);
+ if (NS_FAILED(rv))
+ MRUTime = 0;
+
+ if (hasNew && MRUTime > lastMRUTime)
+ {
+ rv = msgFolder->GetURI(aFolderURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return NS_OK;
+ }
+ } // if we have more potential folders to enumerate
+ }
+
+ // If we got here, then something when pretty wrong.
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemPropertyFlagChanged(nsIMsgDBHdr *item, nsIAtom *property, uint32_t oldFlag, uint32_t newFlag)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemAdded(nsIMsgFolder *, nsISupports *)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemBoolPropertyChanged(nsIMsgFolder *aItem,
+ nsIAtom *aProperty,
+ bool aOldValue,
+ bool aNewValue)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemEvent(nsIMsgFolder *, nsIAtom *)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnItemIntPropertyChanged(nsIMsgFolder *aItem, nsIAtom *aProperty, int64_t aOldValue, int64_t aNewValue)
+{
+ nsCString atomName;
+ // if we got new mail show an icon in the system tray
+ if (mBiffStateAtom == aProperty && mFoldersWithNewMail)
+ {
+ nsCOMPtr<nsIWeakReference> weakFolder = do_GetWeakReference(aItem);
+ uint32_t indexInNewArray;
+ nsresult rv = mFoldersWithNewMail->IndexOf(0, weakFolder, &indexInNewArray);
+ bool folderFound = NS_SUCCEEDED(rv);
+
+ if (aNewValue == nsIMsgFolder::nsMsgBiffState_NewMail)
+ {
+ // only show a system tray icon iff we are performing biff
+ // (as opposed to the user getting new mail)
+ bool performingBiff = false;
+ nsCOMPtr<nsIMsgIncomingServer> server;
+ aItem->GetServer(getter_AddRefs(server));
+ if (server)
+ server->GetPerformingBiff(&performingBiff);
+ if (!performingBiff)
+ return NS_OK; // kick out right now...
+
+ if (!folderFound)
+ mFoldersWithNewMail->AppendElement(weakFolder, false);
+ // now regenerate the tooltip
+ FillToolTipInfo();
+ }
+ else if (aNewValue == nsIMsgFolder::nsMsgBiffState_NoMail)
+ {
+ if (folderFound) {
+ mFoldersWithNewMail->RemoveElementAt(indexInNewArray);
+ }
+ }
+ } // if the biff property changed
+ else if (mNewMailReceivedAtom == aProperty)
+ {
+ FillToolTipInfo();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnStartRunningUrl(nsIURI *aUrl)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMessengerUnixIntegration::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
+{
+ if (NS_SUCCEEDED(aExitCode))
+ // preview fetch is done.
+ FillToolTipInfo();
+ return NS_OK;
+}
+
+nsresult
+nsMessengerUnixIntegration::GetMRUTimestampForFolder(nsIMsgFolder *aFolder,
+ uint32_t *aLastMRUTime)
+{
+ nsCOMPtr<nsIMsgFolder> rootFolder = nullptr;
+ nsresult rv = aFolder->GetRootFolder(getter_AddRefs(rootFolder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString rootFolderURI;
+ rootFolder->GetURI(rootFolderURI);
+ if (!mLastMRUTimes.Get(rootFolderURI, aLastMRUTime))
+ aLastMRUTime = 0;
+
+ return NS_OK;
+}
+
+nsresult
+nsMessengerUnixIntegration::PutMRUTimestampForFolder(nsIMsgFolder *aFolder,
+ uint32_t aLastMRUTime)
+{
+ nsresult rv;
+ nsCOMPtr<nsIMsgFolder> rootFolder = nullptr;
+ rv = aFolder->GetRootFolder(getter_AddRefs(rootFolder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString rootFolderURI;
+ rootFolder->GetURI(rootFolderURI);
+ mLastMRUTimes.Put(rootFolderURI, aLastMRUTime);
+
+ return NS_OK;
+}