Bug 389982 - Download Manager is not friendly to embedders or extensions. r=mano

This commit is contained in:
sdwilsh%shawnwilsher.com 2007-08-28 00:10:29 +00:00
Родитель 3429356407
Коммит c3a0267055
8 изменённых файлов: 226 добавлений и 163 удалений

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

@ -47,6 +47,7 @@ MODULE = downloads
XPIDLSRCS = nsIDownloadManager.idl \
nsIDownloadProgressListener.idl \
nsIDownload.idl \
nsIDownloadManagerUI.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -41,7 +41,6 @@
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsIURI;
interface nsILocalFile;
interface nsIDownload;
@ -51,7 +50,7 @@ interface nsIDownloadProgressListener;
interface nsISimpleEnumerator;
interface mozIStorageConnection;
[scriptable, uuid(b23d291f-2893-48ea-abda-ba9c9fe69c95)]
[scriptable, uuid(05ed1d45-0aff-4ba0-9e2c-a9ef20383048)]
interface nsIDownloadManager : nsISupports {
// Download States
const short DOWNLOAD_NOTSTARTED = -1;
@ -165,17 +164,6 @@ interface nsIDownloadManager : nsISupports {
*/
void retryDownload(in unsigned long aID);
/**
* Opens the Download Manager front end, selecting the specified download.
*
* @param aParent The parent, or opener, of the front end (optional).
* @param aID The unique ID of the download to be selected.
* @see nsIWindowWatcher::openWindow for behavior of null aParent.
* @throws NS_ERROR_FAILURE if the Download Manager does not know about the
* download.
*/
void open(in nsIDOMWindow aParent, in unsigned long aID);
/**
* The database connection to the downloads database.
*/

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

@ -0,0 +1,65 @@
/* ***** BEGIN LICENSE BLOCK *****
* 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
* Shawn Wilsher <me@shawnwilsher.com>.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#include "nsISupports.idl"
interface nsIInterfaceRequestor;
[scriptable, uuid(67796ac0-effe-4cb0-91d4-229176956164)]
interface nsIDownloadManagerUI : nsISupports {
/**
* Shows the Download Manager's UI to the user.
*
* @param aWindowContext
* The parent window context to show the UI.
* @param aID
* The id of the download to be preselected upon opening.
*/
void show([optional] in nsIInterfaceRequestor aWindowContext,
[optional] in unsigned long aID);
/**
* Indicates if the UI is visible or not.
*/
readonly attribute boolean visible;
/**
* Brings attention to the UI if it is already visible
*
* @throws NS_ERROR_UNEXPECTED if the UI is not visible.
*/
void getAttention();
};

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

@ -76,6 +76,10 @@ ifeq ($(OS_ARCH),WINNT)
CPPSRCS += nsDownloadScanner.cpp
endif
EXTRA_COMPONENTS = \
nsDownloadManagerUI.js \
$(NULL)
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)

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

