From 13e75deaadacfac2edc6876010d940c305f3436c Mon Sep 17 00:00:00 2001 From: "ben%bengoodger.com" Date: Thu, 27 Nov 2003 00:54:33 +0000 Subject: [PATCH] 215467, Part I. New Download Manager. git-svn-id: svn://10.0.0.236/trunk@149788 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/browser/app/profile/all.js | 6 +- mozilla/browser/app/profile/firebird.js | 6 +- mozilla/browser/app/splash.rc | 4 +- .../browser/base/content/browser-menubar.inc | 2 + mozilla/browser/base/content/browser-sets.inc | 11 +- mozilla/browser/base/content/browser.js | 5 + mozilla/browser/base/content/browser.xul | 7 +- mozilla/browser/base/locale/browser.dtd | 12 +- mozilla/browser/components/Makefile.in | 2 +- mozilla/browser/components/build/Makefile.in | 6 - mozilla/browser/components/build/nsModule.cpp | 14 +- .../prefwindow/content/pref-privacy.js | 13 +- .../prefwindow/content/pref-privacy.xul | 22 +- .../components/prefwindow/content/pref.xul | 53 +- mozilla/toolkit/components/Makefile.in | 8 +- mozilla/toolkit/components/alerts/Makefile.in | 32 + mozilla/toolkit/components/alerts/jar.mn | 7 + .../components/alerts/public/Makefile.in | 35 + .../alerts/public/nsIAlertsService.idl | 68 + .../alerts/resources/content/alert.js | 129 ++ .../alerts/resources/content/alert.xul | 49 + .../alerts/resources/skin/alert.css | 84 + .../toolkit/components/alerts/src/Makefile.in | 48 + .../components/alerts/src/nsAlertsService.cpp | 127 ++ .../components/alerts/src/nsAlertsService.h | 57 + mozilla/toolkit/components/build/Makefile.in | 18 + mozilla/toolkit/components/build/nsModule.cpp | 26 + .../components/build/nsToolkitCompsCID.h | 16 + .../toolkit/components/downloads/Makefile.in | 32 + .../components/downloads/public/Makefile.in | 35 + .../downloads/public/nsIDownloadManager.idl | 197 ++ .../public/nsIDownloadProgressListener.idl | 95 + .../components/downloads/src/Makefile.in | 67 + .../downloads/src/nsDownloadManager.cpp | 1722 +++++++++++++++++ .../downloads/src/nsDownloadManager.h | 184 ++ .../src/nsDownloadProgressListener.js | 319 +++ .../downloads/src/nsDownloadProxy.h | 207 ++ .../toolkit/components/downloads/src/old.cpp | 74 + mozilla/toolkit/content/globalOverlay.js | 7 +- .../content/DownloadProgressListener.js | 264 +++ .../mozapps/downloads/content/download.xml | 458 +++++ .../downloads/content/downloadProperties.js | 60 + .../downloads/content/downloadProperties.xul | 56 + .../mozapps/downloads/content/downloads.css | 33 + .../mozapps/downloads/content/downloads.js | 477 +++++ .../mozapps/downloads/content/downloads.xul | 171 ++ .../downloads/content/pref-downloads.js | 16 +- .../downloads/content/pref-downloads.xul | 129 +- .../downloads/locale/downloadProperties.dtd | 7 + .../mozapps/downloads/locale/downloads.dtd | 58 + .../downloads/locale/downloads.properties | 35 + .../downloads/skin/downloadCleanup.png | Bin 0 -> 1519 bytes .../skin/downloadCleanupDisabled.png | Bin 0 -> 1169 bytes .../mozapps/downloads/skin/downloadFader.png | Bin 0 -> 849 bytes .../mozapps/downloads/skin/downloadIcon.png | Bin 0 -> 2497 bytes .../downloads/skin/downloadOptions.png | Bin 0 -> 1633 bytes .../downloads/skin/downloadSelected.png | Bin 0 -> 1589 bytes .../mozapps/downloads/skin/downloads.css | 100 + .../mozapps/downloads/skin/downloads.xml | 19 + .../mozapps/downloads/skin/downloadsBG.png | Bin 0 -> 17507 bytes mozilla/toolkit/mozapps/downloads/skin/jar.mn | 13 +- .../downloads/skin/mac/downloadCleanup.png | Bin 0 -> 1519 bytes .../skin/mac/downloadCleanupDisabled.png | Bin 0 -> 1169 bytes .../downloads/skin/mac/downloadFader.png | Bin 0 -> 849 bytes .../downloads/skin/mac/downloadIcon.png | Bin 0 -> 2497 bytes .../downloads/skin/mac/downloadOptions.png | Bin 0 -> 1633 bytes .../downloads/skin/mac/downloadSelected.png | Bin 0 -> 1589 bytes .../mozapps/downloads/skin/mac/downloads.css | 100 + .../mozapps/downloads/skin/mac/downloads.xml | 19 + .../downloads/skin/mac/downloadsBG.png | Bin 0 -> 17507 bytes .../toolkit/mozapps/downloads/skin/mac/jar.mn | 13 +- .../mozapps/downloads/skin/mac/viewFader.png | Bin 0 -> 849 bytes .../mozapps/downloads/skin/viewFader.png | Bin 0 -> 849 bytes mozilla/toolkit/mozapps/jar.mn | 10 + mozilla/toolkit/mozapps/pref/skin/pref.css | 10 +- 75 files changed, 5701 insertions(+), 153 deletions(-) create mode 100644 mozilla/toolkit/components/alerts/Makefile.in create mode 100644 mozilla/toolkit/components/alerts/jar.mn create mode 100644 mozilla/toolkit/components/alerts/public/Makefile.in create mode 100644 mozilla/toolkit/components/alerts/public/nsIAlertsService.idl create mode 100644 mozilla/toolkit/components/alerts/resources/content/alert.js create mode 100644 mozilla/toolkit/components/alerts/resources/content/alert.xul create mode 100644 mozilla/toolkit/components/alerts/resources/skin/alert.css create mode 100644 mozilla/toolkit/components/alerts/src/Makefile.in create mode 100644 mozilla/toolkit/components/alerts/src/nsAlertsService.cpp create mode 100644 mozilla/toolkit/components/alerts/src/nsAlertsService.h create mode 100644 mozilla/toolkit/components/downloads/Makefile.in create mode 100644 mozilla/toolkit/components/downloads/public/Makefile.in create mode 100644 mozilla/toolkit/components/downloads/public/nsIDownloadManager.idl create mode 100644 mozilla/toolkit/components/downloads/public/nsIDownloadProgressListener.idl create mode 100644 mozilla/toolkit/components/downloads/src/Makefile.in create mode 100644 mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp create mode 100644 mozilla/toolkit/components/downloads/src/nsDownloadManager.h create mode 100644 mozilla/toolkit/components/downloads/src/nsDownloadProgressListener.js create mode 100644 mozilla/toolkit/components/downloads/src/nsDownloadProxy.h create mode 100644 mozilla/toolkit/components/downloads/src/old.cpp create mode 100644 mozilla/toolkit/mozapps/downloads/content/DownloadProgressListener.js create mode 100644 mozilla/toolkit/mozapps/downloads/content/download.xml create mode 100644 mozilla/toolkit/mozapps/downloads/content/downloadProperties.js create mode 100644 mozilla/toolkit/mozapps/downloads/content/downloadProperties.xul create mode 100644 mozilla/toolkit/mozapps/downloads/content/downloads.css create mode 100644 mozilla/toolkit/mozapps/downloads/content/downloads.js create mode 100644 mozilla/toolkit/mozapps/downloads/content/downloads.xul create mode 100644 mozilla/toolkit/mozapps/downloads/locale/downloadProperties.dtd create mode 100644 mozilla/toolkit/mozapps/downloads/locale/downloads.dtd create mode 100644 mozilla/toolkit/mozapps/downloads/locale/downloads.properties create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadCleanup.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadCleanupDisabled.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadFader.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadIcon.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadOptions.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadSelected.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloads.css create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloads.xml create mode 100644 mozilla/toolkit/mozapps/downloads/skin/downloadsBG.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadCleanup.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadCleanupDisabled.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadFader.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadIcon.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadOptions.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadSelected.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloads.css create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloads.xml create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/downloadsBG.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/mac/viewFader.png create mode 100644 mozilla/toolkit/mozapps/downloads/skin/viewFader.png diff --git a/mozilla/browser/app/profile/all.js b/mozilla/browser/app/profile/all.js index 331186c3e99..fe5bdb07120 100644 --- a/mozilla/browser/app/profile/all.js +++ b/mozilla/browser/app/profile/all.js @@ -124,12 +124,12 @@ pref("accessibility.typeaheadfind.enabletimeout", true); pref("accessibility.typeaheadfind.soundURL", "default"); pref("accessibility.typeaheadfind.enablesound", true); -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.useProgressDialogs", true); pref("browser.download.openSidebar", false); pref("browser.download.useDownloadDir", true); pref("browser.download.folderList", 0); +pref("browser.download.retention", 2); +pref("browser.download.showWhenStarting", true); +pref("browser.download.closeWhenDone", true); // pointer to the default engine name pref("browser.search.defaultenginename", "chrome://browser-region/locale/region.properties"); diff --git a/mozilla/browser/app/profile/firebird.js b/mozilla/browser/app/profile/firebird.js index 331186c3e99..fe5bdb07120 100644 --- a/mozilla/browser/app/profile/firebird.js +++ b/mozilla/browser/app/profile/firebird.js @@ -124,12 +124,12 @@ pref("accessibility.typeaheadfind.enabletimeout", true); pref("accessibility.typeaheadfind.soundURL", "default"); pref("accessibility.typeaheadfind.enablesound", true); -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.useProgressDialogs", true); pref("browser.download.openSidebar", false); pref("browser.download.useDownloadDir", true); pref("browser.download.folderList", 0); +pref("browser.download.retention", 2); +pref("browser.download.showWhenStarting", true); +pref("browser.download.closeWhenDone", true); // pointer to the default engine name pref("browser.search.defaultenginename", "chrome://browser-region/locale/region.properties"); diff --git a/mozilla/browser/app/splash.rc b/mozilla/browser/app/splash.rc index 6623bf3aa03..ed85f8366d1 100644 --- a/mozilla/browser/app/splash.rc +++ b/mozilla/browser/app/splash.rc @@ -67,8 +67,8 @@ IDD_SPLASH DIALOGEX STRINGTABLE DISCARDABLE BEGIN - ID_DDE_APPLICATION_NAME, "Mozilla Firebird" - IDS_STARTMENU_APPNAME, "Mozilla Firebird" + ID_DDE_APPLICATION_NAME, "Mozilla Firebird Debug" + IDS_STARTMENU_APPNAME, "Mozilla Firebird Debug" END #ifdef MOZ_STATIC_BUILD diff --git a/mozilla/browser/base/content/browser-menubar.inc b/mozilla/browser/base/content/browser-menubar.inc index 921e5d27778..aa57b2de5dd 100644 --- a/mozilla/browser/base/content/browser-menubar.inc +++ b/mozilla/browser/base/content/browser-menubar.inc @@ -248,6 +248,8 @@ + #ifndef XP_MACOSX diff --git a/mozilla/browser/base/content/browser-sets.inc b/mozilla/browser/base/content/browser-sets.inc index 4cae8934330..bf8f2294e8e 100644 --- a/mozilla/browser/base/content/browser-sets.inc +++ b/mozilla/browser/base/content/browser-sets.inc @@ -1,4 +1,4 @@ - + @@ -93,17 +93,14 @@ + + #ifdef XP_MACOSX #endif - - @@ -216,7 +213,7 @@ - + #ifdef XP_MACOSX diff --git a/mozilla/browser/base/content/browser.js b/mozilla/browser/base/content/browser.js index b1e652e709f..b296164bfc5 100644 --- a/mozilla/browser/base/content/browser.js +++ b/mozilla/browser/base/content/browser.js @@ -1806,6 +1806,11 @@ function deleteHistoryItems(aParent) } } +function toDownloads() +{ + toOpenWindowByType("Download:Manager", "chrome://mozapps/content/downloads/downloads.xul"); +} + function toJavaScriptConsole() { toOpenWindowByType("global:console", "chrome://global/content/console.xul"); diff --git a/mozilla/browser/base/content/browser.xul b/mozilla/browser/base/content/browser.xul index 89129e0f698..8893c57ab95 100644 --- a/mozilla/browser/base/content/browser.xul +++ b/mozilla/browser/base/content/browser.xul @@ -36,7 +36,7 @@ # All DTD information is stored in a separate file so that it can be shared by # hiddenWindow.xul. #include browser-doctype.inc - + + observes="Tools:Downloads" + label="&downloads.label;" + tooltiptext="&downloads.tooltip;"/> - - - + + + + @@ -253,9 +254,6 @@ - - - @@ -270,8 +268,6 @@ - - diff --git a/mozilla/browser/components/Makefile.in b/mozilla/browser/components/Makefile.in index 7fa6736d9f1..98cff96fbe2 100644 --- a/mozilla/browser/components/Makefile.in +++ b/mozilla/browser/components/Makefile.in @@ -42,6 +42,6 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = bookmarks downloads history prefwindow security sidebar cookieviewer build +DIRS = bookmarks history prefwindow security sidebar cookieviewer build include $(topsrcdir)/config/rules.mk diff --git a/mozilla/browser/components/build/Makefile.in b/mozilla/browser/components/build/Makefile.in index 1cb0d6f71c4..fd4ec9f4b60 100644 --- a/mozilla/browser/components/build/Makefile.in +++ b/mozilla/browser/components/build/Makefile.in @@ -20,15 +20,11 @@ REQUIRES = \ pref \ rdf \ intl \ - downloads \ uriloader \ dom \ necko \ nkcache \ txmgr \ - webbrowserpersist \ - progressDlg \ - mimetype \ bookmarks \ $(NULL) @@ -42,12 +38,10 @@ OS_LIBS += $(call EXPAND_LIBNAME,ole32 shell32) endif LOCAL_INCLUDES = \ - -I$(srcdir)/../downloads/src \ -I$(srcdir)/../bookmarks/src \ $(NULL) SHARED_LIBRARY_LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)download_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)bookmarks_s.$(LIB_SUFFIX) \ $(NULL) diff --git a/mozilla/browser/components/build/nsModule.cpp b/mozilla/browser/components/build/nsModule.cpp index 2a0e064c93c..4bb517bd965 100644 --- a/mozilla/browser/components/build/nsModule.cpp +++ b/mozilla/browser/components/build/nsModule.cpp @@ -39,14 +39,10 @@ #include "nsIGenericFactory.h" #include "nsBrowserCompsCID.h" -#include "nsDownloadManager.h" -#include "nsDownloadProxy.h" #include "nsBookmarksService.h" ///////////////////////////////////////////////////////////////////////////// -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDownloadManager, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsBookmarksService, Init) ///////////////////////////////////////////////////////////////////////////// @@ -57,15 +53,7 @@ static const nsModuleComponentInfo components[] = nsBookmarksServiceConstructor }, { "Bookmarks", NS_BOOKMARKS_SERVICE_CID, NS_BOOKMARKS_DATASOURCE_CONTRACTID, nsBookmarksServiceConstructor }, - { "Download Manager", - NS_DOWNLOADMANAGER_CID, - NS_DOWNLOADMANAGER_CONTRACTID, - nsDownloadManagerConstructor }, - - { "Download", - NS_DOWNLOAD_CID, - NS_DOWNLOAD_CONTRACTID, - nsDownloadProxyConstructor } }; NS_IMPL_NSGETMODULE(nsBrowserCompsModule, components) + diff --git a/mozilla/browser/components/prefwindow/content/pref-privacy.js b/mozilla/browser/components/prefwindow/content/pref-privacy.js index 12133030059..69df1ac825b 100644 --- a/mozilla/browser/components/prefwindow/content/pref-privacy.js +++ b/mozilla/browser/components/prefwindow/content/pref-privacy.js @@ -41,7 +41,8 @@ var _elementIDs = ["histDay", "browserCacheDiskCache", "cookieBehavior", "enableCookies", "enableCookiesForOriginatingSiteOnly", "enableCookiesForCurrentSessionOnly", - "enableCookiesButAskFirst", "enableFormFill", "enablePasswords"]; + "enableCookiesButAskFirst", "enableFormFill", "enablePasswords", + "downloadsRetentionPolicy"]; function Startup() { @@ -97,11 +98,11 @@ function Startup() { // the bound element. dbaron is helping me with this with a reduced test case, but in // the meantime, I'm working around this bug by placing the menulist outside the bound element // until it is completely initialized and then scooting it in, which is what this code does. -# var drb = document.getElementById("downloadsRetentionBox"); -# var drp = document.getElementById("downloadsRetentionPolicy"); -# drp.removeAttribute("hidden"); -# document.documentElement.removeChild(drp); -# drb.appendChild(drp); + var drb = document.getElementById("downloadsRetentionBox"); + var drp = document.getElementById("downloadsRetentionPolicy"); + drp.removeAttribute("hidden"); + document.documentElement.removeChild(drp); + drb.appendChild(drp); } function unload() diff --git a/mozilla/browser/components/prefwindow/content/pref-privacy.xul b/mozilla/browser/components/prefwindow/content/pref-privacy.xul index 26237fafcbc..64e43bf715f 100644 --- a/mozilla/browser/components/prefwindow/content/pref-privacy.xul +++ b/mozilla/browser/components/prefwindow/content/pref-privacy.xul @@ -93,9 +93,9 @@ &downloadsDescription.label; -# -# &downloadsRetentionPolicy.label; -# + + &downloadsRetentionPolicy.label; + @@ -147,14 +147,14 @@ -# + diff --git a/mozilla/browser/components/prefwindow/content/pref.xul b/mozilla/browser/components/prefwindow/content/pref.xul index 36b0984771c..5022e159f7b 100644 --- a/mozilla/browser/components/prefwindow/content/pref.xul +++ b/mozilla/browser/components/prefwindow/content/pref.xul @@ -9,7 +9,7 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&prefWindow.title;" style="&prefWindow.size;" - buttons="accept,cancel" + buttons="accept,cancel" windowtype="Browser:Options" onload="Startup();" onunload="Shutdown();" ondialogaccept="return hPrefWindow.onOK(event);" ondialogcancel="return hPrefWindow.onCancel(event);" @@ -20,10 +20,13 @@ @@ -65,7 +82,7 @@ + + diff --git a/mozilla/toolkit/components/alerts/resources/skin/alert.css b/mozilla/toolkit/components/alerts/resources/skin/alert.css new file mode 100644 index 00000000000..66a65e628da --- /dev/null +++ b/mozilla/toolkit/components/alerts/resources/skin/alert.css @@ -0,0 +1,84 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott MacGregor + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* ===== alert.css ===================================================== + == Styles specific to the alerts dialog. + ======================================================================= */ + +@import url("chrome://global/skin/"); + +@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); + +.alertBox { + border-right: 2px solid #7B969C; + border-bottom: 2px solid #7B969C; + border-top: 2px solid #7B969C; + border-left: 2px solid #7B969C; + background-color: -moz-Dialog; + min-height: 50px; +} + +.alertImageBox { + margin-left: 4px; + margin-right: 6px; + min-height: 46px; +} + +.alertTitle { + font-weight: bold; +} + +.alertText { + margin-right: 6px; +} + +.alertText[clickable="true"] { + cursor: pointer; + color: #1455D6; + text-decoration: underline; +} + +.alertText[clickable="true"]:hover:active { + color: #424F63; +} + +.alertTextBox +{ + padding-right: 10px; + padding-top: 5px; +} + diff --git a/mozilla/toolkit/components/alerts/src/Makefile.in b/mozilla/toolkit/components/alerts/src/Makefile.in new file mode 100644 index 00000000000..07c3e75e446 --- /dev/null +++ b/mozilla/toolkit/components/alerts/src/Makefile.in @@ -0,0 +1,48 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = alerts +LIBRARY_NAME = alerts_s +REQUIRES = xpcom \ + string \ + windowwatcher \ + dom \ + $(NULL) + +CPPSRCS = \ + nsAlertsService.cpp \ + $(NULL) + +# we don't want the shared lib, but we want to force the creation of a +# static lib. +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/config/rules.mk + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) diff --git a/mozilla/toolkit/components/alerts/src/nsAlertsService.cpp b/mozilla/toolkit/components/alerts/src/nsAlertsService.cpp new file mode 100644 index 00000000000..dcb7de985a0 --- /dev/null +++ b/mozilla/toolkit/components/alerts/src/nsAlertsService.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott MacGregor + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsAlertsService.h" +#include "nsISupportsArray.h" +#include "nsXPCOM.h" +#include "nsISupportsPrimitives.h" +#include "nsIServiceManager.h" +#include "nsIDOMWindowInternal.h" +#include "nsIWindowWatcher.h" +#include "nsDependentString.h" + +#define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul" + +NS_IMPL_THREADSAFE_ADDREF(nsAlertsService) +NS_IMPL_THREADSAFE_RELEASE(nsAlertsService) + +NS_INTERFACE_MAP_BEGIN(nsAlertsService) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService) + NS_INTERFACE_MAP_ENTRY(nsIAlertsService) +NS_INTERFACE_MAP_END_THREADSAFE + +nsAlertsService::nsAlertsService() +{ +} + +nsAlertsService::~nsAlertsService() +{} + +NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const char * aImageUrl, const PRUnichar * aAlertTitle, + const PRUnichar * aAlertText, PRBool aAlertTextClickable, + const PRUnichar * aAlertCookie, + nsIAlertListener * aAlertListener) +{ + nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + nsCOMPtr newWindow; + nsresult rv; + + nsCOMPtr argsArray; + rv = NS_NewISupportsArray(getter_AddRefs(argsArray)); + NS_ENSURE_SUCCESS(rv, rv); + + // create scriptable versions of our strings that we can store in our nsISupportsArray.... + nsCOMPtr scriptableImageUrl (do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableImageUrl, NS_ERROR_FAILURE); + + scriptableImageUrl->SetData(nsDependentCString(aImageUrl)); + argsArray->AppendElement(scriptableImageUrl); + + nsCOMPtr scriptableAlertTitle (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertTitle, NS_ERROR_FAILURE); + + scriptableAlertTitle->SetData(nsDependentString(aAlertTitle)); + argsArray->AppendElement(scriptableAlertTitle); + + nsCOMPtr scriptableAlertText (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertText, NS_ERROR_FAILURE); + + scriptableAlertText->SetData(nsDependentString(aAlertText)); + argsArray->AppendElement(scriptableAlertText); + + nsCOMPtr scriptableIsClickable (do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID)); + NS_ENSURE_TRUE(scriptableIsClickable, NS_ERROR_FAILURE); + + scriptableIsClickable->SetData(aAlertTextClickable); + argsArray->AppendElement(scriptableIsClickable); + + nsCOMPtr scriptableAlertCookie (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + NS_ENSURE_TRUE(scriptableAlertCookie, NS_ERROR_FAILURE); + + scriptableAlertCookie->SetData(nsDependentString(aAlertCookie)); + argsArray->AppendElement(scriptableAlertCookie); + + if (aAlertListener) + { + nsCOMPtr ifptr = do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr iSupports (do_QueryInterface(aAlertListener)); + ifptr->SetData(iSupports); + ifptr->SetDataIID(&NS_GET_IID(nsISupports)); + argsArray->AppendElement(ifptr); +#if 0 + argsArray->AppendElement(aAlertListener); +#endif + } + + rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank", + "chrome,dialog=yes,titlebar=no,popup=yes", argsArray, + getter_AddRefs(newWindow)); + return rv; +} diff --git a/mozilla/toolkit/components/alerts/src/nsAlertsService.h b/mozilla/toolkit/components/alerts/src/nsAlertsService.h new file mode 100644 index 00000000000..091d448c806 --- /dev/null +++ b/mozilla/toolkit/components/alerts/src/nsAlertsService.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott MacGregor + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAlertsService_h__ +#define nsAlertsService_h__ + +#include "nsIAlertsService.h" +#include "nsCOMPtr.h" + +class nsAlertsService : public nsIAlertsService +{ +public: + NS_DECL_NSIALERTSSERVICE + NS_DECL_ISUPPORTS + + nsAlertsService(); + virtual ~nsAlertsService(); + +protected: +}; + +#endif /* nsAlertsService_h__ */ diff --git a/mozilla/toolkit/components/build/Makefile.in b/mozilla/toolkit/components/build/Makefile.in index c7197f8c9e1..37df7c45b72 100644 --- a/mozilla/toolkit/components/build/Makefile.in +++ b/mozilla/toolkit/components/build/Makefile.in @@ -44,6 +44,10 @@ REQUIRES = \ intl \ docshell \ autocomplete \ + downloads \ + mimetype \ + webbrowserpersist \ + progressDlg \ history \ satchel \ necko \ @@ -51,24 +55,38 @@ REQUIRES = \ uriloader \ $(NULL) +ifeq ($(OS_ARCH),WINNT) +REQUIRES += alerts +endif + EXPORTS = nsToolkitCompsCID.h CPPSRCS = nsModule.cpp LOCAL_INCLUDES = \ -I$(srcdir)/../autocomplete/src \ + -I$(srcdir)/../downloads/src \ -I$(srcdir)/../history/src \ -I$(srcdir)/../satchel/src \ -I$(srcdir)/../passwordmgr/base \ $(NULL) +ifeq ($(OS_ARCH),WINNT) +LOCAL_INCLUDES += -I$(srcdir)/../alerts/src +endif + SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)autocomplete_s.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)download_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)history_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)satchel_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)passwordmgr_s.$(LIB_SUFFIX) \ $(NULL) +ifeq ($(OS_ARCH),WINNT) +SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)alerts_s.$(LIB_SUFFIX) +endif + EXTRA_DSO_LIBS = gkgfx EXTRA_DSO_LDOPTS += \ diff --git a/mozilla/toolkit/components/build/nsModule.cpp b/mozilla/toolkit/components/build/nsModule.cpp index 008ade48680..9efdba0ad9f 100644 --- a/mozilla/toolkit/components/build/nsModule.cpp +++ b/mozilla/toolkit/components/build/nsModule.cpp @@ -37,9 +37,14 @@ #include "nsIGenericFactory.h" +#ifdef XP_WIN +#include "nsAlertsService.h" +#endif #include "nsToolkitCompsCID.h" #include "nsAutoCompleteController.h" #include "nsAutoCompleteMdbResult.h" +#include "nsDownloadManager.h" +#include "nsDownloadProxy.h" #include "nsFormHistory.h" #include "nsFormFillController.h" #include "nsGlobalHistory.h" @@ -48,8 +53,13 @@ ///////////////////////////////////////////////////////////////////////////// +#ifdef XP_WIN +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService) +#endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteController) NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteMdbResult) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDownloadManager, Init) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsFormHistory, nsFormHistory::GetInstance) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormFillController) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGlobalHistory, Init) @@ -69,6 +79,12 @@ static void PR_CALLBACK nsToolkitCompModuleDtor(nsIModule* self) static const nsModuleComponentInfo components[] = { +#ifdef XP_WIN + { "Alerts Service", + NS_ALERTSSERVICE_CID, + NS_ALERTSERVICE_CONTRACTID, + nsAlertsServiceConstructor }, +#endif { "AutoComplete Controller", NS_AUTOCOMPLETECONTROLLER_CID, NS_AUTOCOMPLETECONTROLLER_CONTRACTID, @@ -79,6 +95,16 @@ static const nsModuleComponentInfo components[] = NS_AUTOCOMPLETEMDBRESULT_CONTRACTID, nsAutoCompleteMdbResultConstructor }, + { "Download Manager", + NS_DOWNLOADMANAGER_CID, + NS_DOWNLOADMANAGER_CONTRACTID, + nsDownloadManagerConstructor }, + + { "Download", + NS_DOWNLOAD_CID, + NS_DOWNLOAD_CONTRACTID, + nsDownloadProxyConstructor }, + { "HTML Form History", NS_FORMHISTORY_CID, NS_FORMHISTORY_CONTRACTID, diff --git a/mozilla/toolkit/components/build/nsToolkitCompsCID.h b/mozilla/toolkit/components/build/nsToolkitCompsCID.h index 56db4472945..0fecbf15f09 100644 --- a/mozilla/toolkit/components/build/nsToolkitCompsCID.h +++ b/mozilla/toolkit/components/build/nsToolkitCompsCID.h @@ -35,12 +35,21 @@ * * ***** END LICENSE BLOCK ***** */ +#define NS_ALERTSERVICE_CONTRACTID \ + "@mozilla.org/alerts-service;1" + +#define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \ + "@mozilla.org/autocomplete/controller;1" + #define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \ "@mozilla.org/autocomplete/controller;1" #define NS_AUTOCOMPLETEMDBRESULT_CONTRACTID \ "@mozilla.org/autocomplete/mdb-result;1" +#define NS_DOWNLOADMANAGER_CONTRACTID \ + "@mozilla.org/download-manager;1" + #define NS_FORMHISTORY_CONTRACTID \ "@mozilla.org/satchel/form-history;1" @@ -55,6 +64,10 @@ ///////////////////////////////////////////////////////////////////////////// +// {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117} +#define NS_ALERTSSERVICE_CID \ +{ 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } } + // {F6D5EBBD-34F4-487d-9D10-3D34123E3EB9} #define NS_AUTOCOMPLETECONTROLLER_CID \ { 0xf6d5ebbd, 0x34f4, 0x487d, { 0x9d, 0x10, 0x3d, 0x34, 0x12, 0x3e, 0x3e, 0xb9 } } @@ -63,6 +76,9 @@ #define NS_AUTOCOMPLETEMDBRESULT_CID \ { 0x7a6f70b6, 0x2bbd, 0x44b5, { 0x93, 0x4, 0x50, 0x13, 0x52, 0xd4, 0x4a, 0xb5 } } +#define NS_DOWNLOADMANAGER_CID \ + { 0xedb0490e, 0x1dd1, 0x11b2, { 0x83, 0xb8, 0xdb, 0xf8, 0xd8, 0x59, 0x06, 0xa6 } } + // {895DB6C7-DBDF-40ea-9F64-B175033243DC} #define NS_FORMFILLCONTROLLER_CID \ { 0x895db6c7, 0xdbdf, 0x40ea, { 0x9f, 0x64, 0xb1, 0x75, 0x3, 0x32, 0x43, 0xdc } } diff --git a/mozilla/toolkit/components/downloads/Makefile.in b/mozilla/toolkit/components/downloads/Makefile.in new file mode 100644 index 00000000000..45aa93750bb --- /dev/null +++ b/mozilla/toolkit/components/downloads/Makefile.in @@ -0,0 +1,32 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/toolkit/components/downloads/public/Makefile.in b/mozilla/toolkit/components/downloads/public/Makefile.in new file mode 100644 index 00000000000..1164a2a0e94 --- /dev/null +++ b/mozilla/toolkit/components/downloads/public/Makefile.in @@ -0,0 +1,35 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = downloads + +XPIDLSRCS = nsIDownloadManager.idl \ + nsIDownloadProgressListener.idl \ + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/toolkit/components/downloads/public/nsIDownloadManager.idl b/mozilla/toolkit/components/downloads/public/nsIDownloadManager.idl new file mode 100644 index 00000000000..992d99e065a --- /dev/null +++ b/mozilla/toolkit/components/downloads/public/nsIDownloadManager.idl @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross + * Ben Goodger + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +// Keeps track of ongoing downloads, in the form of nsIDownload's. + +#include "nsISupports.idl" + +interface nsIDOMWindow; +interface nsIURI; +interface nsILocalFile; +interface nsIDownload; +interface nsIWebBrowserPersist; +interface nsIMIMEInfo; +interface nsIRDFDataSource; +interface nsIDownloadProgressListener; +interface nsISupportsArray; + +[scriptable, uuid(9be66cc0-1dd1-11b2-8617-e3a3ed26e3b0)] +interface nsIDownloadManager : nsISupports { + + // Methods called by clients to carry out various managing functions + + /** + * Creates an nsIDownload and adds it to be managed by the download manager. + * + * @param aSource The source (nsIURI) of the download. + * + * @param aTarget The local file to which the download is being saved. + * + * @param aDisplayName The user-readable description of the download. + * + * @param aPersist The "persist" used to transfer the download. If set, + * the manager will set its listener to the download item + * and use it for cancellation. If not set, the client + * is expected to set the download item as the listener on + * whatever transfer component is being used, and to + * set an observer on the download item that listens for + * the "oncancel" topic and cancels the download. + * + * @return The newly created download item with the passed-in properties. + */ + nsIDownload addDownload(in nsIURI aSource, + in nsILocalFile aTarget, + in wstring aDisplayName, + in nsIMIMEInfo aMIMEInfo, + in long long startTime, + in nsIWebBrowserPersist aPersist); + + /** + * Retrieves an in-progress download managed by the download manager. + * + * @param aPersistentDescriptor The unique identifier used to describe a + * a download, and an attribute of nsILocalFile. + * On Windows and Linux, this is just the path + * of the target, but on Mac this is guaranteed + * to be unique. + * + * @return The download with the specified persistent descriptor. + */ + nsIDownload getDownload(in wstring aPersistentDescriptor); + + /** + * Cancels the download with the specified persistent descriptor if it's + * currently in progress. If a "persist" was specified for the download, + * nsIWebBrowserPersist::CancelSave will be called. If an observer was set + * on the nsIDownload, it will be notified with the "oncancel" topic. Clients + * that don't provide a "persist" must listen for this topic and cancel the + * download. + * + * @param aPersistentDescriptor The persistent descriptor of the download to + * be cancelled. + */ + void cancelDownload(in wstring aPersistentDescriptor); + + /** + * Removes the download with the specified persistent descriptor if it's not + * currently in progress. Whereas cancelDownload simply cancels the transfer + * but retains information about it, removeDownload removes all knowledge of it. + * + * @param aPersistentDescriptor The persistent descriptor of the download to + * be removed. + */ + void removeDownload(in wstring aPersistentDescriptor); + + /** + * Pause the specified download. + */ + void pauseDownload(in wstring aPersistentDescriptor); + + /** + * Resume the specified download. + */ + void resumeDownload(in wstring aPersistentDescriptor); + + // Front end and Front end update methods. + + /** + * Opens the Download Manager front end. + * + * @param aParent The parent, or opener, of the front end (optional). + * @param aDownload A download to pass to the manager widnow. Useful if, + * for example, you want the window to select a certain + * download (optional). + */ + + void open(in nsIDOMWindow aParent, in wstring aPersistentDescriptor); + + /** + * The Download Manager's progress listener. + */ + attribute nsIDownloadProgressListener listener; + + /** + * Indicate that a batch update (e.g. mass removal) is about to start. + */ + + void startBatchUpdate(); + + /** + * Indicate that a batch update is ending. + */ + + void endBatchUpdate(); + + // Downloads list book-keeping + + /** + * Whether or not there are downloads that can be cleaned up (removed) + * i.e. downloads that have completed, have failed or have been canceled. + */ + readonly attribute boolean canCleanUp; + + /** + * Removes completed, failed, and canceled downloads from the list. + */ + void cleanUp(); + + /** + * The number of files currently being downloaded. + */ + readonly attribute long activeDownloadCount; + + /** + * An enumeration of active downloads. + */ + readonly attribute nsISupportsArray activeDownloads; + + /** + * Update the download datasource. + */ + void saveState(); + + /** + * Flush the download datasource to disk. + */ + void flush(); + + readonly attribute nsIRDFDataSource datasource; +}; + + diff --git a/mozilla/toolkit/components/downloads/public/nsIDownloadProgressListener.idl b/mozilla/toolkit/components/downloads/public/nsIDownloadProgressListener.idl new file mode 100644 index 00000000000..648ae81fa29 --- /dev/null +++ b/mozilla/toolkit/components/downloads/public/nsIDownloadProgressListener.idl @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* A minimally extended progress listener used by download manager + * to update its default UI. This is implemented in nsDownloadProgressListener.js. + * See nsIWebProgressListener for documentation, and use its constants. This isn't + * too pretty, but the alternative is having this extend nsIWebProgressListener and + * adding an |item| attribute, which would mean a separate nsIDownloadProgressListener + * for every nsIDownloadItem, which is a waste... + */ + +#include "nsISupports.idl" + +interface nsIWebProgress; +interface nsIRequest; +interface nsIURI; +interface nsIDownload; +interface nsIDOMDocument; + +[scriptable, uuid(09cddbea-1dd2-11b2-aa15-c41ffea19d79)] +interface nsIDownloadProgressListener : nsISupports { + + /** + * document + * The document of the download manager frontend. + */ + + attribute nsIDOMDocument document; + + void onStateChange(in nsIWebProgress aWebProgress, + in nsIRequest aRequest, + in unsigned long aStateFlags, + in nsresult aStatus, + in nsIDownload aDownload); + + void onProgressChange(in nsIWebProgress aWebProgress, + in nsIRequest aRequest, + in long aCurSelfProgress, + in long aMaxSelfProgress, + in long aCurTotalProgress, + in long aMaxTotalProgress, + in nsIDownload aDownload); + + void onStatusChange(in nsIWebProgress aWebProgress, + in nsIRequest aRequest, + in nsresult aStatus, + in wstring aMessage, + in nsIDownload aDownload); + + void onLocationChange(in nsIWebProgress aWebProgress, + in nsIRequest aRequest, + in nsIURI aLocation, + in nsIDownload aDownload); + + void onSecurityChange(in nsIWebProgress aWebProgress, + in nsIRequest aRequest, + in unsigned long aState, + in nsIDownload aDownload); + +}; \ No newline at end of file diff --git a/mozilla/toolkit/components/downloads/src/Makefile.in b/mozilla/toolkit/components/downloads/src/Makefile.in new file mode 100644 index 00000000000..d0407037cf2 --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/Makefile.in @@ -0,0 +1,67 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Stuart Parmenter +# + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = downloads +LIBRARY_NAME = download_s + +REQUIRES = xpcom \ + string \ + rdf \ + uriloader \ + mimetype \ + necko \ + pref \ + progressDlg \ + intl \ + windowwatcher \ + webbrowserpersist \ + appshell \ + dom \ + toolkitcomps \ + $(NULL) + +ifeq ($(OS_ARCH),WINNT) +REQUIRES += alerts +endif + +CPPSRCS = \ + nsDownloadManager.cpp \ + $(NULL) + +EXTRA_COMPONENTS = nsDownloadProgressListener.js + +# we don't want the shared lib, but we want to force the creation of a +# static lib. +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/config/rules.mk + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) + diff --git a/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp b/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp new file mode 100644 index 00000000000..fad9ea8e45c --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/nsDownloadManager.cpp @@ -0,0 +1,1722 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross (Original Author) + * Ben Goodger (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsDownloadManager.h" +#include "nsIWebProgress.h" +#include "nsIRDFLiteral.h" +#include "rdf.h" +#include "nsNetUtil.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventTarget.h" +#include "nsRDFCID.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIWebBrowserPersist.h" +#include "nsIObserver.h" +#include "nsIProgressDialog.h" +#include "nsIWebBrowserPersist.h" +#include "nsIWindowWatcher.h" +#include "nsIStringBundle.h" +#include "nsISupportsPrimitives.h" +#include "nsCRT.h" +#include "nsIWindowMediator.h" +#include "nsIPromptService.h" +#include "nsIObserverService.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsVoidArray.h" + +/* Outstanding issues/todo: + * 1. Implement pause/resume. + */ + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); +static PRBool gQuitting = PR_FALSE; + +#define DOWNLOAD_MANAGER_FE_URL "chrome://mozapps/content/downloads/downloads.xul" +#define DOWNLOAD_MANAGER_BUNDLE "chrome://mozapps/locale/downloads/downloads.properties" +#define DOWNLOAD_MANAGER_ALERT_ICON "chrome://mozapps/skin/downloads/downloadIcon.png" +#define INTERVAL 500 + +static nsIRDFResource* gNC_DownloadsRoot = nsnull; +static nsIRDFResource* gNC_File = nsnull; +static nsIRDFResource* gNC_URL = nsnull; +static nsIRDFResource* gNC_Name = nsnull; +static nsIRDFResource* gNC_ProgressPercent = nsnull; +static nsIRDFResource* gNC_Transferred = nsnull; +static nsIRDFResource* gNC_DownloadState = nsnull; +static nsIRDFResource* gNC_StatusText = nsnull; +static nsIRDFResource* gNC_DateStarted = nsnull; +static nsIRDFResource* gNC_DateEnded = nsnull; + +static nsIRDFService* gRDFService = nsnull; +static nsIObserverService* gObserverService = nsnull; +static PRInt32 gRefCnt = 0; + +/////////////////////////////////////////////////////////////////////////////// +// nsDownloadManager + +NS_IMPL_ISUPPORTS2(nsDownloadManager, nsIDownloadManager, nsIObserver) + +nsDownloadManager::nsDownloadManager() : mBatches(0) +{ +} + +nsDownloadManager::~nsDownloadManager() +{ + if (--gRefCnt != 0 || !gRDFService || !gObserverService) + // Either somebody tried to use |CreateInstance| instead of + // |GetService| or |Init| failed very early, so there's nothing to + // do here. + return; + + gRDFService->UnregisterDataSource(mDataSource); + + gObserverService->RemoveObserver(this, "quit-application"); + gObserverService->RemoveObserver(this, "quit-application-requested"); + + NS_IF_RELEASE(gNC_DownloadsRoot); + NS_IF_RELEASE(gNC_File); + NS_IF_RELEASE(gNC_URL); + NS_IF_RELEASE(gNC_Name); + NS_IF_RELEASE(gNC_ProgressPercent); + NS_IF_RELEASE(gNC_Transferred); + NS_IF_RELEASE(gNC_DownloadState); + NS_IF_RELEASE(gNC_StatusText); + NS_IF_RELEASE(gNC_DateStarted); + NS_IF_RELEASE(gNC_DateEnded); + + NS_RELEASE(gRDFService); + NS_RELEASE(gObserverService); +} + +PRInt32 PR_CALLBACK nsDownloadManager::CancelAllDownloads(nsHashKey* aKey, void* aData, void* aClosure) +{ + nsStringKey* key = (nsStringKey*)aKey; + nsresult rv; + + nsCOMPtr manager = do_QueryInterface((nsISupports*)aClosure, &rv); + if (NS_FAILED(rv)) return kHashEnumerateRemove; + + DownloadState state; + NS_STATIC_CAST(nsDownload*, aData)->GetDownloadState(&state); + if (state == NOTSTARTED || state == DOWNLOADING || state == PAUSED) + manager->CancelDownload(key->GetString()); + else + NS_STATIC_CAST(nsDownloadManager*, aClosure)->DownloadEnded(key->GetString(), nsnull); + + return kHashEnumerateRemove; +} + +nsresult +nsDownloadManager::Init() +{ + if (gRefCnt++ != 0) { + NS_NOTREACHED("download manager should be used as a service"); + return NS_ERROR_UNEXPECTED; // This will make the |CreateInstance| fail. + } + + nsresult rv; + mRDFContainerUtils = do_GetService("@mozilla.org/rdf/container-utils;1", &rv); + if (NS_FAILED(rv)) return rv; + + rv = CallGetService("@mozilla.org/observer-service;1", &gObserverService); + if (NS_FAILED(rv)) return rv; + + gObserverService->AddObserver(this, "quit-application", PR_FALSE); + gObserverService->AddObserver(this, "quit-application-requested", PR_FALSE); + + rv = CallGetService(kRDFServiceCID, &gRDFService); + if (NS_FAILED(rv)) return rv; + + gRDFService->GetResource(NS_LITERAL_CSTRING("NC:DownloadsRoot"), &gNC_DownloadsRoot); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "File"), &gNC_File); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"), &gNC_URL); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"), &gNC_Name); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "ProgressPercent"), &gNC_ProgressPercent); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Transferred"), &gNC_Transferred); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "DownloadState"), &gNC_DownloadState); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "StatusText"), &gNC_StatusText); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "DateStarted"), &gNC_DateStarted); + gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "DateEnded"), &gNC_DateEnded); + + nsCAutoString downloadsDB; + rv = GetProfileDownloadsFileURL(downloadsDB); + if (NS_FAILED(rv)) return rv; + + rv = gRDFService->GetDataSourceBlocking(downloadsDB.get(), getter_AddRefs(mDataSource)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr bundleService = do_GetService(kStringBundleServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + return bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(mBundle)); +} + +PRInt32 +nsDownloadManager::GetRetentionBehavior() +{ + PRInt32 val = 0; + nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (pref) { + nsresult rv = pref->GetIntPref("browser.download.retention", &val); + if (NS_FAILED(rv)) + val = 0; // Use 0 as the default ("remove when done") + } + + return val; +} + +nsresult +nsDownloadManager::DownloadStarted(const PRUnichar* aPath) +{ + nsStringKey key(aPath); + if (mCurrDownloads.Exists(&key)) { + + // Assert the date and time that the download ended. + nsCOMPtr dateLiteral; + if (NS_SUCCEEDED(gRDFService->GetDateLiteral(PR_Now(), getter_AddRefs(dateLiteral)))) { + nsCOMPtr res; + nsCOMPtr node; + + gRDFService->GetUnicodeResource(nsDependentString(aPath), getter_AddRefs(res)); + + mDataSource->GetTarget(res, gNC_DateStarted, PR_TRUE, getter_AddRefs(node)); + if (node) + mDataSource->Change(res, gNC_DateStarted, node, dateLiteral); + else + mDataSource->Assert(res, gNC_DateStarted, dateLiteral, PR_TRUE); + } + + AssertProgressInfoFor(aPath); + } + + return NS_OK; +} + +nsresult +nsDownloadManager::DownloadEnded(const PRUnichar* aPath, const PRUnichar* aMessage) +{ + nsStringKey key(aPath); + if (mCurrDownloads.Exists(&key)) { + + // Assert the date and time that the download ended. + nsCOMPtr dateLiteral; + if (NS_SUCCEEDED(gRDFService->GetDateLiteral(PR_Now(), getter_AddRefs(dateLiteral)))) { + nsCOMPtr res; + nsCOMPtr node; + + gRDFService->GetUnicodeResource(nsDependentString(aPath), getter_AddRefs(res)); + + mDataSource->GetTarget(res, gNC_DateEnded, PR_TRUE, getter_AddRefs(node)); + if (node) + mDataSource->Change(res, gNC_DateEnded, node, dateLiteral); + else + mDataSource->Assert(res, gNC_DateEnded, dateLiteral, PR_TRUE); + } + + AssertProgressInfoFor(aPath); + + nsDownload* download = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + NS_RELEASE(download); + + if (!gQuitting) + mCurrDownloads.Remove(&key); + } + + return NS_OK; +} + +nsresult +nsDownloadManager::GetProfileDownloadsFileURL(nsCString& aDownloadsFileURL) +{ + nsCOMPtr downloadsFile; + nsresult rv = NS_GetSpecialDirectory(NS_APP_DOWNLOADS_50_FILE, getter_AddRefs(downloadsFile)); + if (NS_FAILED(rv)) + return rv; + + return NS_GetURLSpecFromFile(downloadsFile, aDownloadsFileURL); +} + +nsresult +nsDownloadManager::GetDownloadsContainer(nsIRDFContainer** aResult) +{ + if (mDownloadsContainer) { + *aResult = mDownloadsContainer; + NS_ADDREF(*aResult); + return NS_OK; + } + + PRBool isContainer; + nsresult rv = mRDFContainerUtils->IsContainer(mDataSource, gNC_DownloadsRoot, &isContainer); + if (NS_FAILED(rv)) return rv; + + if (!isContainer) { + rv = mRDFContainerUtils->MakeSeq(mDataSource, gNC_DownloadsRoot, getter_AddRefs(mDownloadsContainer)); + if (NS_FAILED(rv)) return rv; + } + else { + mDownloadsContainer = do_CreateInstance(NS_RDF_CONTRACTID "/container;1", &rv); + if (NS_FAILED(rv)) return rv; + rv = mDownloadsContainer->Init(mDataSource, gNC_DownloadsRoot); + if (NS_FAILED(rv)) return rv; + } + + *aResult = mDownloadsContainer; + NS_IF_ADDREF(*aResult); + + return rv; +} + +nsresult +nsDownloadManager::GetInternalListener(nsIDownloadProgressListener** aListener) +{ + *aListener = mListener; + NS_IF_ADDREF(*aListener); + return NS_OK; +} + +nsresult +nsDownloadManager::GetDataSource(nsIRDFDataSource** aDataSource) +{ + *aDataSource = mDataSource; + NS_IF_ADDREF(*aDataSource); + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::GetActiveDownloadCount(PRInt32* aResult) +{ + *aResult = mCurrDownloads.Count(); + + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::GetActiveDownloads(nsISupportsArray** aResult) +{ + nsCOMPtr ary; + NS_NewISupportsArray(getter_AddRefs(ary)); + mCurrDownloads.Enumerate(BuildActiveDownloadsList, (void*)ary); + + NS_ADDREF(*aResult = ary); + + return NS_OK; +} + +PRInt32 PR_CALLBACK +nsDownloadManager::BuildActiveDownloadsList(nsHashKey* aKey, void* aData, void* aClosure) +{ + nsCOMPtr ary(do_QueryInterface((nsISupports*)aClosure)); + nsCOMPtr dl(do_QueryInterface((nsISupports*)aData)); + + ary->AppendElement(dl); + + return kHashEnumerateNext; +} + +NS_IMETHODIMP +nsDownloadManager::SaveState() +{ + nsCOMPtr supports; + nsCOMPtr res; + nsCOMPtr intLiteral; + + DownloadState states[] = { DOWNLOADING, PAUSED }; + + for (int i = 0; i < 2; ++i) { + gRDFService->GetIntLiteral(states[i], getter_AddRefs(intLiteral)); + nsCOMPtr downloads; + nsresult rv = mDataSource->GetSources(gNC_DownloadState, intLiteral, PR_TRUE, getter_AddRefs(downloads)); + if (NS_FAILED(rv)) return rv; + + PRBool hasMoreElements; + downloads->HasMoreElements(&hasMoreElements); + + while (hasMoreElements) { + const char* uri; + downloads->GetNext(getter_AddRefs(supports)); + res = do_QueryInterface(supports); + res->GetValueConst(&uri); + AssertProgressInfoFor(NS_ConvertASCIItoUCS2(uri).get()); + downloads->HasMoreElements(&hasMoreElements); + } + } + + return NS_OK; +} + +nsresult +nsDownloadManager::AssertProgressInfoFor(const PRUnichar* aPath) +{ + nsStringKey key(aPath); + if (!mCurrDownloads.Exists(&key)) + return NS_ERROR_FAILURE; + + nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + nsCOMPtr download; + internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) getter_AddRefs(download)); + if (!download) + return NS_ERROR_FAILURE; + + nsresult rv; + PRInt32 percentComplete; + nsCOMPtr oldTarget; + nsCOMPtr intLiteral; + nsCOMPtr res; + nsCOMPtr literal; + + gRDFService->GetUnicodeResource(nsDependentString(aPath), getter_AddRefs(res)); + + DownloadState state; + internalDownload->GetDownloadState(&state); + + // update download state (not started, downloading, queued, finished, etc...) + gRDFService->GetIntLiteral(state, getter_AddRefs(intLiteral)); + + mDataSource->GetTarget(res, gNC_DownloadState, PR_TRUE, getter_AddRefs(oldTarget)); + + if (oldTarget) + rv = mDataSource->Change(res, gNC_DownloadState, oldTarget, intLiteral); + else + rv = mDataSource->Assert(res, gNC_DownloadState, intLiteral, PR_TRUE); + if (NS_FAILED(rv)) return rv; + + // update percentage + download->GetPercentComplete(&percentComplete); + + mDataSource->GetTarget(res, gNC_ProgressPercent, PR_TRUE, getter_AddRefs(oldTarget)); + gRDFService->GetIntLiteral(percentComplete, getter_AddRefs(intLiteral)); + + if (oldTarget) + rv = mDataSource->Change(res, gNC_ProgressPercent, oldTarget, intLiteral); + else + rv = mDataSource->Assert(res, gNC_ProgressPercent, intLiteral, PR_TRUE); + if (NS_FAILED(rv)) return rv; + + // update transferred + PRInt32 current = 0; + PRInt32 max = 0; + internalDownload->GetTransferInformation(¤t, &max); + + nsAutoString currBytes; currBytes.AppendInt(current); + nsAutoString maxBytes; maxBytes.AppendInt(max); + const PRUnichar *strings[] = { + currBytes.get(), + maxBytes.get() + }; + + nsXPIDLString value; + rv = mBundle->FormatStringFromName(NS_LITERAL_STRING("transferred").get(), + strings, 2, getter_Copies(value)); + if (NS_FAILED(rv)) return rv; + + gRDFService->GetLiteral(value, getter_AddRefs(literal)); + + mDataSource->GetTarget(res, gNC_Transferred, PR_TRUE, getter_AddRefs(oldTarget)); + + if (oldTarget) + rv = mDataSource->Change(res, gNC_Transferred, oldTarget, literal); + else + rv = mDataSource->Assert(res, gNC_Transferred, literal, PR_TRUE); + if (NS_FAILED(rv)) return rv; + + // XXX should also store and update time elapsed + return Flush(); +} + +/////////////////////////////////////////////////////////////////////////////// +// nsIDownloadManager + +NS_IMETHODIMP +nsDownloadManager::AddDownload(nsIURI* aSource, + nsILocalFile* aTarget, + const PRUnichar* aDisplayName, + nsIMIMEInfo *aMIMEInfo, + PRInt64 aStartTime, + nsIWebBrowserPersist* aPersist, + nsIDownload** aDownload) +{ + NS_ENSURE_ARG_POINTER(aSource); + NS_ENSURE_ARG_POINTER(aTarget); + NS_ENSURE_ARG_POINTER(aDownload); + + nsCOMPtr downloads; + nsresult rv = GetDownloadsContainer(getter_AddRefs(downloads)); + if (NS_FAILED(rv)) return rv; + + nsDownload* internalDownload = new nsDownload(); + if (!internalDownload) + return NS_ERROR_OUT_OF_MEMORY; + + internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) aDownload); + if (!aDownload) + return NS_ERROR_FAILURE; + + NS_ADDREF(*aDownload); + + // give our new nsIDownload some info so it's ready to go off into the world + internalDownload->SetDownloadManager(this); + internalDownload->SetTarget(aTarget); + internalDownload->SetSource(aSource); + + // the persistent descriptor of the target is the unique identifier we use + nsAutoString path; + rv = aTarget->GetPath(path); + if (NS_FAILED(rv)) return rv; + + nsStringKey key(path); + if (mCurrDownloads.Exists(&key)) + CancelDownload(path.get()); + + nsCOMPtr downloadRes; + gRDFService->GetUnicodeResource(path, getter_AddRefs(downloadRes)); + + // if the resource is in the container already (the user has already + // downloaded this file), remove it + PRInt32 itemIndex; + nsCOMPtr node; + downloads->IndexOf(downloadRes, &itemIndex); + if (itemIndex > 0) { + rv = downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + if (NS_FAILED(rv)) return rv; + } + rv = downloads->InsertElementAt(downloadRes, 1, PR_TRUE); + if (NS_FAILED(rv)) return rv; + + // Assert source url information + nsCAutoString spec; + aSource->GetSpec(spec); + + nsCOMPtr urlResource; + gRDFService->GetResource(spec, getter_AddRefs(urlResource)); + mDataSource->GetTarget(downloadRes, gNC_URL, PR_TRUE, getter_AddRefs(node)); + if (node) + rv = mDataSource->Change(downloadRes, gNC_URL, node, urlResource); + else + rv = mDataSource->Assert(downloadRes, gNC_URL, urlResource, PR_TRUE); + if (NS_FAILED(rv)) { + downloads->IndexOf(downloadRes, &itemIndex); + downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + return rv; + } + + // Set and assert the "pretty" (display) name of the download + nsAutoString displayName; displayName.Assign(aDisplayName); + if (displayName.IsEmpty()) { + aTarget->GetLeafName(displayName); + } + (*aDownload)->SetDisplayName(displayName.get()); + + nsCOMPtr nameLiteral; + gRDFService->GetLiteral(displayName.get(), getter_AddRefs(nameLiteral)); + mDataSource->GetTarget(downloadRes, gNC_Name, PR_TRUE, getter_AddRefs(node)); + if (node) + rv = mDataSource->Change(downloadRes, gNC_Name, node, nameLiteral); + else + rv = mDataSource->Assert(downloadRes, gNC_Name, nameLiteral, PR_TRUE); + if (NS_FAILED(rv)) { + downloads->IndexOf(downloadRes, &itemIndex); + downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + return rv; + } + + internalDownload->SetMIMEInfo(aMIMEInfo); + internalDownload->SetStartTime(aStartTime); + + // Assert file information + nsCOMPtr fileResource; + gRDFService->GetUnicodeResource(path, getter_AddRefs(fileResource)); + rv = mDataSource->Assert(downloadRes, gNC_File, fileResource, PR_TRUE); + if (NS_FAILED(rv)) { + downloads->IndexOf(downloadRes, &itemIndex); + downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + return rv; + } + + // Assert download state information (NOTSTARTED, since it's just now being added) + nsCOMPtr intLiteral; + gRDFService->GetIntLiteral(NOTSTARTED, getter_AddRefs(intLiteral)); + mDataSource->GetTarget(downloadRes, gNC_DownloadState, PR_TRUE, getter_AddRefs(node)); + if (node) + rv = mDataSource->Change(downloadRes, gNC_DownloadState, node, intLiteral); + else + rv = mDataSource->Assert(downloadRes, gNC_DownloadState, intLiteral, PR_TRUE); + if (NS_FAILED(rv)) { + downloads->IndexOf(downloadRes, &itemIndex); + downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + return rv; + } + + // Now flush all this to disk + if (NS_FAILED(Flush())) { + downloads->IndexOf(downloadRes, &itemIndex); + downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + return rv; + } + + // if a persist object was specified, set the download item as the progress listener + // this will create a cycle that will be broken in nsDownload::OnStateChange + if (aPersist) { + internalDownload->SetPersist(aPersist); + nsCOMPtr listener = do_QueryInterface(*aDownload); + aPersist->SetProgressListener(listener); + } + + mCurrDownloads.Put(&key, *aDownload); + gObserverService->NotifyObservers(*aDownload, "dl-start", nsnull); + return rv; +} + +NS_IMETHODIMP +nsDownloadManager::GetDownload(const PRUnichar* aPath, nsIDownload** aDownloadItem) +{ + NS_ENSURE_ARG_POINTER(aDownloadItem); + + // if it's currently downloading we can get it from the table + // XXX otherwise we should look for it in the datasource and + // create a new nsIDownload with the resource's properties + nsStringKey key(aPath); + if (mCurrDownloads.Exists(&key)) { + *aDownloadItem = NS_STATIC_CAST(nsIDownload*, mCurrDownloads.Get(&key)); + NS_ADDREF(*aDownloadItem); + return NS_OK; + } + + *aDownloadItem = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::CancelDownload(const PRUnichar* aPath) +{ + nsresult rv = NS_OK; + nsStringKey key(aPath); + if (!mCurrDownloads.Exists(&key)) + return RemoveDownload(aPath); // XXXBlake for now, to provide a workaround for stuck downloads + + nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + nsCOMPtr download; + CallQueryInterface(internalDownload, NS_STATIC_CAST(nsIDownload**, + getter_AddRefs(download))); + if (!download) + return NS_ERROR_FAILURE; + + // Don't cancel if download is already finished + if (internalDownload->mDownloadState == FINISHED) + return NS_OK; + + internalDownload->SetDownloadState(CANCELED); + + // if a persist was provided, we can do the cancel ourselves. + nsCOMPtr persist; + download->GetPersist(getter_AddRefs(persist)); + if (persist) { + rv = persist->CancelSave(); + if (NS_FAILED(rv)) return rv; + } + + // if an observer was provided, notify that the download was cancelled. + // if no persist was provided, this is necessary so that whatever transfer + // component being used can cancel the download itself. + nsCOMPtr observer; + download->GetObserver(getter_AddRefs(observer)); + if (observer) { + rv = observer->Observe(download, "oncancel", nsnull); + if (NS_FAILED(rv)) return rv; + } + + DownloadEnded(aPath, nsnull); + + gObserverService->NotifyObservers(download, "dl-cancel", nsnull); + + // if there's a progress dialog open for the item, + // we have to notify it that we're cancelling + nsCOMPtr dialog; + internalDownload->GetDialog(getter_AddRefs(dialog)); + if (dialog) { + observer = do_QueryInterface(dialog); + rv = observer->Observe(download, "oncancel", nsnull); + if (NS_FAILED(rv)) return rv; + } + + return rv; +} + +NS_IMETHODIMP +nsDownloadManager::RemoveDownload(const PRUnichar* aPath) +{ + nsStringKey key(aPath); + + // RemoveDownload is for downloads not currently in progress. Having it + // cancel in-progress downloads would make things complicated, so just return. + PRBool inProgress = mCurrDownloads.Exists(&key); + NS_ASSERTION(!inProgress, "Can't call RemoveDownload on a download in progress!"); + if (inProgress) + return NS_ERROR_FAILURE; + + nsCOMPtr res; + gRDFService->GetUnicodeResource(nsDependentString(aPath), getter_AddRefs(res)); + + return RemoveDownload(res); +} + +// This is an internal method only because it does NOT check to see whether +// or not a download is in progress or not before removing it. The FE should use +// RemoveDownload(const PRUnichar* aPath) as supplied by nsIDownloadManager which +// does the appropriate checking. +nsresult +nsDownloadManager::RemoveDownload(nsIRDFResource* aDownload) +{ + nsCOMPtr downloads; + nsresult rv = GetDownloadsContainer(getter_AddRefs(downloads)); + if (NS_FAILED(rv)) return rv; + + // remove all the arcs for this resource, and then remove it from the Seq + nsCOMPtr arcs; + rv = mDataSource->ArcLabelsOut(aDownload, getter_AddRefs(arcs)); + if (NS_FAILED(rv)) return rv; + + PRBool moreArcs; + rv = arcs->HasMoreElements(&moreArcs); + if (NS_FAILED(rv)) return rv; + + while (moreArcs) { + nsCOMPtr supports; + rv = arcs->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr arc(do_QueryInterface(supports, &rv)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr targets; + rv = mDataSource->GetTargets(aDownload, arc, PR_TRUE, getter_AddRefs(targets)); + if (NS_FAILED(rv)) return rv; + + PRBool moreTargets; + rv = targets->HasMoreElements(&moreTargets); + if (NS_FAILED(rv)) return rv; + + while (moreTargets) { + rv = targets->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr target(do_QueryInterface(supports, &rv)); + if (NS_FAILED(rv)) return rv; + + // and now drop this assertion from the graph + rv = mDataSource->Unassert(aDownload, arc, target); + if (NS_FAILED(rv)) return rv; + + rv = targets->HasMoreElements(&moreTargets); + if (NS_FAILED(rv)) return rv; + } + rv = arcs->HasMoreElements(&moreArcs); + if (NS_FAILED(rv)) return rv; + } + + PRInt32 itemIndex; + downloads->IndexOf(aDownload, &itemIndex); + if (itemIndex <= 0) + return NS_ERROR_FAILURE; + + nsCOMPtr node; + rv = downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node)); + if (NS_FAILED(rv)) return rv; + + // if a mass removal is being done, we don't want to flush every time + if (mBatches) return rv; + + return Flush(); +} + +// We implement this here in the download manager service as inspecting +// datasource directly is a more reliable way of clearing things up, rather +// than relying on the template builder's fuzzy facsimile of the contents +// of the datasource. The template builder filters out bad entries, which would +// remain and accumulate if we did not happen to remove them here. +NS_IMETHODIMP +nsDownloadManager::CleanUp() +{ + nsCOMPtr downloadRes; + nsCOMPtr intLiteral; + nsCOMPtr downloads; + + StartBatchUpdate(); + + // 1). First, clean out the usual suspects - downloads that are + // finished, failed or canceled. + DownloadState states[] = { FINISHED, FAILED, CANCELED }; + + for (int i = 0; i < 3; ++i) { + gRDFService->GetIntLiteral(states[i], getter_AddRefs(intLiteral)); + nsresult rv = mDataSource->GetSources(gNC_DownloadState, intLiteral, PR_TRUE, getter_AddRefs(downloads)); + if (NS_FAILED(rv)) return rv; + + PRBool hasMoreElements; + downloads->HasMoreElements(&hasMoreElements); + + while (hasMoreElements) { + downloads->GetNext(getter_AddRefs(downloadRes)); + + // Use the internal method because we know what we're doing! (We hope!) + RemoveDownload(downloadRes); + + downloads->HasMoreElements(&hasMoreElements); + } + } + + // 2). Now, ensure that all the other download items are valid. + ValidateDownloadsContainer(); + + EndBatchUpdate(); + + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::GetCanCleanUp(PRBool* aResult) +{ + nsCOMPtr downloadRes; + nsCOMPtr intLiteral; + + *aResult = PR_FALSE; + + // 1). Downloads that can be cleaned up include those that are finished, + // failed or canceled. + DownloadState states[] = { FINISHED, FAILED, CANCELED }; + + for (int i = 0; i < 3; ++i) { + gRDFService->GetIntLiteral(states[i], getter_AddRefs(intLiteral)); + + mDataSource->GetSource(gNC_DownloadState, intLiteral, PR_TRUE, getter_AddRefs(downloadRes)); + if (downloadRes) { + *aResult = PR_TRUE; + break; + } + } + return NS_OK; +} + +nsresult +nsDownloadManager::ValidateDownloadsContainer() +{ + nsCOMPtr downloads; + GetDownloadsContainer(getter_AddRefs(downloads)); + + nsCOMPtr e; + downloads->GetElements(getter_AddRefs(e)); + + // This is our list of bad download entries. + nsCOMPtr ary; + NS_NewISupportsArray(getter_AddRefs(ary)); + + PRBool hasMore; + e->HasMoreElements(&hasMore); + nsCOMPtr downloadRes; + while (hasMore) { + e->GetNext(getter_AddRefs(downloadRes)); + + PRBool hasProperty; + + // A valid download entry in the datasource will have at least the following + // properties: + // - NC:DownloadState -- the current state of the download, defined as + // an integer value, see enumeration in + // nsDownloadManager.h, e.g. |0| (|DOWNLOADING|) + // - NC:File -- where the file is to be saved, e.g. + // "C:\\FirebirdSetup.exe" + // - NC:Name -- the visual display name of the download, e.g. + // "FirebirdSetup.exe" + + nsIRDFResource* properties[] = { gNC_DownloadState, gNC_File, gNC_Name }; + for (PRInt32 i = 0; i < 3; ++i) { + mDataSource->HasArcOut(downloadRes, properties[i], &hasProperty); + if (!hasProperty) { + ary->AppendElement(downloadRes); + break; + } + } + +#if 0 + // NC:DownloadState + mDataSource->HasArcOut(downloadRes, gNC_DownloadState, &hasProperty); + if (!hasProperty) + ary->AppendElement(downloadRes); + else { + // NC:File + mDataSource->HasArcOut(downloadRes, gNC_File, &hasProperty); + if (!hasProperty) + ary->AppendElement(downloadRes); + else { + // NC:Name + mDataSource->HasArcOut(downloadRes, gNC_Name, &hasProperty); + if (!hasProperty) + ary->AppendElement(downloadRes); + } + } +#endif + + e->HasMoreElements(&hasMore); + } + + // Now Remove all the bad downloads. + PRUint32 cnt; + ary->Count(&cnt); + for (PRInt32 i = 0; i < cnt; ++i) { + nsCOMPtr download(do_QueryElementAt(ary, i)); + + // Use the internal method because we know what we're doing! (We hope!) + RemoveDownload(download); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::SetListener(nsIDownloadProgressListener* aListener) +{ + mListener = aListener; + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::GetListener(nsIDownloadProgressListener** aListener) +{ + *aListener = mListener; + NS_IF_ADDREF(*aListener); + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::StartBatchUpdate() +{ + ++mBatches; + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::EndBatchUpdate() +{ + return --mBatches == 0 ? Flush() : NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::PauseDownload(const PRUnichar* aPath) +{ + return PauseResumeDownload(aPath, PR_TRUE); +} + +NS_IMETHODIMP +nsDownloadManager::ResumeDownload(const PRUnichar* aPath) +{ + return PauseResumeDownload(aPath, PR_FALSE); +} + +nsresult +nsDownloadManager::PauseResumeDownload(const PRUnichar* aPath, PRBool aPause) +{ + nsresult rv; + + nsStringKey key(aPath); + if (!mCurrDownloads.Exists(&key)) + return NS_ERROR_FAILURE; + + nsCOMPtr download; + nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) getter_AddRefs(download)); + if (!download) + return NS_ERROR_FAILURE; + + // Update download state in the DataSource + nsCOMPtr intLiteral; + + gRDFService->GetIntLiteral(aPause ? PAUSED : DOWNLOADING, getter_AddRefs(intLiteral)); + + nsCOMPtr res; + gRDFService->GetUnicodeResource(nsDependentString(aPath), getter_AddRefs(res)); + + nsCOMPtr oldTarget; + mDataSource->GetTarget(res, gNC_DownloadState, PR_TRUE, getter_AddRefs(oldTarget)); + + if (oldTarget) { + rv = mDataSource->Change(res, gNC_DownloadState, oldTarget, intLiteral); + if (NS_FAILED(rv)) return rv; + } + else { + rv = mDataSource->Assert(res, gNC_DownloadState, intLiteral, PR_TRUE); + if (NS_FAILED(rv)) return rv; + } + + // Pause the actual download + internalDownload->Pause(aPause); + + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::Flush() +{ + // Before writing, always be sure what we're about to write is good data. + ValidateDownloadsContainer(); + + nsCOMPtr remote(do_QueryInterface(mDataSource)); + return remote->Flush(); +} + +NS_IMETHODIMP +nsDownloadManager::GetDatasource(nsIRDFDataSource** aDatasource) +{ + *aDatasource = mDataSource; + NS_IF_ADDREF(*aDatasource); + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::Open(nsIDOMWindow* aParent, const PRUnichar* aPath) +{ + // 1). First check to see if we should open at all, based on the user's + // preferences. + PRBool showDM = PR_TRUE; + nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (pref) + pref->GetBoolPref("browser.download.showWhenStarting", &showDM); + + if (!showDM) + return NS_OK; + + // 2). Retrieve the download object for the supplied path. + nsStringKey key(aPath); + if (!mCurrDownloads.Exists(&key)) + return NS_ERROR_FAILURE; + + nsCOMPtr download; + nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) getter_AddRefs(download)); + if (!download) + return NS_ERROR_FAILURE; + + // 3). Update the DataSource. + AssertProgressInfoFor(aPath); + + nsVoidArray* params = new nsVoidArray(); + if (!params) + return NS_ERROR_OUT_OF_MEMORY; + + params->AppendElement((void*)aParent); + params->AppendElement((void*)internalDownload); + + // 4). Look for an existing Download Manager window, if we find one we just + // tell it that a new download has begun (we don't focus, that's + // annoying), otherwise we need to open the window. We do this on a timer + // so that we can see if the download has already completed, if so, don't + // bother opening the window. + mDMOpenTimer = do_CreateInstance("@mozilla.org/timer;1"); + return mDMOpenTimer->InitWithFuncCallback(OpenTimerCallback, + (void*)params, + kDownloadWindowCacheDelay, + nsITimer::TYPE_ONE_SHOT); +} + +void +nsDownloadManager::OpenTimerCallback(nsITimer* aTimer, void* aClosure) +{ + nsVoidArray* params = (nsVoidArray*)aClosure; + nsIDOMWindow* parent = (nsIDOMWindow*)params->ElementAt(0); + nsDownload* download = (nsDownload*)params->ElementAt(1); + + PRInt32 complete; + download->GetPercentComplete(&complete); + + // We only show the download window if the download is taking more than a non-tiny + // amount of time to complete. + if (complete < 100) { + PRBool focusDM = PR_FALSE; + nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (pref) + pref->GetBoolPref("browser.download.focusWhenStarting", &focusDM); + + nsDownloadManager::OpenDownloadManager(focusDM, download, parent); + } + + delete params; +} + +nsresult +nsDownloadManager::OpenDownloadManager(PRBool aShouldFocus, nsIDownload* aDownload, nsIDOMWindow* aParent) +{ + nsresult rv = NS_OK; + + nsCOMPtr wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr recentWindow; + wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(), getter_AddRefs(recentWindow)); + if (recentWindow) { + nsCOMPtr obsService = do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_FAILED(rv)) return rv; + + if (aShouldFocus) + recentWindow->Focus(); + } + else { + // If we ever have the capability to display the UI of third party dl managers, + // we'll open their UI here instead. + nsCOMPtr ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + // pass the datasource to the window + nsCOMPtr params; + NS_NewISupportsArray(getter_AddRefs(params)); + + // I love static members. + nsCOMPtr dlMgr(do_GetService("@mozilla.org/download-manager;1")); + nsCOMPtr ds; + dlMgr->GetDatasource(getter_AddRefs(ds)); + + params->AppendElement(ds); + params->AppendElement(aDownload); + + nsCOMPtr newWindow; + rv = ww->OpenWindow(aParent, + DOWNLOAD_MANAGER_FE_URL, + "_blank", + "chrome,all,dialog=no,resizable", + params, + getter_AddRefs(newWindow)); + } + return rv; +} + +/////////////////////////////////////////////////////////////////////////////// +// nsIObserver + +NS_IMETHODIMP +nsDownloadManager::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) +{ + nsresult rv; + PRInt32 currDownloadCount = 0; + + if (nsCRT::strcmp(aTopic, "oncancel") == 0) { + nsCOMPtr dialog = do_QueryInterface(aSubject); + nsCOMPtr target; + dialog->GetTarget(getter_AddRefs(target)); + + nsAutoString path; + rv = target->GetPath(path); + if (NS_FAILED(rv)) return rv; + + nsStringKey key(path); + if (mCurrDownloads.Exists(&key)) { + // unset dialog since it's closing + nsDownload* download = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + download->SetDialog(nsnull); + + return CancelDownload(path.get()); + } + } + else if (nsCRT::strcmp(aTopic, "quit-application") == 0 && mCurrDownloads.Count()) { + gQuitting = PR_TRUE; + mCurrDownloads.Enumerate(CancelAllDownloads, this); + + // Now go and update the datasource so that we "cancel" all paused downloads. + SaveState(); + + // Now that active downloads have been canceled, remove all downloads if + // the user's retention policy specifies it. + if (GetRetentionBehavior() == 1) { + nsCOMPtr ctr; + GetDownloadsContainer(getter_AddRefs(ctr)); + + StartBatchUpdate(); + + nsCOMPtr ary; + NS_NewISupportsArray(getter_AddRefs(ary)); + + if (ary) { + nsCOMPtr e; + ctr->GetElements(getter_AddRefs(e)); + + PRBool hasMore; + e->HasMoreElements(&hasMore); + while(hasMore) { + nsCOMPtr curr; + e->GetNext(getter_AddRefs(curr)); + + ary->AppendElement(curr); + + e->HasMoreElements(&hasMore); + } + + // Now Remove all the downloads. + PRUint32 cnt; + ary->Count(&cnt); + for (PRInt32 i = 0; i < cnt; ++i) { + nsCOMPtr download(do_QueryElementAt(ary, i)); + // Here we use the internal RemoveDownload method, and only here + // because this is _after_ the download table |mCurrDownloads| has been + // cleared of active downloads, so we know we're not accidentally + // clearing active downloads. + RemoveDownload(download); + } + } + + EndBatchUpdate(); + } + } + else if (nsCRT::strcmp(aTopic, "quit-application-requested") == 0 && + (currDownloadCount = mCurrDownloads.Count())) { + nsXPIDLString title, message, quitButton; + + nsCOMPtr bundleService = do_GetService(kStringBundleServiceCID, &rv); + nsCOMPtr bundle; + if (bundleService) + rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle)); + if (bundle) { + bundle->GetStringFromName(NS_LITERAL_STRING("quitCancelDownloadsAlertTitle").get(), getter_Copies(title)); + + nsAutoString countString; + countString.AppendInt(currDownloadCount); + const PRUnichar* strings[1] = { countString.get() }; +#ifndef XP_MACOSX + if (currDownloadCount > 1) + bundle->FormatStringFromName(NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMultiple").get(), strings, 1, getter_Copies(message)); + else + bundle->GetStringFromName(NS_LITERAL_STRING("quitCancelDownloadsAlertMsg").get(), getter_Copies(message)); +#else + if (currDownloadCount > 1) + bundle->FormatStringFromName(NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMacMultiple").get(), strings, 1, getter_Copies(message)); + else + bundle->GetStringFromName(NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMac").get(), getter_Copies(message)); +#endif + if (currDownloadCount > 1) + bundle->FormatStringFromName(NS_LITERAL_STRING("quitCancelDownloadsOKTextMultiple").get(), strings, 1, getter_Copies(quitButton)); + else + bundle->GetStringFromName(NS_LITERAL_STRING("quitCancelDownloadsOKText").get(), getter_Copies(quitButton)); + } + + // Get Download Manager window, to be parent of alert. + nsCOMPtr wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); + nsCOMPtr dmWindow; + if (wm) + wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(), getter_AddRefs(dmWindow)); + + // Show alert. + nsCOMPtr prompter(do_GetService("@mozilla.org/embedcomp/prompt-service;1")); + if (prompter) { + PRInt32 flags = (nsIPromptService::BUTTON_TITLE_IS_STRING * nsIPromptService::BUTTON_POS_0) + (nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_1); + PRBool nothing = PR_FALSE; + PRInt32 button; + prompter->ConfirmEx(dmWindow, title, message, flags, quitButton.get(), nsnull, nsnull, nsnull, ¬hing, &button); + + nsCOMPtr theBool(do_QueryInterface(aSubject)); + theBool->SetData(button == 1); + } + } + return NS_OK; +} + +#ifdef XP_WIN +/////////////////////////////////////////////////////////////////////////////// +// nsIAlertListener +NS_IMETHODIMP +nsDownloadManager::OnAlertFinished(const PRUnichar* aAlertCookie) +{ + // Nothing to do here. + return NS_OK; +} + +NS_IMETHODIMP +nsDownloadManager::OnAlertClickCallback(const PRUnichar* aAlertCookie) +{ + nsresult rv; + + // Attempt to locate a browser window to parent the download manager to + nsCOMPtr wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); + nsCOMPtr browserWindow; + if (wm) + wm->GetMostRecentWindow(NS_LITERAL_STRING("navigator:browser").get(), getter_AddRefs(browserWindow)); + + return OpenDownloadManager(PR_TRUE, nsnull, browserWindow); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// nsDownload + +NS_IMPL_ISUPPORTS2(nsDownload, nsIDownload, nsIWebProgressListener) + +nsDownload::nsDownload():mDownloadState(NOTSTARTED), + mPercentComplete(0), + mCurrBytes(0), + mMaxBytes(0), + mStartTime(0), + mLastUpdate(-500) +{ +} + +nsDownload::~nsDownload() +{ +} + +nsresult +nsDownload::SetDownloadManager(nsDownloadManager* aDownloadManager) +{ + mDownloadManager = aDownloadManager; + return NS_OK; +} + +nsresult +nsDownload::SetDialogListener(nsIWebProgressListener* aDialogListener) +{ + mDialogListener = aDialogListener; + return NS_OK; +} + +nsresult +nsDownload::GetDialogListener(nsIWebProgressListener** aDialogListener) +{ + *aDialogListener = mDialogListener; + NS_IF_ADDREF(*aDialogListener); + return NS_OK; +} + +nsresult +nsDownload::SetDialog(nsIProgressDialog* aDialog) +{ + mDialog = aDialog; + return NS_OK; +} + +nsresult +nsDownload::GetDialog(nsIProgressDialog** aDialog) +{ + *aDialog = mDialog; + NS_IF_ADDREF(*aDialog); + return NS_OK; +} + +nsresult +nsDownload::GetDownloadState(DownloadState* aState) +{ + *aState = mDownloadState; + return NS_OK; +} + +nsresult +nsDownload::SetDownloadState(DownloadState aState) +{ + mDownloadState = aState; + return NS_OK; +} + +nsresult +nsDownload::SetPersist(nsIWebBrowserPersist* aPersist) +{ + mPersist = aPersist; + return NS_OK; +} + +nsresult +nsDownload::SetSource(nsIURI* aSource) +{ + mSource = aSource; + return NS_OK; +} + +nsresult +nsDownload::SetTarget(nsILocalFile* aTarget) +{ + mTarget = aTarget; + return NS_OK; +} + +nsresult +nsDownload::GetTransferInformation(PRInt32* aCurr, PRInt32* aMax) +{ + *aCurr = mCurrBytes; + *aMax = mMaxBytes; + return NS_OK; +} + +nsresult +nsDownload::SetStartTime(PRInt64 aStartTime) +{ + mStartTime = aStartTime; + return NS_OK; +} + +nsresult +nsDownload::SetMIMEInfo(nsIMIMEInfo *aMIMEInfo) +{ + mMIMEInfo = aMIMEInfo; + return NS_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// nsIWebProgressListener + +NS_IMETHODIMP +nsDownload::OnProgressChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRInt32 aCurSelfProgress, + PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, + PRInt32 aMaxTotalProgress) +{ + + if (!mRequest) + mRequest = aRequest; // used for pause/resume + + // filter notifications since they come in so frequently + PRTime delta; + PRTime now = PR_Now(); + LL_SUB(delta, now, mLastUpdate); + if (LL_CMP(delta, <, INTERVAL) && aMaxTotalProgress != -1 && aCurTotalProgress < aMaxTotalProgress) + return NS_OK; + + mLastUpdate = now; + + if (mDownloadState == NOTSTARTED) { + nsAutoString path; + nsresult rv = mTarget->GetPath(path); + if (NS_FAILED(rv)) return rv; + + mDownloadState = DOWNLOADING; + mDownloadManager->DownloadStarted(path.get()); + } + + if (aMaxTotalProgress > 0) + mPercentComplete = (PRInt32)((PRFloat64)aCurTotalProgress * 100 / aMaxTotalProgress + .5); + else + mPercentComplete = -1; + + mCurrBytes = (PRInt32)((PRFloat64)aCurTotalProgress / 1024.0 + .5); + mMaxBytes = (PRInt32)((PRFloat64)aMaxTotalProgress / 1024 + .5); + + if (mDownloadManager->NeedsUIUpdate()) { + nsCOMPtr dpl; + mDownloadManager->GetInternalListener(getter_AddRefs(dpl)); + if (dpl) { + dpl->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress, this); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::OnLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsIURI *aLocation) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsresult aStatus, + const PRUnichar *aMessage) +{ + if (NS_FAILED(aStatus)) { + mDownloadState = FAILED; + nsAutoString path; + nsresult rv = mTarget->GetPath(path); + if (NS_SUCCEEDED(rv)) { + mDownloadManager->DownloadEnded(path.get(), nsnull); + gObserverService->NotifyObservers(NS_STATIC_CAST(nsIDownload *, this), "dl-failed", nsnull); + } + + // Get title for alert. + nsXPIDLString title; + + nsCOMPtr bundleService = do_GetService(kStringBundleServiceCID, &rv); + nsCOMPtr bundle; + if (bundleService) + rv = bundleService->CreateBundle(DOWNLOAD_MANAGER_BUNDLE, getter_AddRefs(bundle)); + if (bundle) + bundle->GetStringFromName(NS_LITERAL_STRING("downloadErrorAlertTitle").get(), getter_Copies(title)); + + // Get Download Manager window, to be parent of alert. + nsCOMPtr wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv); + nsCOMPtr dmWindow; + if (wm) + wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(), getter_AddRefs(dmWindow)); + + // Show alert. + nsCOMPtr prompter(do_GetService("@mozilla.org/embedcomp/prompt-service;1")); + if (prompter) + prompter->Alert(dmWindow, title, aMessage); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, PRUint32 aStateFlags, + nsresult aStatus) +{ + if (aStateFlags & STATE_START) + mStartTime = PR_Now(); + + // When we break the ref cycle with mPersist, we don't want to lose + // access to out member vars! + nsCOMPtr kungFuDeathGrip; + CallQueryInterface(this, NS_STATIC_CAST(nsIDownload**, + getter_AddRefs(kungFuDeathGrip))); + + // We need to update mDownloadState before updating the dialog, because + // that will close and call CancelDownload if it was the last open window. + nsresult rv = NS_OK; + if (aStateFlags & STATE_STOP) { + if (mDownloadState == DOWNLOADING || mDownloadState == NOTSTARTED) { + mDownloadState = FINISHED; + // Files less than 1Kb shouldn't show up as 0Kb. + if (mMaxBytes==0) + mMaxBytes = 1; + mCurrBytes = mMaxBytes; + mPercentComplete = 100; + + nsAutoString path; + rv = mTarget->GetPath(path); + // can't do an early return; have to break reference cycle below + if (NS_SUCCEEDED(rv)) { + mDownloadManager->DownloadEnded(path.get(), nsnull); + } + + gObserverService->NotifyObservers(NS_STATIC_CAST(nsIDownload *, this), "dl-done", nsnull); + +#ifdef XP_WIN + if ((mDownloadManager->mCurrDownloads).Count() == 0) { + nsCOMPtr alerts(do_GetService("@mozilla.org/alerts-service;1")); + if (alerts) { + nsXPIDLString title, message; + + mDownloadManager->mBundle->GetStringFromName(NS_LITERAL_STRING("downloadsCompleteTitle").get(), getter_Copies(title)); + mDownloadManager->mBundle->GetStringFromName(NS_LITERAL_STRING("downloadsCompleteMsg").get(), getter_Copies(message)); + + PRBool removeWhenDone = mDownloadManager->GetRetentionBehavior() == 0; + + + // If downloads are automatically removed per the user's retention policy, + // there's no reason to make the text clickable because if it is, they'll + // click open the download manager and the items they downloaded will have + // been removed. + alerts->ShowAlertNotification(DOWNLOAD_MANAGER_ALERT_ICON, title, message, !removeWhenDone, + NS_LITERAL_STRING("").get(), NS_STATIC_CAST(nsIAlertListener*, mDownloadManager)); + } + } +#endif + } + + // break the cycle we created in AddDownload + if (mPersist) + mPersist->SetProgressListener(nsnull); + + // Now remove the download if the user's retention policy is "Remove when Done" + if (mDownloadManager->GetRetentionBehavior() == 0) { + nsAutoString path; + mTarget->GetPath(path); + + mDownloadManager->RemoveDownload(path.get()); + } + } + + if (mDownloadManager->NeedsUIUpdate()) { + nsCOMPtr dpl; + mDownloadManager->GetInternalListener(getter_AddRefs(dpl)); + if (dpl) { + dpl->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus, this); + } + } + + return rv; +} + +NS_IMETHODIMP +nsDownload::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRUint32 aState) +{ + return NS_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// nsIDownload + +NS_IMETHODIMP +nsDownload::Init(nsIURI* aSource, + nsILocalFile* aTarget, + const PRUnichar* aDisplayName, + nsIMIMEInfo *aMIMEInfo, + PRInt64 aStartTime, + nsIWebBrowserPersist* aPersist) +{ + NS_WARNING("Huh...how did we get here?!"); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::SetDisplayName(const PRUnichar* aDisplayName) +{ + mDisplayName = aDisplayName; + + nsCOMPtr ds; + mDownloadManager->GetDataSource(getter_AddRefs(ds)); + + nsCOMPtr nameLiteral; + nsCOMPtr res; + nsAutoString path; + nsresult rv = mTarget->GetPath(path); + if (NS_FAILED(rv)) return rv; + + gRDFService->GetUnicodeResource(path, getter_AddRefs(res)); + + gRDFService->GetLiteral(aDisplayName, getter_AddRefs(nameLiteral)); + ds->Assert(res, gNC_Name, nameLiteral, PR_TRUE); + + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetDisplayName(PRUnichar** aDisplayName) +{ + *aDisplayName = ToNewUnicode(mDisplayName); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetTarget(nsILocalFile** aTarget) +{ + *aTarget = mTarget; + NS_IF_ADDREF(*aTarget); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetSource(nsIURI** aSource) +{ + *aSource = mSource; + NS_IF_ADDREF(*aSource); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetPersist(nsIWebBrowserPersist** aPersist) +{ + *aPersist = mPersist; + NS_IF_ADDREF(*aPersist); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetStartTime(PRInt64* aStartTime) +{ + *aStartTime = mStartTime; + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetPercentComplete(PRInt32* aPercentComplete) +{ + *aPercentComplete = mPercentComplete; + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::SetListener(nsIWebProgressListener* aListener) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetListener(nsIWebProgressListener** aListener) +{ + *aListener = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::SetObserver(nsIObserver* aObserver) +{ + mObserver = aObserver; + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetObserver(nsIObserver** aObserver) +{ + *aObserver = mObserver; + NS_IF_ADDREF(*aObserver); + return NS_OK; +} + +NS_IMETHODIMP +nsDownload::GetMIMEInfo(nsIMIMEInfo** aMIMEInfo) +{ + *aMIMEInfo = mMIMEInfo; + NS_IF_ADDREF(*aMIMEInfo); + return NS_OK; +} + +void +nsDownload::Pause(PRBool aPaused) +{ + if (mPaused != aPaused) { + if (mRequest) { + if (aPaused) { + mRequest->Suspend(); + mDownloadState = PAUSED; + } + else { + mRequest->Resume(); + mDownloadState = DOWNLOADING; + } + } + } +} + +PRBool +nsDownload::IsPaused() +{ + return mPaused; +} + diff --git a/mozilla/toolkit/components/downloads/src/nsDownloadManager.h b/mozilla/toolkit/components/downloads/src/nsDownloadManager.h new file mode 100644 index 00000000000..9c0c22df33b --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/nsDownloadManager.h @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross + * Ben Goodger + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef downloadmanager___h___ +#define downloadmanager___h___ + +#include "nsIDownloadManager.h" +#include "nsIDownloadProgressListener.h" +#include "nsIDownload.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFRemoteDataSource.h" +#include "nsIRDFService.h" +#include "nsIDOMDocument.h" +#include "nsIDOMEventListener.h" +#include "nsIRDFContainerUtils.h" +#include "nsIWebProgressListener.h" +#include "nsIURI.h" +#include "nsIWebBrowserPersist.h" +#include "nsILocalFile.h" +#include "nsHashtable.h" +#include "nsIRequest.h" +#include "nsIObserver.h" +#include "nsIStringBundle.h" +#include "nsIProgressDialog.h" +#include "nsIMIMEInfo.h" +#include "nsITimer.h" +#ifdef XP_WIN +#include "nsIAlertsService.h" +#endif + +enum DownloadState { NOTSTARTED = -1, DOWNLOADING, FINISHED, FAILED, CANCELED, PAUSED }; + +class nsDownloadManager : public nsIDownloadManager, + public nsIObserver +#ifdef XP_WIN + , public nsIAlertListener +#endif +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOWNLOADMANAGER + NS_DECL_NSIOBSERVER +#ifdef XP_WIN + NS_DECL_NSIALERTLISTENER +#endif + + nsresult Init(); + + nsDownloadManager(); + virtual ~nsDownloadManager(); + + static PRInt32 PR_CALLBACK CancelAllDownloads(nsHashKey* aKey, void* aData, void* aClosure); + static PRInt32 PR_CALLBACK BuildActiveDownloadsList(nsHashKey* aKey, void* aData, void* aClosure); + nsresult DownloadEnded(const PRUnichar* aPersistentDescriptor, const PRUnichar* aMessage); + +protected: + nsresult GetDownloadsContainer(nsIRDFContainer** aResult); + nsresult GetProfileDownloadsFileURL(nsCString& aDownloadsFileURL); + nsresult GetDataSource(nsIRDFDataSource** aDataSource); + nsresult DownloadStarted(const PRUnichar* aPersistentDescriptor); + nsresult AssertProgressInfoFor(const PRUnichar* aPersistentDescriptor); + nsresult GetInternalListener(nsIDownloadProgressListener** aListener); + nsresult PauseResumeDownload(const PRUnichar* aPath, PRBool aPause); + nsresult RemoveDownload(nsIRDFResource* aDownload); + nsresult ValidateDownloadsContainer(); + + static void OpenTimerCallback(nsITimer* aTimer, void* aClosure); + static nsresult OpenDownloadManager(PRBool aShouldFocus, nsIDownload* aDownload, nsIDOMWindow* aParent); + + PRBool NeedsUIUpdate() { return mListener != nsnull; } + PRInt32 GetRetentionBehavior(); + +private: + nsCOMPtr mListener; + nsCOMPtr mDataSource; + nsCOMPtr mDownloadsContainer; + nsCOMPtr mRDFContainerUtils; + nsCOMPtr mBundle; + nsCOMPtr mDMOpenTimer; + PRInt32 mBatches; + nsHashtable mCurrDownloads; + + enum { + kDownloadWindowCacheDelay = 2000 // The delay before the Download Manager + // window pops up after a link, to prevent + // the window from showing if the download + // is instantaneous (e.g. from cache) + }; + + friend class nsDownload; +}; + +class nsDownload : public nsIDownload, + public nsIWebProgressListener +{ +public: + NS_DECL_NSIWEBPROGRESSLISTENER + NS_DECL_NSIDOWNLOAD + NS_DECL_ISUPPORTS + + nsDownload(); + virtual ~nsDownload(); + +protected: + nsresult SetDownloadManager(nsDownloadManager* aDownloadManager); + nsresult SetDialogListener(nsIWebProgressListener* aInternalListener); + nsresult GetDialogListener(nsIWebProgressListener** aInternalListener); + nsresult SetDialog(nsIProgressDialog* aDialog); + nsresult GetDialog(nsIProgressDialog** aDialog); + nsresult SetPersist(nsIWebBrowserPersist* aPersist); + nsresult SetTarget(nsILocalFile* aTarget); + nsresult SetSource(nsIURI* aSource); + nsresult GetTransferInformation(PRInt32* aCurr, PRInt32* aMax); + nsresult GetDownloadState(DownloadState* aState); + nsresult SetDownloadState(DownloadState aState); + nsresult SetMIMEInfo(nsIMIMEInfo* aMIMEInfo); + nsresult SetStartTime(PRInt64 aStartTime); + + void Pause(PRBool aPaused); + PRBool IsPaused(); + + nsDownloadManager* mDownloadManager; + nsCOMPtr mTarget; + +private: + nsString mDisplayName; + + nsCOMPtr mSource; + nsCOMPtr mDialogListener; + nsCOMPtr mPersist; + nsCOMPtr mRequest; + nsCOMPtr mDialog; + nsCOMPtr mObserver; + nsCOMPtr mMIMEInfo; + + DownloadState mDownloadState; + + PRBool mPaused; + PRInt32 mPercentComplete; + PRInt32 mCurrBytes; + PRInt32 mMaxBytes; + PRInt64 mStartTime; + PRTime mLastUpdate; + + friend class nsDownloadManager; +}; + +#endif diff --git a/mozilla/toolkit/components/downloads/src/nsDownloadProgressListener.js b/mozilla/toolkit/components/downloads/src/nsDownloadProgressListener.js new file mode 100644 index 00000000000..b22ad9de338 --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/nsDownloadProgressListener.js @@ -0,0 +1,319 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gStrings = new Array; +const interval = 500; // Update every 500 milliseconds. + +function nsDownloadProgressListener() { +} + +nsDownloadProgressListener.prototype = { + elapsed: 0, + rateChanges: 0, + rateChangeLimit: 0, + priorRate: 0, + lastUpdate: -500, + doc: null, + get document() { + return this.doc; + }, + set document(newval) { + return this.doc = newval; + }, + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload) + { + if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) + { + var aDownloadID = aDownload.target.persistentDescriptor; + var elt = this.doc.getElementById(aDownloadID).firstChild.firstChild; + + var timeRemainingCol = elt.nextSibling.nextSibling.nextSibling; + timeRemainingCol.setAttribute("label", ""); + + var speedCol = timeRemainingCol.nextSibling.nextSibling; + speedCol.setAttribute("label", ""); + + var elapsedCol = speedCol.nextSibling; + elapsedCol.setAttribute("label", ""); + } + }, + + onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress, aDownload) + { + var overallProgress = aCurTotalProgress; + // Get current time. + var now = ( new Date() ).getTime(); + // If interval hasn't elapsed, ignore it. + if ( now - this.lastUpdate < interval && aMaxTotalProgress != "-1" && parseInt(aCurTotalProgress) < parseInt(aMaxTotalProgress) ) { + return; + } + + // Update this time. + this.lastUpdate = now; + + // Update download rate. + this.elapsed = now - (aDownload.startTime / 1000); + var rate; // aCurTotalProgress/sec + if ( this.elapsed ) + rate = ( aCurTotalProgress * 1000 ) / this.elapsed; + else + rate = 0; + + var aDownloadID = aDownload.target.persistentDescriptor; + var elt = this.doc.getElementById(aDownloadID).firstChild.firstChild; + if (this.doc.getElementById("TimeElapsed").getAttribute("hidden") != "true") { + elapsedCol = elt.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling; + // Update elapsed time display. + elapsedCol.setAttribute("label", formatSeconds( this.elapsed / 1000, this.doc )); + } + // Calculate percentage. + var percent; + var progressCol = elt.nextSibling; + if ( aMaxTotalProgress > 0) + { + percent = Math.floor((overallProgress*100.0)/aMaxTotalProgress); + if ( percent > 100 ) + percent = 100; + + // Advance progress meter. + progressCol.setAttribute( "value", percent ); + + progressCol.setAttribute("mode", "normal"); + } + else + { + percent = -1; + + // Progress meter should be barber-pole in this case. + progressCol.setAttribute( "mode", "undetermined" ); + } + + // now that we've set the progress and the time, update # bytes downloaded... + // Update status (nnK of mmK bytes at xx.xK aCurTotalProgress/sec) + var status = getString( "progressMsgNoRate", this.doc ); + + // Insert 1 is the number of kilobytes downloaded so far. + status = replaceInsert( status, 1, parseInt( overallProgress/1024 + .5 ) ); + + // Insert 2 is the total number of kilobytes to be downloaded (if known). + if ( aMaxTotalProgress != "-1" ) + status = replaceInsert( status, 2, parseInt( aMaxTotalProgress/1024 + .5 ) ); + else + status = replaceInsert( status, 2, "??" ); + + var rateMsg = getString( "rateMsg", this.doc ); + if ( rate ) + { + // rate is bytes/sec + var kRate = rate / 1024; // K bytes/sec; + kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits) + // Don't update too often! + if ( kRate != this.priorRate ) + { + if ( this.rateChanges++ == this.rateChangeLimit ) + { + // Time to update download rate. + this.priorRate = kRate; + this.rateChanges = 0; + } + else + { + // Stick with old rate for a bit longer. + kRate = this.priorRate; + } + } + else + this.rateChanges = 0; + + var fraction = kRate % 10; + kRate = parseInt( ( kRate - fraction ) / 10 ); + + // Insert 3 is the download rate (in kilobytes/sec). + rateMsg = replaceInsert( rateMsg, 1, kRate + "." + fraction ); + } + else + rateMsg = replaceInsert( rateMsg, 1, "??.?" ); + + var timeRemainingCol = elt.nextSibling.nextSibling.nextSibling; + + // Update status msg. + var statusCol = timeRemainingCol.nextSibling; + statusCol.setAttribute("label", status); + + var speedCol = statusCol.nextSibling; + speedCol.setAttribute("label", rateMsg); + // Update percentage label on progress meter. + if (this.doc.getElementById("ProgressPercent").getAttribute("hidden") != "true") { + var progressText = elt.nextSibling.nextSibling; + if (percent < 0) + progressText.setAttribute("label", ""); + else { + var percentMsg = getString( "percentMsg", this.doc ); + percentMsg = replaceInsert( percentMsg, 1, percent ); + progressText.setAttribute("label", percentMsg); + } + } + // Update time remaining. + if ( rate && (aMaxTotalProgress > 0) ) + { + var rem = ( aMaxTotalProgress - aCurTotalProgress ) / rate; + rem = parseInt( rem + .5 ); + timeRemainingCol.setAttribute("label", formatSeconds( rem, this.doc )); + } + else + timeRemainingCol.setAttribute("label", getString( "unknownTime", this.doc )); + }, + onLocationChange: function(aWebProgress, aRequest, aLocation, aDownload) + { + }, + onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage, aDownload) + { + }, + onSecurityChange: function(aWebProgress, aRequest, state, aDownload) + { + }, + QueryInterface : function(iid) + { + if (iid.equals(Components.interfaces.nsIDownloadProgressListener) || + iid.equals(Components.interfaces.nsISupports)) + return this; + + throw Components.results.NS_NOINTERFACE; + } +}; + +var nsDownloadProgressListenerFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + + return (new nsDownloadProgressListener()).QueryInterface(iid); + } +}; + +var nsDownloadProgressListenerModule = { + + registerSelf: function (compMgr, fileSpec, location, type) + { + var compReg = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar); + compReg.registerFactoryLocation(Components.ID("{09cddbea-1dd2-11b2-aa15-c41ffea19d79}"), + "Download Progress Listener", + "@mozilla.org/download-manager/listener;1", fileSpec, + location, type); + }, + canUnload: function(compMgr) + { + return true; + }, + + getClassObject: function (compMgr, cid, iid) { + if (!cid.equals(Components.ID("{09cddbea-1dd2-11b2-aa15-c41ffea19d79}"))) + throw Components.results.NS_ERROR_NO_INTERFACE; + + if (!iid.equals(Components.interfaces.nsIFactory)) + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; + + return nsDownloadProgressListenerFactory; + } +}; + +function NSGetModule(compMgr, fileSpec) { + return nsDownloadProgressListenerModule; +} + +function replaceInsert( text, index, value ) { + var result = text; + var regExp = new RegExp( "#"+index ); + result = result.replace( regExp, value ); + return result; +} + +function getString( stringId, doc ) { + // Check if we've fetched this string already. + if ( !gStrings[ stringId ] ) { + // Try to get it. + var elem = doc.getElementById( "strings."+stringId ); + try { + if ( elem + && + elem.childNodes + && + elem.childNodes[0] + && + elem.childNodes[0].nodeValue ) { + gStrings[ stringId ] = elem.childNodes[0].nodeValue; + } else { + // If unable to fetch string, use an empty string. + gStrings[ stringId ] = ""; + } + } catch (e) { gStrings[ stringId ] = ""; } + } + return gStrings[ stringId ]; +} + +function formatSeconds( secs, doc ) +{ + // Round the number of seconds to remove fractions. + secs = parseInt( secs + .5 ); + var hours = parseInt( secs/3600 ); + secs -= hours*3600; + var mins = parseInt( secs/60 ); + secs -= mins*60; + var result; + if ( hours ) + result = getString( "longTimeFormat", doc ); + else + result = getString( "shortTimeFormat", doc ); + + if ( hours < 10 ) + hours = "0" + hours; + if ( mins < 10 ) + mins = "0" + mins; + if ( secs < 10 ) + secs = "0" + secs; + + // Insert hours, minutes, and seconds into result string. + result = replaceInsert( result, 1, hours ); + result = replaceInsert( result, 2, mins ); + result = replaceInsert( result, 3, secs ); + + return result; +} + + diff --git a/mozilla/toolkit/components/downloads/src/nsDownloadProxy.h b/mozilla/toolkit/components/downloads/src/nsDownloadProxy.h new file mode 100644 index 00000000000..63b889018a2 --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/nsDownloadProxy.h @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Blake Ross (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef downloadproxy___h___ +#define downloadproxy___h___ + +#include "nsIDownload.h" +#include "nsIDownloadManager.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsIMIMEInfo.h" + +#define USE_PROGRESS_DIALOGS_PREF "browser.download.useProgressDialogs" + +class nsDownloadProxy : public nsIDownload, + public nsIWebProgressListener +{ +public: + + nsDownloadProxy() { } + virtual ~nsDownloadProxy() { }; + + NS_DECL_ISUPPORTS + + NS_IMETHODIMP Init(nsIURI* aSource, + nsILocalFile* aTarget, + const PRUnichar* aDisplayName, + nsIMIMEInfo *aMIMEInfo, + PRInt64 aStartTime, + nsIWebBrowserPersist* aPersist) { + nsresult rv; + nsCOMPtr dm = do_GetService("@mozilla.org/download-manager;1", &rv); + if (NS_FAILED(rv)) return rv; + + rv = dm->AddDownload(aSource, aTarget, aDisplayName, aMIMEInfo, aStartTime, aPersist, getter_AddRefs(mInner)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); + if (NS_FAILED(rv)) return rv; + nsCOMPtr branch = do_QueryInterface(prefs); + + PRBool useProgressDialogs = PR_TRUE; + branch->GetBoolPref(USE_PROGRESS_DIALOGS_PREF, &useProgressDialogs); + if (useProgressDialogs) { + nsAutoString path; + rv = aTarget->GetPath(path); + if (NS_FAILED(rv)) return rv; + return dm->Open(nsnull, path.get()); + } + return rv; + } + + + NS_IMETHODIMP GetDisplayName(PRUnichar** aDisplayName) + { + return mInner->GetDisplayName(aDisplayName); + } + + NS_IMETHODIMP SetDisplayName(const PRUnichar* aDisplayName) + { + return mInner->SetDisplayName(aDisplayName); + } + + NS_IMETHODIMP GetMIMEInfo(nsIMIMEInfo** aMIMEInfo) + { + return mInner->GetMIMEInfo(aMIMEInfo); + } + + NS_IMETHODIMP GetSource(nsIURI** aSource) + { + return mInner->GetSource(aSource); + } + + NS_IMETHODIMP GetTarget(nsILocalFile** aTarget) + { + return mInner->GetTarget(aTarget); + } + + NS_IMETHODIMP GetStartTime(PRInt64* aStartTime) + { + return mInner->GetStartTime(aStartTime); + } + + NS_IMETHODIMP GetPercentComplete(PRInt32* aPercentComplete) + { + return mInner->GetPercentComplete(aPercentComplete); + } + + NS_IMETHODIMP GetListener(nsIWebProgressListener** aListener) + { + return mInner->GetListener(aListener); + } + + NS_IMETHODIMP SetListener(nsIWebProgressListener* aListener) + { + return mInner->SetListener(aListener); + } + + NS_IMETHODIMP GetObserver(nsIObserver** aObserver) + { + return mInner->GetObserver(aObserver); + } + + NS_IMETHODIMP SetObserver(nsIObserver* aObserver) + { + return mInner->SetObserver(aObserver); + } + + NS_IMETHODIMP GetPersist(nsIWebBrowserPersist** aPersist) + { + return mInner->GetPersist(aPersist); + } + + NS_IMETHODIMP OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, PRUint32 aStateFlags, + PRUint32 aStatus) + { + nsCOMPtr listener = do_QueryInterface(mInner); + if (listener) + return listener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus); + return NS_OK; + } + + NS_IMETHODIMP OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsresult aStatus, + const PRUnichar *aMessage) + { + nsCOMPtr listener = do_QueryInterface(mInner); + if (listener) + return listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage); + return NS_OK; + } + + NS_IMETHODIMP OnLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsIURI *aLocation) + { + nsCOMPtr listener = do_QueryInterface(mInner); + if (listener) + return listener->OnLocationChange(aWebProgress, aRequest, aLocation); + return NS_OK; + } + + NS_IMETHODIMP OnProgressChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRInt32 aCurSelfProgress, + PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, + PRInt32 aMaxTotalProgress) + { + nsCOMPtr listener = do_QueryInterface(mInner); + if (listener) + return listener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, + aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress); + return NS_OK; + } + + NS_IMETHODIMP OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRUint32 aState) + { + nsCOMPtr listener = do_QueryInterface(mInner); + if (listener) + return listener->OnSecurityChange(aWebProgress, aRequest, aState); + return NS_OK; + } + +private: + nsCOMPtr mInner; +}; + +NS_IMPL_ISUPPORTS2(nsDownloadProxy, nsIDownload, nsIWebProgressListener) + +#endif diff --git a/mozilla/toolkit/components/downloads/src/old.cpp b/mozilla/toolkit/components/downloads/src/old.cpp new file mode 100644 index 00000000000..89251123b0c --- /dev/null +++ b/mozilla/toolkit/components/downloads/src/old.cpp @@ -0,0 +1,74 @@ + /** + * Opens an individual progress dialog displaying progress for the download. + * + * @param aPersistentDescriptor The persistent descriptor of the download to + * display progress for. + * + * @param aParent The parent, or opener, of the front end (optional). + */ + + void openProgressDialogFor(in wstring aPersistentDescriptor, in nsIDOMWindow aParent); + +NS_IMETHODIMP +nsDownloadManager::OpenProgressDialogFor(const PRUnichar* aPath, nsIDOMWindow* aParent) +{ + nsresult rv; + nsStringKey key(aPath); + if (!mCurrDownloads.Exists(&key)) + return NS_ERROR_FAILURE; + + nsCOMPtr download; + nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); + internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) getter_AddRefs(download)); + if (!download) + return NS_ERROR_FAILURE; + + + nsCOMPtr oldDialog; + internalDownload->GetDialog(getter_AddRefs(oldDialog)); + + if (oldDialog) { + nsCOMPtr window; + oldDialog->GetDialog(getter_AddRefs(window)); + if (window) { + nsCOMPtr internalWin = do_QueryInterface(window); + internalWin->Focus(); + return NS_OK; + } + } + + nsCOMPtr dialog(do_CreateInstance("@mozilla.org/progressdialog;1", &rv)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr dl = do_QueryInterface(dialog); + + // now give the dialog the necessary context + + // start time... + PRInt64 startTime = 0; + download->GetStartTime(&startTime); + + // source... + nsCOMPtr source; + download->GetSource(getter_AddRefs(source)); + + // target... + nsCOMPtr target; + download->GetTarget(getter_AddRefs(target)); + + // helper app... + nsCOMPtr mimeInfo; + download->GetMIMEInfo(getter_AddRefs(mimeInfo)); + + dl->Init(source, target, nsnull, mimeInfo, startTime, nsnull); + dl->SetObserver(this); + + // now set the listener so we forward notifications to the dialog + nsCOMPtr listener = do_QueryInterface(dialog); + internalDownload->SetDialogListener(listener); + + internalDownload->SetDialog(dialog); + + return dialog->Open(aParent); +} + diff --git a/mozilla/toolkit/content/globalOverlay.js b/mozilla/toolkit/content/globalOverlay.js index 2aed0da59dd..6b3effe5350 100644 --- a/mozilla/toolkit/content/globalOverlay.js +++ b/mozilla/toolkit/content/globalOverlay.js @@ -6,7 +6,12 @@ function goQuitApplication() { try { - ObserverService.notifyObservers(null, "quit-application-requested", null); + var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].createInstance(Components.interfaces.nsISupportsPRBool); + ObserverService.notifyObservers(cancelQuit, "quit-application-requested", null); + + // Something aborted the quit process. + if (cancelQuit.data) + return; } catch (ex) { diff --git a/mozilla/toolkit/mozapps/downloads/content/DownloadProgressListener.js b/mozilla/toolkit/mozapps/downloads/content/DownloadProgressListener.js new file mode 100644 index 00000000000..db44d9b03ce --- /dev/null +++ b/mozilla/toolkit/mozapps/downloads/content/DownloadProgressListener.js @@ -0,0 +1,264 @@ +var gStrings = []; +const interval = 500; // Update every 500 milliseconds. + +function DownloadProgressListener (aDocument, aStringBundle) +{ + this.doc = aDocument; + + this._statusFormat = aStringBundle.getString("statusFormat"); + this._statusFormatKBMB = aStringBundle.getString("statusFormatKBMB"); + this._statusFormatKBKB = aStringBundle.getString("statusFormatKBKB"); + this._statusFormatMBMB = aStringBundle.getString("statusFormatMBMB"); + this._longTimeFormat = aStringBundle.getString("longTimeFormat"); + this._shortTimeFormat = aStringBundle.getString("shortTimeFormat"); + +} + +DownloadProgressListener.prototype = +{ + elapsed: 0, + rateChanges: 0, + rateChangeLimit: 0, + priorRate: 0, + lastUpdate: -500, + doc: null, + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload) + { + if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) { + var aDownloadID = aDownload.target.persistentDescriptor; + var download = this.doc.getElementById(aDownloadID); + if (download) + download.setAttribute("status", ""); + } + }, + + onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress, aDownload) + { + var overallProgress = aCurTotalProgress; + // Get current time. + var now = (new Date()).getTime(); + + // If interval hasn't elapsed, ignore it. + if (now - this.lastUpdate < interval && aMaxTotalProgress != "-1" && + parseInt(aCurTotalProgress) < parseInt(aMaxTotalProgress)) { + return; + } + + // Update this time. + this.lastUpdate = now; + + // Update download rate. + this.elapsed = now - (aDownload.startTime / 1000); + var rate; // aCurTotalProgress/sec + if (this.elapsed) + rate = (aCurTotalProgress * 1000) / this.elapsed; + else + rate = 0; + + var aDownloadID = aDownload.target.persistentDescriptor; + var download = this.doc.getElementById(aDownloadID); + + // Calculate percentage. + var percent; + if (aMaxTotalProgress > 0) { + percent = Math.floor((overallProgress*100.0)/aMaxTotalProgress); + if (percent > 100) + percent = 100; + + // Advance progress meter. + if (download) { + download.setAttribute("progress", percent); + + download.setAttribute("progressmode", "normal"); + + onUpdateProgress(); + } + } + else { + percent = -1; + + // Progress meter should be barber-pole in this case. + download.setAttribute("progressmode", "undetermined"); + } + + // Now that we've set the progress and the time, update the UI with + // all the the pertinent information (bytes transferred, bytes total, + // download rate, time remaining). + var status = this._statusFormat; + + // Insert the progress so far using the formatting routine. + var KBProgress = parseInt(overallProgress/1024 + .5); + var KBTotal = parseInt(aMaxTotalProgress/1024 + .5); + var kbProgress = this._formatKBytes(KBProgress, KBTotal); + status = this._replaceInsert(status, 1, kbProgress); + if (download) + download.setAttribute("status-internal", kbProgress); + + if (rate) { + // rate is bytes/sec + var kRate = rate / 1024; // K bytes/sec; + kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits) + // Don't update too often! + if (kRate != this.priorRate) { + if (this.rateChanges++ == this.rateChangeLimit) { + // Time to update download rate. + this.priorRate = kRate; + this.rateChanges = 0; + } + else { + // Stick with old rate for a bit longer. + kRate = this.priorRate; + } + } + else + this.rateChanges = 0; + + var fraction = kRate % 10; + kRate = parseInt((kRate - fraction) / 10); + + // Insert 3 is the download rate (in kilobytes/sec). + status = this._replaceInsert(status, 2, kRate + "." + fraction); + } + else + status = this._replaceInsert(status, 2, "??.?"); + + // Update time remaining. + if (rate && (aMaxTotalProgress > 0)) { + var rem = (aMaxTotalProgress - aCurTotalProgress) / rate; + rem = parseInt(rem + .5); + + status = this._replaceInsert(status, 3, this._formatSeconds(rem, this.doc)); + } + else + status = this._replaceInsert(status, 3, "???"); + + if (download) + download.setAttribute("status", status); + }, + onLocationChange: function(aWebProgress, aRequest, aLocation, aDownload) + { + }, + onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage, aDownload) + { + }, + onSecurityChange: function(aWebProgress, aRequest, state, aDownload) + { + }, + QueryInterface : function(iid) + { + if (iid.equals(Components.interfaces.nsIDownloadProgressListener) || + iid.equals(Components.interfaces.nsISupports)) + return this; + + throw Components.results.NS_NOINTERFACE; + }, + + _replaceInsert: function ( text, index, value ) + { + var result = text; + var regExp = new RegExp( "#"+index ); + result = result.replace( regExp, value ); + return result; + }, + + // aBytes aTotalKBytes returns: + // x, < 1MB y < 1MB x of y KB + // x, < 1MB y >= 1MB x KB of y MB + // x, >= 1MB y >= 1MB x of y MB + _formatKBytes: function (aKBytes, aTotalKBytes) + { + var progressHasMB = parseInt(aKBytes/1000) > 0; + var totalHasMB = parseInt(aTotalKBytes/1000) > 0; + + var format = ""; + if (!progressHasMB && !totalHasMB) { + format = this._statusFormatKBKB; + format = this._replaceInsert(format, 1, aKBytes); + format = this._replaceInsert(format, 2, aTotalKBytes); + } + else if (progressHasMB && totalHasMB) { + format = this._statusFormatMBMB; + format = this._replaceInsert(format, 1, (aKBytes / 1000).toFixed(1)); + format = this._replaceInsert(format, 2, (aTotalKBytes / 1000).toFixed(1)); + } + else if (totalHasMB && !progressHasMB) { + format = this._statusFormatKBMB; + format = this._replaceInsert(format, 1, aKBytes); + format = this._replaceInsert(format, 2, (aTotalKBytes / 1000).toFixed(1)); + } + else { + // This is an undefined state! + dump("*** huh?!\n"); + } + + return format; + }, + + _formatSeconds: function (secs, doc) + { + // Round the number of seconds to remove fractions. + secs = parseInt(secs + .5); + var hours = parseInt(secs/3600); + secs -= hours * 3600; + + var mins = parseInt(secs/60); + secs -= mins * 60; + var result = hours ? this._longTimeFormat : this._shortTimeFormat; + + if (hours < 10) + hours = "0" + hours; + if (mins < 10) + mins = "0" + mins; + if (secs < 10) + secs = "0" + secs; + + // Insert hours, minutes, and seconds into result string. + result = this._replaceInsert(result, 1, hours); + result = this._replaceInsert(result, 2, mins); + result = this._replaceInsert(result, 3, secs); + + return result; + }, + +}; + +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla.org Code. +# +# The Initial Developer of the Original Code is +# Doron Rosenberg. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Blake Ross (Original Author) +# Ben Goodger (v2.0) +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + + diff --git a/mozilla/toolkit/mozapps/downloads/content/download.xml b/mozilla/toolkit/mozapps/downloads/content/download.xml new file mode 100644 index 00000000000..688ebf76555 --- /dev/null +++ b/mozilla/toolkit/mozapps/downloads/content/download.xml @@ -0,0 +1,458 @@ + + +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla.org Code. +# +# The Initial Developer of the Original Code is +# Doron Rosenberg. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Ben Goodger (v2.0) +# Blake Ross +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + + + + %downloadDTD; +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + + + + + + + + 0 + true + -1 + + + + + + + + + + + + + + + + + + + + 0 + + + + + + aDownload._adl_kUpperBounds) { + aDownload.fireEvent('animated'); + return; + } + + // Don't even bother if we're going away. + if (!aContent.ownerDocument) + return; + + aDownload._adlStep += aDownload._adl_kIncrement; + aContent.setAttribute("style", "-moz-opacity: " + aDownload._adlStep + "!important;"); + + setTimeout(aDownload._adlTimerCallback, aDownload._adl_kTimeout, aDownload, aContent); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + +#ifdef XP_WIN + + + +#endif + + + + + + + + + + + + + + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mozilla/toolkit/mozapps/downloads/content/downloadProperties.js b/mozilla/toolkit/mozapps/downloads/content/downloadProperties.js new file mode 100644 index 00000000000..600887d08f0 --- /dev/null +++ b/mozilla/toolkit/mozapps/downloads/content/downloadProperties.js @@ -0,0 +1,60 @@ +function Startup() +{ + const NC_NS = "http://home.netscape.com/NC-rdf#"; + const rdfSvcContractID = "@mozilla.org/rdf/rdf-service;1"; + const rdfSvcIID = Components.interfaces.nsIRDFService; + var rdfService = Components.classes[rdfSvcContractID].getService(rdfSvcIID); + + const dlmgrContractID = "@mozilla.org/download-manager;1"; + const dlmgrIID = Components.interfaces.nsIDownloadManager; + var downloadMgr = Components.classes[dlmgrContractID].getService(dlmgrIID); + var ds = downloadMgr.datasource; + + const dateTimeContractID = "@mozilla.org/intl/scriptabledateformat;1"; + const dateTimeIID = Components.interfaces.nsIScriptableDateFormat; + var dateTimeService = Components.classes[dateTimeContractID].getService(dateTimeIID); + + var resource = rdfService.GetUnicodeResource(window.arguments[0]); + var dateStartedRes = rdfService.GetResource(NC_NS + "DateStarted"); + var dateEndedRes = rdfService.GetResource(NC_NS + "DateEnded"); + var sourceRes = rdfService.GetResource(NC_NS + "URL"); + + var dateStartedField = document.getElementById("dateStarted"); + var dateEndedField = document.getElementById("dateEnded"); + var pathField = document.getElementById("path"); + var sourceField = document.getElementById("source"); + + try { + var dateStarted = ds.GetTarget(resource, dateStartedRes, true).QueryInterface(Components.interfaces.nsIRDFDate).Value; + dateStarted = new Date(dateStarted/1000); + dateStarted = dateTimeService.FormatDateTime("", dateTimeService.dateFormatShort, dateTimeService.timeFormatSeconds, dateStarted.getFullYear(), dateStarted.getMonth()+1, dateStarted.getDate(), dateStarted.getHours(), dateStarted.getMinutes(), dateStarted.getSeconds()); + dateStartedField.setAttribute("value", dateStarted); + } + catch (e) { + } + + try { + var dateEnded = ds.GetTarget(resource, dateEndedRes, true).QueryInterface(Components.interfaces.nsIRDFDate).Value; + dateEnded = new Date(dateEnded/1000); + dateEnded = dateTimeService.FormatDateTime("", dateTimeService.dateFormatShort, dateTimeService.timeFormatSeconds, dateEnded.getFullYear(), dateEnded.getMonth()+1, dateEnded.getDate(), dateEnded.getHours(), dateEnded.getMinutes(), dateEnded.getSeconds()); + dateEndedField.setAttribute("value", dateEnded); + } + catch (e) { + } + + var source = ds.GetTarget(resource, sourceRes, true).QueryInterface(Components.interfaces.nsIRDFResource).Value; + + pathField.value = window.arguments[0]; + sourceField.value = source; + + var dl = window.opener.gDownloadManager.getDownload(window.arguments[0]); + if (dl) { + document.getElementById("dateEndedRow").hidden = true; + document.getElementById("dateEndedSeparator").hidden = true; + } + + document.documentElement.getButton("accept").label = document.documentElement.getAttribute("acceptbuttontext"); + + document.documentElement.getButton("accept").focus(); +} + \ No newline at end of file diff --git a/mozilla/toolkit/mozapps/downloads/content/downloadProperties.xul b/mozilla/toolkit/mozapps/downloads/content/downloadProperties.xul new file mode 100644 index 00000000000..63d750b6613 --- /dev/null +++ b/mozilla/toolkit/mozapps/downloads/content/downloadProperties.xul @@ -0,0 +1,56 @@ + + + + +%downloadPropertiesDTD; +]> + + + +