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.enable_launch_reveal_buttons", true);
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", "");
// various default search settings

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

@ -46,7 +46,7 @@
interface nsIAlertListener : nsISupports
{
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)]

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

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

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

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

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

@ -63,14 +63,12 @@
#include "nsISound.h"
#include "nsIPrefService.h"
#include "nsIFileURL.h"
#include "nsIAlertsService.h"
/* Outstanding issues/todo:
* 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_BUNDLE "chrome://communicator/locale/downloadmanager/downloadmanager.properties"
#define INTERVAL 500
@ -162,7 +160,7 @@ nsDownloadManager::Init()
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;
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);
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;
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.
AssertProgressInfo();
//check for an existing manager window and focus it
// check for an existing manager window and focus it
nsresult rv;
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
@ -921,7 +919,7 @@ nsDownloadManager::Observe(nsISupports* aSubject, const char* aTopic, const PRUn
///////////////////////////////////////////////////////////////////////////////
// nsDownload
NS_IMPL_ISUPPORTS4(nsDownload, nsIDownload, nsITransfer, nsIWebProgressListener, nsIObserver)
NS_IMPL_ISUPPORTS5(nsDownload, nsIDownload, nsITransfer, nsIWebProgressListener, nsIObserver, nsIAlertListener)
nsDownload::nsDownload(nsDownloadManager* aManager,
nsIURI* aTarget,
@ -1104,7 +1102,7 @@ nsDownload::OnStatusChange(nsIWebProgress *aWebProgress,
// Get title for alert.
nsXPIDLString title;
nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(kStringBundleServiceCID, &rv);
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
nsCOMPtr<nsIStringBundle> bundle;
if (bundleService)
rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle));
@ -1127,6 +1125,41 @@ nsDownload::OnStatusChange(nsIWebProgress *aWebProgress,
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
nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, PRUint32 aStateFlags,
@ -1154,7 +1187,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
mCurrBytes = mMaxBytes;
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;
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1");
@ -1162,14 +1197,19 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
if (prefs) {
nsCOMPtr<nsIPrefBranch> prefBranch;
prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
if (prefBranch)
prefBranch->GetCharPref("browser.download.finished_sound_url", getter_Copies(soundStr));
if (prefBranch) {
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()) {
nsCOMPtr<nsISound> snd = do_GetService("@mozilla.org/sound;1");
if (snd) { //hopefully we got it
if (snd) {
nsCOMPtr<nsIURI> soundURI;
NS_NewURI(getter_AddRefs(soundURI), soundStr);
@ -1180,7 +1220,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
snd->Beep();
}
}
if (showAlert)
DisplayDownloadFinishedAlert();
nsCAutoString path;
rv = GetFilePathUTF8(mTarget, path);
// can't do an early return; have to break reference cycle below
@ -1227,6 +1269,23 @@ nsDownload::OnSecurityChange(nsIWebProgress *aWebProgress,
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

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

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

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

@ -2,23 +2,21 @@ function Startup()
{
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
var newMailNotificationAlertUI = document.getElementById("newMailNotificationAlert");
newMailNotificationAlertUI.hidden = !("@mozilla.org/alerts-service;1" in Components.classes);
var downloadDoneNotificationAlertUI = document.getElementById("finishedNotificationAlert");
downloadDoneNotificationAlertUI.hidden = !("@mozilla.org/alerts-service;1" in Components.classes);
}
function PlaySoundCheck()
{
var playSound = document.getElementById("newMailNotification").checked;
var playSoundType = document.getElementById("newMailNotificationType");
playSoundType.disabled = !playSound;
var playSound = document.getElementById("finishedNotificationSound").checked;
var disableCustomUI = !(playSound && playSoundType.value == 1);
var mailnewsSoundFileUrl = document.getElementById("mailnewsSoundFileUrl");
var disableCustomUI = !playSound;
var finishedSoundUrl = document.getElementById("finishedSoundUrl");
mailnewsSoundFileUrl.disabled = disableCustomUI
document.getElementById("preview").disabled = disableCustomUI || (mailnewsSoundFileUrl.value == "");
finishedSoundUrl.disabled = disableCustomUI;
document.getElementById("preview").disabled = disableCustomUI || (finishedSoundUrl.value == "");
document.getElementById("browse").disabled = disableCustomUI;
}
@ -27,7 +25,7 @@ const nsIFilePicker = Components.interfaces.nsIFilePicker;
function Browse()
{
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 filter by .wav
@ -36,19 +34,20 @@ function Browse()
var ret = fp.show();
if (ret == nsIFilePicker.returnOK) {
var mailnewsSoundFileUrl = document.getElementById("mailnewsSoundFileUrl");
var soundUrl = document.getElementById("finishedSoundUrl");
// 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;
function PreviewSound()
{
var soundURL = document.getElementById("mailnewsSoundFileUrl").value;
var soundURL = document.getElementById("finishedSoundUrl").value;
if (!gSound)
gSound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
@ -60,7 +59,7 @@ function PreviewSound()
}
else {
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);
gSound.play(url)
}

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

@ -45,12 +45,14 @@
onload="parent.initPanel('chrome://communicator/content/pref/pref-download.xul');"
headertitle="&lHeader;">
<script type="application/x-javascript" src="chrome://communicator/content/pref/pref-download.js"/>
<script type="application/x-javascript">
<![CDATA[
var _elementIDs = ["downloadBehavior"];
var _elementIDs = ["downloadBehavior", "finishedNotificationAlert",
"finishedNotificationSound", "finishedSoundUrl"];
]]>
</script>browser.downloadmanager.behavior
<groupbox>
<caption label="&downloadBehavior.label;"/>
<radiogroup id="downloadBehavior" prefstring="browser.downloadmanager.behavior">
@ -58,7 +60,31 @@
<radio value="1" label="&openProgressDialog.label;" accesskey="&openProgressDialog.accesskey;"/>
<radio value="2" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/>
</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>
</page>

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

@ -1,8 +1,20 @@
<!ENTITY lHeader "Downloads">
<!ENTITY downloadBehavior.label "When starting a download">
<!ENTITY finishedBehavior.label "When a download completes">
<!ENTITY openDM.label "Open the download manager">
<!ENTITY openDM.accesskey "m">
<!ENTITY openProgressDialog.label "Open a progress dialog">
<!ENTITY openProgressDialog.accesskey "p">
<!ENTITY doNothing.label "Don't open anything">
<!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">