Bug 260818 Pop up an alert when a download finishes

patch by cst@andrew.cmu.edu r=timeless sr=jag
This commit is contained in:
timeless%mozdev.org 2004-10-19 02:48:26 +00:00
Родитель e9feb9853d
Коммит 76f1d77afd
9 изменённых файлов: 139 добавлений и 34 удалений

Просмотреть файл

@ -87,6 +87,8 @@ pref("browser.show_about_as_stupid_modal_window", false);
pref("browser.download.progressDnldDialog.keepAlive", true); // keep the dnload progress dialog up after dnload is complete pref("browser.download.progressDnldDialog.keepAlive", true); // keep the dnload progress dialog up after dnload is complete
pref("browser.download.progressDnldDialog.enable_launch_reveal_buttons", true); pref("browser.download.progressDnldDialog.enable_launch_reveal_buttons", true);
pref("browser.download.progressDnlgDialog.dontAskForLaunch", false); pref("browser.download.progressDnlgDialog.dontAskForLaunch", false);
pref("browser.download.finished_download_sound", false);
pref("browser.download.finished_download_alert", false);
pref("browser.download.finished_sound_url", ""); pref("browser.download.finished_sound_url", "");
// various default search settings // various default search settings

Просмотреть файл

@ -46,7 +46,7 @@
interface nsIAlertListener : nsISupports interface nsIAlertListener : nsISupports
{ {
void onAlertFinished(in wstring aAlertCookie); void onAlertFinished(in wstring aAlertCookie);
void onAlertClickCallback(in wstring aAlertCookie); // if the user clicks on the link and you wanted notified.... void onAlertClickCallback(in wstring aAlertCookie); // if the user clicks the link and you wanted to be notified...
}; };
[scriptable, uuid(7E8B76C6-A70C-4075-81AA-D48B6152E1B4)] [scriptable, uuid(7E8B76C6-A70C-4075-81AA-D48B6152E1B4)]

Просмотреть файл

@ -5,6 +5,8 @@ failed=Failed
finished=Finished finished=Finished
canceled=Canceled canceled=Canceled
alertTitle=Download Error alertTitle=Download Error
finishedTitle=Download Complete
finishedText=%S has finished downloading
profileSwitchTitle=Downloads in progress profileSwitchTitle=Downloads in progress
profileSwitchText=Downloads are in progress. Switching profiles will stop them. profileSwitchText=Downloads are in progress. Switching profiles will stop them.

Просмотреть файл

@ -61,6 +61,7 @@ REQUIRES = xpcom \
profile \ profile \
widget \ widget \
pref \ pref \
appcomps \
$(NULL) $(NULL)
CPPSRCS = \ CPPSRCS = \
nsDownloadManager.cpp \ nsDownloadManager.cpp \

Просмотреть файл

