1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/download/download_manager_impl.h"
10 #include "base/callback.h"
11 #include "base/debug/alias.h"
12 #include "base/i18n/case_conversion.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "base/supports_user_data.h"
19 #include "base/synchronization/lock.h"
20 #include "build/build_config.h"
21 #include "content/browser/byte_stream.h"
22 #include "content/browser/download/download_create_info.h"
23 #include "content/browser/download/download_file_factory.h"
24 #include "content/browser/download/download_item_factory.h"
25 #include "content/browser/download/download_item_impl.h"
26 #include "content/browser/download/download_stats.h"
27 #include "content/browser/loader/resource_dispatcher_host_impl.h"
28 #include "content/browser/renderer_host/render_view_host_impl.h"
29 #include "content/browser/web_contents/web_contents_impl.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/content_browser_client.h"
33 #include "content/public/browser/download_interrupt_reasons.h"
34 #include "content/public/browser/download_manager_delegate.h"
35 #include "content/public/browser/download_url_parameters.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/notification_types.h"
38 #include "content/public/browser/render_process_host.h"
39 #include "content/public/browser/resource_context.h"
40 #include "content/public/browser/web_contents_delegate.h"
41 #include "content/public/common/referrer.h"
42 #include "net/base/elements_upload_data_stream.h"
43 #include "net/base/load_flags.h"
44 #include "net/base/request_priority.h"
45 #include "net/base/upload_bytes_element_reader.h"
46 #include "net/url_request/url_request_context.h"
47 #include "url/origin.h"
52 void BeginDownload(scoped_ptr
<DownloadUrlParameters
> params
,
54 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
55 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
56 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
57 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
58 scoped_ptr
<net::URLRequest
> request(
59 params
->resource_context()->GetRequestContext()->CreateRequest(
60 params
->url(), net::DEFAULT_PRIORITY
, NULL
));
61 request
->set_method(params
->method());
62 if (!params
->post_body().empty()) {
63 const std::string
& body
= params
->post_body();
64 scoped_ptr
<net::UploadElementReader
> reader(
65 net::UploadOwnedBytesElementReader::CreateWithString(body
));
67 net::ElementsUploadDataStream::CreateWithReader(reader
.Pass(), 0));
69 if (params
->post_id() >= 0) {
70 // The POST in this case does not have an actual body, and only works
71 // when retrieving data from cache. This is done because we don't want
72 // to do a re-POST without user consent, and currently don't have a good
73 // plan on how to display the UI for that.
74 DCHECK(params
->prefer_cache());
75 DCHECK_EQ("POST", params
->method());
76 ScopedVector
<net::UploadElementReader
> element_readers
;
77 request
->set_upload(make_scoped_ptr(
78 new net::ElementsUploadDataStream(element_readers
.Pass(),
82 // If we're not at the beginning of the file, retrieve only the remaining
84 bool has_last_modified
= !params
->last_modified().empty();
85 bool has_etag
= !params
->etag().empty();
87 // If we've asked for a range, we want to make sure that we only
88 // get that range if our current copy of the information is good.
89 // We shouldn't be asked to continue if we don't have a verifier.
90 DCHECK(params
->offset() == 0 || has_etag
|| has_last_modified
);
92 if (params
->offset() > 0) {
93 request
->SetExtraRequestHeaderByName(
95 base::StringPrintf("bytes=%" PRId64
"-", params
->offset()),
98 if (has_last_modified
) {
99 request
->SetExtraRequestHeaderByName("If-Unmodified-Since",
100 params
->last_modified(),
104 request
->SetExtraRequestHeaderByName("If-Match", params
->etag(), true);
108 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter
109 = params
->request_headers_begin();
110 iter
!= params
->request_headers_end();
112 request
->SetExtraRequestHeaderByName(
113 iter
->first
, iter
->second
, false /*overwrite*/);
116 scoped_ptr
<DownloadSaveInfo
> save_info(new DownloadSaveInfo());
117 save_info
->file_path
= params
->file_path();
118 save_info
->suggested_name
= params
->suggested_name();
119 save_info
->offset
= params
->offset();
120 save_info
->hash_state
= params
->hash_state();
121 save_info
->prompt_for_save_location
= params
->prompt();
122 save_info
->file
= params
->GetFile();
124 ResourceDispatcherHost::Get()->BeginDownload(
127 params
->content_initiated(),
128 params
->resource_context(),
129 params
->render_process_host_id(),
130 params
->render_view_host_routing_id(),
131 params
->render_frame_host_routing_id(),
132 params
->prefer_cache(),
133 params
->do_not_prompt_for_login(),
139 class MapValueIteratorAdapter
{
141 explicit MapValueIteratorAdapter(
142 base::hash_map
<int64
, DownloadItem
*>::const_iterator iter
)
145 ~MapValueIteratorAdapter() {}
147 DownloadItem
* operator*() { return iter_
->second
; }
149 MapValueIteratorAdapter
& operator++() {
154 bool operator!=(const MapValueIteratorAdapter
& that
) const {
155 return iter_
!= that
.iter_
;
159 base::hash_map
<int64
, DownloadItem
*>::const_iterator iter_
;
160 // Allow copy and assign.
163 class DownloadItemFactoryImpl
: public DownloadItemFactory
{
165 DownloadItemFactoryImpl() {}
166 ~DownloadItemFactoryImpl() override
{}
168 DownloadItemImpl
* CreatePersistedItem(
169 DownloadItemImplDelegate
* delegate
,
171 const base::FilePath
& current_path
,
172 const base::FilePath
& target_path
,
173 const std::vector
<GURL
>& url_chain
,
174 const GURL
& referrer_url
,
175 const std::string
& mime_type
,
176 const std::string
& original_mime_type
,
177 const base::Time
& start_time
,
178 const base::Time
& end_time
,
179 const std::string
& etag
,
180 const std::string
& last_modified
,
181 int64 received_bytes
,
183 DownloadItem::DownloadState state
,
184 DownloadDangerType danger_type
,
185 DownloadInterruptReason interrupt_reason
,
187 const net::BoundNetLog
& bound_net_log
) override
{
188 return new DownloadItemImpl(
210 DownloadItemImpl
* CreateActiveItem(
211 DownloadItemImplDelegate
* delegate
,
213 const DownloadCreateInfo
& info
,
214 const net::BoundNetLog
& bound_net_log
) override
{
215 return new DownloadItemImpl(delegate
, download_id
, info
, bound_net_log
);
218 DownloadItemImpl
* CreateSavePageItem(
219 DownloadItemImplDelegate
* delegate
,
221 const base::FilePath
& path
,
223 const std::string
& mime_type
,
224 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
,
225 const net::BoundNetLog
& bound_net_log
) override
{
226 return new DownloadItemImpl(delegate
, download_id
, path
, url
,
227 mime_type
, request_handle
.Pass(),
234 DownloadManagerImpl::DownloadManagerImpl(
235 net::NetLog
* net_log
,
236 BrowserContext
* browser_context
)
237 : item_factory_(new DownloadItemFactoryImpl()),
238 file_factory_(new DownloadFileFactory()),
240 shutdown_needed_(true),
241 browser_context_(browser_context
),
244 weak_factory_(this) {
245 DCHECK(browser_context
);
248 DownloadManagerImpl::~DownloadManagerImpl() {
249 DCHECK(!shutdown_needed_
);
252 DownloadItemImpl
* DownloadManagerImpl::CreateActiveItem(
253 uint32 id
, const DownloadCreateInfo
& info
) {
254 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
255 DCHECK(!ContainsKey(downloads_
, id
));
256 net::BoundNetLog bound_net_log
=
257 net::BoundNetLog::Make(net_log_
, net::NetLog::SOURCE_DOWNLOAD
);
258 DownloadItemImpl
* download
=
259 item_factory_
->CreateActiveItem(this, id
, info
, bound_net_log
);
260 downloads_
[id
] = download
;
264 void DownloadManagerImpl::GetNextId(const DownloadIdCallback
& callback
) {
265 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
267 delegate_
->GetNextId(callback
);
270 static uint32 next_id
= content::DownloadItem::kInvalidId
+ 1;
271 callback
.Run(next_id
++);
274 void DownloadManagerImpl::DetermineDownloadTarget(
275 DownloadItemImpl
* item
, const DownloadTargetCallback
& callback
) {
276 // Note that this next call relies on
277 // DownloadItemImplDelegate::DownloadTargetCallback and
278 // DownloadManagerDelegate::DownloadTargetCallback having the same
279 // type. If the types ever diverge, gasket code will need to
281 if (!delegate_
|| !delegate_
->DetermineDownloadTarget(item
, callback
)) {
282 base::FilePath target_path
= item
->GetForcedFilePath();
283 // TODO(asanka): Determine a useful path if |target_path| is empty.
284 callback
.Run(target_path
,
285 DownloadItem::TARGET_DISPOSITION_OVERWRITE
,
286 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
,
291 bool DownloadManagerImpl::ShouldCompleteDownload(
292 DownloadItemImpl
* item
, const base::Closure
& complete_callback
) {
294 delegate_
->ShouldCompleteDownload(item
, complete_callback
)) {
297 // Otherwise, the delegate has accepted responsibility to run the
298 // callback when the download is ready for completion.
302 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(
303 const base::FilePath
& path
) {
307 return delegate_
->ShouldOpenFileBasedOnExtension(path
);
310 bool DownloadManagerImpl::ShouldOpenDownload(
311 DownloadItemImpl
* item
, const ShouldOpenDownloadCallback
& callback
) {
315 // Relies on DownloadItemImplDelegate::ShouldOpenDownloadCallback and
316 // DownloadManagerDelegate::DownloadOpenDelayedCallback "just happening"
317 // to have the same type :-}.
318 return delegate_
->ShouldOpenDownload(item
, callback
);
321 void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate
* delegate
) {
322 delegate_
= delegate
;
325 DownloadManagerDelegate
* DownloadManagerImpl::GetDelegate() const {
329 void DownloadManagerImpl::Shutdown() {
330 DVLOG(20) << __FUNCTION__
<< "()"
331 << " shutdown_needed_ = " << shutdown_needed_
;
332 if (!shutdown_needed_
)
334 shutdown_needed_
= false;
336 FOR_EACH_OBSERVER(Observer
, observers_
, ManagerGoingDown(this));
337 // TODO(benjhayden): Consider clearing observers_.
339 // If there are in-progress downloads, cancel them. This also goes for
340 // dangerous downloads which will remain in history if they aren't explicitly
341 // accepted or discarded. Canceling will remove the intermediate download
343 for (DownloadMap::iterator it
= downloads_
.begin(); it
!= downloads_
.end();
345 DownloadItemImpl
* download
= it
->second
;
346 if (download
->GetState() == DownloadItem::IN_PROGRESS
)
347 download
->Cancel(false);
349 STLDeleteValues(&downloads_
);
351 // We'll have nothing more to report to the observers after this point.
355 delegate_
->Shutdown();
359 void DownloadManagerImpl::StartDownload(
360 scoped_ptr
<DownloadCreateInfo
> info
,
361 scoped_ptr
<ByteStreamReader
> stream
,
362 const DownloadUrlParameters::OnStartedCallback
& on_started
) {
363 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
365 uint32 download_id
= info
->download_id
;
366 const bool new_download
= (download_id
== content::DownloadItem::kInvalidId
);
367 base::Callback
<void(uint32
)> got_id(base::Bind(
368 &DownloadManagerImpl::StartDownloadWithId
,
369 weak_factory_
.GetWeakPtr(),
370 base::Passed(info
.Pass()),
371 base::Passed(stream
.Pass()),
377 got_id
.Run(download_id
);
381 void DownloadManagerImpl::StartDownloadWithId(
382 scoped_ptr
<DownloadCreateInfo
> info
,
383 scoped_ptr
<ByteStreamReader
> stream
,
384 const DownloadUrlParameters::OnStartedCallback
& on_started
,
387 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
388 DCHECK_NE(content::DownloadItem::kInvalidId
, id
);
389 DownloadItemImpl
* download
= NULL
;
391 download
= CreateActiveItem(id
, *info
);
393 DownloadMap::iterator item_iterator
= downloads_
.find(id
);
394 // Trying to resume an interrupted download.
395 if (item_iterator
== downloads_
.end() ||
396 (item_iterator
->second
->GetState() == DownloadItem::CANCELLED
)) {
397 // If the download is no longer known to the DownloadManager, then it was
398 // removed after it was resumed. Ignore. If the download is cancelled
399 // while resuming, then also ignore the request.
400 info
->request_handle
.CancelRequest();
401 if (!on_started
.is_null())
402 on_started
.Run(NULL
, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
);
405 download
= item_iterator
->second
;
406 DCHECK_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
407 download
->MergeOriginInfoOnResume(*info
);
410 base::FilePath default_download_directory
;
412 base::FilePath website_save_directory
; // Unused
413 bool skip_dir_check
= false; // Unused
414 delegate_
->GetSaveDir(GetBrowserContext(), &website_save_directory
,
415 &default_download_directory
, &skip_dir_check
);
418 // Create the download file and start the download.
419 scoped_ptr
<DownloadFile
> download_file(
420 file_factory_
->CreateFile(
421 info
->save_info
.Pass(), default_download_directory
,
422 info
->url(), info
->referrer_url
,
423 delegate_
&& delegate_
->GenerateFileHash(),
424 stream
.Pass(), download
->GetBoundNetLog(),
425 download
->DestinationObserverAsWeakPtr()));
427 // Attach the client ID identifying the app to the AV system.
428 if (download_file
.get() && delegate_
) {
429 download_file
->SetClientGuid(
430 delegate_
->ApplicationClientIdForFileScanning());
433 scoped_ptr
<DownloadRequestHandleInterface
> req_handle(
434 new DownloadRequestHandle(info
->request_handle
));
435 download
->Start(download_file
.Pass(), req_handle
.Pass());
437 // For interrupted downloads, Start() will transition the state to
438 // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
439 // For new downloads, we notify here, rather than earlier, so that
440 // the download_file is bound to download and all the usual
441 // setters (e.g. Cancel) work.
443 FOR_EACH_OBSERVER(Observer
, observers_
, OnDownloadCreated(this, download
));
445 if (!on_started
.is_null())
446 on_started
.Run(download
, DOWNLOAD_INTERRUPT_REASON_NONE
);
449 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
450 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
451 for (DownloadMap::iterator it
= downloads_
.begin();
452 it
!= downloads_
.end(); ++it
) {
453 DownloadItemImpl
* item
= it
->second
;
454 CheckForFileRemoval(item
);
458 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl
* download_item
) {
459 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
460 if ((download_item
->GetState() == DownloadItem::COMPLETE
) &&
461 !download_item
->GetFileExternallyRemoved() &&
463 delegate_
->CheckForFileExistence(
465 base::Bind(&DownloadManagerImpl::OnFileExistenceChecked
,
466 weak_factory_
.GetWeakPtr(), download_item
->GetId()));
470 void DownloadManagerImpl::OnFileExistenceChecked(uint32 download_id
,
472 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
473 if (!result
) { // File does not exist.
474 if (ContainsKey(downloads_
, download_id
))
475 downloads_
[download_id
]->OnDownloadedFileRemoved();
479 BrowserContext
* DownloadManagerImpl::GetBrowserContext() const {
480 return browser_context_
;
483 void DownloadManagerImpl::CreateSavePackageDownloadItem(
484 const base::FilePath
& main_file_path
,
485 const GURL
& page_url
,
486 const std::string
& mime_type
,
487 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
,
488 const DownloadItemImplCreated
& item_created
) {
489 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
490 GetNextId(base::Bind(
491 &DownloadManagerImpl::CreateSavePackageDownloadItemWithId
,
492 weak_factory_
.GetWeakPtr(),
496 base::Passed(request_handle
.Pass()),
500 void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
501 const base::FilePath
& main_file_path
,
502 const GURL
& page_url
,
503 const std::string
& mime_type
,
504 scoped_ptr
<DownloadRequestHandleInterface
> request_handle
,
505 const DownloadItemImplCreated
& item_created
,
507 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
508 DCHECK_NE(content::DownloadItem::kInvalidId
, id
);
509 DCHECK(!ContainsKey(downloads_
, id
));
510 net::BoundNetLog bound_net_log
=
511 net::BoundNetLog::Make(net_log_
, net::NetLog::SOURCE_DOWNLOAD
);
512 DownloadItemImpl
* download_item
= item_factory_
->CreateSavePageItem(
518 request_handle
.Pass(),
520 downloads_
[download_item
->GetId()] = download_item
;
521 FOR_EACH_OBSERVER(Observer
, observers_
, OnDownloadCreated(
522 this, download_item
));
523 if (!item_created
.is_null())
524 item_created
.Run(download_item
);
527 void DownloadManagerImpl::OnSavePackageSuccessfullyFinished(
528 DownloadItem
* download_item
) {
529 FOR_EACH_OBSERVER(Observer
, observers_
,
530 OnSavePackageSuccessfullyFinished(this, download_item
));
533 // Resume a download of a specific URL. We send the request to the
534 // ResourceDispatcherHost, and let it send us responses like a regular
536 void DownloadManagerImpl::ResumeInterruptedDownload(
537 scoped_ptr
<content::DownloadUrlParameters
> params
,
539 RecordDownloadSource(INITIATED_BY_RESUMPTION
);
540 BrowserThread::PostTask(
543 base::Bind(&BeginDownload
, base::Passed(¶ms
), id
));
546 void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
547 scoped_ptr
<DownloadItemFactory
> item_factory
) {
548 item_factory_
= item_factory
.Pass();
551 void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
552 scoped_ptr
<DownloadFileFactory
> file_factory
) {
553 file_factory_
= file_factory
.Pass();
556 DownloadFileFactory
* DownloadManagerImpl::GetDownloadFileFactoryForTesting() {
557 return file_factory_
.get();
560 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl
* download
) {
564 uint32 download_id
= download
->GetId();
565 if (downloads_
.erase(download_id
) == 0)
572 bool RemoveDownloadBetween(base::Time remove_begin
,
573 base::Time remove_end
,
574 const DownloadItemImpl
* download_item
) {
575 return download_item
->GetStartTime() >= remove_begin
&&
576 (remove_end
.is_null() || download_item
->GetStartTime() < remove_end
);
579 bool RemoveDownloadByOriginAndTime(const url::Origin
& origin
,
580 base::Time remove_begin
,
581 base::Time remove_end
,
582 const DownloadItemImpl
* download_item
) {
583 return origin
.IsSameOriginWith(url::Origin(download_item
->GetURL())) &&
584 RemoveDownloadBetween(remove_begin
, remove_end
, download_item
);
589 int DownloadManagerImpl::RemoveDownloads(const DownloadRemover
& remover
) {
591 DownloadMap::const_iterator it
= downloads_
.begin();
592 while (it
!= downloads_
.end()) {
593 DownloadItemImpl
* download
= it
->second
;
595 // Increment done here to protect against invalidation below.
598 if (download
->GetState() != DownloadItem::IN_PROGRESS
&&
599 remover
.Run(download
)) {
607 int DownloadManagerImpl::RemoveDownloadsByOriginAndTime(
608 const url::Origin
& origin
,
609 base::Time remove_begin
,
610 base::Time remove_end
) {
611 return RemoveDownloads(base::Bind(&RemoveDownloadByOriginAndTime
,
612 base::ConstRef(origin
), remove_begin
,
616 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin
,
617 base::Time remove_end
) {
618 return RemoveDownloads(
619 base::Bind(&RemoveDownloadBetween
, remove_begin
, remove_end
));
622 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin
) {
623 return RemoveDownloadsBetween(remove_begin
, base::Time());
626 int DownloadManagerImpl::RemoveAllDownloads() {
627 // The null times make the date range unbounded.
628 int num_deleted
= RemoveDownloadsBetween(base::Time(), base::Time());
629 RecordClearAllSize(num_deleted
);
633 void DownloadManagerImpl::DownloadUrl(
634 scoped_ptr
<DownloadUrlParameters
> params
) {
635 if (params
->post_id() >= 0) {
636 // Check this here so that the traceback is more useful.
637 DCHECK(params
->prefer_cache());
638 DCHECK_EQ("POST", params
->method());
640 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
, base::Bind(
641 &BeginDownload
, base::Passed(¶ms
),
642 content::DownloadItem::kInvalidId
));
645 void DownloadManagerImpl::AddObserver(Observer
* observer
) {
646 observers_
.AddObserver(observer
);
649 void DownloadManagerImpl::RemoveObserver(Observer
* observer
) {
650 observers_
.RemoveObserver(observer
);
653 DownloadItem
* DownloadManagerImpl::CreateDownloadItem(
655 const base::FilePath
& current_path
,
656 const base::FilePath
& target_path
,
657 const std::vector
<GURL
>& url_chain
,
658 const GURL
& referrer_url
,
659 const std::string
& mime_type
,
660 const std::string
& original_mime_type
,
661 const base::Time
& start_time
,
662 const base::Time
& end_time
,
663 const std::string
& etag
,
664 const std::string
& last_modified
,
665 int64 received_bytes
,
667 DownloadItem::DownloadState state
,
668 DownloadDangerType danger_type
,
669 DownloadInterruptReason interrupt_reason
,
671 if (ContainsKey(downloads_
, id
)) {
675 DownloadItemImpl
* item
= item_factory_
->CreatePersistedItem(
694 net::BoundNetLog::Make(net_log_
, net::NetLog::SOURCE_DOWNLOAD
));
695 downloads_
[id
] = item
;
696 FOR_EACH_OBSERVER(Observer
, observers_
, OnDownloadCreated(this, item
));
697 DVLOG(20) << __FUNCTION__
<< "() download = " << item
->DebugString(true);
701 int DownloadManagerImpl::InProgressCount() const {
703 for (DownloadMap::const_iterator it
= downloads_
.begin();
704 it
!= downloads_
.end(); ++it
) {
705 if (it
->second
->GetState() == DownloadItem::IN_PROGRESS
)
711 int DownloadManagerImpl::NonMaliciousInProgressCount() const {
713 for (DownloadMap::const_iterator it
= downloads_
.begin();
714 it
!= downloads_
.end(); ++it
) {
715 if (it
->second
->GetState() == DownloadItem::IN_PROGRESS
&&
716 it
->second
->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_URL
&&
717 it
->second
->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT
&&
718 it
->second
->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST
&&
719 it
->second
->GetDangerType() !=
720 DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED
) {
727 DownloadItem
* DownloadManagerImpl::GetDownload(uint32 download_id
) {
728 return ContainsKey(downloads_
, download_id
) ? downloads_
[download_id
] : NULL
;
731 void DownloadManagerImpl::GetAllDownloads(DownloadVector
* downloads
) {
732 for (DownloadMap::iterator it
= downloads_
.begin();
733 it
!= downloads_
.end(); ++it
) {
734 downloads
->push_back(it
->second
);
738 void DownloadManagerImpl::OpenDownload(DownloadItemImpl
* download
) {
739 int num_unopened
= 0;
740 for (DownloadMap::iterator it
= downloads_
.begin();
741 it
!= downloads_
.end(); ++it
) {
742 DownloadItemImpl
* item
= it
->second
;
743 if ((item
->GetState() == DownloadItem::COMPLETE
) &&
747 RecordOpensOutstanding(num_unopened
);
750 delegate_
->OpenDownload(download
);
753 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl
* download
) {
755 delegate_
->ShowDownloadInShell(download
);
758 } // namespace content