IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / download / download_manager_impl.cc
blobf796f2ff6821a9e0c84804b696f6cb87e59ea874
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"
7 #include <iterator>
9 #include "base/bind.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/load_flags.h"
43 #include "net/base/request_priority.h"
44 #include "net/base/upload_bytes_element_reader.h"
45 #include "net/base/upload_data_stream.h"
46 #include "net/url_request/url_request_context.h"
48 namespace content {
49 namespace {
51 void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
52 uint32 download_id) {
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
54 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
55 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
56 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
57 scoped_ptr<net::URLRequest> request(
58 params->resource_context()->GetRequestContext()->CreateRequest(
59 params->url(), net::DEFAULT_PRIORITY, NULL));
60 request->SetLoadFlags(request->load_flags() | params->load_flags());
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));
66 request->set_upload(make_scoped_ptr(
67 net::UploadDataStream::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::UploadDataStream(element_readers.Pass(), params->post_id())));
81 // If we're not at the beginning of the file, retrieve only the remaining
82 // portion.
83 bool has_last_modified = !params->last_modified().empty();
84 bool has_etag = !params->etag().empty();
86 // If we've asked for a range, we want to make sure that we only
87 // get that range if our current copy of the information is good.
88 // We shouldn't be asked to continue if we don't have a verifier.
89 DCHECK(params->offset() == 0 || has_etag || has_last_modified);
91 if (params->offset() > 0) {
92 request->SetExtraRequestHeaderByName(
93 "Range",
94 base::StringPrintf("bytes=%" PRId64 "-", params->offset()),
95 true);
97 if (has_last_modified) {
98 request->SetExtraRequestHeaderByName("If-Unmodified-Since",
99 params->last_modified(),
100 true);
102 if (has_etag) {
103 request->SetExtraRequestHeaderByName("If-Match", params->etag(), true);
107 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter
108 = params->request_headers_begin();
109 iter != params->request_headers_end();
110 ++iter) {
111 request->SetExtraRequestHeaderByName(
112 iter->first, iter->second, false /*overwrite*/);
115 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
116 save_info->file_path = params->file_path();
117 save_info->suggested_name = params->suggested_name();
118 save_info->offset = params->offset();
119 save_info->hash_state = params->hash_state();
120 save_info->prompt_for_save_location = params->prompt();
121 save_info->file_stream = params->GetFileStream();
123 ResourceDispatcherHost::Get()->BeginDownload(
124 request.Pass(),
125 params->referrer(),
126 params->content_initiated(),
127 params->resource_context(),
128 params->render_process_host_id(),
129 params->render_view_host_routing_id(),
130 params->prefer_cache(),
131 save_info.Pass(),
132 download_id,
133 params->callback());
136 class MapValueIteratorAdapter {
137 public:
138 explicit MapValueIteratorAdapter(
139 base::hash_map<int64, DownloadItem*>::const_iterator iter)
140 : iter_(iter) {
142 ~MapValueIteratorAdapter() {}
144 DownloadItem* operator*() { return iter_->second; }
146 MapValueIteratorAdapter& operator++() {
147 ++iter_;
148 return *this;
151 bool operator!=(const MapValueIteratorAdapter& that) const {
152 return iter_ != that.iter_;
155 private:
156 base::hash_map<int64, DownloadItem*>::const_iterator iter_;
157 // Allow copy and assign.
160 class DownloadItemFactoryImpl : public DownloadItemFactory {
161 public:
162 DownloadItemFactoryImpl() {}
163 virtual ~DownloadItemFactoryImpl() {}
165 virtual DownloadItemImpl* CreatePersistedItem(
166 DownloadItemImplDelegate* delegate,
167 uint32 download_id,
168 const base::FilePath& current_path,
169 const base::FilePath& target_path,
170 const std::vector<GURL>& url_chain,
171 const GURL& referrer_url,
172 const base::Time& start_time,
173 const base::Time& end_time,
174 const std::string& etag,
175 const std::string& last_modified,
176 int64 received_bytes,
177 int64 total_bytes,
178 DownloadItem::DownloadState state,
179 DownloadDangerType danger_type,
180 DownloadInterruptReason interrupt_reason,
181 bool opened,
182 const net::BoundNetLog& bound_net_log) OVERRIDE {
183 return new DownloadItemImpl(
184 delegate,
185 download_id,
186 current_path,
187 target_path,
188 url_chain,
189 referrer_url,
190 start_time,
191 end_time,
192 etag,
193 last_modified,
194 received_bytes,
195 total_bytes,
196 state,
197 danger_type,
198 interrupt_reason,
199 opened,
200 bound_net_log);
203 virtual DownloadItemImpl* CreateActiveItem(
204 DownloadItemImplDelegate* delegate,
205 uint32 download_id,
206 const DownloadCreateInfo& info,
207 const net::BoundNetLog& bound_net_log) OVERRIDE {
208 return new DownloadItemImpl(delegate, download_id, info, bound_net_log);
211 virtual DownloadItemImpl* CreateSavePageItem(
212 DownloadItemImplDelegate* delegate,
213 uint32 download_id,
214 const base::FilePath& path,
215 const GURL& url,
216 const std::string& mime_type,
217 scoped_ptr<DownloadRequestHandleInterface> request_handle,
218 const net::BoundNetLog& bound_net_log) OVERRIDE {
219 return new DownloadItemImpl(delegate, download_id, path, url,
220 mime_type, request_handle.Pass(),
221 bound_net_log);
225 } // namespace
227 DownloadManagerImpl::DownloadManagerImpl(
228 net::NetLog* net_log,
229 BrowserContext* browser_context)
230 : item_factory_(new DownloadItemFactoryImpl()),
231 file_factory_(new DownloadFileFactory()),
232 history_size_(0),
233 shutdown_needed_(true),
234 browser_context_(browser_context),
235 delegate_(NULL),
236 net_log_(net_log),
237 weak_factory_(this) {
238 DCHECK(browser_context);
241 DownloadManagerImpl::~DownloadManagerImpl() {
242 DCHECK(!shutdown_needed_);
245 DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
246 uint32 id, const DownloadCreateInfo& info) {
247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
248 DCHECK(!ContainsKey(downloads_, id));
249 net::BoundNetLog bound_net_log =
250 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
251 DownloadItemImpl* download =
252 item_factory_->CreateActiveItem(this, id, info, bound_net_log);
253 downloads_[id] = download;
254 return download;
257 void DownloadManagerImpl::GetNextId(const DownloadIdCallback& callback) {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
259 if (delegate_) {
260 delegate_->GetNextId(callback);
261 return;
263 static uint32 next_id = content::DownloadItem::kInvalidId + 1;
264 callback.Run(next_id++);
267 void DownloadManagerImpl::DetermineDownloadTarget(
268 DownloadItemImpl* item, const DownloadTargetCallback& callback) {
269 // Note that this next call relies on
270 // DownloadItemImplDelegate::DownloadTargetCallback and
271 // DownloadManagerDelegate::DownloadTargetCallback having the same
272 // type. If the types ever diverge, gasket code will need to
273 // be written here.
274 if (!delegate_ || !delegate_->DetermineDownloadTarget(item, callback)) {
275 base::FilePath target_path = item->GetForcedFilePath();
276 // TODO(asanka): Determine a useful path if |target_path| is empty.
277 callback.Run(target_path,
278 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
279 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
280 target_path);
284 bool DownloadManagerImpl::ShouldCompleteDownload(
285 DownloadItemImpl* item, const base::Closure& complete_callback) {
286 if (!delegate_ ||
287 delegate_->ShouldCompleteDownload(item, complete_callback)) {
288 return true;
290 // Otherwise, the delegate has accepted responsibility to run the
291 // callback when the download is ready for completion.
292 return false;
295 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(
296 const base::FilePath& path) {
297 if (!delegate_)
298 return false;
300 return delegate_->ShouldOpenFileBasedOnExtension(path);
303 bool DownloadManagerImpl::ShouldOpenDownload(
304 DownloadItemImpl* item, const ShouldOpenDownloadCallback& callback) {
305 if (!delegate_)
306 return true;
308 // Relies on DownloadItemImplDelegate::ShouldOpenDownloadCallback and
309 // DownloadManagerDelegate::DownloadOpenDelayedCallback "just happening"
310 // to have the same type :-}.
311 return delegate_->ShouldOpenDownload(item, callback);
314 void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate* delegate) {
315 delegate_ = delegate;
318 DownloadManagerDelegate* DownloadManagerImpl::GetDelegate() const {
319 return delegate_;
322 void DownloadManagerImpl::Shutdown() {
323 VLOG(20) << __FUNCTION__ << "()"
324 << " shutdown_needed_ = " << shutdown_needed_;
325 if (!shutdown_needed_)
326 return;
327 shutdown_needed_ = false;
329 FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown(this));
330 // TODO(benjhayden): Consider clearing observers_.
332 // If there are in-progress downloads, cancel them. This also goes for
333 // dangerous downloads which will remain in history if they aren't explicitly
334 // accepted or discarded. Canceling will remove the intermediate download
335 // file.
336 for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end();
337 ++it) {
338 DownloadItemImpl* download = it->second;
339 if (download->GetState() == DownloadItem::IN_PROGRESS)
340 download->Cancel(false);
342 STLDeleteValues(&downloads_);
343 downloads_.clear();
345 // We'll have nothing more to report to the observers after this point.
346 observers_.Clear();
348 if (delegate_)
349 delegate_->Shutdown();
350 delegate_ = NULL;
353 void DownloadManagerImpl::StartDownload(
354 scoped_ptr<DownloadCreateInfo> info,
355 scoped_ptr<ByteStreamReader> stream,
356 const DownloadUrlParameters::OnStartedCallback& on_started) {
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
358 DCHECK(info);
359 uint32 download_id = info->download_id;
360 const bool new_download = (download_id == content::DownloadItem::kInvalidId);
361 base::Callback<void(uint32)> got_id(base::Bind(
362 &DownloadManagerImpl::StartDownloadWithId,
363 weak_factory_.GetWeakPtr(),
364 base::Passed(info.Pass()),
365 base::Passed(stream.Pass()),
366 on_started,
367 new_download));
368 if (new_download) {
369 GetNextId(got_id);
370 } else {
371 got_id.Run(download_id);
375 void DownloadManagerImpl::StartDownloadWithId(
376 scoped_ptr<DownloadCreateInfo> info,
377 scoped_ptr<ByteStreamReader> stream,
378 const DownloadUrlParameters::OnStartedCallback& on_started,
379 bool new_download,
380 uint32 id) {
381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
382 DCHECK_NE(content::DownloadItem::kInvalidId, id);
383 DownloadItemImpl* download = NULL;
384 if (new_download) {
385 download = CreateActiveItem(id, *info);
386 } else {
387 DownloadMap::iterator item_iterator = downloads_.find(id);
388 // Trying to resume an interrupted download.
389 if (item_iterator == downloads_.end() ||
390 (item_iterator->second->GetState() == DownloadItem::CANCELLED)) {
391 // If the download is no longer known to the DownloadManager, then it was
392 // removed after it was resumed. Ignore. If the download is cancelled
393 // while resuming, then also ignore the request.
394 info->request_handle.CancelRequest();
395 if (!on_started.is_null())
396 on_started.Run(NULL, net::ERR_ABORTED);
397 return;
399 download = item_iterator->second;
400 DCHECK_EQ(DownloadItem::INTERRUPTED, download->GetState());
401 download->MergeOriginInfoOnResume(*info);
404 base::FilePath default_download_directory;
405 if (delegate_) {
406 base::FilePath website_save_directory; // Unused
407 bool skip_dir_check = false; // Unused
408 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory,
409 &default_download_directory, &skip_dir_check);
412 // Create the download file and start the download.
413 scoped_ptr<DownloadFile> download_file(
414 file_factory_->CreateFile(
415 info->save_info.Pass(), default_download_directory,
416 info->url(), info->referrer_url,
417 delegate_ && delegate_->GenerateFileHash(),
418 stream.Pass(), download->GetBoundNetLog(),
419 download->DestinationObserverAsWeakPtr()));
421 // Attach the client ID identifying the app to the AV system.
422 if (download_file.get() && delegate_) {
423 download_file->SetClientGuid(
424 delegate_->ApplicationClientIdForFileScanning());
427 scoped_ptr<DownloadRequestHandleInterface> req_handle(
428 new DownloadRequestHandle(info->request_handle));
429 download->Start(download_file.Pass(), req_handle.Pass());
431 // For interrupted downloads, Start() will transition the state to
432 // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
433 // For new downloads, we notify here, rather than earlier, so that
434 // the download_file is bound to download and all the usual
435 // setters (e.g. Cancel) work.
436 if (new_download)
437 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
439 if (!on_started.is_null())
440 on_started.Run(download, net::OK);
443 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 for (DownloadMap::iterator it = downloads_.begin();
446 it != downloads_.end(); ++it) {
447 DownloadItemImpl* item = it->second;
448 CheckForFileRemoval(item);
452 void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
453 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
454 if ((download_item->GetState() == DownloadItem::COMPLETE) &&
455 !download_item->GetFileExternallyRemoved() &&
456 delegate_) {
457 delegate_->CheckForFileExistence(
458 download_item,
459 base::Bind(&DownloadManagerImpl::OnFileExistenceChecked,
460 weak_factory_.GetWeakPtr(), download_item->GetId()));
464 void DownloadManagerImpl::OnFileExistenceChecked(uint32 download_id,
465 bool result) {
466 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
467 if (!result) { // File does not exist.
468 if (ContainsKey(downloads_, download_id))
469 downloads_[download_id]->OnDownloadedFileRemoved(true);
473 BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
474 return browser_context_;
477 void DownloadManagerImpl::CreateSavePackageDownloadItem(
478 const base::FilePath& main_file_path,
479 const GURL& page_url,
480 const std::string& mime_type,
481 scoped_ptr<DownloadRequestHandleInterface> request_handle,
482 const DownloadItemImplCreated& item_created) {
483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484 GetNextId(base::Bind(
485 &DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
486 weak_factory_.GetWeakPtr(),
487 main_file_path,
488 page_url,
489 mime_type,
490 base::Passed(request_handle.Pass()),
491 item_created));
494 void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
495 const base::FilePath& main_file_path,
496 const GURL& page_url,
497 const std::string& mime_type,
498 scoped_ptr<DownloadRequestHandleInterface> request_handle,
499 const DownloadItemImplCreated& item_created,
500 uint32 id) {
501 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
502 DCHECK_NE(content::DownloadItem::kInvalidId, id);
503 DCHECK(!ContainsKey(downloads_, id));
504 net::BoundNetLog bound_net_log =
505 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
506 DownloadItemImpl* download_item = item_factory_->CreateSavePageItem(
507 this,
509 main_file_path,
510 page_url,
511 mime_type,
512 request_handle.Pass(),
513 bound_net_log);
514 downloads_[download_item->GetId()] = download_item;
515 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
516 this, download_item));
517 if (!item_created.is_null())
518 item_created.Run(download_item);
521 void DownloadManagerImpl::OnSavePackageSuccessfullyFinished(
522 DownloadItem* download_item) {
523 FOR_EACH_OBSERVER(Observer, observers_,
524 OnSavePackageSuccessfullyFinished(this, download_item));
527 // Resume a download of a specific URL. We send the request to the
528 // ResourceDispatcherHost, and let it send us responses like a regular
529 // download.
530 void DownloadManagerImpl::ResumeInterruptedDownload(
531 scoped_ptr<content::DownloadUrlParameters> params,
532 uint32 id) {
533 RecordDownloadSource(INITIATED_BY_RESUMPTION);
534 BrowserThread::PostTask(
535 BrowserThread::IO,
536 FROM_HERE,
537 base::Bind(&BeginDownload, base::Passed(&params), id));
540 void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
541 scoped_ptr<DownloadItemFactory> item_factory) {
542 item_factory_ = item_factory.Pass();
545 void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
546 scoped_ptr<DownloadFileFactory> file_factory) {
547 file_factory_ = file_factory.Pass();
550 DownloadFileFactory* DownloadManagerImpl::GetDownloadFileFactoryForTesting() {
551 return file_factory_.get();
554 void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
555 if (!download)
556 return;
558 uint32 download_id = download->GetId();
559 if (downloads_.erase(download_id) == 0)
560 return;
561 delete download;
564 int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
565 base::Time remove_end) {
566 int count = 0;
567 DownloadMap::const_iterator it = downloads_.begin();
568 while (it != downloads_.end()) {
569 DownloadItemImpl* download = it->second;
571 // Increment done here to protect against invalidation below.
572 ++it;
574 if (download->GetStartTime() >= remove_begin &&
575 (remove_end.is_null() || download->GetStartTime() < remove_end) &&
576 (download->GetState() != DownloadItem::IN_PROGRESS)) {
577 // Erases the download from downloads_.
578 download->Remove();
579 count++;
582 return count;
585 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) {
586 return RemoveDownloadsBetween(remove_begin, base::Time());
589 int DownloadManagerImpl::RemoveAllDownloads() {
590 // The null times make the date range unbounded.
591 int num_deleted = RemoveDownloadsBetween(base::Time(), base::Time());
592 RecordClearAllSize(num_deleted);
593 return num_deleted;
596 void DownloadManagerImpl::DownloadUrl(
597 scoped_ptr<DownloadUrlParameters> params) {
598 if (params->post_id() >= 0) {
599 // Check this here so that the traceback is more useful.
600 DCHECK(params->prefer_cache());
601 DCHECK_EQ("POST", params->method());
603 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
604 &BeginDownload, base::Passed(&params),
605 content::DownloadItem::kInvalidId));
608 void DownloadManagerImpl::AddObserver(Observer* observer) {
609 observers_.AddObserver(observer);
612 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
613 observers_.RemoveObserver(observer);
616 DownloadItem* DownloadManagerImpl::CreateDownloadItem(
617 uint32 id,
618 const base::FilePath& current_path,
619 const base::FilePath& target_path,
620 const std::vector<GURL>& url_chain,
621 const GURL& referrer_url,
622 const base::Time& start_time,
623 const base::Time& end_time,
624 const std::string& etag,
625 const std::string& last_modified,
626 int64 received_bytes,
627 int64 total_bytes,
628 DownloadItem::DownloadState state,
629 DownloadDangerType danger_type,
630 DownloadInterruptReason interrupt_reason,
631 bool opened) {
632 if (ContainsKey(downloads_, id)) {
633 NOTREACHED();
634 return NULL;
636 DownloadItemImpl* item = item_factory_->CreatePersistedItem(
637 this,
639 current_path,
640 target_path,
641 url_chain,
642 referrer_url,
643 start_time,
644 end_time,
645 etag,
646 last_modified,
647 received_bytes,
648 total_bytes,
649 state,
650 danger_type,
651 interrupt_reason,
652 opened,
653 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD));
654 downloads_[id] = item;
655 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item));
656 VLOG(20) << __FUNCTION__ << "() download = " << item->DebugString(true);
657 return item;
660 int DownloadManagerImpl::InProgressCount() const {
661 int count = 0;
662 for (DownloadMap::const_iterator it = downloads_.begin();
663 it != downloads_.end(); ++it) {
664 if (it->second->GetState() == DownloadItem::IN_PROGRESS)
665 ++count;
667 return count;
670 int DownloadManagerImpl::NonMaliciousInProgressCount() const {
671 int count = 0;
672 for (DownloadMap::const_iterator it = downloads_.begin();
673 it != downloads_.end(); ++it) {
674 if (it->second->GetState() == DownloadItem::IN_PROGRESS &&
675 it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_URL &&
676 it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT &&
677 it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST &&
678 it->second->GetDangerType() !=
679 DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED) {
680 ++count;
683 return count;
686 DownloadItem* DownloadManagerImpl::GetDownload(uint32 download_id) {
687 return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
690 void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) {
691 for (DownloadMap::iterator it = downloads_.begin();
692 it != downloads_.end(); ++it) {
693 downloads->push_back(it->second);
697 void DownloadManagerImpl::OpenDownload(DownloadItemImpl* download) {
698 int num_unopened = 0;
699 for (DownloadMap::iterator it = downloads_.begin();
700 it != downloads_.end(); ++it) {
701 DownloadItemImpl* item = it->second;
702 if ((item->GetState() == DownloadItem::COMPLETE) &&
703 !item->GetOpened())
704 ++num_unopened;
706 RecordOpensOutstanding(num_unopened);
708 if (delegate_)
709 delegate_->OpenDownload(download);
712 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl* download) {
713 if (delegate_)
714 delegate_->ShowDownloadInShell(download);
717 } // namespace content