Bug 380250 - Convert Download Manager's RDF backend to mozStorage. r=cbiesinger,r=mconnor

This commit is contained in:
sdwilsh@shawnwilsher.com 2007-05-21 17:03:33 -07:00
parent ed953e9af2
commit e75178083f
18 changed files with 1648 additions and 1927 deletions

View File

@ -137,7 +137,7 @@ nsDownloadListener::GetSize(PRUint64 *aSize)
/* attribute wstring displayName; */
NS_IMETHODIMP
nsDownloadListener::GetDisplayName(PRUnichar * *aDisplayName)
nsDownloadListener::GetDisplayName(nsAString &aDisplayName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -180,6 +180,18 @@ nsDownloadListener::SetListener(nsIWebProgressListener * aListener)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDownloadListener::GetId(PRUint64 *aId)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDownloadListener::GetState(PRInt16 *aState)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#pragma mark -
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */

View File

@ -87,6 +87,7 @@ REQUIRES = \
alerts \
url-classifier \
feeds \
storage \
$(NULL)
EXPORTS = nsToolkitCompsCID.h

View File

@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
DIRS = public src test
include $(topsrcdir)/config/rules.mk

View File

@ -47,11 +47,11 @@ interface nsILocalFile;
interface nsIDownload;
interface nsICancelable;
interface nsIMIMEInfo;
interface nsIRDFDataSource;
interface nsIDownloadProgressListener;
interface nsISupportsArray;
interface nsISimpleEnumerator;
interface mozIStorageConnection;
[scriptable, uuid(1f280341-30f4-4009-bb0d-a78f2936d1fb)]
[scriptable, uuid(541712be-f582-4e1c-a85e-7b4652c4f392)]
interface nsIDownloadManager : nsISupports {
// Download States
const short DOWNLOAD_NOTSTARTED = -1;
@ -63,8 +63,6 @@ interface nsIDownloadManager : nsISupports {
const short DOWNLOAD_TYPE_DOWNLOAD = 0;
// Methods called by clients to carry out various managing functions
/**
* Creates an nsIDownload and adds it to be managed by the download manager.
*
@ -91,6 +89,11 @@ interface nsIDownloadManager : nsISupports {
* Must not be null.
*
* @return The newly created download item with the passed-in properties.
*
* @note This does not actually start a download. If you want to add and
* start a download, you need to create an nsIWebBrowserPersist, pass it
* as the aCancelable object, call this method, set the progressListener
* as the returned download object, then call saveURI.
*/
nsIDownload addDownload(in short aDownloadType,
in nsIURI aSource,
@ -103,80 +106,70 @@ interface nsIDownloadManager : nsISupports {
in nsICancelable aCancelable);
/**
* Retrieves an in-progress download managed by the download manager.
* 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.
* @param aID The unique ID of the download.
* @return The download with the specified ID.
* @throws NS_ERROR_FAILURE if the download is not in-progress.
*/
nsIDownload getDownload(in wstring aPersistentDescriptor);
nsIDownload getDownload(in unsigned long aID);
/**
* Cancels the download with the specified persistent descriptor if it's
* currently in progress. This calls cancel(NS_BINDING_ABORTED) on the
* nsICancelable provided for the download.
* Cancels the download with the specified ID if it's currently in-progress.
* This calls cancel(NS_BINDING_ABORTED) on the nsICancelable provided by the
* download.
*
* @param aPersistentDescriptor The persistent descriptor of the download to
* be cancelled.
* @param aID The unique ID of the download.
* @throws NS_ERROR_FAILURE if the download is not in-progress.
*/
void cancelDownload(in wstring aPersistentDescriptor);
void cancelDownload(in unsigned long aID);
/**
* 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.
* Removes the download with the specified id 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.
* @param aID The unique ID of the download.
* @throws NS_ERROR_FAILURE if the download is active.
*/
void removeDownload(in wstring aPersistentDescriptor);
void removeDownload(in unsigned long aID);
/**
* Pause the specified download.
*
* @param aID The unique ID of the download.
* @throws NS_ERROR_FAILURE if the download is not in-progress.
*/
void pauseDownload(in wstring aPersistentDescriptor);
void pauseDownload(in unsigned long aID);
/**
* Resume the specified download.
*
* @param aID The unique ID of the download.
* @throws NS_ERROR_FAILURE if the download is not in-progress.
*/
void resumeDownload(in wstring aPersistentDescriptor);
// Front end and Front end update methods.
void resumeDownload(in unsigned long aID);
/**
* Opens the Download Manager front end.
* Opens the Download Manager front end, selecting the specified download.
*
* @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).
* @param aID The unique ID of the download to be selected.
* @see nsIWindowWatcher::openWindow for behavior of null aParent.
* @throws NS_ERROR_FAILUIRE if the download is not in-progress.
*/
void open(in nsIDOMWindow aParent, in unsigned long aID);
void open(in nsIDOMWindow aParent, in wstring aPersistentDescriptor);
/**
* The database connection to the downloads database.
*/
readonly attribute mozIStorageConnection DBConnection;
/**
* 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.
@ -194,21 +187,9 @@ interface nsIDownloadManager : nsISupports {
readonly attribute long activeDownloadCount;
/**
* An enumeration of active downloads.
* An enumeration of active nsIDownloads
*/
readonly attribute nsISupportsArray activeDownloads;
/**
* Update the download datasource.
*/
void saveState();
/**
* Flush the download datasource to disk.
*/
void flush();
readonly attribute nsIRDFDataSource datasource;
readonly attribute nsISimpleEnumerator activeDownloads;
};

View File

@ -62,6 +62,15 @@ interface nsIDownloadProgressListener : nsISupports {
attribute nsIDOMDocument document;
/**
* Dispatched whenever the state of the download changes.
*
* @param aState The previous download sate.
* @param aDownload The download object.
* @see nsIDownloadManager for download states.
*/
void onDownloadStateChange(in short aState, in nsIDownload aDownload);
void onStateChange(in nsIWebProgress aWebProgress,
in nsIRequest aRequest,
in unsigned long aStateFlags,

View File

@ -65,6 +65,7 @@ REQUIRES = xpcom \
xpinstall \
embed_base \
alerts \
storage \
$(NULL)
CPPSRCS = \

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,7 @@
* Contributor(s):
* Blake Ross <blaker@netscape.com>
* Ben Goodger <ben@netscape.com>
* Shawn Wilsher <me@shawnwilsher.com>
*
* 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
@ -44,28 +45,28 @@
#include "nsIXPInstallManagerUI.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 "nsIWebProgressListener2.h"
#include "nsIXPIProgressDialog.h"
#include "nsIURI.h"
#include "nsIWebBrowserPersist.h"
#include "nsILocalFile.h"
#include "nsHashtable.h"
#include "nsIRequest.h"
#include "nsIObserver.h"
#include "nsString.h"
#include "nsIStringBundle.h"
#include "nsISupportsPrimitives.h"
#include "nsIProgressDialog.h"
#include "nsIMIMEInfo.h"
#include "nsITimer.h"
#include "nsIAlertsService.h"
#include "nsCycleCollectionParticipant.h"
#include "mozIStorageConnection.h"
#include "nsISupportsArray.h"
#include "nsCOMArray.h"
#include "nsArrayEnumerator.h"
#include "nsAutoPtr.h"
#include "nsIObserverService.h"
typedef PRInt16 DownloadState;
typedef PRInt16 DownloadType;
@ -85,34 +86,50 @@ public:
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);
public:
nsresult AssertProgressInfoFor(const PRUnichar* aPersistentDescriptor);
protected:
nsresult GetDownloadsContainer(nsIRDFContainer** aResult);
nsresult GetProfileDownloadsFileURL(nsCString& aDownloadsFileURL);
nsresult GetDataSource(nsIRDFDataSource** aDataSource);
nsresult DownloadStarted(const PRUnichar* aPersistentDescriptor);
nsresult GetInternalListener(nsIDownloadProgressListener** aListener);
nsresult PauseResumeDownload(const PRUnichar* aPath, PRBool aPause);
nsresult RemoveDownload(nsIRDFResource* aDownload);
nsresult ValidateDownloadsContainer();
struct TimerParams {
nsRefPtr<nsDownload> download;
nsCOMPtr<nsIDOMWindow> parent;
};
nsresult InitDB(PRBool *aDoImport);
nsresult CreateTable();
nsresult ImportDownloadHistory();
void ConfirmCancelDownloads(PRInt32 aCount, nsISupportsPRBool* aCancelDownloads,
/**
* Adds a download with the specified information to the DB.
*
* @return The id of the download, or 0 if there was an error.
*/
PRInt64 AddDownloadToDB(const nsAString &aName,
const nsACString &aSource,
const nsACString &aTarget,
const nsAString &aIconURL,
PRInt64 aStartTime,
PRInt64 aEndTime,
PRInt32 aState);
nsDownload *FindDownload(PRUint32 aID);
nsresult PauseResumeDownload(PRUint32 aID, PRBool aPause);
nsresult CancelAllDownloads();
inline PRBool RemoveDownloadFromCurrent(nsDownload *aDownload)
{
return mCurrentDownloads.RemoveObject(aDownload);
}
void ConfirmCancelDownloads(PRInt32 aCount,
nsISupportsPRBool* aCancelDownloads,
const PRUnichar* aTitle,
const PRUnichar* aCancelMessageMultiple,
const PRUnichar* aCancelMessageSingle,
const PRUnichar* aDontCancelButton);
static void OpenTimerCallback(nsITimer* aTimer, void* aClosure);
static nsresult OpenDownloadManager(PRBool aShouldFocus, PRInt32 aFlashCount, nsIDownload* aDownload, nsIDOMWindow* aParent);
static void OpenTimerCallback(nsITimer* aTimer, void* aClosure);
static nsresult OpenDownloadManager(PRBool aShouldFocus, PRInt32 aFlashCount,
nsIDownload* aDownload,
nsIDOMWindow* aParent);
PRBool NeedsUIUpdate() { return mListener != nsnull; }
PRInt32 GetRetentionBehavior();
@ -141,15 +158,13 @@ protected:
private:
nsCOMPtr<nsIDownloadProgressListener> mListener;
nsCOMPtr<nsIRDFDataSource> mDataSource;
nsCOMPtr<nsIXPIProgressDialog> mXPIProgress;
nsCOMPtr<nsIRDFContainer> mDownloadsContainer;
nsCOMPtr<nsIRDFContainerUtils> mRDFContainerUtils;
nsCOMPtr<nsIStringBundle> mBundle;
nsCOMPtr<nsITimer> mDMOpenTimer;
PRInt32 mBatches;
nsHashtable mCurrDownloads;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMArray<nsDownload> mCurrentDownloads;
nsCOMPtr<nsIObserverService> mObserverService;
friend class nsDownload;
};
@ -170,32 +185,11 @@ public:
protected:
void RemoveDownloadAtIndex(PRUint32 aIndex);
inline void AssertProgressInfoForDownload(nsDownload* aDownload);
private:
nsDownloadManager* mDownloadManager;
nsCOMPtr<nsISupportsArray> mDownloads;
};
class nsDownloadsDataSource : public nsIRDFDataSource,
public nsIRDFRemoteDataSource
{
public:
NS_DECL_NSIRDFDATASOURCE
NS_DECL_NSIRDFREMOTEDATASOURCE
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDownloadsDataSource,
nsIRDFDataSource)
nsDownloadsDataSource() { }
virtual ~nsDownloadsDataSource() { }
nsresult LoadDataSource();
private:
nsCOMPtr<nsIRDFDataSource> mInner;
};
class nsDownload : public nsIDownload
{
public:
@ -209,37 +203,21 @@ public:
virtual ~nsDownload();
public:
DownloadState GetDownloadState();
void SetDownloadState(DownloadState aState);
/**
* This method MUST be called when changing states on a download. It will
* notify the download listener when a change happens.
*/
void SetState(DownloadState aState);
DownloadType GetDownloadType();
void SetDownloadType(DownloadType aType);
nsresult UpdateDB();
protected:
nsresult SetDownloadManager(nsDownloadManager* aDownloadManager);
nsresult SetDialogListener(nsIWebProgressListener* aInternalListener);
nsresult GetDialogListener(nsIWebProgressListener** aInternalListener);
nsresult SetDialog(nsIProgressDialog* aDialog);
nsresult GetDialog(nsIProgressDialog** aDialog);
nsresult SetTempFile(nsILocalFile* aTempFile);
nsresult GetTempFile(nsILocalFile** aTempFile);
nsresult SetCancelable(nsICancelable* aCancelable);
nsresult SetTarget(nsIURI* aTarget);
nsresult SetDisplayName(const PRUnichar* aDisplayName);
nsresult SetSource(nsIURI* aSource);
nsresult SetMIMEInfo(nsIMIMEInfo* aMIMEInfo);
nsresult SetStartTime(PRInt64 aStartTime);
void SetStartTime(PRInt64 aStartTime);
void Pause(PRBool aPaused);
PRBool IsPaused();
struct TransferInformation {
PRInt64 mCurrBytes, mMaxBytes;
TransferInformation(PRInt64 aCurr, PRInt64 aMax) :
mCurrBytes(aCurr),
mMaxBytes(aMax)
{}
};
TransferInformation GetTransferInformation();
nsresult PauseResume(PRBool aPause);
nsDownloadManager* mDownloadManager;
nsCOMPtr<nsIURI> mTarget;
@ -248,7 +226,6 @@ private:
nsString mDisplayName;
nsCOMPtr<nsIURI> mSource;
nsCOMPtr<nsIWebProgressListener> mDialogListener;
nsCOMPtr<nsICancelable> mCancelable;
nsCOMPtr<nsIRequest> mRequest;
nsCOMPtr<nsIProgressDialog> mDialog;
@ -258,12 +235,13 @@ private:
DownloadState mDownloadState;
DownloadType mDownloadType;
PRBool mPaused;
PRUint32 mID;
PRInt32 mPercentComplete;
PRUint64 mCurrBytes;
PRUint64 mMaxBytes;
PRTime mStartTime;
PRTime mLastUpdate;
PRBool mPaused;
double mSpeed;
friend class nsDownloadManager;

View File

@ -39,7 +39,6 @@
#ifndef downloadproxy___h___
#define downloadproxy___h___
#include "nsIDownload.h"
#include "nsIDownloadManager.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
@ -49,7 +48,7 @@
#define PREF_BDM_SHOWWHENSTARTING "browser.download.manager.showWhenStarting"
#define PREF_BDM_USEWINDOW "browser.download.manager.useWindow"
class nsDownloadProxy : public nsIDownload
class nsDownloadProxy : public nsITransfer
{
public:
@ -67,98 +66,35 @@ public:
nsICancelable* aCancelable) {
nsresult rv;
nsCOMPtr<nsIDownloadManager> dm = do_GetService("@mozilla.org/download-manager;1", &rv);
if (NS_FAILED(rv))
return rv;
NS_ENSURE_SUCCESS(rv, rv);
rv = dm->AddDownload(nsIDownloadManager::DOWNLOAD_TYPE_DOWNLOAD, aSource,
aTarget, aDisplayName, EmptyString(), aMIMEInfo,
aStartTime, aTempFile, aCancelable,
getter_AddRefs(mInner));
if (NS_FAILED(rv)) return rv;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
if (NS_FAILED(rv)) return rv;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
PRBool showDM = PR_TRUE;
branch->GetBoolPref(PREF_BDM_SHOWWHENSTARTING , &showDM);
if (branch)
branch->GetBoolPref(PREF_BDM_SHOWWHENSTARTING , &showDM);
PRBool useWindow = PR_TRUE;
branch->GetBoolPref(PREF_BDM_USEWINDOW, &useWindow);
if (branch)
branch->GetBoolPref(PREF_BDM_USEWINDOW, &useWindow);
if (showDM && useWindow) {
nsAutoString path;
PRUint32 id;
mInner->GetId(&id);
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aTarget, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIFile> file;
rv = fileURL->GetFile(getter_AddRefs(file));
if (NS_FAILED(rv)) return rv;
rv = file->GetPath(path);
if (NS_FAILED(rv)) return rv;
return dm->Open(nsnull, path.get());
return dm->Open(nsnull, id);
}
return rv;
}
NS_IMETHODIMP GetDisplayName(PRUnichar** aDisplayName)
{
return mInner->GetDisplayName(aDisplayName);
}
NS_IMETHODIMP GetMIMEInfo(nsIMIMEInfo** aMIMEInfo)
{
return mInner->GetMIMEInfo(aMIMEInfo);
}
NS_IMETHODIMP GetSource(nsIURI** aSource)
{
return mInner->GetSource(aSource);
}
NS_IMETHODIMP GetTarget(nsIURI** 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 GetAmountTransferred(PRUint64* aAmountTransferred)
{
return mInner->GetAmountTransferred(aAmountTransferred);
}
NS_IMETHODIMP GetSize(PRUint64* aSize)
{
return mInner->GetSize(aSize);
}
NS_IMETHODIMP GetCancelable(nsICancelable** aCancelable)
{
return mInner->GetCancelable(aCancelable);
}
NS_IMETHODIMP GetTargetFile(nsILocalFile** aTargetFile)
{
return mInner->GetTargetFile(aTargetFile);
}
NS_IMETHODIMP GetSpeed(double* aSpeed)
{
return mInner->GetSpeed(aSpeed);
}
NS_IMETHODIMP OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, PRUint32 aStateFlags,
PRUint32 aStatus)
@ -245,7 +181,7 @@ private:
nsCOMPtr<nsIDownload> mInner;
};
NS_IMPL_ISUPPORTS4(nsDownloadProxy, nsIDownload, nsITransfer,
NS_IMPL_ISUPPORTS3(nsDownloadProxy, nsITransfer,
nsIWebProgressListener, nsIWebProgressListener2)
#endif

View File

@ -0,0 +1,51 @@
#
# ***** 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 code.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Shawn Wilsher <me@shawnwilsher.com> (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 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = test_dm
XPCSHELL_TESTS = unit
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:NC="http://home.netscape.com/NC-rdf#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<RDF:Description RDF:about="file:///Users/sdwilsh/Desktop/Parallels Desktop 3188 Mac en.dmg"
NC:Name="Parallels Desktop 3188 Mac en.dmg"
NC:DownloadAnimated="true"
NC:Transferred="58625KB of 58787KB">
<NC:URL RDF:resource="http://download.parallels.com/GA/Parallels%20Desktop%203188%20Mac%20en.dmg"/>
<NC:File RDF:resource="file:///Users/sdwilsh/Desktop/Parallels Desktop 3188 Mac en.dmg"/>
<NC:DateStarted NC:parseType="Date">Tue May 08 13:19:12 EDT 2007 +864155</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Tue May 08 13:20:34 EDT 2007 +923536</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Description RDF:about="file:///Users/sdwilsh/Desktop/vlc-plugin-0.8.6b-intel.dmg"
NC:Name="vlc-plugin-0.8.6b-intel.dmg"
NC:DownloadAnimated="true"
NC:Transferred="9819KB of 9819KB">
<NC:URL RDF:resource="http://mirrors.optralan.com/videolan/vlc/0.8.6b/macosx/vlc-plugin-0.8.6b-intel.dmg"/>
<NC:File RDF:resource="file:///Users/sdwilsh/Desktop/vlc-plugin-0.8.6b-intel.dmg"/>
<NC:DateStarted NC:parseType="Date">Sun May 13 16:59:00 EDT 2007 +681898</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Sun May 13 16:59:34 EDT 2007 +198019</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Seq RDF:about="NC:DownloadsRoot">
<RDF:li RDF:resource="/Users/sdwilsh/Desktop/CVS-Contributor-Form.pdf"/>
<RDF:li RDF:resource="/Users/sdwilsh/Desktop/firefox-3.0a5pre.en-US.mac.dmg"/>
<RDF:li RDF:resource="file:///Users/sdwilsh/Desktop/vlc-plugin-0.8.6b-intel.dmg"/>
<RDF:li RDF:resource="file:///Users/sdwilsh/Desktop/vlc-0.8.6b-intel.dmg"/>
<RDF:li RDF:resource="file:///Users/sdwilsh/Desktop/Firefox 2.0.0.3.dmg"/>
<RDF:li RDF:resource="file:///Users/sdwilsh/Desktop/Parallels Desktop 3188 Mac en.dmg"/>
<RDF:li RDF:resource="file:///Users/sdwilsh/Desktop/Adium_1.0.2.dmg"/>
</RDF:Seq>
<RDF:Description RDF:about="file:///Users/sdwilsh/Desktop/Firefox 2.0.0.3.dmg"
NC:Name="Firefox 2.0.0.3.dmg"
NC:DownloadAnimated="true"
NC:DownloadStatus="9.4 of 17.6 MB"
NC:Transferred="17892KB of 18029KB">
<NC:URL RDF:resource="http://ftp-mozilla.netscape.com/pub/mozilla.org/firefox/releases/2.0.0.3/mac/en-US/Firefox%202.0.0.3.dmg"/>
<NC:File RDF:resource="file:///Users/sdwilsh/Desktop/Firefox 2.0.0.3.dmg"/>
<NC:DateStarted NC:parseType="Date">Sat May 12 18:55:32 EDT 2007 +870690</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Sat May 12 18:57:16 EDT 2007 +647483</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Description RDF:about="/Users/sdwilsh/Desktop/firefox-3.0a5pre.en-US.mac.dmg"
NC:Name="firefox-3.0a5pre.en-US.mac.dmg"
NC:DownloadAnimated="true"
NC:Transferred="17040KB of 17056KB">
<NC:URL RDF:resource="http://ftp.mozilla.org/pub/mozilla.org/firefox/tinderbox-builds/bm-xserve08-trunk/firefox-3.0a5pre.en-US.mac.dmg"/>
<NC:File RDF:resource="/Users/sdwilsh/Desktop/firefox-3.0a5pre.en-US.mac.dmg"/>
<NC:DateStarted NC:parseType="Date">Sun May 13 22:12:40 EDT 2007 +237698</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Sun May 13 22:13:33 EDT 2007 +347125</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Description RDF:about="file:///Users/sdwilsh/Desktop/vlc-0.8.6b-intel.dmg"
NC:Name="vlc-0.8.6b-intel.dmg"
NC:DownloadAnimated="true"
NC:Transferred="14043KB of 14048KB">
<NC:URL RDF:resource="http://mirrors.optralan.com/videolan/vlc/0.8.6b/macosx/vlc-0.8.6b-intel.dmg"/>
<NC:File RDF:resource="file:///Users/sdwilsh/Desktop/vlc-0.8.6b-intel.dmg"/>
<NC:DateStarted NC:parseType="Date">Sun May 13 16:58:47 EDT 2007 +179475</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Sun May 13 16:59:34 EDT 2007 +089741</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Description RDF:about="file:///Users/sdwilsh/Desktop/Adium_1.0.2.dmg"
NC:Name="Adium_1.0.2.dmg"
NC:DownloadAnimated="true"
NC:Transferred="15025KB of 15062KB">
<NC:URL RDF:resource="http://adiumx.cachefly.net/Adium_1.0.2.dmg"/>
<NC:File RDF:resource="file:///Users/sdwilsh/Desktop/Adium_1.0.2.dmg"/>
<NC:DateStarted NC:parseType="Date">Mon May 07 19:54:56 EDT 2007 +582642</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Mon May 07 20:00:00 EDT 2007 +820348</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
<RDF:Description RDF:about="/Users/sdwilsh/Desktop/CVS-Contributor-Form.pdf"
NC:Name="CVS-Contributor-Form.pdf"
NC:Transferred="917KB of 917KB">
<NC:URL RDF:resource="http://www.mozilla.org/hacking/CVS-Contributor-Form.pdf"/>
<NC:File RDF:resource="/Users/sdwilsh/Desktop/CVS-Contributor-Form.pdf"/>
<NC:DateStarted NC:parseType="Date">Mon May 14 13:36:46 EDT 2007 +769315</NC:DateStarted>
<NC:DateEnded NC:parseType="Date">Mon May 14 13:36:46 EDT 2007 +770448</NC:DateEnded>
<NC:DownloadState NC:parseType="Integer">1</NC:DownloadState>
<NC:ProgressPercent NC:parseType="Integer">100</NC:ProgressPercent>
</RDF:Description>
</RDF:RDF>

View File

@ -0,0 +1,294 @@
/* ***** 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 Download Manager Test Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (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 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 ***** */
// This file tests the download manager backend
do_import_script("netwerk/test/httpserver/httpd.js");
function createURI(aObj)
{
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) :
ios.newURI(aObj, null, null);
}
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var profileDir = null;
try {
profileDir = dirSvc.get("ProfD", Ci.nsIFile);
} catch (e) { }
if (!profileDir) {
// Register our own provider for the profile directory.
// It will simply return the current directory.
var provider = {
getFile: function(prop, persistent) {
persistent.value = true;
if (prop == "ProfD") {
return dirSvc.get("CurProcD", Ci.nsILocalFile);
} else if (prop = "DLoads") {
var file = dirSvc.get("CurProcD", Ci.nsILocalFile);
file.append("downloads.rdf");
return file;
}
throw Cr.NS_ERROR_FAILURE;
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIDirectoryProvider) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
}
function cleanup()
{
// removing rdf
var rdfFile = dirSvc.get("DLoads", Ci.nsIFile);
if (rdfFile.exists()) rdfFile.remove(true);
// removing database
var dbFile = dirSvc.get("ProfD", Ci.nsIFile);
dbFile.append("downloads.sqlite");
if (dbFile.exists()) dbFile.remove(true);
// removing downloaded file
var destFile = dirSvc.get("ProfD", Ci.nsIFile);
destFile.append("download.result");
if (destFile.exists()) destFile.remove(true);
}
cleanup();
const nsIDownloadManager = Ci.nsIDownloadManager;
const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDownloadManager);
function test_get_download_empty_queue()
{
try {
dm.getDownload(0);
do_throw("Hey! We expect to get an excpetion with this!");
} catch(e) {
do_check_eq(Components.lastResult, Cr.NS_ERROR_FAILURE);
}
}
function test_connection()
{
var ds = dm.DBConnection;
do_check_true(ds.connectionReady);
do_check_true(ds.tableExists("moz_downloads"));
}
function test_count_empty_queue()
{
do_check_eq(0, dm.activeDownloadCount);
do_check_false(dm.activeDownloads.hasMoreElements());
}
function test_canCleanUp_empty_queue()
{
do_check_false(dm.canCleanUp);
}
function test_pauseDownload_empty_queue()
{
try {
dm.pauseDownload(0);
do_throw("This should not be reached");
} catch (e) {
do_check_eq(Cr.NS_ERROR_FAILED, e.error);
}
}
function test_resumeDownload_empty_queue()
{
try {
dm.resumeDownload(0);
do_throw("This should not be reached");
} catch (e) {
do_check_eq(Cr.NS_ERROR_FAILED, e.error);
}
}
function addDownload()
{
const nsIWBP = Ci.nsIWebBrowserPersist;
var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);
persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
var destFile = dirSvc.get("ProfD", Ci.nsIFile);
destFile.append("download.result");
var srcFile = dirSvc.get("ProfD", Ci.nsIFile);
srcFile.append("LICENSE");
var dl = dm.addDownload(nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD,
createURI("http://localhost:4444/LICENSE"),
createURI(destFile), null, null, null,
Math.round(Date.now() * 1000), null, persist);
// This will throw if it isn't found, and that would mean test failure, so no
// try catch block
var test = dm.getDownload(dl.id);
// it is part of the active downloads now, even if it hasn't started.
gDownloadCount++;
persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener);
persist.saveURI(dl.source, null, null, null, null, dl.targetFile);
return dl;
}
function test_addDownload_normal()
{
addDownload();
}
function test_addDownload_cancel()
{
var dl = addDownload();
dm.cancelDownload(dl.id);
do_check_eq(nsIDownloadManager.DOWNLOAD_CANCELED, dl.state);
}
var tests = [test_get_download_empty_queue, test_connection,
test_count_empty_queue, test_canCleanUp_empty_queue,
test_pauseDownload_empty_queue, test_resumeDownload_empty_queue,
test_addDownload_normal, test_addDownload_cancel];
var gDownloadCount = 0;
var httpserv = null;
function run_test()
{
httpserv = new nsHttpServer();
httpserv.registerDirectory("/", dirSvc.get("ProfD", Ci.nsILocalFile));
httpserv.start(4444);
// our download listener
var listener = {
onDownloadStateChange: function(aState, aDownload)
{
if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED)
gDownloadCount--;
if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_CANCELED ||
aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FAILED) {
gDownloadCount--;
}
do_check_eq(gDownloadCount, dm.activeDownloadCount);
if (gDownloadCount == 0)
httpserv.stop();
},
onStateChange: function(a, b, c, d, e) { },
onProgressChange: function(a, b, c, d, e, f, g) { },
onStatusChange: function(a, b, c, d, e) { },
onLocationChange: function(a, b, c, d) { },
onSecurityChange: function(a, b, c, d) { }
};
dm.listener = listener;
var observer = {
observe: function(aSubject, aTopic, aData) {
var dl = aSubject.QueryInterface(Ci.nsIDownload);
switch (aTopic) {
case "dl-start":
do_check_eq(nsIDownloadManager.DOWNLOAD_DOWNLOADING, dl.state);
do_test_pending();
break;
case "dl-failed":
do_check_eq(nsIDownloadManager.DOWNLOAD_FAILED, dl.state);
do_test_finished();
break;
case "dl-cancel":
do_check_eq(nsIDownloadManager.DOWNLOAD_CANCELED, dl.state);
do_test_finished();
break;
case "dl-done":
dm.removeDownload(dl.id);
var stmt = dm.DBConnection.createStmt("SELECT COUNT(*) " +
"FROM moz_downloads " +
"WHERE id = ?1");
stmt.bindInt32Parameter(0, dl.id);
stmt.executeStep();
do_check_eq(0, stmt.getInt32(0));
stmt.reset();
do_check_eq(nsIDownloadManager.DOWNLOAD_FINISHED, dl.state);
do_test_finished();
break;
};
}
};
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.addObserver(observer, "dl-start", false);
os.addObserver(observer, "dl-failed", false);
os.addObserver(observer, "dl-cancel", false);
os.addObserver(observer, "dl-done", false);
for (var i = 0; i < tests.length; i++)
tests[i]();
cleanup();
var thread = Cc["@mozilla.org/thread-manager;1"]
.getService().currentThread;
while (!httpserv.isStopped())
thread.processNextEvent(true);
// get rid of any pending requests
while (thread.hasPendingEvents())
thread.processNextEvent(true);
}

