/* -*- 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 "nsStatusBarBiffManager.h" #include "nsMsgBiffManager.h" #include "nsIMsgMailSession.h" #include "nsIMsgAccountManager.h" #include "nsIObserverService.h" #include "nsIWindowMediator.h" #include "nsIMsgMailSession.h" #include "MailNewsTypes.h" #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... #include "nsMsgDBFolder.h" #include "nsIFileChannel.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" #include "nsIURL.h" #include "nsNetUtil.h" #include "nsIFileURL.h" #include "nsIFile.h" #include "nsMsgUtils.h" #include "mozilla/Services.h" // QueryInterface, AddRef, and Release // NS_IMPL_ISUPPORTS(nsStatusBarBiffManager, nsIStatusBarBiffManager, nsIFolderListener, nsIObserver) nsStatusBarBiffManager::nsStatusBarBiffManager() : mInitialized(false), mCurrentBiffState(nsIMsgFolder::nsMsgBiffState_Unknown) {} nsStatusBarBiffManager::~nsStatusBarBiffManager() {} #define NEW_MAIL_PREF_BRANCH "mail.biff." #define CHAT_PREF_BRANCH "mail.chat." #define FEED_PREF_BRANCH "mail.feed." #define PREF_PLAY_SOUND "play_sound" #define PREF_SOUND_URL "play_sound.url" #define PREF_SOUND_TYPE "play_sound.type" #define SYSTEM_SOUND_TYPE 0 #define CUSTOM_SOUND_TYPE 1 #define PREF_CHAT_ENABLED "mail.chat.enabled" #define PLAY_CHAT_NOTIFICATION_SOUND "play-chat-notification-sound" nsresult nsStatusBarBiffManager::Init() { if (mInitialized) return NS_ERROR_ALREADY_INITIALIZED; nsresult rv; nsCOMPtr mailSession = do_GetService("@mozilla.org/messenger/services/session;1", &rv); if (NS_SUCCEEDED(rv)) mailSession->AddFolderListener(this, nsIFolderListener::intPropertyChanged); nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); bool chatEnabled = false; if (NS_SUCCEEDED(rv)) rv = pref->GetBoolPref(PREF_CHAT_ENABLED, &chatEnabled); if (NS_SUCCEEDED(rv) && chatEnabled) { nsCOMPtr observerService = mozilla::services::GetObserverService(); if (observerService) observerService->AddObserver(this, PLAY_CHAT_NOTIFICATION_SOUND, false); } mInitialized = true; return NS_OK; } nsresult nsStatusBarBiffManager::PlayBiffSound(const char* aPrefBranch) { nsresult rv; nsCOMPtr prefSvc = (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr pref; rv = prefSvc->GetBranch(aPrefBranch, getter_AddRefs(pref)); NS_ENSURE_SUCCESS(rv, rv); bool playSound; if (mServerType.EqualsLiteral("rss")) { nsCOMPtr prefFeed; rv = prefSvc->GetBranch(FEED_PREF_BRANCH, getter_AddRefs(prefFeed)); NS_ENSURE_SUCCESS(rv, rv); rv = prefFeed->GetBoolPref(PREF_PLAY_SOUND, &playSound); } else { rv = pref->GetBoolPref(PREF_PLAY_SOUND, &playSound); } NS_ENSURE_SUCCESS(rv, rv); if (!playSound) return NS_OK; // lazily create the sound instance if (!mSound) mSound = do_CreateInstance("@mozilla.org/sound;1"); int32_t soundType = SYSTEM_SOUND_TYPE; rv = pref->GetIntPref(PREF_SOUND_TYPE, &soundType); NS_ENSURE_SUCCESS(rv, rv); #ifndef XP_MACOSX bool customSoundPlayed = false; #endif if (soundType == CUSTOM_SOUND_TYPE) { nsCString soundURLSpec; rv = pref->GetCharPref(PREF_SOUND_URL, soundURLSpec); if (NS_SUCCEEDED(rv) && !soundURLSpec.IsEmpty()) { if (!strncmp(soundURLSpec.get(), "file://", 7)) { nsCOMPtr fileURI; rv = NS_NewURI(getter_AddRefs(fileURI), soundURLSpec); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr soundURL = do_QueryInterface(fileURI, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr soundFile; rv = soundURL->GetFile(getter_AddRefs(soundFile)); if (NS_SUCCEEDED(rv)) { bool soundFileExists = false; rv = soundFile->Exists(&soundFileExists); if (NS_SUCCEEDED(rv) && soundFileExists) { rv = mSound->Play(soundURL); #ifndef XP_MACOSX if (NS_SUCCEEDED(rv)) customSoundPlayed = true; #endif } } } } // XXX TODO: See if we can create a nsIFile using the string as a native // path. } } #ifndef XP_MACOSX // if nothing played, play the default system sound if (!customSoundPlayed) { rv = mSound->PlayEventSound(nsISound::EVENT_NEW_MAIL_RECEIVED); NS_ENSURE_SUCCESS(rv, rv); } #endif return rv; } // nsIFolderListener methods.... NS_IMETHODIMP nsStatusBarBiffManager::OnFolderAdded(nsIMsgFolder* parent, nsIMsgFolder* child) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnMessageAdded(nsIMsgFolder* parent, nsIMsgDBHdr* msg) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderRemoved(nsIMsgFolder* parent, nsIMsgFolder* child) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnMessageRemoved(nsIMsgFolder* parent, nsIMsgDBHdr* msg) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderPropertyChanged(nsIMsgFolder* folder, const nsACString& property, const nsACString& oldValue, const nsACString& newValue) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderIntPropertyChanged(nsIMsgFolder* folder, const nsACString& property, int64_t oldValue, int64_t newValue) { if (property.Equals(kBiffState) && mCurrentBiffState != newValue) { // if we got new mail, attempt to play a sound. // if we fail along the way, don't return. // we still need to update the UI. if (newValue == nsIMsgFolder::nsMsgBiffState_NewMail) { // Get the folder's server type. nsCOMPtr server; nsresult rv = folder->GetServer(getter_AddRefs(server)); if (NS_SUCCEEDED(rv) && server) server->GetType(mServerType); // if we fail to play the biff sound, keep going. (void)PlayBiffSound(NEW_MAIL_PREF_BRANCH); } mCurrentBiffState = newValue; // don't care if notification fails nsCOMPtr observerService = mozilla::services::GetObserverService(); if (observerService) observerService->NotifyObservers( static_cast(this), "mail:biff-state-changed", nullptr); } else if (property.Equals(kNewMailReceived)) { (void)PlayBiffSound(NEW_MAIL_PREF_BRANCH); } return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderBoolPropertyChanged(nsIMsgFolder* folder, const nsACString& property, bool oldValue, bool newValue) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderUnicharPropertyChanged( nsIMsgFolder* folder, const nsACString& property, const nsAString& oldValue, const nsAString& newValue) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderPropertyFlagChanged(nsIMsgDBHdr* msg, const nsACString& property, uint32_t oldFlag, uint32_t newFlag) { return NS_OK; } NS_IMETHODIMP nsStatusBarBiffManager::OnFolderEvent(nsIMsgFolder* folder, const nsACString& event) { return NS_OK; } // nsIObserver implementation NS_IMETHODIMP nsStatusBarBiffManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { return PlayBiffSound(CHAT_PREF_BRANCH); } // nsIStatusBarBiffManager method.... NS_IMETHODIMP nsStatusBarBiffManager::GetBiffState(int32_t* aBiffState) { NS_ENSURE_ARG_POINTER(aBiffState); *aBiffState = mCurrentBiffState; return NS_OK; }