@ -63,14 +63,12 @@
#include "nsISound.h" #include "nsISound.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "nsIFileURL.h" #include "nsIFileURL.h"
#include "nsIAlertsService.h"
/* Outstanding issues/todo: /* Outstanding issues/todo:
* 1. Implement pause/resume. * 1. Implement pause/resume.
*/ */
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
#define DOWNLOAD_MANAGER_FE_URL "chrome://communicator/content/downloadmanager/downloadmanager.xul" #define DOWNLOAD_MANAGER_FE_URL "chrome://communicator/content/downloadmanager/downloadmanager.xul"
#define DOWNLOAD_MANAGER_BUNDLE "chrome://communicator/locale/downloadmanager/downloadmanager.properties" #define DOWNLOAD_MANAGER_BUNDLE "chrome://communicator/locale/downloadmanager/downloadmanager.properties"
#define INTERVAL 500 #define INTERVAL 500
@ -162,7 +160,7 @@ nsDownloadManager::Init()
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
rv = CallGetService(kRDFServiceCID, &gRDFService); rv = CallGetService("@mozilla.org/rdf/rdf-service;1", &gRDFService);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
gRDFService->GetResource(NS_LITERAL_CSTRING("NC:DownloadsRoot"), &gNC_DownloadsRoot); gRDFService->GetResource(NS_LITERAL_CSTRING("NC:DownloadsRoot"), &gNC_DownloadsRoot);
@ -185,7 +183,7 @@ nsDownloadManager::Init()
mListener = do_CreateInstance("@mozilla.org/download-manager/listener;1", &rv); mListener = do_CreateInstance("@mozilla.org/download-manager/listener;1", &rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(kStringBundleServiceCID, &rv); nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(mBundle)); rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(mBundle));
@ -713,7 +711,7 @@ nsDownloadManager::Open(nsIDOMWindow* aParent, nsIDownload* aDownload)
// if this fails, it fails -- continue. // if this fails, it fails -- continue.
AssertProgressInfo(); AssertProgressInfo();
//check for an existing manager window and focus it // check for an existing manager window and focus it
nsresult rv; nsresult rv;
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
@ -921,7 +919,7 @@ nsDownloadManager::Observe(nsISupports* aSubject, const char* aTopic, const PRUn
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// nsDownload // nsDownload
NS_IMPL_ISUPPORTS4(nsDownload, nsIDownload, nsITransfer, nsIWebProgressListener, nsIObserver) NS_IMPL_ISUPPORTS5(nsDownload, nsIDownload, nsITransfer, nsIWebProgressListener, nsIObserver, nsIAlertListener)
nsDownload::nsDownload(nsDownloadManager* aManager, nsDownload::nsDownload(nsDownloadManager* aManager,
nsIURI* aTarget, nsIURI* aTarget,
@ -1104,7 +1102,7 @@ nsDownload::OnStatusChange(nsIWebProgress *aWebProgress,
// Get title for alert. // Get title for alert.
nsXPIDLString title; nsXPIDLString title;
nsresult rv; nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(kStringBundleServiceCID, &rv); nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
nsCOMPtr<nsIStringBundle> bundle; nsCOMPtr<nsIStringBundle> bundle;
if (bundleService) if (bundleService)
rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle)); rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle));
@ -1127,6 +1125,41 @@ nsDownload::OnStatusChange(nsIWebProgress *aWebProgress,
return NS_OK; return NS_OK;
} }
void nsDownload::DisplayDownloadFinishedAlert()
{
nsresult rv;
nsCOMPtr<nsIAlertsService> alertsService(do_GetService(NS_ALERTSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIStringBundle> bundle;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return;
rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle));
if (NS_FAILED(rv))
return;
nsXPIDLString finishedTitle, finishedText;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("finishedTitle").get(),
getter_Copies(finishedTitle));
if (NS_FAILED(rv))
return;
const PRUnichar *strings[] = { mDisplayName.get() };
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("finishedText").get(),
strings, 1, getter_Copies(finishedText));
if (NS_FAILED(rv))
return;
nsCAutoString url;
mTarget->GetSpec(url);
alertsService->ShowAlertNotification(PromiseFlatCString(NS_LITERAL_CSTRING("moz-icon://") + url).get(),
finishedTitle, finishedText, PR_TRUE,
NS_LITERAL_STRING("download").get(), this);
}
NS_IMETHODIMP NS_IMETHODIMP
nsDownload::OnStateChange(nsIWebProgress* aWebProgress, nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, PRUint32 aStateFlags, nsIRequest* aRequest, PRUint32 aStateFlags,
@ -1154,7 +1187,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
mCurrBytes = mMaxBytes; mCurrBytes = mMaxBytes;
mPercentComplete = 100; mPercentComplete = 100;
//Play a sound when the download finishes // Play a sound or show an alert when the download finishes
PRBool playSound = PR_FALSE;
PRBool showAlert = PR_FALSE;
nsXPIDLCString soundStr; nsXPIDLCString soundStr;
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1"); nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1");
@ -1162,14 +1197,19 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
if (prefs) { if (prefs) {
nsCOMPtr<nsIPrefBranch> prefBranch; nsCOMPtr<nsIPrefBranch> prefBranch;
prefs->GetBranch(nsnull, getter_AddRefs(prefBranch)); prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
if (prefBranch) if (prefBranch) {
prefBranch->GetCharPref("browser.download.finished_sound_url", getter_Copies(soundStr)); rv = prefBranch->GetBoolPref("browser.download.finished_download_sound", &playSound);
if (NS_SUCCEEDED(rv) && playSound)
prefBranch->GetCharPref("browser.download.finished_sound_url", getter_Copies(soundStr));
rv = prefBranch->GetBoolPref("browser.download.finished_download_alert", &showAlert);
if (NS_FAILED(rv))
showAlert = PR_FALSE;
}
} }
//only continue if it isn't blank
if (!soundStr.IsEmpty()) { if (!soundStr.IsEmpty()) {
nsCOMPtr<nsISound> snd = do_GetService("@mozilla.org/sound;1"); nsCOMPtr<nsISound> snd = do_GetService("@mozilla.org/sound;1");
if (snd) { //hopefully we got it if (snd) {
nsCOMPtr<nsIURI> soundURI; nsCOMPtr<nsIURI> soundURI;
NS_NewURI(getter_AddRefs(soundURI), soundStr); NS_NewURI(getter_AddRefs(soundURI), soundStr);
@ -1180,6 +1220,8 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
snd->Beep(); snd->Beep();
} }
} }
if (showAlert)
DisplayDownloadFinishedAlert();
nsCAutoString path; nsCAutoString path;
rv = GetFilePathUTF8(mTarget, path); rv = GetFilePathUTF8(mTarget, path);
@ -1227,6 +1269,23 @@ nsDownload::OnSecurityChange(nsIWebProgress *aWebProgress,
return NS_OK; return NS_OK;
} }
///////////////////////////////////////////////////////////////////////////////
// nsIAlertListener
NS_IMETHODIMP
nsDownload::OnAlertFinished(const PRUnichar * aAlertCookie)
{
return NS_OK;
}
NS_IMETHODIMP
nsDownload::OnAlertClickCallback(const PRUnichar * aAlertCookie)
{
// show the download manager
mDownloadManager->Open(nsnull, this);
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// nsIDownload // nsIDownload

Просмотреть файл

@ -59,6 +59,7 @@
#include "nsIStringBundle.h" #include "nsIStringBundle.h"
#include "nsIProgressDialog.h" #include "nsIProgressDialog.h"
#include "nsIMIMEInfo.h" #include "nsIMIMEInfo.h"
#include "nsIAlertsService.h"
enum DownloadState { NOTSTARTED = -1, DOWNLOADING, FINISHED, FAILED, CANCELED }; enum DownloadState { NOTSTARTED = -1, DOWNLOADING, FINISHED, FAILED, CANCELED };
@ -105,7 +106,8 @@ private:
class nsDownload : public nsIDownload, class nsDownload : public nsIDownload,
public nsIWebProgressListener, public nsIWebProgressListener,
public nsIObserver public nsIObserver,
public nsIAlertListener
{ {
public: public:
NS_DECL_NSIWEBPROGRESSLISTENER NS_DECL_NSIWEBPROGRESSLISTENER
@ -113,12 +115,14 @@ public:
NS_DECL_NSIDOWNLOAD NS_DECL_NSIDOWNLOAD
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIALERTLISTENER
nsDownload(nsDownloadManager* aManager, nsIURI* aTarget, nsIURI* aSource); nsDownload(nsDownloadManager* aManager, nsIURI* aTarget, nsIURI* aSource);
~nsDownload(); ~nsDownload();
nsresult Suspend(); nsresult Suspend();
nsresult Resume(); nsresult Resume();
void DisplayDownloadFinishedAlert();
void SetDialogListener(nsIWebProgressListener* aInternalListener) { void SetDialogListener(nsIWebProgressListener* aInternalListener) {
mDialogListener = aInternalListener; mDialogListener = aInternalListener;

Просмотреть файл

@ -2,23 +2,21 @@ function Startup()
{ {
PlaySoundCheck(); PlaySoundCheck();
// if we don't have the alert service, hide the pref UI for using alerts to notify on new mail // if we don't have the alert service, hide the pref UI for using alerts to notify on download completion
// see bug #158711 // see bug #158711
var newMailNotificationAlertUI = document.getElementById("newMailNotificationAlert"); var downloadDoneNotificationAlertUI = document.getElementById("finishedNotificationAlert");
newMailNotificationAlertUI.hidden = !("@mozilla.org/alerts-service;1" in Components.classes); downloadDoneNotificationAlertUI.hidden = !("@mozilla.org/alerts-service;1" in Components.classes);
} }
function PlaySoundCheck() function PlaySoundCheck()
{ {
var playSound = document.getElementById("newMailNotification").checked; var playSound = document.getElementById("finishedNotificationSound").checked;
var playSoundType = document.getElementById("newMailNotificationType");
playSoundType.disabled = !playSound;
var disableCustomUI = !(playSound && playSoundType.value == 1); var disableCustomUI = !playSound;
var mailnewsSoundFileUrl = document.getElementById("mailnewsSoundFileUrl"); var finishedSoundUrl = document.getElementById("finishedSoundUrl");
mailnewsSoundFileUrl.disabled = disableCustomUI finishedSoundUrl.disabled = disableCustomUI;
document.getElementById("preview").disabled = disableCustomUI || (mailnewsSoundFileUrl.value == ""); document.getElementById("preview").disabled = disableCustomUI || (finishedSoundUrl.value == "");
document.getElementById("browse").disabled = disableCustomUI; document.getElementById("browse").disabled = disableCustomUI;
} }
@ -27,7 +25,7 @@ const nsIFilePicker = Components.interfaces.nsIFilePicker;
function Browse() function Browse()
{ {
var fp = Components.classes["@mozilla.org/filepicker;1"] var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker); .createInstance(nsIFilePicker);
// XXX todo, persist the last sound directory and pass it in // XXX todo, persist the last sound directory and pass it in
// XXX todo filter by .wav // XXX todo filter by .wav
@ -36,19 +34,20 @@ function Browse()
var ret = fp.show(); var ret = fp.show();
if (ret == nsIFilePicker.returnOK) { if (ret == nsIFilePicker.returnOK) {
var mailnewsSoundFileUrl = document.getElementById("mailnewsSoundFileUrl"); var soundUrl = document.getElementById("finishedSoundUrl");
// convert the nsILocalFile into a nsIFile url // convert the nsILocalFile into a nsIFile url
mailnewsSoundFileUrl.value = fp.fileURL.spec; soundUrl.value = fp.fileURL.spec;
} }
document.getElementById("preview").disabled = (document.getElementById("mailnewsSoundFileUrl").value == ""); document.getElementById("preview").disabled =
(document.getElementById("finishedSoundUrl").value == "");
} }
var gSound = null; var gSound = null;
function PreviewSound() function PreviewSound()
{ {
var soundURL = document.getElementById("mailnewsSoundFileUrl").value; var soundURL = document.getElementById("finishedSoundUrl").value;
if (!gSound) if (!gSound)
gSound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound); gSound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
@ -60,7 +59,7 @@ function PreviewSound()
} }
else { else {
var ioService = Components.classes["@mozilla.org/network/io-service;1"] var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService); .getService(Components.interfaces.nsIIOService);
var url = ioService.newURI(soundURL, null, null); var url = ioService.newURI(soundURL, null, null);
gSound.play(url) gSound.play(url)
} }

Просмотреть файл

@ -45,9 +45,11 @@
onload="parent.initPanel('chrome://communicator/content/pref/pref-download.xul');" onload="parent.initPanel('chrome://communicator/content/pref/pref-download.xul');"
headertitle="&lHeader;"> headertitle="&lHeader;">
<script type="application/x-javascript" src="chrome://communicator/content/pref/pref-download.js"/>
<script type="application/x-javascript"> <script type="application/x-javascript">
<![CDATA[ <![CDATA[
var _elementIDs = ["downloadBehavior"]; var _elementIDs = ["downloadBehavior", "finishedNotificationAlert",
"finishedNotificationSound", "finishedSoundUrl"];
]]> ]]>
</script>browser.downloadmanager.behavior </script>browser.downloadmanager.behavior
@ -58,7 +60,31 @@
<radio value="1" label="&openProgressDialog.label;" accesskey="&openProgressDialog.accesskey;"/> <radio value="1" label="&openProgressDialog.label;" accesskey="&openProgressDialog.accesskey;"/>
<radio value="2" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/> <radio value="2" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/>
</radiogroup> </radiogroup>
</groupbox>
<groupbox>
<caption label="&finishedBehavior.label;"/>
<vbox align="start">
<checkbox id="finishedNotificationAlert" label="&showAlert.label;"
prefstring="browser.download.finished_download_alert"
accesskey="&showAlert.accesskey;"/>
<checkbox id="finishedNotificationSound" label="&playSound.label;"
prefstring="browser.download.finished_download_sound"
accesskey="&playSound.accesskey;"
oncommand="PlaySoundCheck()"/>
</vbox>
<hbox align="center" class="indent">
<textbox readonly="true" flex="1" id="finishedSoundUrl" preftype="string"
prefstring="browser.download.finished_sound_url"/>
<hbox align="center">
<button id="browse" label="&browse.label;" filepickertitle="&browse.title;"
accesskey="&browse.accesskey;" oncommand="Browse()"/>
<button id="preview" label="&preview.label;"
accesskey="&preview.accesskey;" oncommand="PreviewSound()"/>
</hbox>
</hbox>
</groupbox> </groupbox>
</page> </page>

Просмотреть файл

@ -1,8 +1,20 @@
<!ENTITY lHeader "Downloads"> <!ENTITY lHeader "Downloads">
<!ENTITY downloadBehavior.label "When starting a download"> <!ENTITY downloadBehavior.label "When starting a download">
<!ENTITY finishedBehavior.label "When a download completes">
<!ENTITY openDM.label "Open the download manager"> <!ENTITY openDM.label "Open the download manager">
<!ENTITY openDM.accesskey "m"> <!ENTITY openDM.accesskey "m">
<!ENTITY openProgressDialog.label "Open a progress dialog"> <!ENTITY openProgressDialog.label "Open a progress dialog">
<!ENTITY openProgressDialog.accesskey "p"> <!ENTITY openProgressDialog.accesskey "p">
<!ENTITY doNothing.label "Don't open anything"> <!ENTITY doNothing.label "Don't open anything">
<!ENTITY doNothing.accesskey "D"> <!ENTITY doNothing.accesskey "D">
<!ENTITY playSound.label "Play a sound">
<!ENTITY playSound.accesskey "S">
<!ENTITY showAlert.label "Show an alert">
<!ENTITY showAlert.accesskey "A">
<!ENTITY browse.label "Browse...">
<!ENTITY browse.accesskey "B">
<!ENTITY browse.title "Choose a sound">
<!ENTITY preview.label "Preview">
<!ENTITY preview.accesskey "v">
<!ENTITY soundURL.label "Sound URL:">
<!ENTITY soundURL.accesskey "U">