View File

@ -0,0 +1,151 @@
/* ***** 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 Download Manager Test Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (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 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 ***** */
// This tests the migration code to make sure we properly migrate downloads.rdf
// Also tests cleanUp function of DM since we have a good number of entries to
// clean up after importing.
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var profileDir = null;
try {
profileDir = dirSvc.get("ProfD", Ci.nsIFile);
} catch (e) { }
if (!profileDir) {
// Register our own provider for the profile directory.
// It will simply return the current directory.
var provider = {
getFile: function(prop, persistent) {
persistent.value = true;
if (prop == "ProfD") {
return dirSvc.get("CurProcD", Ci.nsILocalFile);
} else if (prop == "DLoads") {
var file = dirSvc.get("CurProcD", Ci.nsILocalFile);
file.append("downloads.rdf");
return file;
}
throw Cr.NS_ERROR_FAILURE;
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIDirectoryProvider) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
}
function cleanup()
{
// removing rdf
var rdfFile = dirSvc.get("DLoads", Ci.nsIFile);
if (rdfFile.exists()) rdfFile.remove(true);
// removing database
var dbFile = dirSvc.get("ProfD", Ci.nsIFile);
dbFile.append("downloads.sqlite");
if (dbFile.exists()) dbFile.remove(true);
}
cleanup();
// bringing in the file we want to migrate
var file = do_get_file("toolkit/components/downloads/test/unit/downloads.rdf");
var newFile = dirSvc.get("ProfD", Ci.nsIFile);
file.copyTo(newFile, "downloads.rdf");
const nsIDownloadManager = Ci.nsIDownloadManager;
const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDownloadManager);
function test_count_entries()
{
var stmt = dm.DBConnection.createStatement("SELECT COUNT(*) " +
"FROM moz_downloads");
stmt.executeStep();
do_check_eq(7, stmt.getInt32(0));
stmt.reset();
}
function test_random_download()
{
var stmt = dm.DBConnection.createStatement("SELECT COUNT(*), source, target," +
" iconURL, state " +
"FROM moz_downloads " +
"WHERE name = ?1");
stmt.bindStringParameter(0, "Firefox 2.0.0.3.dmg");
stmt.executeStep();
do_check_eq(1, stmt.getInt32(0));
do_check_eq("http://ftp-mozilla.netscape.com/pub/mozilla.org/firefox/releases/2.0.0.3/mac/en-US/Firefox%202.0.0.3.dmg", stmt.getUTF8String(1));
do_check_eq("file:///Users/sdwilsh/Desktop/Firefox 2.0.0.3.dmg", stmt.getUTF8String(2));
do_check_eq("", stmt.getString(3));
do_check_eq(1, stmt.getInt32(4));
stmt.reset();
}
// This provides us with a lot of download entries to test the cleanup function
function test_dm_cleanup()
{
dm.cleanUp();
var stmt = dm.DBConnection.createStatement("SELECT COUNT(*) " +
"FROM moz_downloads");
stmt.executeStep();
do_check_eq(0, stmt.getInt32(0));
stmt.reset();
}
var tests = [test_count_entries, test_random_download, test_dm_cleanup];
function run_test()
{
for (var i = 0; i < tests.length; i++)
tests[i]();
cleanup();
}