@ -69,6 +69,7 @@
#include "nsIAlertsService.h"
#include "nsIPropertyBag2.h"
#include "nsIHttpChannel.h"
#include "nsIDownloadManagerUI.h"
#ifdef XP_WIN
#include <shlobj.h>
@ -77,17 +78,12 @@
static PRBool gStoppingDownloads = 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 PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete"
#define PREF_BDM_SHOWALERTINTERVAL "browser.download.manager.showAlertInterval"
#define PREF_BDM_RETENTION "browser.download.manager.retention"
#define PREF_BDM_OPENDELAY "browser.download.manager.openDelay"
#define PREF_BDM_SHOWWHENSTARTING "browser.download.manager.showWhenStarting"
#define PREF_BDM_FOCUSWHENSTARTING "browser.download.manager.focusWhenStarting"
#define PREF_BDM_CLOSEWHENDONE "browser.download.manager.closeWhenDone"
#define PREF_BDM_FLASHCOUNT "browser.download.manager.flashCount"
#define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs"
static const PRInt64 gUpdateInterval = 400 * PR_USEC_PER_MSEC;
@ -1178,130 +1174,6 @@ nsDownloadManager::PauseResumeDownload(PRUint32 aID, PRBool aPause)
return dl->PauseResume(aPause);
}
NS_IMETHODIMP
nsDownloadManager::Open(nsIDOMWindow* aParent, PRUint32 aID)
{
// try to get an active download
nsRefPtr<nsDownload> dl = FindDownload(aID);
if (!dl) {
// try to get a finished download from the database
(void)GetDownloadFromDB(aID, getter_AddRefs(dl));
if (!dl) return NS_ERROR_FAILURE;
}
TimerParams* params = new TimerParams();
NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
params->parent = aParent;
params->download = dl;
PRInt32 delay = 0;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (pref)
pref->GetIntPref(PREF_BDM_OPENDELAY, &delay);
// 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, delay,
nsITimer::TYPE_ONE_SHOT);
}
void
nsDownloadManager::OpenTimerCallback(nsITimer* aTimer, void* aClosure)
{
TimerParams* params = static_cast<TimerParams*>(aClosure);
PRInt32 complete;
params->download->GetPercentComplete(&complete);
PRBool closeDM = PR_FALSE;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (pref)
pref->GetBoolPref(PREF_BDM_CLOSEWHENDONE, &closeDM);
// Check closeWhenDone pref before opening download manager
if (!closeDM || complete < 100) {
PRBool focusDM = PR_FALSE;
PRBool showDM = PR_TRUE;
PRInt32 flashCount = -1;
if (pref) {
pref->GetBoolPref(PREF_BDM_FOCUSWHENSTARTING, &focusDM);
// We only flash the download manager if the user has the download manager show
pref->GetBoolPref(PREF_BDM_SHOWWHENSTARTING, &showDM);
if (showDM)
pref->GetIntPref(PREF_BDM_FLASHCOUNT, &flashCount);
else
flashCount = 0;
}
nsDownloadManager::OpenDownloadManager(focusDM, flashCount,
params->download, params->parent);
}
delete params;
}
nsresult
nsDownloadManager::OpenDownloadManager(PRBool aShouldFocus,
PRInt32 aFlashCount,
nsIDownload *aDownload,
nsIDOMWindow *aParent)
{
nsresult rv;
nsCOMPtr<nsIWindowMediator> wm =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMWindowInternal> recentWindow;
wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(),
getter_AddRefs(recentWindow));
if (recentWindow) {
if (aShouldFocus) {
recentWindow->Focus();
} else {
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(recentWindow));
chromeWindow->GetAttentionWithCycleCount(aFlashCount);
}
} else {
// If we ever have the capability to display the UI of third party dl
// managers, we'll open their UI here instead.
nsCOMPtr<nsIWindowWatcher> ww =
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// pass the datasource to the window
nsCOMPtr<nsIMutableArray> params =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDownloadManager> dlMgr =
do_GetService("@mozilla.org/download-manager;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageConnection> DBConn;
(void)dlMgr->GetDBConnection(getter_AddRefs(DBConn));
params->AppendElement(DBConn, PR_FALSE);
params->AppendElement(aDownload, PR_FALSE);
nsCOMPtr<nsIDOMWindow> newWindow;
rv = ww->OpenWindow(aParent,
DOWNLOAD_MANAGER_FE_URL,
"_blank",
"chrome,dialog=no,resizable",
params,
getter_AddRefs(newWindow));
}
return rv;
}
NS_IMETHODIMP
nsDownloadManager::GetDBConnection(mozIStorageConnection **aDBConn)
{
@ -1419,15 +1291,10 @@ nsDownloadManager::Observe(nsISupports *aSubject,
NS_LITERAL_STRING("offlineCancelDownloadsAlertMsg").get(),
NS_LITERAL_STRING("dontGoOfflineButton").get());
} else if (strcmp(aTopic, "alertclickcallback") == 0) {
// Attempt to locate a browser window to parent the download manager to
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<nsIDOMWindowInternal> browserWindow;
if (wm) {
wm->GetMostRecentWindow(NS_LITERAL_STRING("navigator:browser").get(),
getter_AddRefs(browserWindow));
}
return OpenDownloadManager(PR_TRUE, -1, nsnull, browserWindow);
nsCOMPtr<nsIDownloadManagerUI> dmui =
do_GetService("@mozilla.org/download-manager-ui;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
return dmui->Show(nsnull, 0);
}
return NS_OK;

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

@ -57,7 +57,6 @@
#include "nsIStringBundle.h"
#include "nsISupportsPrimitives.h"
#include "nsIMIMEInfo.h"
#include "nsITimer.h"
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "nsISupportsArray.h"
@ -95,10 +94,6 @@ private:
#endif
protected:
struct TimerParams {
nsRefPtr<nsDownload> download;
nsCOMPtr<nsIDOMWindow> parent;
};
nsresult InitDB(PRBool *aDoImport);
nsresult CreateTable();
nsresult ImportDownloadHistory();
@ -161,11 +156,6 @@ protected:
const PRUnichar* aCancelMessageSingle,
const PRUnichar* aDontCancelButton);
static void OpenTimerCallback(nsITimer* aTimer, void* aClosure);
static nsresult OpenDownloadManager(PRBool aShouldFocus, PRInt32 aFlashCount,
nsIDownload* aDownload,
nsIDOMWindow* aParent);
PRInt32 GetRetentionBehavior();
static PRBool IsInFinalStage(DownloadState aState)
@ -190,7 +180,6 @@ protected:
private:
nsCOMArray<nsIDownloadProgressListener> mListeners;
nsCOMPtr<nsIStringBundle> mBundle;
nsCOMPtr<nsITimer> mDMOpenTimer;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMArray<nsDownload> mCurrentDownloads;
nsCOMPtr<nsIObserverService> mObserverService;

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

