1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cin: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Blake Ross <blaker@netscape.com> (Original Author)
25 * Ben Goodger <ben@netscape.com> (Original Author)
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsDownloadManager.h"
42 #include "nsIWebProgress.h"
43 #include "nsIRDFLiteral.h"
45 #include "nsNetUtil.h"
46 #include "nsIDOMWindow.h"
47 #include "nsIDOMWindowInternal.h"
48 #include "nsIDOMEvent.h"
49 #include "nsIDOMEventTarget.h"
51 #include "nsAppDirectoryServiceDefs.h"
52 #include "nsIObserver.h"
53 #include "nsIProgressDialog.h"
54 #include "nsIWebBrowserPersist.h"
55 #include "nsIWindowWatcher.h"
56 #include "nsIStringBundle.h"
58 #include "nsIWindowMediator.h"
59 #include "nsIPromptService.h"
60 #include "nsIObserverService.h"
61 #include "nsIProfileChangeStatus.h"
62 #include "nsIPrefService.h"
63 #include "nsIFileURL.h"
64 #include "nsIAlertsService.h"
65 #include "nsEmbedCID.h"
67 #include "nsToolkitCompsCID.h"
69 /* Outstanding issues/todo:
70 * 1. Implement pause/resume.
73 #define DOWNLOAD_MANAGER_FE_URL "chrome://communicator/content/downloadmanager/downloadmanager.xul"
74 #define DOWNLOAD_MANAGER_BUNDLE "chrome://communicator/locale/downloadmanager/downloadmanager.properties"
76 static const nsInt64
gInterval((PRUint32
)(400 * PR_USEC_PER_MSEC
));
78 static nsIRDFResource
* gNC_DownloadsRoot
= nsnull
;
79 static nsIRDFResource
* gNC_File
= nsnull
;
80 static nsIRDFResource
* gNC_URL
= nsnull
;
81 static nsIRDFResource
* gNC_Name
= nsnull
;
82 static nsIRDFResource
* gNC_ProgressMode
= nsnull
;
83 static nsIRDFResource
* gNC_ProgressPercent
= nsnull
;
84 static nsIRDFResource
* gNC_Transferred
= nsnull
;
85 static nsIRDFResource
* gNC_DownloadState
= nsnull
;
86 static nsIRDFResource
* gNC_StatusText
= nsnull
;
88 static nsIRDFService
* gRDFService
= nsnull
;
90 static PRInt32 gRefCnt
= 0;
93 * This function extracts the local file path corresponding to the given URI.
96 GetFilePathUTF8(nsIURI
*aURI
, nsACString
&aResult
)
100 nsCOMPtr
<nsIFileURL
> fileURL
= do_QueryInterface(aURI
, &rv
);
101 if (NS_FAILED(rv
)) return rv
;
103 nsCOMPtr
<nsIFile
> file
;
104 rv
= fileURL
->GetFile(getter_AddRefs(file
));
105 if (NS_FAILED(rv
)) return rv
;
108 rv
= file
->GetPath(path
);
109 if (NS_SUCCEEDED(rv
))
110 CopyUTF16toUTF8(path
, aResult
);
114 ///////////////////////////////////////////////////////////////////////////////
117 NS_IMPL_ISUPPORTS3(nsDownloadManager
, nsIDownloadManager
, nsIDOMEventListener
, nsIObserver
)
119 nsDownloadManager::nsDownloadManager() : mBatches(0)
123 nsDownloadManager::~nsDownloadManager()
125 if (--gRefCnt
!= 0 || !gRDFService
)
126 // Either somebody tried to use |CreateInstance| instead of
127 // |GetService| or |Init| failed very early, so there's nothing to
131 gRDFService
->UnregisterDataSource(mDataSource
);
133 NS_IF_RELEASE(gNC_DownloadsRoot
);
134 NS_IF_RELEASE(gNC_File
);
135 NS_IF_RELEASE(gNC_URL
);
136 NS_IF_RELEASE(gNC_Name
);
137 NS_IF_RELEASE(gNC_ProgressMode
);
138 NS_IF_RELEASE(gNC_ProgressPercent
);
139 NS_IF_RELEASE(gNC_Transferred
);
140 NS_IF_RELEASE(gNC_DownloadState
);
141 NS_IF_RELEASE(gNC_StatusText
);
143 NS_RELEASE(gRDFService
);
147 nsDownloadManager::Init()
149 if (gRefCnt
++ != 0) {
150 NS_NOTREACHED("download manager should be used as a service");
151 return NS_ERROR_UNEXPECTED
; // This will make the |CreateInstance| fail.
154 if (!mCurrDownloads
.Init())
155 return NS_ERROR_FAILURE
;
158 mRDFContainerUtils
= do_GetService("@mozilla.org/rdf/container-utils;1", &rv
);
159 if (NS_FAILED(rv
)) return rv
;
161 nsCOMPtr
<nsIObserverService
> obsService
= do_GetService("@mozilla.org/observer-service;1", &rv
);
162 if (NS_FAILED(rv
)) return rv
;
165 rv
= CallGetService("@mozilla.org/rdf/rdf-service;1", &gRDFService
);
166 if (NS_FAILED(rv
)) return rv
;
168 gRDFService
->GetResource(NS_LITERAL_CSTRING("NC:DownloadsRoot"), &gNC_DownloadsRoot
);
169 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"File"), &gNC_File
);
170 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"URL"), &gNC_URL
);
171 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"Name"), &gNC_Name
);
172 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"ProgressMode"), &gNC_ProgressMode
);
173 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"ProgressPercent"), &gNC_ProgressPercent
);
174 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"Transferred"), &gNC_Transferred
);
175 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"DownloadState"), &gNC_DownloadState
);
176 gRDFService
->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI
"StatusText"), &gNC_StatusText
);
178 nsCAutoString downloadsDB
;
179 rv
= GetProfileDownloadsFileURL(downloadsDB
);
180 if (NS_FAILED(rv
)) return rv
;
182 rv
= gRDFService
->GetDataSourceBlocking(downloadsDB
.get(), getter_AddRefs(mDataSource
));
183 if (NS_FAILED(rv
)) return rv
;
185 mListener
= do_CreateInstance("@mozilla.org/download-manager/listener;1", &rv
);
186 if (NS_FAILED(rv
)) return rv
;
188 nsCOMPtr
<nsIStringBundleService
> bundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
189 if (NS_FAILED(rv
)) return rv
;
191 rv
= bundleService
->CreateBundle(DOWNLOAD_MANAGER_BUNDLE
, getter_AddRefs(mBundle
));
195 // The following two AddObserver calls must be the last lines in this function,
196 // because otherwise, this function may fail (and thus, this object would be not
197 // completely initialized), but the observerservice would still keep a reference
198 // to us and notify us about shutdown, which may cause crashes.
199 // failure to add an observer is not critical
200 obsService
->AddObserver(this, "profile-before-change", PR_FALSE
);
201 obsService
->AddObserver(this, "profile-approve-change", PR_FALSE
);
207 nsDownloadManager::DownloadStarted(const nsACString
& aTargetPath
)
209 if (mCurrDownloads
.GetWeak(aTargetPath
))
210 AssertProgressInfoFor(aTargetPath
);
216 nsDownloadManager::DownloadEnded(const nsACString
& aTargetPath
, const PRUnichar
* aMessage
)
218 nsDownload
* dl
= mCurrDownloads
.GetWeak(aTargetPath
);
220 AssertProgressInfoFor(aTargetPath
);
221 mCurrDownloads
.Remove(aTargetPath
);
228 nsDownloadManager::GetProfileDownloadsFileURL(nsCString
& aDownloadsFileURL
)
230 nsCOMPtr
<nsIFile
> downloadsFile
;
231 nsresult rv
= NS_GetSpecialDirectory(NS_APP_DOWNLOADS_50_FILE
, getter_AddRefs(downloadsFile
));
235 return NS_GetURLSpecFromFile(downloadsFile
, aDownloadsFileURL
);
239 nsDownloadManager::GetDownloadsContainer(nsIRDFContainer
** aResult
)
241 if (mDownloadsContainer
) {
242 *aResult
= mDownloadsContainer
;
248 nsresult rv
= mRDFContainerUtils
->IsContainer(mDataSource
, gNC_DownloadsRoot
, &isContainer
);
249 if (NS_FAILED(rv
)) return rv
;
252 rv
= mRDFContainerUtils
->MakeSeq(mDataSource
, gNC_DownloadsRoot
, getter_AddRefs(mDownloadsContainer
));
253 if (NS_FAILED(rv
)) return rv
;
256 mDownloadsContainer
= do_CreateInstance(NS_RDF_CONTRACTID
"/container;1", &rv
);
257 if (NS_FAILED(rv
)) return rv
;
258 rv
= mDownloadsContainer
->Init(mDataSource
, gNC_DownloadsRoot
);
259 if (NS_FAILED(rv
)) return rv
;
262 *aResult
= mDownloadsContainer
;
263 NS_IF_ADDREF(*aResult
);
269 nsDownloadManager::GetInternalListener(nsIDownloadProgressListener
** aInternalListener
)
271 *aInternalListener
= mListener
;
272 NS_IF_ADDREF(*aInternalListener
);
277 nsDownloadManager::GetDataSource(nsIRDFDataSource
** aDataSource
)
279 *aDataSource
= mDataSource
;
280 NS_ADDREF(*aDataSource
);
285 nsDownloadManager::AssertProgressInfo()
287 nsCOMPtr
<nsISupports
> supports
;
288 nsCOMPtr
<nsIRDFResource
> res
;
289 nsCOMPtr
<nsIRDFInt
> intLiteral
;
291 gRDFService
->GetIntLiteral(DOWNLOADING
, getter_AddRefs(intLiteral
));
292 nsCOMPtr
<nsISimpleEnumerator
> downloads
;
293 nsresult rv
= mDataSource
->GetSources(gNC_DownloadState
, intLiteral
, PR_TRUE
, getter_AddRefs(downloads
));
294 if (NS_FAILED(rv
)) return rv
;
296 PRBool hasMoreElements
;
297 downloads
->HasMoreElements(&hasMoreElements
);
299 while (hasMoreElements
) {
301 downloads
->GetNext(getter_AddRefs(supports
));
302 res
= do_QueryInterface(supports
);
303 res
->GetValueConst(&uri
);
304 AssertProgressInfoFor(nsDependentCString(uri
));
305 downloads
->HasMoreElements(&hasMoreElements
);
311 nsDownloadManager::AssertProgressInfoFor(const nsACString
& aTargetPath
)
313 nsDownload
* internalDownload
= mCurrDownloads
.GetWeak(aTargetPath
);
314 if (!internalDownload
)
315 return NS_ERROR_FAILURE
;
318 PRInt32 percentComplete
;
319 nsCOMPtr
<nsIRDFNode
> oldTarget
;
320 nsCOMPtr
<nsIRDFInt
> intLiteral
;
321 nsCOMPtr
<nsIRDFResource
> res
;
322 nsCOMPtr
<nsIRDFLiteral
> literal
;
324 gRDFService
->GetResource(aTargetPath
, getter_AddRefs(res
));
326 DownloadState state
= internalDownload
->GetDownloadState();
328 // update progress mode
329 nsAutoString progressMode
;
330 if (state
== DOWNLOADING
)
331 progressMode
.AssignLiteral("normal");
333 progressMode
.AssignLiteral("none");
335 gRDFService
->GetLiteral(progressMode
.get(), getter_AddRefs(literal
));
337 rv
= mDataSource
->GetTarget(res
, gNC_ProgressMode
, PR_TRUE
, getter_AddRefs(oldTarget
));
340 rv
= mDataSource
->Change(res
, gNC_ProgressMode
, oldTarget
, literal
);
342 rv
= mDataSource
->Assert(res
, gNC_ProgressMode
, literal
, PR_TRUE
);
343 if (NS_FAILED(rv
)) return rv
;
345 // update download state (not started, downloading, queued, finished, etc...)
346 gRDFService
->GetIntLiteral(state
, getter_AddRefs(intLiteral
));
348 mDataSource
->GetTarget(res
, gNC_DownloadState
, PR_TRUE
, getter_AddRefs(oldTarget
));
351 rv
= mDataSource
->Change(res
, gNC_DownloadState
, oldTarget
, intLiteral
);
352 if (NS_FAILED(rv
)) return rv
;
356 if (state
== NOTSTARTED
)
357 strKey
.AssignLiteral("notStarted");
358 else if (state
== DOWNLOADING
)
359 strKey
.AssignLiteral("downloading");
360 else if (state
== FINISHED
)
361 strKey
.AssignLiteral("finished");
362 else if (state
== FAILED
)
363 strKey
.AssignLiteral("failed");
364 else if (state
== CANCELED
)
365 strKey
.AssignLiteral("canceled");
368 rv
= mBundle
->GetStringFromName(strKey
.get(), getter_Copies(value
));
369 if (NS_FAILED(rv
)) return rv
;
371 gRDFService
->GetLiteral(value
, getter_AddRefs(literal
));
373 rv
= mDataSource
->GetTarget(res
, gNC_StatusText
, PR_TRUE
, getter_AddRefs(oldTarget
));
376 rv
= mDataSource
->Change(res
, gNC_StatusText
, oldTarget
, literal
);
377 if (NS_FAILED(rv
)) return rv
;
380 rv
= mDataSource
->Assert(res
, gNC_StatusText
, literal
, PR_TRUE
);
381 if (NS_FAILED(rv
)) return rv
;
385 internalDownload
->GetPercentComplete(&percentComplete
);
387 mDataSource
->GetTarget(res
, gNC_ProgressPercent
, PR_TRUE
, getter_AddRefs(oldTarget
));
388 gRDFService
->GetIntLiteral(percentComplete
, getter_AddRefs(intLiteral
));
391 rv
= mDataSource
->Change(res
, gNC_ProgressPercent
, oldTarget
, intLiteral
);
393 rv
= mDataSource
->Assert(res
, gNC_ProgressPercent
, intLiteral
, PR_TRUE
);
394 if (NS_FAILED(rv
)) return rv
;
396 // update transferred
397 nsDownload::TransferInformation transferInfo
=
398 internalDownload
->GetTransferInformation();
400 // convert from bytes to kbytes for progress display
401 PRInt64 current
= (transferInfo
.mCurrBytes
+ 512) / 1024;
402 PRInt64 max
= (transferInfo
.mMaxBytes
+ 512) / 1024;
404 nsAutoString currBytes
; currBytes
.AppendInt(current
);
405 nsAutoString maxBytes
; maxBytes
.AppendInt(max
);
406 const PRUnichar
*strings
[] = {
411 rv
= mBundle
->FormatStringFromName(NS_LITERAL_STRING("transferred").get(),
412 strings
, 2, getter_Copies(value
));
413 if (NS_FAILED(rv
)) return rv
;
415 gRDFService
->GetLiteral(value
, getter_AddRefs(literal
));
417 mDataSource
->GetTarget(res
, gNC_Transferred
, PR_TRUE
, getter_AddRefs(oldTarget
));
420 rv
= mDataSource
->Change(res
, gNC_Transferred
, oldTarget
, literal
);
422 rv
= mDataSource
->Assert(res
, gNC_Transferred
, literal
, PR_TRUE
);
423 if (NS_FAILED(rv
)) return rv
;
425 nsCOMPtr
<nsIRDFRemoteDataSource
> remote
= do_QueryInterface(mDataSource
);
428 // XXX should also store and update time elapsed
432 ///////////////////////////////////////////////////////////////////////////////
433 // nsIDownloadManager
436 nsDownloadManager::AddDownload(nsIURI
* aSource
,
438 const nsAString
& aDisplayName
,
439 nsIMIMEInfo
*aMIMEInfo
,
441 nsILocalFile
* aTempFile
,
442 nsICancelable
* aCancelable
,
443 nsIDownload
** aDownload
)
445 NS_ENSURE_ARG_POINTER(aSource
);
446 NS_ENSURE_ARG_POINTER(aTarget
);
447 NS_ENSURE_ARG_POINTER(aDownload
);
449 nsCOMPtr
<nsIRDFContainer
> downloads
;
450 nsresult rv
= GetDownloadsContainer(getter_AddRefs(downloads
));
451 if (NS_FAILED(rv
)) return rv
;
453 // this will create a cycle that will be broken in nsDownload::OnStateChange
454 nsDownload
* internalDownload
= new nsDownload(this, aTarget
, aSource
, aCancelable
);
455 if (!internalDownload
)
456 return NS_ERROR_OUT_OF_MEMORY
;
458 NS_ADDREF(*aDownload
= internalDownload
);
460 // the path of the target is the unique identifier we use
461 nsCOMPtr
<nsILocalFile
> targetFile
;
462 rv
= internalDownload
->GetTargetFile(getter_AddRefs(targetFile
));
463 if (NS_FAILED(rv
)) return rv
;
466 rv
= targetFile
->GetPath(path
);
467 if (NS_FAILED(rv
)) return rv
;
469 NS_ConvertUTF16toUTF8
utf8Path(path
);
471 nsCOMPtr
<nsIRDFResource
> downloadRes
;
472 gRDFService
->GetResource(utf8Path
, getter_AddRefs(downloadRes
));
474 nsCOMPtr
<nsIRDFNode
> node
;
476 // Assert source url information
478 aSource
->GetSpec(spec
);
480 nsCOMPtr
<nsIRDFResource
> urlResource
;
481 gRDFService
->GetResource(spec
, getter_AddRefs(urlResource
));
482 mDataSource
->GetTarget(downloadRes
, gNC_URL
, PR_TRUE
, getter_AddRefs(node
));
484 rv
= mDataSource
->Change(downloadRes
, gNC_URL
, node
, urlResource
);
486 rv
= mDataSource
->Assert(downloadRes
, gNC_URL
, urlResource
, PR_TRUE
);
487 if (NS_FAILED(rv
)) return rv
;
489 // Set and assert the "pretty" (display) name of the download
490 nsAutoString displayName
; displayName
.Assign(aDisplayName
);
491 if (displayName
.IsEmpty()) {
492 targetFile
->GetLeafName(displayName
);
494 internalDownload
->SetDisplayName(displayName
.get());
495 internalDownload
->SetTempFile(aTempFile
);
497 nsCOMPtr
<nsIRDFLiteral
> nameLiteral
;
498 gRDFService
->GetLiteral(displayName
.get(), getter_AddRefs(nameLiteral
));
499 mDataSource
->GetTarget(downloadRes
, gNC_Name
, PR_TRUE
, getter_AddRefs(node
));
501 rv
= mDataSource
->Change(downloadRes
, gNC_Name
, node
, nameLiteral
);
503 rv
= mDataSource
->Assert(downloadRes
, gNC_Name
, nameLiteral
, PR_TRUE
);
504 if (NS_FAILED(rv
)) return rv
;
506 internalDownload
->SetMIMEInfo(aMIMEInfo
);
507 internalDownload
->SetStartTime(aStartTime
);
509 // Assert file information
510 nsCOMPtr
<nsIRDFResource
> fileResource
;
511 gRDFService
->GetResource(utf8Path
, getter_AddRefs(fileResource
));
512 rv
= mDataSource
->Assert(downloadRes
, gNC_File
, fileResource
, PR_TRUE
);
513 if (NS_FAILED(rv
)) return rv
;
515 // Assert download state information (NOTSTARTED, since it's just now being added)
516 nsCOMPtr
<nsIRDFInt
> intLiteral
;
517 gRDFService
->GetIntLiteral(NOTSTARTED
, getter_AddRefs(intLiteral
));
518 mDataSource
->GetTarget(downloadRes
, gNC_DownloadState
, PR_TRUE
, getter_AddRefs(node
));
520 rv
= mDataSource
->Change(downloadRes
, gNC_DownloadState
, node
, intLiteral
);
522 rv
= mDataSource
->Assert(downloadRes
, gNC_DownloadState
, intLiteral
, PR_TRUE
);
523 if (NS_FAILED(rv
)) return rv
;
526 downloads
->IndexOf(downloadRes
, &itemIndex
);
527 if (itemIndex
== -1) {
528 rv
= downloads
->AppendElement(downloadRes
);
529 if (NS_FAILED(rv
)) return rv
;
532 // Now flush all this to disk
533 nsCOMPtr
<nsIRDFRemoteDataSource
> remote(do_QueryInterface(mDataSource
));
534 rv
= remote
->Flush();
535 if (NS_FAILED(rv
)) return rv
;
537 mCurrDownloads
.Put(utf8Path
, internalDownload
);
543 nsDownloadManager::GetDownload(const nsACString
& aTargetPath
, nsIDownload
** aDownloadItem
)
545 NS_ENSURE_ARG_POINTER(aDownloadItem
);
547 // if it's currently downloading we can get it from the table
548 // XXX otherwise we should look for it in the datasource and
549 // create a new nsIDownload with the resource's properties
550 NS_IF_ADDREF(*aDownloadItem
= mCurrDownloads
.GetWeak(aTargetPath
));
555 nsDownloadManager::CancelDownload(const nsACString
& aTargetPath
)
557 nsRefPtr
<nsDownload
> internalDownload
= mCurrDownloads
.GetWeak(aTargetPath
);
558 if (!internalDownload
)
559 return NS_ERROR_FAILURE
;
561 return internalDownload
->Cancel();
565 nsDownloadManager::PauseDownload(nsIDownload
* aDownload
)
567 NS_ENSURE_ARG_POINTER(aDownload
);
568 return static_cast<nsDownload
*>(aDownload
)->Suspend();
572 nsDownloadManager::ResumeDownload(const nsACString
& aTargetPath
)
574 nsDownload
* dl
= mCurrDownloads
.GetWeak(aTargetPath
);
576 return NS_ERROR_NOT_AVAILABLE
;
581 nsDownloadManager::RemoveDownload(const nsACString
& aTargetPath
)
583 // RemoveDownload is for downloads not currently in progress. Having it
584 // cancel in-progress downloads would make things complicated, so just return.
585 nsDownload
* inProgress
= mCurrDownloads
.GetWeak(aTargetPath
);
586 NS_ASSERTION(!inProgress
, "Can't call RemoveDownload on a download in progress!");
588 return NS_ERROR_FAILURE
;
590 nsCOMPtr
<nsIRDFContainer
> downloads
;
591 nsresult rv
= GetDownloadsContainer(getter_AddRefs(downloads
));
592 if (NS_FAILED(rv
)) return rv
;
594 nsCOMPtr
<nsIRDFResource
> res
;
595 gRDFService
->GetResource(aTargetPath
, getter_AddRefs(res
));
597 // remove all the arcs for this resource, and then remove it from the Seq
598 nsCOMPtr
<nsISimpleEnumerator
> arcs
;
599 rv
= mDataSource
->ArcLabelsOut(res
, getter_AddRefs(arcs
));
600 if (NS_FAILED(rv
)) return rv
;
603 rv
= arcs
->HasMoreElements(&moreArcs
);
604 if (NS_FAILED(rv
)) return rv
;
607 nsCOMPtr
<nsISupports
> supports
;
608 rv
= arcs
->GetNext(getter_AddRefs(supports
));
609 if (NS_FAILED(rv
)) return rv
;
611 nsCOMPtr
<nsIRDFResource
> arc(do_QueryInterface(supports
, &rv
));
612 if (NS_FAILED(rv
)) return rv
;
614 nsCOMPtr
<nsISimpleEnumerator
> targets
;
615 rv
= mDataSource
->GetTargets(res
, arc
, PR_TRUE
, getter_AddRefs(targets
));
616 if (NS_FAILED(rv
)) return rv
;
619 rv
= targets
->HasMoreElements(&moreTargets
);
620 if (NS_FAILED(rv
)) return rv
;
622 while (moreTargets
) {
623 rv
= targets
->GetNext(getter_AddRefs(supports
));
624 if (NS_FAILED(rv
)) return rv
;
626 nsCOMPtr
<nsIRDFNode
> target(do_QueryInterface(supports
, &rv
));
627 if (NS_FAILED(rv
)) return rv
;
629 // and now drop this assertion from the graph
630 rv
= mDataSource
->Unassert(res
, arc
, target
);
631 if (NS_FAILED(rv
)) return rv
;
633 rv
= targets
->HasMoreElements(&moreTargets
);
634 if (NS_FAILED(rv
)) return rv
;
636 rv
= arcs
->HasMoreElements(&moreArcs
);
637 if (NS_FAILED(rv
)) return rv
;
641 downloads
->IndexOf(res
, &itemIndex
);
643 return NS_ERROR_FAILURE
;
645 nsCOMPtr
<nsIRDFNode
> node
;
646 rv
= downloads
->RemoveElementAt(itemIndex
, PR_TRUE
, getter_AddRefs(node
));
647 if (NS_FAILED(rv
)) return rv
;
649 // if a mass removal is being done, we don't want to flush every time
650 if (mBatches
) return rv
;
652 nsCOMPtr
<nsIRDFRemoteDataSource
> remote
= do_QueryInterface(mDataSource
);
653 return remote
->Flush();
657 nsDownloadManager::StartBatchUpdate()
664 nsDownloadManager::EndBatchUpdate()
667 if (--mBatches
== 0) {
668 nsCOMPtr
<nsIRDFRemoteDataSource
> remote
= do_QueryInterface(mDataSource
);
669 rv
= remote
->Flush();
675 nsDownloadManager::Open(nsIDOMWindow
* aParent
, nsIDownload
* aDownload
)
678 // first assert new progress info so the ui is correctly updated
679 // if this fails, it fails -- continue.
680 AssertProgressInfo();
682 // check for an existing manager window and focus it
684 nsCOMPtr
<nsIWindowMediator
> wm
= do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
, &rv
);
685 if (NS_FAILED(rv
)) return rv
;
687 nsCOMPtr
<nsISupports
> dlSupports(do_QueryInterface(aDownload
));
689 // if the window's already open, do nothing (focusing it would be annoying)
690 nsCOMPtr
<nsIDOMWindowInternal
> recentWindow
;
691 wm
->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(), getter_AddRefs(recentWindow
));
693 nsCOMPtr
<nsIObserverService
> obsService
= do_GetService("@mozilla.org/observer-service;1", &rv
);
694 if (NS_FAILED(rv
)) return rv
;
695 return obsService
->NotifyObservers(dlSupports
, "download-starting", nsnull
);
698 // if we ever have the capability to display the UI of third party dl managers,
699 // we'll open their UI here instead.
700 nsCOMPtr
<nsIWindowWatcher
> ww
= do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
701 if (NS_FAILED(rv
)) return rv
;
703 // pass the datasource to the window
704 nsCOMPtr
<nsISupportsArray
> params(do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID
));
705 nsCOMPtr
<nsISupports
> dsSupports(do_QueryInterface(mDataSource
));
706 params
->AppendElement(dsSupports
);
707 params
->AppendElement(dlSupports
);
709 nsCOMPtr
<nsIDOMWindow
> newWindow
;
710 rv
= ww
->OpenWindow(aParent
,
711 DOWNLOAD_MANAGER_FE_URL
,
713 "chrome,all,dialog=no,resizable",
715 getter_AddRefs(newWindow
));
717 if (NS_FAILED(rv
)) return rv
;
719 nsCOMPtr
<nsIDOMEventTarget
> target
= do_QueryInterface(newWindow
);
720 if (!target
) return NS_ERROR_FAILURE
;
722 rv
= target
->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE
);
723 if (NS_FAILED(rv
)) return rv
;
725 return target
->AddEventListener(NS_LITERAL_STRING("unload"), this, PR_FALSE
);
729 nsDownloadManager::OpenProgressDialogFor(nsIDownload
* aDownload
, nsIDOMWindow
* aParent
, PRBool aCancelDownloadOnClose
)
731 NS_ENSURE_ARG_POINTER(aDownload
);
733 nsDownload
* internalDownload
= static_cast<nsDownload
*>(aDownload
);
734 nsIProgressDialog
* oldDialog
= internalDownload
->GetDialog();
737 nsCOMPtr
<nsIDOMWindow
> window
;
738 oldDialog
->GetDialog(getter_AddRefs(window
));
740 nsCOMPtr
<nsIDOMWindowInternal
> internalWin
= do_QueryInterface(window
);
741 internalWin
->Focus();
746 nsCOMPtr
<nsIProgressDialog
> dialog(do_CreateInstance("@mozilla.org/progressdialog;1", &rv
));
747 if (NS_FAILED(rv
)) return rv
;
749 dialog
->SetCancelDownloadOnClose(aCancelDownloadOnClose
);
751 // now give the dialog the necessary context
754 PRInt64 startTime
= 0;
755 aDownload
->GetStartTime(&startTime
);
758 nsCOMPtr
<nsIURI
> source
;
759 aDownload
->GetSource(getter_AddRefs(source
));
762 nsCOMPtr
<nsIURI
> target
;
763 aDownload
->GetTarget(getter_AddRefs(target
));
766 nsCOMPtr
<nsIMIMEInfo
> mimeInfo
;
767 aDownload
->GetMIMEInfo(getter_AddRefs(mimeInfo
));
769 dialog
->Init(source
, target
, EmptyString(), mimeInfo
, startTime
, nsnull
,
771 dialog
->SetObserver(internalDownload
);
773 // now set the listener so we forward notifications to the dialog
774 nsCOMPtr
<nsIDownloadProgressListener
> listener
= do_QueryInterface(dialog
);
775 internalDownload
->SetDialogListener(listener
);
777 internalDownload
->SetDialog(dialog
);
779 return dialog
->Open(aParent
);
783 nsDownloadManager::OnClose()
786 mListener
->SetDocument(nsnull
);
790 ///////////////////////////////////////////////////////////////////////////////
791 // nsIDOMEventListener
794 nsDownloadManager::HandleEvent(nsIDOMEvent
* aEvent
)
796 // the event is either load or unload
797 nsAutoString eventType
;
798 aEvent
->GetType(eventType
);
799 if (eventType
.EqualsLiteral("unload"))
802 nsCOMPtr
<nsIDOMEventTarget
> target
;
803 nsresult rv
= aEvent
->GetTarget(getter_AddRefs(target
));
804 if (NS_FAILED(rv
)) return rv
;
806 mDocument
= do_QueryInterface(target
);
807 mListener
->SetDocument(mDocument
);
811 ///////////////////////////////////////////////////////////////////////////////
815 nsDownloadManager::Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
818 if (nsCRT::strcmp(aTopic
, "profile-approve-change") == 0) {
819 // Only run this on profile switch
820 if (!NS_LITERAL_STRING("switch").Equals(aData
))
823 // If count == 0, nothing to do
824 if (mCurrDownloads
.Count() == 0)
827 nsCOMPtr
<nsIProfileChangeStatus
> changeStatus(do_QueryInterface(aSubject
));
829 return NS_ERROR_UNEXPECTED
;
831 nsXPIDLString title
, text
, proceed
, cancel
;
832 nsresult rv
= mBundle
->GetStringFromName(NS_LITERAL_STRING("profileSwitchTitle").get(),
833 getter_Copies(title
));
834 NS_ENSURE_SUCCESS(rv
, rv
);
835 rv
= mBundle
->GetStringFromName(NS_LITERAL_STRING("profileSwitchText").get(),
836 getter_Copies(text
));
837 NS_ENSURE_SUCCESS(rv
, rv
);
838 rv
= mBundle
->GetStringFromName(NS_LITERAL_STRING("profileSwitchContinue").get(),
839 getter_Copies(proceed
));
840 NS_ENSURE_SUCCESS(rv
, rv
);
842 nsCOMPtr
<nsIPromptService
> promptService(do_GetService(NS_PROMPTSERVICE_CONTRACTID
, &rv
));
847 rv
= promptService
->ConfirmEx(nsnull
, title
.get(), text
.get(),
848 nsIPromptService::BUTTON_TITLE_CANCEL
* nsIPromptService::BUTTON_POS_0
|
849 nsIPromptService::BUTTON_TITLE_IS_STRING
* nsIPromptService::BUTTON_POS_1
,
860 changeStatus
->VetoChange();
862 else if (nsCRT::strcmp(aTopic
, "profile-before-change") == 0) {
863 nsCOMPtr
<nsISupports
> supports
;
864 nsCOMPtr
<nsIRDFResource
> res
;
865 nsCOMPtr
<nsIRDFInt
> intLiteral
;
867 gRDFService
->GetIntLiteral(DOWNLOADING
, getter_AddRefs(intLiteral
));
868 nsCOMPtr
<nsISimpleEnumerator
> downloads
;
869 rv
= mDataSource
->GetSources(gNC_DownloadState
, intLiteral
, PR_TRUE
, getter_AddRefs(downloads
));
870 if (NS_FAILED(rv
)) return rv
;
872 PRBool hasMoreElements
;
873 downloads
->HasMoreElements(&hasMoreElements
);
875 while (hasMoreElements
) {
878 downloads
->GetNext(getter_AddRefs(supports
));
879 res
= do_QueryInterface(supports
);
880 res
->GetValueConst(&uri
);
881 CancelDownload(nsDependentCString(uri
));
882 downloads
->HasMoreElements(&hasMoreElements
);
888 ///////////////////////////////////////////////////////////////////////////////
891 NS_IMPL_ISUPPORTS5(nsDownload
, nsIDownload
, nsITransfer
, nsIWebProgressListener
,
892 nsIWebProgressListener2
, nsIObserver
)
894 nsDownload::nsDownload(nsDownloadManager
* aManager
,
897 nsICancelable
* aCancelable
) :
898 mDownloadManager(aManager
),
901 mCancelable(aCancelable
),
902 mDownloadState(NOTSTARTED
),
907 mLastUpdate(PR_Now() - (PRUint32
)gInterval
),
912 nsDownload::~nsDownload()
915 nsresult rv
= GetFilePathUTF8(mTarget
, path
);
916 if (NS_FAILED(rv
)) return;
918 mDownloadManager
->AssertProgressInfoFor(path
);
922 nsDownload::Suspend()
925 return NS_ERROR_UNEXPECTED
;
926 return mRequest
->Suspend();
932 // Don't cancel if download is already finished or canceled
933 if (GetDownloadState() == FINISHED
|| GetDownloadState() == CANCELED
)
936 nsresult rv
= mCancelable
->Cancel(NS_BINDING_ABORTED
);
940 SetDownloadState(CANCELED
);
943 rv
= GetFilePathUTF8(mTarget
, path
);
946 mDownloadManager
->DownloadEnded(path
, nsnull
);
948 // Dump the temp file. This should really be done when the transfer
949 // is cancelled, but there are other cancellation causes that shouldn't
950 // remove this. We need to improve those bits.
953 mTempFile
->Exists(&exists
);
955 mTempFile
->Remove(PR_FALSE
);
958 // if there's a progress dialog open for the item,
959 // we have to notify it that we're cancelling
960 nsCOMPtr
<nsIObserver
> observer
= do_QueryInterface(GetDialog());
962 rv
= observer
->Observe(static_cast<nsIDownload
*>(this), "oncancel", nsnull
);
969 nsDownload::SetDisplayName(const PRUnichar
* aDisplayName
)
971 mDisplayName
= aDisplayName
;
973 nsCOMPtr
<nsIRDFDataSource
> ds
;
974 mDownloadManager
->GetDataSource(getter_AddRefs(ds
));
976 nsCOMPtr
<nsIRDFLiteral
> nameLiteral
;
977 nsCOMPtr
<nsIRDFResource
> res
;
979 nsresult rv
= GetFilePathUTF8(mTarget
, path
);
980 if (NS_FAILED(rv
)) return rv
;
982 gRDFService
->GetResource(path
, getter_AddRefs(res
));
984 gRDFService
->GetLiteral(aDisplayName
, getter_AddRefs(nameLiteral
));
985 ds
->Assert(res
, gNC_Name
, nameLiteral
, PR_TRUE
);
994 return NS_ERROR_UNEXPECTED
;
995 return mRequest
->Resume();
998 ///////////////////////////////////////////////////////////////////////////////
1001 nsDownload::Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
1003 if (strcmp(aTopic
, "onpause") == 0) {
1006 if (strcmp(aTopic
, "onresume") == 0) {
1009 if (strcmp(aTopic
, "oncancel") == 0) {
1013 // Ignoring return value; this function will get called twice,
1014 // and bad things happen if we return a failure code the second time.
1018 if (strcmp(aTopic
, "alertclickcallback") == 0) {
1019 // show the download manager
1020 mDownloadManager
->Open(nsnull
, this);
1027 ///////////////////////////////////////////////////////////////////////////////
1028 // nsIWebProgressListener2
1031 nsDownload::OnProgressChange64(nsIWebProgress
*aWebProgress
,
1032 nsIRequest
*aRequest
,
1033 PRInt64 aCurSelfProgress
,
1034 PRInt64 aMaxSelfProgress
,
1035 PRInt64 aCurTotalProgress
,
1036 PRInt64 aMaxTotalProgress
)
1039 mRequest
= aRequest
; // used for pause/resume
1041 // Filter notifications since they come in so frequently, but we want to
1042 // process the last notification.
1043 PRTime now
= PR_Now();
1044 nsInt64 delta
= now
- mLastUpdate
;
1045 if (delta
< gInterval
&& aCurTotalProgress
!= aMaxTotalProgress
)
1050 if (mDownloadState
== NOTSTARTED
) {
1052 nsresult rv
= GetFilePathUTF8(mTarget
, path
);
1053 if (NS_FAILED(rv
)) return rv
;
1055 mDownloadState
= DOWNLOADING
;
1056 mDownloadManager
->DownloadStarted(path
);
1059 // Calculate the speed using the elapsed delta time and bytes downloaded
1060 // during that time for more accuracy.
1061 double elapsedSecs
= double(delta
) / PR_USEC_PER_SEC
;
1062 if (elapsedSecs
> 0) {
1063 nsUint64 curTotalProgress
= (PRUint64
)aCurTotalProgress
;
1064 nsUint64 diffBytes
= curTotalProgress
- nsUint64(mCurrBytes
);
1065 double speed
= double(diffBytes
) / elapsedSecs
;
1066 if (LL_IS_ZERO(mCurrBytes
))
1069 // Calculate 'smoothed average' of 10 readings.
1070 mSpeed
= mSpeed
* 0.9 + speed
* 0.1;
1074 if (aMaxTotalProgress
> 0)
1075 mPercentComplete
= aCurTotalProgress
* 100 / aMaxTotalProgress
;
1077 mPercentComplete
= -1;
1079 mCurrBytes
= aCurTotalProgress
;
1080 mMaxBytes
= aMaxTotalProgress
;
1082 if (mDownloadManager
->MustUpdateUI()) {
1083 nsCOMPtr
<nsIDownloadProgressListener
> internalListener
;
1084 mDownloadManager
->GetInternalListener(getter_AddRefs(internalListener
));
1085 if (internalListener
) {
1086 internalListener
->OnProgressChange(aWebProgress
, aRequest
, aCurSelfProgress
, aMaxSelfProgress
,
1087 aCurTotalProgress
, aMaxTotalProgress
, this);
1091 if (mDialogListener
) {
1092 mDialogListener
->OnProgressChange(aWebProgress
, aRequest
, aCurSelfProgress
, aMaxSelfProgress
,
1093 aCurTotalProgress
, aMaxTotalProgress
, this);
1099 ///////////////////////////////////////////////////////////////////////////////
1100 // nsIWebProgressListener
1103 nsDownload::OnProgressChange(nsIWebProgress
*aWebProgress
,
1104 nsIRequest
*aRequest
,
1105 PRInt32 aCurSelfProgress
,
1106 PRInt32 aMaxSelfProgress
,
1107 PRInt32 aCurTotalProgress
,
1108 PRInt32 aMaxTotalProgress
)
1110 return OnProgressChange64(aWebProgress
, aRequest
,
1111 aCurSelfProgress
, aMaxSelfProgress
,
1112 aCurTotalProgress
, aMaxTotalProgress
);
1116 nsDownload::OnRefreshAttempted(nsIWebProgress
*aWebProgress
,
1120 PRBool
*allowRefresh
)
1122 *allowRefresh
= PR_TRUE
;
1127 nsDownload::OnLocationChange(nsIWebProgress
*aWebProgress
,
1128 nsIRequest
*aRequest
, nsIURI
*aLocation
)
1130 if (mDownloadManager
->MustUpdateUI()) {
1131 nsCOMPtr
<nsIDownloadProgressListener
> internalListener
;
1132 mDownloadManager
->GetInternalListener(getter_AddRefs(internalListener
));
1133 if (internalListener
)
1134 internalListener
->OnLocationChange(aWebProgress
, aRequest
, aLocation
, this);
1137 if (mDialogListener
)
1138 mDialogListener
->OnLocationChange(aWebProgress
, aRequest
, aLocation
, this);
1144 nsDownload::OnStatusChange(nsIWebProgress
*aWebProgress
,
1145 nsIRequest
*aRequest
, nsresult aStatus
,
1146 const PRUnichar
*aMessage
)
1148 if (NS_FAILED(aStatus
)) {
1149 mDownloadState
= FAILED
;
1151 nsresult rv
= GetFilePathUTF8(mTarget
, path
);
1152 if (NS_SUCCEEDED(rv
))
1153 mDownloadManager
->DownloadEnded(path
, aMessage
);
1156 if (mDownloadManager
->MustUpdateUI()) {
1157 nsCOMPtr
<nsIDownloadProgressListener
> internalListener
;
1158 mDownloadManager
->GetInternalListener(getter_AddRefs(internalListener
));
1159 if (internalListener
)
1160 internalListener
->OnStatusChange(aWebProgress
, aRequest
, aStatus
, aMessage
, this);
1163 if (mDialogListener
)
1164 mDialogListener
->OnStatusChange(aWebProgress
, aRequest
, aStatus
, aMessage
, this);
1166 // Need to display error alert ourselves, if an error occurred.
1167 if (NS_FAILED(aStatus
)) {
1168 // Get title for alert.
1169 nsXPIDLString title
;
1171 nsCOMPtr
<nsIStringBundleService
> bundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
1172 nsCOMPtr
<nsIStringBundle
> bundle
;
1174 rv
= bundleService
->CreateBundle(DOWNLOAD_MANAGER_BUNDLE
, getter_AddRefs(bundle
));
1176 bundle
->GetStringFromName(NS_LITERAL_STRING("alertTitle").get(), getter_Copies(title
));
1178 // Get Download Manager window, to be parent of alert.
1179 nsCOMPtr
<nsIWindowMediator
> wm
= do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
, &rv
);
1180 nsCOMPtr
<nsIDOMWindowInternal
> dmWindow
;
1182 wm
->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(), getter_AddRefs(dmWindow
));
1185 nsCOMPtr
<nsIPromptService
> prompter(do_GetService(NS_PROMPTSERVICE_CONTRACTID
));
1187 prompter
->Alert(dmWindow
, title
, aMessage
);
1194 void nsDownload::DisplayDownloadFinishedAlert()
1197 nsCOMPtr
<nsIAlertsService
> alertsService(do_GetService(NS_ALERTSERVICE_CONTRACTID
, &rv
));
1201 nsCOMPtr
<nsIStringBundle
> bundle
;
1202 nsCOMPtr
<nsIStringBundleService
> bundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
1206 rv
= bundleService
->CreateBundle(DOWNLOAD_MANAGER_BUNDLE
, getter_AddRefs(bundle
));
1210 nsXPIDLString finishedTitle
, finishedText
;
1211 rv
= bundle
->GetStringFromName(NS_LITERAL_STRING("finishedTitle").get(),
1212 getter_Copies(finishedTitle
));
1216 const PRUnichar
*strings
[] = { mDisplayName
.get() };
1217 rv
= bundle
->FormatStringFromName(NS_LITERAL_STRING("finishedText").get(),
1218 strings
, 1, getter_Copies(finishedText
));
1223 mTarget
->GetSpec(url
);
1224 alertsService
->ShowAlertNotification(NS_LITERAL_STRING("moz-icon://") + NS_ConvertUTF8toUTF16(url
),
1225 finishedTitle
, finishedText
, PR_TRUE
,
1226 NS_LITERAL_STRING("download"), this,
1231 nsDownload::OnStateChange(nsIWebProgress
* aWebProgress
,
1232 nsIRequest
* aRequest
, PRUint32 aStateFlags
,
1235 // Record the start time only if it hasn't been set.
1236 if (LL_IS_ZERO(mStartTime
) && (aStateFlags
& STATE_START
))
1237 SetStartTime(PR_Now());
1239 // When we break the ref cycle with mPersist, we don't want to lose
1240 // access to out member vars!
1241 nsRefPtr
<nsDownload
> kungFuDeathGrip(this);
1243 // We need to update mDownloadState before updating the dialog, because
1244 // that will close and call CancelDownload if it was the last open window.
1245 nsresult rv
= NS_OK
;
1246 if (aStateFlags
& STATE_STOP
) {
1247 if (mDownloadState
== DOWNLOADING
|| mDownloadState
== NOTSTARTED
) {
1248 mDownloadState
= FINISHED
;
1250 // Set file size at the end of a transfer (for unknown transfer amounts)
1251 if (mMaxBytes
== -1)
1252 mMaxBytes
= mCurrBytes
;
1254 // Files less than 1Kb shouldn't show up as 0Kb.
1255 if (mMaxBytes
< 1024) {
1260 mPercentComplete
= 100;
1262 // Play a sound or show an alert when the download finishes
1263 PRBool playSound
= PR_FALSE
;
1264 PRBool showAlert
= PR_FALSE
;
1265 nsXPIDLCString soundStr
;
1267 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService("@mozilla.org/preferences-service;1");
1270 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
1271 prefs
->GetBranch(nsnull
, getter_AddRefs(prefBranch
));
1273 rv
= prefBranch
->GetBoolPref("browser.download.finished_download_sound", &playSound
);
1274 if (NS_SUCCEEDED(rv
) && playSound
)
1275 prefBranch
->GetCharPref("browser.download.finished_sound_url", getter_Copies(soundStr
));
1276 rv
= prefBranch
->GetBoolPref("browser.download.finished_download_alert", &showAlert
);
1278 showAlert
= PR_FALSE
;
1282 if (!soundStr
.IsEmpty()) {
1283 if (!mDownloadManager
->mSoundInterface
) {
1284 mDownloadManager
->mSoundInterface
= do_CreateInstance("@mozilla.org/sound;1");
1286 if (mDownloadManager
->mSoundInterface
) {
1287 nsCOMPtr
<nsIURI
> soundURI
;
1289 NS_NewURI(getter_AddRefs(soundURI
), soundStr
);
1290 nsCOMPtr
<nsIURL
> soundURL(do_QueryInterface(soundURI
));
1292 mDownloadManager
->mSoundInterface
->Play(soundURL
);
1294 mDownloadManager
->mSoundInterface
->Beep();
1298 DisplayDownloadFinishedAlert();
1301 rv
= GetFilePathUTF8(mTarget
, path
);
1302 // can't do an early return; have to break reference cycle below
1303 if (NS_SUCCEEDED(rv
)) {
1304 mDownloadManager
->DownloadEnded(path
, nsnull
);
1308 // break the cycle we created in AddDownload
1309 mCancelable
= nsnull
;
1310 // and the one with the progress dialog
1312 mDialog
->SetObserver(nsnull
);
1317 if (mDownloadManager
->MustUpdateUI()) {
1318 nsCOMPtr
<nsIDownloadProgressListener
> internalListener
;
1319 mDownloadManager
->GetInternalListener(getter_AddRefs(internalListener
));
1320 if (internalListener
)
1321 internalListener
->OnStateChange(aWebProgress
, aRequest
, aStateFlags
, aStatus
, this);
1324 if (mDialogListener
) {
1325 mDialogListener
->OnStateChange(aWebProgress
, aRequest
, aStateFlags
, aStatus
, this);
1326 if (aStateFlags
& STATE_STOP
) {
1327 // Break this cycle, too
1328 mDialogListener
= nsnull
;
1336 nsDownload::OnSecurityChange(nsIWebProgress
*aWebProgress
,
1337 nsIRequest
*aRequest
, PRUint32 aState
)
1339 if (mDownloadManager
->MustUpdateUI()) {
1340 nsCOMPtr
<nsIDownloadProgressListener
> internalListener
;
1341 mDownloadManager
->GetInternalListener(getter_AddRefs(internalListener
));
1342 if (internalListener
)
1343 internalListener
->OnSecurityChange(aWebProgress
, aRequest
, aState
, this);
1346 if (mDialogListener
)
1347 mDialogListener
->OnSecurityChange(aWebProgress
, aRequest
, aState
, this);
1352 ///////////////////////////////////////////////////////////////////////////////
1356 nsDownload::Init(nsIURI
* aSource
,
1358 const nsAString
& aDisplayName
,
1359 nsIMIMEInfo
*aMIMEInfo
,
1361 nsILocalFile
* aTempFile
,
1362 nsICancelable
* aCancelable
)
1364 NS_NOTREACHED("Huh...how did we get here?!");
1369 nsDownload::GetDisplayName(nsAString
&aDisplayName
)
1371 aDisplayName
= mDisplayName
;
1376 nsDownload::GetCancelable(nsICancelable
** aCancelable
)
1378 *aCancelable
= mCancelable
;
1379 NS_IF_ADDREF(*aCancelable
);
1384 nsDownload::GetTarget(nsIURI
** aTarget
)
1387 NS_IF_ADDREF(*aTarget
);
1392 nsDownload::GetSource(nsIURI
** aSource
)
1395 NS_IF_ADDREF(*aSource
);
1400 nsDownload::GetStartTime(PRInt64
* aStartTime
)
1402 *aStartTime
= mStartTime
;
1407 nsDownload::GetPercentComplete(PRInt32
* aPercentComplete
)
1409 *aPercentComplete
= mPercentComplete
;
1414 nsDownload::GetAmountTransferred(PRUint64
* aAmountTransferred
)
1416 *aAmountTransferred
= mCurrBytes
;
1421 nsDownload::GetSize(PRUint64
* aSize
)
1428 nsDownload::GetMIMEInfo(nsIMIMEInfo
** aMIMEInfo
)
1430 *aMIMEInfo
= mMIMEInfo
;
1431 NS_IF_ADDREF(*aMIMEInfo
);
1436 nsDownload::GetTargetFile(nsILocalFile
** aTargetFile
)
1440 nsCOMPtr
<nsIFileURL
> fileURL
= do_QueryInterface(mTarget
, &rv
);
1441 if (NS_FAILED(rv
)) return rv
;
1443 nsCOMPtr
<nsIFile
> file
;
1444 rv
= fileURL
->GetFile(getter_AddRefs(file
));
1445 if (NS_SUCCEEDED(rv
))
1446 rv
= CallQueryInterface(file
, aTargetFile
);
1451 nsDownload::GetSpeed(double* aSpeed
)
1458 nsDownload::GetId(PRUint32
*aId
)
1460 return NS_ERROR_NOT_IMPLEMENTED
;
1464 nsDownload::GetState(PRInt16
*aState
)
1466 *aState
= mDownloadState
;
1471 nsDownload::SetTempFile(nsILocalFile
* aTempFile
)
1473 mTempFile
= aTempFile
;