View File

@ -64,11 +64,19 @@ DownloadProgressListener.prototype =
priorRate: 0,
lastUpdate: -500,
doc: null,
onDownloadStateChange: function dlPL_onDownloadStateChange(aState, aDownload)
{
var downloadID = "dl" + aDownload.id;
var download = this.doc.getElementById(downloadID);
if (download)
download.setAttribute("state", aDownload.state);
},
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload)
{
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
var aDownloadID = aDownload.targetFile.path;
var download = this.doc.getElementById(aDownloadID);
var downloadID = "dl" + aDownload.id;
var download = this.doc.getElementById(downloadID);
if (download)
download.setAttribute("status", "");
}
@ -90,8 +98,8 @@ DownloadProgressListener.prototype =
// Update this time.
this.lastUpdate = now;
var aDownloadID = aDownload.targetFile.path;
var download = this.doc.getElementById(aDownloadID);
var downloadID = "dl" + aDownload.id;
var download = this.doc.getElementById(downloadID);
// Calculate percentage.
var percent;

View File

@ -44,11 +44,18 @@
// Globals
const kObserverServiceProgID = "@mozilla.org/observer-service;1";
const NC_NS = "http://home.netscape.com/NC-rdf#";
const kDlmgrContractID = "@mozilla.org/download-manager;1";
const nsIDownloadManager = Components.interfaces.nsIDownloadManager;
const nsIXPInstallManagerUI = Components.interfaces.nsIXPInstallManagerUI;
const PREF_BDM_CLOSEWHENDONE = "browser.download.manager.closeWhenDone";
const PREF_BDM_ALERTONEXEOPEN = "browser.download.manager.alertOnEXEOpen";
const PREF_BDM_RETENTION = "browser.download.manager.retention";
var gDownloadManager = null;
const nsLocalFile = Components.Constructor("@mozilla.org/file/local;1",
"nsILocalFile", "initWithPath");
var gDownloadManager = Components.classes[kDlmgrContractID]
.getService(nsIDownloadManager);
var gDownloadListener = null;
var gDownloadsView = null;
var gUserInterfered = false;
@ -68,48 +75,6 @@ var gUserInteracted = false;
///////////////////////////////////////////////////////////////////////////////
// Utility Functions
function setRDFProperty(aID, aProperty, aValue)
{
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var db = gDownloadManager.datasource;
var propertyArc = rdf.GetResource(NC_NS + aProperty);
var res = rdf.GetResource(aID);
var node = db.GetTarget(res, propertyArc, true);
if (node)
db.Change(res, propertyArc, node, rdf.GetLiteral(aValue));
else
db.Assert(res, propertyArc, rdf.GetLiteral(aValue), true);
}
function getRDFProperty(aID, aProperty)
{
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var db = gDownloadManager.datasource;
var propertyArc = rdf.GetResource(NC_NS + aProperty);
var res = rdf.GetResource(aID);
var node = db.GetTarget(res, propertyArc, true);
if (!node) return "";
try {
node = node.QueryInterface(Components.interfaces.nsIRDFLiteral);
return node.Value;
}
catch (e) {
try {
node = node.QueryInterface(Components.interfaces.nsIRDFInt);
return node.Value;
}
catch (e) {
node = node.QueryInterface(Components.interfaces.nsIRDFResource);
return node.Value;
}
}
return "";
}
function fireEventForElement(aElement, aEventType)
{
var e = document.createEvent("Events");
@ -118,6 +83,28 @@ function fireEventForElement(aElement, aEventType)
aElement.dispatchEvent(e);
}
function createDownloadItem(aID, aFile, aImage, aTarget, aURI, aState,
aAnimated, aStatus, aProgress)
{
var dl = document.createElement("download");
dl.setAttribute("id", "dl" + aID);
dl.setAttribute("dlid", aID);
dl.setAttribute("image", aImage);
dl.setAttribute("file", aFile);
dl.setAttribute("target", aTarget);
dl.setAttribute("uri", aURI);
dl.setAttribute("state", aState);
dl.setAttribute("animated", aAnimated);
dl.setAttribute("status", aStatus);
dl.setAttribute("progress", aProgress);
return dl;
}
function getDownload(aID)
{
return document.getElementById("dl" + aID);
}
///////////////////////////////////////////////////////////////////////////////
// Start/Stop Observers
function downloadCompleted(aDownload)
@ -126,41 +113,21 @@ function downloadCompleted(aDownload)
// it doesn't really matter if it fails then since well.. we're shutting down
// and there's no UI to update!
try {
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var rdfc = Components.classes["@mozilla.org/rdf/container;1"].createInstance(Components.interfaces.nsIRDFContainer);
var db = gDownloadManager.datasource;
rdfc.Init(db, rdf.GetResource("NC:DownloadsRoot"));
var id = aDownload.targetFile.path;
// getTypeFromFile fails if it can't find a type for this file. Handle this gracefully.
try {
// Refresh the icon, so that executable icons are shown.
var mimeService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"].getService(Components.interfaces.nsIMIMEService);
var contentType = mimeService.getTypeFromFile(aDownload.targetFile);
var listItem = document.getElementById(id);
var listItem = getDownload(aDownload.id)
var oldImage = listItem.getAttribute("image");
// I tack on the content-type here as a hack to bypass the cache which seems
// to be interfering despite the fact the image has 'validate="always"' set
// on it.
listItem.setAttribute("image", oldImage + "&contentType=" + contentType);
} catch (e) {
}
} catch (e) { }
var dlRes = rdf.GetUnicodeResource(id);
var insertIndex = gDownloadManager.activeDownloadCount + 1;
// Don't bother inserting the item into the same place!
if (insertIndex != rdfc.IndexOf(dlRes)) {
rdfc.RemoveElement(dlRes, true);
if (insertIndex == rdfc.GetCount() || insertIndex < 1)
rdfc.AppendElement(dlRes);
else
rdfc.InsertElementAt(dlRes, insertIndex, true);
}
// Remove the download from our book-keeping list and if the count
// falls to zero, update the title here, since we won't be getting
@ -177,21 +144,33 @@ function downloadCompleted(aDownload)
if (gActiveDownloads.length == 0)
document.title = document.documentElement.getAttribute("statictitle");
}
catch (e) {
}
catch (e) { }
}
function autoClose(aDownload)
function autoRemoveAndClose(aDownload)
{
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var autoRemove = false;
try {
// this can throw, since it doesn't exist
autoRemove = pref.getBoolPref(PREF_BDM_RETENTION);
} catch (e) { }
if (dl && autoRemove) {
// The download manager backed removes this, but we have to update the UI!
var dl = getDownload(aDownload.id);
dl.parentNode.removeChild(dl);
}
if (gDownloadManager.activeDownloadCount == 0) {
// For the moment, just use the simple heuristic that if this window was
// opened by the download process, rather than by the user, it should auto-close
// if the pref is set that way. If the user opened it themselves, it should
// not close until they explicitly close it.
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var autoClose = pref.getBoolPref(PREF_BDM_CLOSEWHENDONE)
if (autoClose && (!window.opener || window.opener.location.href == window.location.href) &&
var autoClose = pref.getBoolPref(PREF_BDM_CLOSEWHENDONE);
if (autoClose && (!window.opener ||
window.opener.location.href == window.location.href) &&
gCanAutoClose && !gUserInteracted)
gCloseDownloadManager();
}
@ -209,10 +188,12 @@ var gDownloadObserver = {
{
switch (aTopic) {
case "dl-done":
gDownloadViewController.onCommandUpdate();
var dl = aSubject.QueryInterface(Components.interfaces.nsIDownload);
downloadCompleted(dl);
autoClose(dl);
autoRemoveAndClose(dl);
break;
case "dl-failed":
case "dl-cancel":
@ -220,14 +201,22 @@ var gDownloadObserver = {
downloadCompleted(dl);
break;
case "dl-start":
// whenever a new download starts, it is added to the top, so switch the
// view to it
gDownloadsView.selectedIndex = 0;
// Add this download to the percentage average tally
var dl = aSubject.QueryInterface(Components.interfaces.nsIDownload);
gActiveDownloads.push(dl);
// Adding to the UI
var uri = Components.classes["@mozilla.org/network/util;1"]
.getService(Components.interfaces.nsIIOService)
.newFileURI(dl.targetFile);
var img = "moz-icon://" + uri.spec + "?size=32";
var itm = createDownloadItem(dl.id, uri.spec, img, dl.displayName,
dl.source.spec, dl.state, "",
dl.percentComplete);
gDownloadsView.insertBefore(itm, gDownloadsView.firstChild);
// switch view to it
gDownloadsView.selectedIndex = 0;
break;
case "xpinstall-download-started":
var windowArgs = aSubject.QueryInterface(Components.interfaces.nsISupportsArray);
@ -241,7 +230,7 @@ var gDownloadObserver = {
if ("gDownloadManager" in window) {
var mgr = gDownloadManager.QueryInterface(Components.interfaces.nsIXPInstallManagerUI);
gCanAutoClose = mgr.hasActiveXPIOperations;
autoClose();
autoRemoveAndClose();
}
break;
}
@ -255,9 +244,7 @@ function onDownloadCancel(aEvent)
{
var selectedIndex = gDownloadsView.selectedIndex;
gDownloadManager.cancelDownload(aEvent.target.id);
setRDFProperty(aEvent.target.id, "DownloadAnimated", "false");
gDownloadManager.cancelDownload(aEvent.target.getAttribute("dlid"));
// XXXben -
// If we got here because we resumed the download, we weren't using a temp file
@ -265,7 +252,7 @@ function onDownloadCancel(aEvent)
// employed by the helper app service isn't fully accessible yet... should be fixed...
// talk to bz...)
// the upshot is we have to delete the file if it exists.
var f = getLocalFileFromNativePathOrUrl(aEvent.target.id);
var f = getLocalFileFromNativePathOrUrl(aEvent.target.getAttribute("file"));
if (f.exists())
f.remove(false);
@ -285,10 +272,8 @@ function onDownloadPause(aEvent)
{
var selectedIndex = gDownloadsView.selectedIndex;
var uri = aEvent.target.id;
gDownloadManager.pauseDownload(uri);
setRDFProperty(uri, "DownloadStatus", aEvent.target.getAttribute("status-internal"));
setRDFProperty(uri, "ProgressPercent", aEvent.target.getAttribute("progress"));
var id = aEvent.target.getAttribute("dlid");
gDownloadManager.pauseDownload(id);
// now reset the richlistbox
gDownloadsView.clearSelection();
@ -303,7 +288,7 @@ function onDownloadResume(aEvent)
{
var selectedIndex = gDownloadsView.selectedIndex;
gDownloadManager.resumeDownload(aEvent.target.id);
gDownloadManager.resumeDownload(aEvent.target.getAttribute("dlid"));
// now reset the richlistbox
gDownloadsView.clearSelection();
@ -318,14 +303,15 @@ function onDownloadRemove(aEvent)
{
if (aEvent.target.removable) {
var selectedIndex = gDownloadsView.selectedIndex;
gDownloadManager.removeDownload(aEvent.target.id);
gDownloadManager.removeDownload(aEvent.target.getAttribute("dlid"));
aEvent.target.parentNode.removeChild(aEvent.target);
gDownloadViewController.onCommandUpdate();
}
}
function onDownloadShow(aEvent)
{
var f = getLocalFileFromNativePathOrUrl(aEvent.target.id);
var f = getLocalFileFromNativePathOrUrl(aEvent.target.getAttribute("file"));
if (f.exists()) {
try {
@ -361,12 +347,12 @@ function onDownloadOpen(aEvent)
var download = aEvent.target;
if (download.localName == "download") {
if (download.openable) {
var f = getLocalFileFromNativePathOrUrl(aEvent.target.id);
var f = getLocalFileFromNativePathOrUrl(aEvent.target.getAttribute("file"));
if (f.exists()) {
if (f.isExecutable()) {
var dontAsk = false;
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
.getService(Components.interfaces.nsIPrefBranch);
try {
dontAsk = !pref.getBoolPref(PREF_BDM_ALERTONEXEOPEN);
}
@ -433,16 +419,14 @@ function onDownloadProperties(aEvent)
function onDownloadAnimated(aEvent)
{
gDownloadViewController.onCommandUpdate();
setRDFProperty(aEvent.target.id, "DownloadAnimated", "true");
}
function onDownloadRetry(aEvent)
{
var download = aEvent.target;
if (download.localName == "download") {
var src = getRDFProperty(download.id, "URL");
var f = getLocalFileFromNativePathOrUrl(aEvent.target.id);
var src = document.getElementById(download.id).getAttribute("uri");
var f = getLocalFileFromNativePathOrUrl(aEvent.target.getAttribute("file"));
saveURL(src, f, null, true, true);
}
@ -471,6 +455,9 @@ function onUpdateProgress()
for (var i = 0; i < numActiveDownloads; ++i) {
dl = gActiveDownloads[i];
// Update progress
getDownload(dl.id).setAttribute("progress", dl.percentComplete);
// gActiveDownloads is screwed so it's possible
// to have more files than we're really downloading.
// The good news is that those files have size==0.
@ -511,10 +498,20 @@ function Startup()
{
gDownloadsView = document.getElementById("downloadView");
const dlmgrContractID = "@mozilla.org/download-manager;1";
const dlmgrIID = Components.interfaces.nsIDownloadManager;
gDownloadManager = Components.classes[dlmgrContractID].getService(dlmgrIID);
var db = gDownloadManager.DBConnection;
var stmt = db.createStatement("SELECT id, target, iconURL, name, source," +
"state " +
"FROM moz_downloads " +
"ORDER BY startTime DESC");
while (stmt.executeStep()) {
var i = stmt.getString(2) == "" ?
"moz-icon://" + stmt.getString(1) + "?size=32" : stmt.getString(2);
var dl = createDownloadItem(stmt.getInt64(0), stmt.getString(1), i,
stmt.getString(3), stmt.getString(4),
stmt.getInt32(5), "", "", "100");
gDownloadsView.appendChild(dl);
}
// The DownloadProgressListener (DownloadProgressListener.js) handles progress
// notifications.
var downloadStrings = document.getElementById("downloadStrings");
@ -524,9 +521,10 @@ function Startup()
// The active downloads list is created by the front end only when the download starts,
// so we need to pre-populate it with any downloads that were already going.
var activeDownloads = gDownloadManager.activeDownloads;
var count = activeDownloads.Count();
for (var i = 0; i < count; ++i)
gActiveDownloads.push(activeDownloads.QueryElementAt(i, Components.interfaces.nsIDownload));
while (activeDownloads.hasMoreElements()) {
var download = activeDownloads.getNext().QueryInterface(Ci.nsIDownload);
gActiveDownloads.push(download);
}
// Handlers for events generated by the UI (downloads, list view)
gDownloadsView.addEventListener("download-cancel", onDownloadCancel, false);
@ -572,21 +570,14 @@ function Startup()
// non-active downloads before it can be enabled.
gDownloadsView.controllers.appendController(gDownloadViewController);
// Finally, update the UI.
gDownloadsView.database.AddDataSource(gDownloadManager.datasource);
gDownloadsView.builder.rebuild();
// downloads can finish before Startup() does, so check if the window should close
autoClose();
autoRemoveAndClose();
}
function Shutdown()
{
gDownloadManager.listener = null;
// Assert the current progress for all the downloads in case the window is reopened
gDownloadManager.saveState();
var pbi = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
pbi.removeObserver("browser.download.", gDownloadPrefObserver);
@ -746,6 +737,20 @@ var gDownloadViewController = {
{
if (aCommand == "cmd_cleanUp" && this.isCommandEnabled(aCommand)) {
gDownloadManager.cleanUp();
// Update UI
for (var i = gDownloadsView.children.length - 1; i >= 0; --i) {
var elm = gDownloadsView.children[i];
var state = elm.getAttribute("state");
if (state != nsIDownloadManager.DOWNLOAD_NOTSTARTED &&
state != nsIDownloadManager.DOWNLOAD_DOWNLOADING &&
state != nsIDownloadManager.DOWNLOAD_PAUSED &&
state != nsIXPInstallManagerUI.INSTALL_DOWNLOADING &&
state != nsIXPInstallManagerUI.INSTALL_INSTALLING)
gDownloadsView.removeChild(gDownloadsView.children[i]);
}
this.onCommandUpdate();
}
},
@ -802,7 +807,7 @@ function initAutoDownloadDisplay()
var dir = fileLocator.get(getSpecialFolderKey(aFolder), Components.interfaces.nsILocalFile);
var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
.getService(Components.interfaces.nsIStringBundleService);
bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
var description = bundle.GetStringFromName("myDownloads");
@ -912,9 +917,7 @@ function getLocalFileFromNativePathOrUrl(aPathOrUrl)
} else {
// if it's a pathname, create the nsILocalFile directly
var f = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
f.initWithPath(aPathOrUrl);
var f = new nsLocalFile(aPathOrUrl);
return f;
}

View File

@ -63,11 +63,11 @@
onload="Startup();" onunload="Shutdown();"
onclose="return closeWindow(false);">
<script type="application/x-javascript" src="chrome://mozapps/content/downloads/DownloadProgressListener.js"/>
<script type="application/x-javascript" src="chrome://mozapps/content/downloads/downloads.js"/>
<script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://mozapps/content/downloads/DownloadProgressListener.js"/>
<script type="application/javascript" src="chrome://mozapps/content/downloads/downloads.js"/>
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://global/content/nsDragAndDrop.js"/>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<stringbundleset id="downloadSet">
<stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
@ -136,45 +136,8 @@
<popup id="downloadContextMenu" onpopupshowing="return buildContextMenu(event);"/>
<richlistbox id="downloadView" flex="1" context="downloadContextMenu"
datasources="rdf:null" ref="NC:DownloadsRoot"
ondragover="nsDragAndDrop.dragOver(event, gDownloadDNDObserver);"
ondragdrop="nsDragAndDrop.drop(event, gDownloadDNDObserver);">
<template>
<rule>
<conditions>
<content uri="?uri"/>
<member container="?uri" child="?download"/>
<triple subject="?download"
predicate="http://home.netscape.com/NC-rdf#File"
object="?file"/>
<triple subject="?download"
predicate="http://home.netscape.com/NC-rdf#Name"
object="?target"/>
<triple subject="?download"
predicate="http://home.netscape.com/NC-rdf#DownloadState"
object="?state"/>
</conditions>
<bindings>
<binding subject="?download"
predicate="http://home.netscape.com/NC-rdf#DownloadAnimated"
object="?animated"/>
<binding subject="?download"
predicate="http://home.netscape.com/NC-rdf#DownloadStatus"
object="?status"/>
<binding subject="?download"
predicate="http://home.netscape.com/NC-rdf#ProgressPercent"
object="?progress-percent"/>
<binding subject="?download"
predicate="http://home.netscape.com/NC-rdf#IconURL"
object="?icon"/>
</bindings>
<action>
<download uri="?download"
image="?icon" file="?file" target="?target" state="?state"
animated="?animated" status="?status" progress="?progress-percent"/>
</action>
</rule>
</template>
</richlistbox>
<hbox>

View File

@ -45,7 +45,7 @@ interface nsICancelable;
interface nsIWebProgressListener;
interface nsIMIMEInfo;
[scriptable, uuid(07910093-d70b-4621-9888-b811f42293c3)]
[scriptable, uuid(974db2c6-fbd2-4de1-8d24-f54ce4f3e8bc)]
interface nsIDownload : nsITransfer {
/**
@ -89,7 +89,7 @@ interface nsIDownload : nsITransfer {
/**
* The user-readable description of the transfer.
*/
readonly attribute wstring displayName;
readonly attribute AString displayName;
/**
* The time a transfer was started.
@ -107,6 +107,17 @@ interface nsIDownload : nsITransfer {
* executed.
*/
readonly attribute nsIMIMEInfo MIMEInfo;
/**
* The id of the download that is stored in the database.
*/
readonly attribute unsigned long id;
/**
* The state of the download.
* @see nsIDownloadManager and nsIXPInstallManagerUI
*/
readonly attribute short state;
};
%{C++

View File

@ -1367,9 +1367,9 @@ nsDownload::Init(nsIURI* aSource,
}
NS_IMETHODIMP
nsDownload::GetDisplayName(PRUnichar** aDisplayName)
nsDownload::GetDisplayName(nsAString &aDisplayName)
{
*aDisplayName = ToNewUnicode(mDisplayName);
*aDisplayName = mDisplayName;
return NS_OK;
}
@ -1455,6 +1455,19 @@ nsDownload::GetSpeed(double* aSpeed)
return NS_OK;
}
NS_IMETHODIMP
nsDownload::GetId(PRUint64 *aId)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDownload::GetState(PRInt16 *aState)
{
*aState = mDownloadState;
return NS_OK;
}
nsresult
nsDownload::SetTempFile(nsILocalFile* aTempFile)
{