Download manager. Not part of build.

git-svn-id: svn://10.0.0.236/trunk@114979 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
blakeross%telocity.com 2002-02-20 00:11:23 +00:00
parent f446513d7d
commit 475b54447d

View File

@ -14,17 +14,16 @@
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* 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 <blakeross@telocity.com>
* Ben Goodger <ben@netscape.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
* 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
@ -36,17 +35,23 @@
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDownloadManager.h"
#include "prprf.h"
#include "nsIServiceManager.h"
#include "nsIWebProgress.h"
#include "nsIStringBundle.h"
#include "nsIRDFLiteral.h"
#include "nsIRDFXMLSerializer.h"
#include "nsIContent.h"
#include "nsIRDFXMLSource.h"
#include "rdf.h"
#include "nsNetUtil.h"
#include "nsMemory.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMXULElement.h"
#include "prtime.h"
#include "nsRDFCID.h"
#include "nsCRT.h"
#include "nsString.h"
@ -54,53 +59,61 @@
#include "nsFileSpec.h"
#include "nsFileStream.h"
/* Outstanding issues/todo:
* 1. Client should be able to set cancel callback so users can cancel downloads from manager FE.
* 2. InitializeUI/UnitializeUI is lame...would like to keep manager separate from FE as
much as possible. The document arg is also lame but the listener needs it to update the UI.
* 3. Error handling? Holding off on this until law is done with his changes.
* 4. NotifyDownloadEnded should not be on nsIDownloadManager
*/
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
#define PROFILE_DOWNLOAD_FILE "downloads.rdf"
#define NSDOWNLOADMANAGER_PROPERTIES_URI "chrome://communicator/locale/downloadmanager/downloadmanager.properties"
nsIRDFResource* gNC_DownloadsRoot;
nsIRDFResource* gNC_File;
nsIRDFResource* gNC_URL;
nsIRDFResource* gNC_Name;
nsIRDFResource* gNC_Progress;
nsIRDFResource* gNC_ProgressPercent;
nsIRDFService* gRDFService;
static PRBool gMustUpdateUI = PR_FALSE;
NS_IMPL_ISUPPORTS3(nsDownloadManager, nsIDownloadManager, nsIRDFDataSource, nsIRDFRemoteDataSource)
nsDownloadManager::nsDownloadManager() : mDownloadItems(nsnull)
nsDownloadManager::nsDownloadManager() : mCurrDownloadItems(nsnull)
{
NS_INIT_ISUPPORTS();
NS_INIT_REFCNT();
}
nsDownloadManager::~nsDownloadManager()
{
// write datasource to disk on shutdown
Flush();
gRDFService->UnregisterDataSource(this);
NS_IF_RELEASE(gNC_DownloadsRoot);
NS_IF_RELEASE(gNC_File);
NS_IF_RELEASE(gNC_URL);
NS_IF_RELEASE(gNC_Name);
NS_IF_RELEASE(gNC_Progress);
NS_IF_RELEASE(gNC_ProgressPercent);
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
gRDFService = nsnull;
delete mDownloadItems;
mDownloadItems = nsnull;
delete mCurrDownloadItems;
mCurrDownloadItems = nsnull;
}
nsresult
nsDownloadManager::Init()
{
nsresult rv;
rv = nsServiceManager::GetService(kRDFServiceCID, NS_GET_IID(nsIRDFService),
(nsISupports**) &gRDFService);
nsresult rv = nsServiceManager::GetService(kRDFServiceCID, NS_GET_IID(nsIRDFService),
(nsISupports**) &gRDFService);
if (NS_FAILED(rv)) return rv;
mRDFContainerUtils = do_GetService("@mozilla.org/rdf/container-utils;1", &rv);
@ -110,116 +123,242 @@ nsDownloadManager::Init()
gRDFService->GetResource(NC_NAMESPACE_URI "File", &gNC_File);
gRDFService->GetResource(NC_NAMESPACE_URI "URL", &gNC_URL);
gRDFService->GetResource(NC_NAMESPACE_URI "Name", &gNC_Name);
gRDFService->GetResource(NC_NAMESPACE_URI "Progress", &gNC_Progress);
gRDFService->GetResource(NC_NAMESPACE_URI "ProgressPercent", &gNC_ProgressPercent);
#if 0
mInner = do_GetService(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "in-memory-datasource", &rv);
if (NS_FAILED(rv)) return rv;
#else
mInner = do_GetService(kRDFXMLDataSourceCID, &rv);
if (NS_FAILED(rv)) return rv;
// This should move elsewhere
nsXPIDLCString downloadsDB;
GetProfileDownloadsFileURL(getter_Copies(downloadsDB));
rv = GetProfileDownloadsFileURL(getter_Copies(downloadsDB));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(mInner));
rv = remote->Init(downloadsDB);
if (NS_FAILED(rv)) return rv;
rv = remote->Refresh(PR_TRUE);
if (NS_FAILED(rv)) return rv;
#endif
return gRDFService->RegisterDataSource(this, PR_FALSE);
}
return gRDFService->RegisterDataSource(this, PR_FALSE);
}
NS_IMETHODIMP
nsDownloadManager::GetURI(char** aURI)
{
if (!aURI)
return NS_ERROR_NULL_POINTER;
*aURI = nsCRT::strdup("rdf:downloads");
if (!(*aURI))
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::AddItem(const PRUnichar* aDisplayName, nsIURI* aSourceURI,
nsILocalFile* aLocalFile, const char* aParentID, nsIWebProgress* aProgress)
nsDownloadManager::AddItem(nsIDownloadItem* aDownloadItem)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aDownloadItem);
nsCOMPtr<nsIRDFContainer> downloads;
GetDownloadsContainer(getter_AddRefs(downloads));
nsresult rv = GetDownloadsContainer(getter_AddRefs(downloads));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString filePath;
aLocalFile->GetPath(getter_Copies(filePath));
nsCOMPtr<nsILocalFile> target;
aDownloadItem->GetTarget(getter_AddRefs(target));
if (!target) return NS_ERROR_FAILURE;
target->GetPath(getter_Copies(filePath));
nsCOMPtr<nsIRDFResource> downloadItem;
gRDFService->GetResource(filePath, getter_AddRefs(downloadItem));
// if the resource is in the container already (the user has already
// downloaded this file), remove it
PRInt32 itemIndex;
downloads->IndexOf(downloadItem, &itemIndex);
if (itemIndex > 0) {
nsCOMPtr<nsIRDFNode> node;
downloads->RemoveElementAt(itemIndex, PR_TRUE, getter_AddRefs(node));
}
downloads->AppendElement(downloadItem);
// NC:Name
nsAutoString displayName; displayName.Assign(aDisplayName);
nsXPIDLString prettyName;
aDownloadItem->GetPrettyName(getter_Copies(prettyName));
nsAutoString displayName; displayName.Assign(prettyName);
// NC:Name
if (displayName.IsEmpty()) {
nsXPIDLString unicodeDisplayName;
aLocalFile->GetUnicodeLeafName(getter_Copies(unicodeDisplayName));
displayName.Assign(unicodeDisplayName);
target->GetUnicodeLeafName(getter_Copies(prettyName));
displayName.Assign(prettyName);
}
nsCOMPtr<nsIRDFLiteral> nameLiteral;
gRDFService->GetLiteral(displayName.get(), getter_AddRefs(nameLiteral));
Assert(downloadItem, gNC_Name, nameLiteral, PR_TRUE);
rv = Assert(downloadItem, gNC_Name, nameLiteral, PR_TRUE);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> source;
aDownloadItem->GetSource(getter_AddRefs(source));
// NC:URL
nsXPIDLCString spec;
aSourceURI->GetSpec(getter_Copies(spec));
source->GetSpec(getter_Copies(spec));
nsCOMPtr<nsIDownloadProgressListener> listener(do_CreateInstance("@mozilla.org/download-manager/listener;1", &rv));
if (NS_FAILED(rv)) return rv;
aDownloadItem->SetInternalListener(listener);
if (gMustUpdateUI) {
listener->SetDocument(mDocument);
listener->SetDownloadItem(aDownloadItem);
}
nsCOMPtr<nsIRDFResource> urlResource;
gRDFService->GetResource(spec, getter_AddRefs(urlResource));
Assert(downloadItem, gNC_URL, urlResource, PR_TRUE);
rv = Assert(downloadItem, gNC_URL, urlResource, PR_TRUE);
if (NS_FAILED(rv)) return rv;
// NC:File
nsCOMPtr<nsIRDFResource> fileResource;
gRDFService->GetResource(filePath, getter_AddRefs(fileResource));
Assert(downloadItem, gNC_File, fileResource, PR_TRUE);
rv = Assert(downloadItem, gNC_File, fileResource, PR_TRUE);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(mInner));
rv = remote->Flush();
if (NS_FAILED(rv)) return rv;
DownloadItem* item = new DownloadItem();
if (!item) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(item);
if (!mCurrDownloadItems)
mCurrDownloadItems = new nsHashtable();
if (!mDownloadItems)
mDownloadItems = new nsHashtable();
nsCStringKey key(filePath);
if (mDownloadItems->Exists(&key)) {
DownloadItem* download = (DownloadItem*)mDownloadItems->Get(&key);
if (mCurrDownloadItems->Exists(&key)) {
DownloadItem* download = NS_STATIC_CAST(DownloadItem*, mCurrDownloadItems->Get(&key));
if (download)
delete download;
}
mDownloadItems->Put(&key, item);
mCurrDownloadItems->Put(&key, aDownloadItem);
return rv;
}
rv = item->Init(downloadItem, this, aSourceURI, nsnull, aLocalFile);
NS_IMETHODIMP
nsDownloadManager::GetItem(const char* aID, nsIDownloadItem** aDownloadItem)
{
// if it's currently downloading we can get it from the table
// XXX otherwise we need to look for it in the datasource and
// create a new nsIDownloadItem with the resource's properties
nsCStringKey key(aID);
if (mCurrDownloadItems->Exists(&key)) {
*aDownloadItem = NS_STATIC_CAST(nsIDownloadItem*, mCurrDownloadItems->Get(&key));
NS_ADDREF(*aDownloadItem);
}
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::InitializeUI(nsIDOMXULDocument* aDocument)
{
mDocument = aDocument;
gMustUpdateUI = PR_TRUE;
// get the downloads container
nsCOMPtr<nsIRDFContainer> downloads;
nsresult rv = GetDownloadsContainer(getter_AddRefs(downloads));
if (NS_FAILED(rv)) return rv;
return rv;
// get the container's elements (nsIRDFResource's)
nsCOMPtr<nsISimpleEnumerator> items;
rv = downloads->GetElements(getter_AddRefs(items));
if (NS_FAILED(rv)) return rv;
if (!mCurrDownloadItems)
mCurrDownloadItems = new nsHashtable();
nsCOMPtr<nsISupports> supports;
nsCOMPtr<nsIRDFResource> res;
nsCOMPtr<nsIRDFInt> percent;
nsCOMPtr<nsIDownloadProgressListener> listener;
nsCOMPtr<nsIRDFNode> oldTarget;
char* id;
PRInt32 percentComplete;
// enumerate the resources, use their ids to retrieve the corresponding
// nsIDownloadItems from the hashtable (if they don't exist, the download isn't
// a current transfer), get the items' progress information,
// and assert it into the graph so we can show it in the UI
PRBool moreElements;
items->HasMoreElements(&moreElements);
for( ; moreElements; items->HasMoreElements(&moreElements)) {
items->GetNext(getter_AddRefs(supports));
res = do_QueryInterface(supports);
res->GetValue(&id);
nsCStringKey key(id);
if (mCurrDownloadItems->Exists(&key)) {
nsIDownloadItem* item = NS_STATIC_CAST(nsIDownloadItem*, mCurrDownloadItems->Get(&key));
if (!item) continue; // must be a finished download; don't need to update ui
// update percentage
item->GetPercentComplete(&percentComplete);
rv = GetTarget(res, gNC_ProgressPercent, PR_TRUE, getter_AddRefs(oldTarget));
if (NS_FAILED(rv)) continue;
rv = gRDFService->GetIntLiteral(percentComplete, getter_AddRefs(percent));
if (NS_FAILED(rv)) continue;
if (oldTarget)
rv = Change(res, gNC_ProgressPercent, oldTarget, percent);
else
rv = Assert(res, gNC_ProgressPercent, percent, PR_TRUE);
if (NS_FAILED(rv)) continue;
item->GetInternalListener(getter_AddRefs(listener));
if (listener) {
listener->SetDocument(aDocument);
listener->SetDownloadItem(item);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::UninitializeUI()
{
gMustUpdateUI = PR_FALSE;
mDocument = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::NotifyDownloadEnded(const char* aTargetPath)
{
nsCStringKey key(aTargetPath);
if (mCurrDownloadItems->Exists(&key))
mCurrDownloadItems->Remove(&key);
return NS_OK;
}
nsresult
nsDownloadManager::GetProfileDownloadsFileURL(char** aDownloadsFileURL)
{
nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
nsCOMPtr<nsIFile> profileDir;
// get the profile directory
nsresult rv = fileLocator->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(profileDir));
if (NS_FAILED(rv)) return rv;
// add downloads.rdf to the path
rv = profileDir->Append(PROFILE_DOWNLOAD_FILE);
if (NS_FAILED(rv)) return rv;
return NS_GetURLSpecFromFile(profileDir, aDownloadsFileURL);
}
nsresult
@ -246,183 +385,171 @@ nsDownloadManager::GetDownloadsContainer(nsIRDFContainer** aResult)
rv = ctr->Init(mInner, gNC_DownloadsRoot);
if (NS_FAILED(rv)) return rv;
}
*aResult = ctr;
NS_IF_ADDREF(*aResult);
return rv;
}
NS_IMETHODIMP
///////////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource
NS_IMETHODIMP
nsDownloadManager::GetSource(nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue,
nsIRDFResource** aSource)
nsIRDFResource** aSource)
{
return mInner->GetSource(aProperty, aTarget, aTruthValue, aSource);
}
NS_IMETHODIMP nsDownloadManager::GetSources(nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue,
nsISimpleEnumerator** aSources) {
return mInner->GetSources(aProperty, aTarget, aTruthValue, aSources);
}
NS_IMETHODIMP nsDownloadManager::GetTarget(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
PRBool aTruthValue,
nsIRDFNode** aTarget) {
return mInner->GetTarget(aSource, aProperty, aTruthValue, aTarget);
}
NS_IMETHODIMP nsDownloadManager::GetTargets(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
PRBool aTruthValue,
nsISimpleEnumerator** aTargets) {
return mInner->GetTargets(aSource, aProperty, aTruthValue, aTargets);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::Assert(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue)
PRBool aTruthValue)
{
return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::Unassert(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget)
nsIRDFNode* aTarget)
{
return mInner->Unassert(aSource, aProperty, aTarget);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::Change(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aOldTarget,
nsIRDFNode* aNewTarget)
nsIRDFNode* aNewTarget)
{
return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::Move(nsIRDFResource* aOldSource,
nsIRDFResource* aNewSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget)
nsIRDFNode* aTarget)
{
return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::HasAssertion(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue,
PRBool* hasAssertion)
PRBool* hasAssertion)
{
return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, hasAssertion);
}
NS_IMETHODIMP
nsDownloadManager::AddObserver(nsIRDFObserver* aObserver)
NS_IMETHODIMP
nsDownloadManager::AddObserver(nsIRDFObserver* aObserver)
{
return mInner->AddObserver(aObserver);
}
NS_IMETHODIMP
nsDownloadManager::RemoveObserver(nsIRDFObserver* aObserver)
NS_IMETHODIMP
nsDownloadManager::RemoveObserver(nsIRDFObserver* aObserver)
{
return mInner->RemoveObserver(aObserver);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::HasArcIn(nsIRDFNode* aNode,
nsIRDFResource* aArc, PRBool* _retval)
nsIRDFResource* aArc, PRBool* _retval)
{
return mInner->HasArcIn(aNode, aArc, _retval);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::HasArcOut(nsIRDFResource* aSource,
nsIRDFResource* aArc, PRBool* _retval)
nsIRDFResource* aArc, PRBool* _retval)
{
return mInner->HasArcOut(aSource, aArc, _retval);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::ArcLabelsIn(nsIRDFNode* aNode,
nsISimpleEnumerator** aLabels)
nsISimpleEnumerator** aLabels)
{
return mInner->ArcLabelsIn(aNode, aLabels);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::ArcLabelsOut(nsIRDFResource* aSource,
nsISimpleEnumerator** aLabels)
nsISimpleEnumerator** aLabels)
{
return mInner->ArcLabelsIn(aSource, aLabels);
}
NS_IMETHODIMP
nsDownloadManager::GetAllResources(nsISimpleEnumerator** aResult)
NS_IMETHODIMP
nsDownloadManager::GetAllResources(nsISimpleEnumerator** aResult)
{
return mInner->GetAllResources(aResult);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::GetAllCommands(nsIRDFResource* aSource,
nsIEnumerator** aCommands)
nsIEnumerator** aCommands)
{
return mInner->GetAllCommands(aSource, aCommands);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::GetAllCmds(nsIRDFResource* aSource,
nsISimpleEnumerator** aCommands)
nsISimpleEnumerator** aCommands)
{
return mInner->GetAllCmds(aSource, aCommands);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::IsCommandEnabled(nsISupportsArray* aSources,
nsIRDFResource* aCommand,
nsISupportsArray* aArguments,
PRBool* aResult)
PRBool* aResult)
{
return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDownloadManager::DoCommand(nsISupportsArray* aSources,
nsIRDFResource* aCommand,
nsISupportsArray* aArguments)
nsISupportsArray* aArguments)
{
return mInner->DoCommand(aSources, aCommand, aArguments);
}
nsresult
nsDownloadManager::GetProfileDownloadsFileURL(char** aDownloadsFileURL)
{
nsresult rv;
nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
nsCOMPtr<nsIFile> profileDir;
rv = fileLocator->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(profileDir));
if (NS_FAILED(rv)) return rv;
rv = profileDir->Append(PROFILE_DOWNLOAD_FILE);
if (NS_FAILED(rv)) return rv;
return profileDir->GetURL(aDownloadsFileURL);
}
///////////////////////////////////////////////////////////////////////////////
// nsIRDFRemoteDataSource
NS_IMETHODIMP
nsDownloadManager::GetLoaded(PRBool* aResult)
{
@ -451,9 +578,21 @@ nsDownloadManager::Flush()
}
///////////////////////////////////////////////////////////////////////////////
//
DownloadItem::DownloadItem()
// DownloadItem
DownloadItem::DownloadItem()
{
NS_INIT_ISUPPORTS();
NS_INIT_REFCNT();
}
// for convenience
DownloadItem::DownloadItem(const PRUnichar* aPrettyName, nsILocalFile* aTarget, nsIURI* aSource)
:mPrettyName(aPrettyName), mTarget(aTarget), mSource(aSource)
{
NS_INIT_ISUPPORTS();
NS_INIT_REFCNT();
}
DownloadItem::~DownloadItem()
@ -464,107 +603,93 @@ DownloadItem::~DownloadItem()
nsresult
DownloadItem::UpdateProgressInfo()
{
nsresult rv;
nsCOMPtr<nsIRDFDataSource> ds;
nsCOMPtr<nsIStringBundleService> sbs(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
nsresult rv = gRDFService->GetDataSource("rdf:downloads", getter_AddRefs(ds));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStringBundle> bundle;
rv = sbs->CreateBundle(NSDOWNLOADMANAGER_PROPERTIES_URI, getter_AddRefs(bundle));
nsCOMPtr<nsIRDFNode> oldTarget;
rv = ds->GetTarget(mDownloadItem, gNC_ProgressPercent, PR_TRUE, getter_AddRefs(oldTarget));
if (NS_FAILED(rv)) return rv;
nsAutoString key(NS_LITERAL_STRING("progressFormat"));
nsAutoString curTotalProgressStr; curTotalProgressStr.AppendInt(mCurTotalProgress);
nsAutoString maxTotalProgressStr; maxTotalProgressStr.AppendInt(mMaxTotalProgress);
const PRUnichar* formatStrings[2] = { curTotalProgressStr.get(), maxTotalProgressStr.get() };
nsXPIDLString progressString;
rv = bundle->FormatStringFromName(key.get(), formatStrings, 2, getter_Copies(progressString));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFLiteral> progressLiteral;
rv = gRDFService->GetLiteral(progressString, getter_AddRefs(progressLiteral));
if (NS_FAILED(rv)) return rv;
rv = mDataSource->Assert(mDownloadItem, gNC_Progress, progressLiteral, PR_TRUE);
if (NS_FAILED(rv)) return rv;
// Store Unformatted Elapsed Time
return rv;
}
nsresult
DownloadItem::Init(nsIRDFResource* aDownloadItem,
nsIRDFDataSource* aDataSource,
nsIURI* aURI, nsIInputStream* aPostData, nsILocalFile* aFile)
{
mDownloadItem = aDownloadItem;
mDataSource = aDataSource;
nsresult rv;
mWebBrowserPersist = do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv);
if (NS_FAILED(rv)) return rv;
// XXX using RDF here could really kill perf. Need to investigate timing.
// RDF is probably not worthwhile if we're only looking at a single
// view
nsCOMPtr<nsIWebProgressListener> listener(do_QueryInterface(this));
rv = mWebBrowserPersist->SetProgressListener(listener);
if (NS_FAILED(rv)) return rv;
rv = mWebBrowserPersist->SaveURI(aURI, aPostData, aFile);
nsCOMPtr<nsIRDFInt> percent;
rv = gRDFService->GetIntLiteral(mPercentComplete, getter_AddRefs(percent));
if (NS_FAILED(rv)) return rv;
if (oldTarget)
rv = ds->Change(mDownloadItem, gNC_ProgressPercent, oldTarget, percent);
else
rv = ds->Assert(mDownloadItem, gNC_ProgressPercent, percent, PR_TRUE);
// XXX Store elapsed time here eventually
return rv;
}
NS_IMPL_ISUPPORTS2(DownloadItem, nsIWebProgressListener, nsIDownloadItem)
///////////////////////////////////////////////////////////////////////////////
// nsIWebProgressListener
NS_IMPL_ISUPPORTS1(DownloadItem, nsIWebProgressListener)
NS_IMETHODIMP
DownloadItem::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress,
NS_IMETHODIMP
DownloadItem::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress,
PRInt32 aMaxTotalProgress)
{
if (mCurTotalProgress != aCurTotalProgress) {
mCurTotalProgress = aCurTotalProgress;
mMaxTotalProgress = aMaxTotalProgress;
mPercentComplete = aCurTotalProgress * 100 / aMaxTotalProgress;
PRInt32 percent = (PRInt32)(mCurTotalProgress / mMaxTotalProgress) * 100;
nsCOMPtr<nsIRDFInt> percentInt;
gRDFService->GetIntLiteral(percent, getter_AddRefs(percentInt));
mDataSource->Assert(mDownloadItem, gNC_ProgressPercent, percentInt, PR_TRUE);
}
return NS_OK;
if (mListener) {
mListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
if (gMustUpdateUI && mInternalListener) {
mInternalListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
if (mPropertiesListener) {
mPropertiesListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
}
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *location)
NS_IMETHODIMP
DownloadItem::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *aLocation)
{
return NS_ERROR_NOT_IMPLEMENTED;
if (mListener)
mListener->OnLocationChange(aWebProgress, aRequest, aLocation);
if (gMustUpdateUI && mInternalListener)
mInternalListener->OnLocationChange(aWebProgress, aRequest, aLocation);
if (mPropertiesListener)
mPropertiesListener->OnLocationChange(aWebProgress, aRequest, aLocation);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsresult aStatus,
const PRUnichar *aMessage)
NS_IMETHODIMP
DownloadItem::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsresult aStatus,
const PRUnichar *aMessage)
{
if (aStatus & nsIWebProgressListener::STATE_START)
mRequestObserver->OnStartRequest(aRequest, nsnull);
else if (aStatus & nsIWebProgressListener::STATE_STOP)
mRequestObserver->OnStopRequest(aRequest, nsnull, aStatus);
if (mListener)
mListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
return NS_ERROR_NOT_IMPLEMENTED;
if (gMustUpdateUI && mInternalListener)
mInternalListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
if (mPropertiesListener)
mPropertiesListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
return NS_OK;
}
NS_IMETHODIMP
@ -572,13 +697,149 @@ DownloadItem::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, PRInt32 aStateFlags,
PRUint32 aStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
if (aStateFlags & STATE_START)
mTimeStarted = PR_Now();
else if (aStateFlags & STATE_STOP) {
nsresult rv;
nsCOMPtr<nsIDownloadManager> downloadManager = do_GetService("@mozilla.org/download-manager;1", &rv);
if (NS_FAILED(rv)) return rv;
char* path;
mTarget->GetPath(&path);
downloadManager->NotifyDownloadEnded(path);
}
if (mListener)
mListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
if (gMustUpdateUI && mInternalListener)
mInternalListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
if (mPropertiesListener)
mPropertiesListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt32 state)
NS_IMETHODIMP
DownloadItem::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt32 aState)
{
return NS_ERROR_NOT_IMPLEMENTED;
if (mListener)
mListener->OnSecurityChange(aWebProgress, aRequest, aState);
if (gMustUpdateUI && mInternalListener)
mInternalListener->OnSecurityChange(aWebProgress, aRequest, aState);
if (mPropertiesListener)
mPropertiesListener->OnSecurityChange(aWebProgress, aRequest, aState);
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsIDownloadItem
NS_IMETHODIMP
DownloadItem::GetPrettyName(PRUnichar** aPrettyName)
{
*aPrettyName = ToNewUnicode(mPrettyName);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetPrettyName(const PRUnichar* aPrettyName)
{
mPrettyName = aPrettyName;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetTarget(nsILocalFile** aTarget)
{
*aTarget = mTarget;
NS_ADDREF(*aTarget);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetTarget(nsILocalFile* aTarget)
{
mTarget = aTarget;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetSource(nsIURI** aSource)
{
*aSource = mSource;
NS_ADDREF(*aSource);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetSource(nsIURI* aSource)
{
mSource = aSource;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetTimeStarted(PRInt64* aTimeStarted)
{
*aTimeStarted = mTimeStarted;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetPercentComplete(PRInt32* aPercentComplete)
{
*aPercentComplete = mPercentComplete;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetListener(nsIWebProgressListener* aListener)
{
mListener = aListener;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetListener(nsIWebProgressListener** aListener)
{
*aListener = mListener;
NS_ADDREF(*aListener);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetInternalListener(nsIDownloadProgressListener* aInternalListener)
{
mInternalListener = aInternalListener;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetInternalListener(nsIDownloadProgressListener** aInternalListener)
{
*aInternalListener = mInternalListener;
NS_ADDREF(*aInternalListener);
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::SetPropertiesListener(nsIWebProgressListener* aPropertiesListener)
{
mPropertiesListener = aPropertiesListener;
return NS_OK;
}
NS_IMETHODIMP
DownloadItem::GetPropertiesListener(nsIWebProgressListener** aPropertiesListener)
{
*aPropertiesListener = mPropertiesListener;
NS_ADDREF(*aPropertiesListener);
return NS_OK;
}