@ -0,0 +1,132 @@
/* ***** BEGIN LICENSE BLOCK *****
* 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
* Shawn Wilsher <me@shawnwilsher.com>.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
////////////////////////////////////////////////////////////////////////////////
//// Constants
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const DOWNLOAD_MANAGER_URL = "chrome://mozapps/content/downloads/downloads.xul";
const PREF_FLASH_COUNT = "browser.download.manager.flashCount";
////////////////////////////////////////////////////////////////////////////////
//// nsDownloadManagerUI class
function nsDownloadManagerUI() {}
nsDownloadManagerUI.prototype = {
classDescription: "Used to show the Download Manager's UI to the user",
classID: Components.ID("7dfdf0d1-aff6-4a34-bad1-d0fe74601642"),
contractID: "@mozilla.org/download-manager-ui;1",
//////////////////////////////////////////////////////////////////////////////
//// nsIDownloadManagerUI
show: function show(aWindowContext, aID)
{
// First we see if it is already visible
if (this.recentWindow) {
this.recentWindow.focus();
return;
}
var window = null;
try {
if (aWindowContext)
window = aWindowContext.getInterface(Ci.nsIDOMWindow);
} catch (e) { /* it's OK to not have a parent window */ }
// We pass the download manager and the nsIDownload we want selected
var params = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
var dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
params.appendElement(dm, false);
params.appendElement(dm.getDownload(aID), false);
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(window,
DOWNLOAD_MANAGER_URL,
null,
"chrome,dialog=no,resizable",
params);
},
get visible() {
return (null != this.recentWindow);
},
getAttention: function getAttention()
{
if (!this.visible)
throw Cr.NS_ERROR_UNEXPECTED;
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var flashCount = prefs.getIntPref(PREF_FLASH_COUNT);
var win = this.recentWindow.QueryInteface(Ci.nsIDOMChromeWindow);
win.getAttentionWithCycleCount(flashCount);
},
//////////////////////////////////////////////////////////////////////////////
//// nsDownloadManagerUI
get recentWindow() {
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
return wm.getMostRecentWindow("Download:Manager");
},
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI])
};
////////////////////////////////////////////////////////////////////////////////
//// Module
let components = [nsDownloadManagerUI];
function NSGetModule(compMgr, fileSpec)
{
return XPCOMUtils.generateModule(components);
}

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

@ -44,9 +44,11 @@
#include "nsIPrefService.h"
#include "nsIMIMEInfo.h"
#include "nsIFileURL.h"
#include "nsIDownloadManagerUI.h"
#define PREF_BDM_SHOWWHENSTARTING "browser.download.manager.showWhenStarting"
#define PREF_BDM_USEWINDOW "browser.download.manager.useWindow"
#define PREF_BDM_FOCUSWHENSTARTING "browser.download.manager.focusWhenStarting"
class nsDownloadProxy : public nsITransfer
{
@ -89,7 +91,22 @@ public:
PRUint32 id;
mInner->GetId(&id);
return dm->Open(nsnull, id);
nsCOMPtr<nsIDownloadManagerUI> dmui =
do_GetService("@mozilla.org/download-manager-ui;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRBool visible;
rv = dmui->GetVisible(&visible);
NS_ENSURE_SUCCESS(rv, rv);
PRBool focus = PR_TRUE;
if (branch)
(void)branch->GetBoolPref(PREF_BDM_FOCUSWHENSTARTING, &focus);
if (visible && !focus)
return dmui->GetAttention();
return dmui->Show(nsnull, id);
}
return rv;
}