OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/download/download_manager_impl.h" | 5 #include "content/browser/download/download_manager_impl.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 21 matching lines...) Expand all Loading... | |
32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
33 #include "content/public/browser/content_browser_client.h" | 33 #include "content/public/browser/content_browser_client.h" |
34 #include "content/public/browser/download_interrupt_reasons.h" | 34 #include "content/public/browser/download_interrupt_reasons.h" |
35 #include "content/public/browser/download_manager_delegate.h" | 35 #include "content/public/browser/download_manager_delegate.h" |
36 #include "content/public/browser/download_url_parameters.h" | 36 #include "content/public/browser/download_url_parameters.h" |
37 #include "content/public/browser/notification_service.h" | 37 #include "content/public/browser/notification_service.h" |
38 #include "content/public/browser/notification_types.h" | 38 #include "content/public/browser/notification_types.h" |
39 #include "content/public/browser/render_process_host.h" | 39 #include "content/public/browser/render_process_host.h" |
40 #include "content/public/browser/resource_context.h" | 40 #include "content/public/browser/resource_context.h" |
41 #include "content/public/browser/web_contents_delegate.h" | 41 #include "content/public/browser/web_contents_delegate.h" |
42 #include "content/public/common/referrer.h" | |
42 #include "net/base/load_flags.h" | 43 #include "net/base/load_flags.h" |
43 #include "net/base/upload_bytes_element_reader.h" | 44 #include "net/base/upload_bytes_element_reader.h" |
44 #include "net/base/upload_data_stream.h" | 45 #include "net/base/upload_data_stream.h" |
45 #include "net/url_request/url_request_context.h" | 46 #include "net/url_request/url_request_context.h" |
46 #include "webkit/glue/webkit_glue.h" | 47 #include "webkit/glue/webkit_glue.h" |
47 | 48 |
48 namespace content { | 49 namespace content { |
49 namespace { | 50 namespace { |
50 | 51 |
51 void BeginDownload(scoped_ptr<DownloadUrlParameters> params) { | 52 void BeginDownload(scoped_ptr<DownloadUrlParameters> params, |
53 DownloadId download_id) { | |
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
53 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and | 55 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
54 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so | 56 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
55 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. | 57 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
56 scoped_ptr<net::URLRequest> request( | 58 scoped_ptr<net::URLRequest> request( |
57 params->resource_context()->GetRequestContext()->CreateRequest( | 59 params->resource_context()->GetRequestContext()->CreateRequest( |
58 params->url(), NULL)); | 60 params->url(), NULL)); |
59 request->set_referrer(params->referrer().url.spec()); | 61 request->set_referrer(params->referrer().url.spec()); |
60 webkit_glue::ConfigureURLRequestForReferrerPolicy( | 62 webkit_glue::ConfigureURLRequestForReferrerPolicy( |
61 request.get(), params->referrer().policy); | 63 request.get(), params->referrer().policy); |
(...skipping 10 matching lines...) Expand all Loading... | |
72 // The POST in this case does not have an actual body, and only works | 74 // The POST in this case does not have an actual body, and only works |
73 // when retrieving data from cache. This is done because we don't want | 75 // when retrieving data from cache. This is done because we don't want |
74 // to do a re-POST without user consent, and currently don't have a good | 76 // to do a re-POST without user consent, and currently don't have a good |
75 // plan on how to display the UI for that. | 77 // plan on how to display the UI for that. |
76 DCHECK(params->prefer_cache()); | 78 DCHECK(params->prefer_cache()); |
77 DCHECK(params->method() == "POST"); | 79 DCHECK(params->method() == "POST"); |
78 ScopedVector<net::UploadElementReader> element_readers; | 80 ScopedVector<net::UploadElementReader> element_readers; |
79 request->set_upload(make_scoped_ptr( | 81 request->set_upload(make_scoped_ptr( |
80 new net::UploadDataStream(&element_readers, params->post_id()))); | 82 new net::UploadDataStream(&element_readers, params->post_id()))); |
81 } | 83 } |
84 | |
85 // If we're not at the beginning of the file, retrieve only the remaining | |
86 // portion. | |
87 if (params->offset() > 0) { | |
88 request->SetExtraRequestHeaderByName( | |
89 "Range", | |
90 StringPrintf("bytes=%" PRId64 "-", params->offset()), | |
91 true); | |
92 | |
93 // If we've asked for a range, we want to make sure that we only | |
94 // get that range if our current copy of the information is good. | |
95 if (!params->last_modified().empty()) { | |
96 request->SetExtraRequestHeaderByName("If-Unmodified-Since", | |
97 params->last_modified(), | |
98 true); | |
99 } | |
100 if (!params->etag().empty()) { | |
101 request->SetExtraRequestHeaderByName("If-Match", params->etag(), true); | |
102 } | |
103 } | |
104 | |
82 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter | 105 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter |
83 = params->request_headers_begin(); | 106 = params->request_headers_begin(); |
84 iter != params->request_headers_end(); | 107 iter != params->request_headers_end(); |
85 ++iter) { | 108 ++iter) { |
86 request->SetExtraRequestHeaderByName( | 109 request->SetExtraRequestHeaderByName( |
87 iter->first, iter->second, false/*overwrite*/); | 110 iter->first, iter->second, false/*overwrite*/); |
88 } | 111 } |
89 | 112 |
90 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); | 113 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); |
91 save_info->file_path = params->file_path(); | 114 save_info->file_path = params->file_path(); |
92 save_info->suggested_name = params->suggested_name(); | 115 save_info->suggested_name = params->suggested_name(); |
93 save_info->offset = params->offset(); | 116 save_info->offset = params->offset(); |
94 save_info->hash_state = params->hash_state(); | 117 save_info->hash_state = params->hash_state(); |
95 save_info->prompt_for_save_location = params->prompt(); | 118 save_info->prompt_for_save_location = params->prompt(); |
96 save_info->file_stream = params->GetFileStream(); | 119 save_info->file_stream = params->GetFileStream(); |
97 | 120 |
98 params->resource_dispatcher_host()->BeginDownload( | 121 params->resource_dispatcher_host()->BeginDownload( |
99 request.Pass(), | 122 request.Pass(), |
100 params->content_initiated(), | 123 params->content_initiated(), |
101 params->resource_context(), | 124 params->resource_context(), |
102 params->render_process_host_id(), | 125 params->render_process_host_id(), |
103 params->render_view_host_routing_id(), | 126 params->render_view_host_routing_id(), |
104 params->prefer_cache(), | 127 params->prefer_cache(), |
105 save_info.Pass(), | 128 save_info.Pass(), |
129 download_id, | |
106 params->callback()); | 130 params->callback()); |
107 } | 131 } |
108 | 132 |
109 class MapValueIteratorAdapter { | 133 class MapValueIteratorAdapter { |
110 public: | 134 public: |
111 explicit MapValueIteratorAdapter( | 135 explicit MapValueIteratorAdapter( |
112 base::hash_map<int64, DownloadItem*>::const_iterator iter) | 136 base::hash_map<int64, DownloadItem*>::const_iterator iter) |
113 : iter_(iter) { | 137 : iter_(iter) { |
114 } | 138 } |
115 ~MapValueIteratorAdapter() {} | 139 ~MapValueIteratorAdapter() {} |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 received_bytes, | 190 received_bytes, |
167 total_bytes, | 191 total_bytes, |
168 state, | 192 state, |
169 opened, | 193 opened, |
170 bound_net_log); | 194 bound_net_log); |
171 } | 195 } |
172 | 196 |
173 virtual DownloadItemImpl* CreateActiveItem( | 197 virtual DownloadItemImpl* CreateActiveItem( |
174 DownloadItemImplDelegate* delegate, | 198 DownloadItemImplDelegate* delegate, |
175 const DownloadCreateInfo& info, | 199 const DownloadCreateInfo& info, |
176 scoped_ptr<DownloadRequestHandleInterface> request_handle, | |
177 const net::BoundNetLog& bound_net_log) OVERRIDE { | 200 const net::BoundNetLog& bound_net_log) OVERRIDE { |
178 return new DownloadItemImpl(delegate, info, request_handle.Pass(), | 201 return new DownloadItemImpl(delegate, info, bound_net_log); |
179 bound_net_log); | |
180 } | 202 } |
181 | 203 |
182 virtual DownloadItemImpl* CreateSavePageItem( | 204 virtual DownloadItemImpl* CreateSavePageItem( |
183 DownloadItemImplDelegate* delegate, | 205 DownloadItemImplDelegate* delegate, |
184 const FilePath& path, | 206 const FilePath& path, |
185 const GURL& url, | 207 const GURL& url, |
186 DownloadId download_id, | 208 DownloadId download_id, |
187 const std::string& mime_type, | 209 const std::string& mime_type, |
188 const net::BoundNetLog& bound_net_log) OVERRIDE { | 210 const net::BoundNetLog& bound_net_log) OVERRIDE { |
189 return new DownloadItemImpl(delegate, path, url, download_id, | 211 return new DownloadItemImpl(delegate, path, url, download_id, |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 browser_context_ = browser_context; | 354 browser_context_ = browser_context; |
333 | 355 |
334 return true; | 356 return true; |
335 } | 357 } |
336 | 358 |
337 DownloadItem* DownloadManagerImpl::StartDownload( | 359 DownloadItem* DownloadManagerImpl::StartDownload( |
338 scoped_ptr<DownloadCreateInfo> info, | 360 scoped_ptr<DownloadCreateInfo> info, |
339 scoped_ptr<ByteStreamReader> stream) { | 361 scoped_ptr<ByteStreamReader> stream) { |
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
341 | 363 |
342 net::BoundNetLog bound_net_log = | |
343 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
344 | |
345 FilePath default_download_directory; | 364 FilePath default_download_directory; |
346 if (delegate_) { | 365 if (delegate_) { |
347 FilePath website_save_directory; // Unused | 366 FilePath website_save_directory; // Unused |
348 bool skip_dir_check = false; // Unused | 367 bool skip_dir_check = false; // Unused |
349 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, | 368 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, |
350 &default_download_directory, &skip_dir_check); | 369 &default_download_directory, &skip_dir_check); |
351 } | 370 } |
352 | 371 |
353 // We create the DownloadItem before the DownloadFile because the | 372 // We create the DownloadItem before the DownloadFile because the |
354 // DownloadItem already needs to handle a state in which there is | 373 // DownloadItem already needs to handle a state in which there is |
355 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) | 374 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) |
356 DownloadItemImpl* download = | 375 DownloadItemImpl* download = GetOrCreateDownloadItem(info.get()); |
357 CreateDownloadItem(info.get(), bound_net_log); | |
358 scoped_ptr<DownloadFile> download_file( | 376 scoped_ptr<DownloadFile> download_file( |
359 file_factory_->CreateFile( | 377 file_factory_->CreateFile( |
360 info->save_info.Pass(), default_download_directory, | 378 info->save_info.Pass(), default_download_directory, |
361 info->url(), info->referrer_url, | 379 info->url(), info->referrer_url, |
362 delegate_->GenerateFileHash(), | 380 delegate_->GenerateFileHash(), |
363 stream.Pass(), bound_net_log, | 381 stream.Pass(), download->GetBoundNetLog(), |
364 download->DestinationObserverAsWeakPtr())); | 382 download->DestinationObserverAsWeakPtr())); |
365 download->Start(download_file.Pass()); | 383 scoped_ptr<DownloadRequestHandleInterface> req_handle( |
384 new DownloadRequestHandle(info->request_handle)); | |
385 download->Start(download_file.Pass(), req_handle.Pass()); | |
366 | 386 |
367 // Delay notification until after Start() so that download_file is bound | 387 // Delay notification until after Start() so that download_file is bound |
368 // to download and all the usual setters (e.g. Cancel) work. | 388 // to download and all the usual setters (e.g. Cancel) work. |
369 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); | 389 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); |
370 | 390 |
371 return download; | 391 return download; |
372 } | 392 } |
373 | 393 |
374 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { | 394 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { |
375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { | 427 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { |
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
409 if (ContainsKey(downloads_, download_id)) | 429 if (ContainsKey(downloads_, download_id)) |
410 downloads_[download_id]->OnDownloadedFileRemoved(); | 430 downloads_[download_id]->OnDownloadedFileRemoved(); |
411 } | 431 } |
412 | 432 |
413 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { | 433 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { |
414 return browser_context_; | 434 return browser_context_; |
415 } | 435 } |
416 | 436 |
417 DownloadItemImpl* DownloadManagerImpl::CreateDownloadItem( | 437 DownloadItemImpl* DownloadManagerImpl::GetOrCreateDownloadItem( |
418 DownloadCreateInfo* info, const net::BoundNetLog& bound_net_log) { | 438 DownloadCreateInfo* info) { |
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
420 | 440 |
421 if (!info->download_id.IsValid()) | 441 if (!info->download_id.IsValid()) |
422 info->download_id = GetNextId(); | 442 info->download_id = GetNextId(); |
423 DownloadItemImpl* download = item_factory_->CreateActiveItem( | |
424 this, *info, | |
425 scoped_ptr<DownloadRequestHandleInterface>( | |
426 new DownloadRequestHandle(info->request_handle)).Pass(), | |
427 bound_net_log); | |
428 | 443 |
429 DCHECK(!ContainsKey(downloads_, download->GetId())); | 444 DownloadItemImpl* download = NULL; |
430 downloads_[download->GetId()] = download; | 445 if (ContainsKey(downloads_, info->download_id.local())) { |
446 // Resuming an existing download. | |
447 download = downloads_[info->download_id.local()]; | |
448 DCHECK(download->IsInterrupted()); | |
449 } else { | |
450 // New download | |
451 net::BoundNetLog bound_net_log = | |
452 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | |
453 download = item_factory_->CreateActiveItem(this, *info, bound_net_log); | |
454 downloads_[download->GetId()] = download; | |
455 } | |
456 | |
431 return download; | 457 return download; |
432 } | 458 } |
433 | 459 |
434 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( | 460 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( |
435 const FilePath& main_file_path, | 461 const FilePath& main_file_path, |
436 const GURL& page_url, | 462 const GURL& page_url, |
437 const std::string& mime_type, | 463 const std::string& mime_type, |
438 DownloadItem::Observer* observer) { | 464 DownloadItem::Observer* observer) { |
439 net::BoundNetLog bound_net_log = | 465 net::BoundNetLog bound_net_log = |
440 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); | 466 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); |
(...skipping 17 matching lines...) Expand all Loading... | |
458 return download_item; | 484 return download_item; |
459 } | 485 } |
460 | 486 |
461 void DownloadManagerImpl::CancelDownload(int32 download_id) { | 487 void DownloadManagerImpl::CancelDownload(int32 download_id) { |
462 DownloadItem* download = GetDownload(download_id); | 488 DownloadItem* download = GetDownload(download_id); |
463 if (!download || !download->IsInProgress()) | 489 if (!download || !download->IsInProgress()) |
464 return; | 490 return; |
465 download->Cancel(true); | 491 download->Cancel(true); |
466 } | 492 } |
467 | 493 |
494 // Resume a download of a specific URL. We send the request to the | |
495 // ResourceDispatcherHost, and let it send us responses like a regular | |
496 // download. | |
497 void DownloadManagerImpl::ResumeInterruptedDownload( | |
benjhayden
2013/01/06 15:46:04
Could this be merged with DownloadUrl if DownloadU
Randy Smith (Not in Mondays)
2013/01/07 20:54:10
I don't think it should be--the routines have two
| |
498 scoped_ptr<content::DownloadUrlParameters> params, | |
499 content::DownloadId id) { | |
500 BrowserThread::PostTask( | |
501 BrowserThread::IO, | |
502 FROM_HERE, | |
503 base::Bind(&BeginDownload, base::Passed(params.Pass()), id)); | |
504 } | |
505 | |
468 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( | 506 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( |
469 scoped_ptr<DownloadItemFactory> item_factory) { | 507 scoped_ptr<DownloadItemFactory> item_factory) { |
470 item_factory_ = item_factory.Pass(); | 508 item_factory_ = item_factory.Pass(); |
471 } | 509 } |
472 | 510 |
473 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( | 511 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( |
474 scoped_ptr<DownloadFileFactory> file_factory) { | 512 scoped_ptr<DownloadFileFactory> file_factory) { |
475 file_factory_ = file_factory.Pass(); | 513 file_factory_ = file_factory.Pass(); |
476 } | 514 } |
477 | 515 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
537 } | 575 } |
538 | 576 |
539 void DownloadManagerImpl::DownloadUrl( | 577 void DownloadManagerImpl::DownloadUrl( |
540 scoped_ptr<DownloadUrlParameters> params) { | 578 scoped_ptr<DownloadUrlParameters> params) { |
541 if (params->post_id() >= 0) { | 579 if (params->post_id() >= 0) { |
542 // Check this here so that the traceback is more useful. | 580 // Check this here so that the traceback is more useful. |
543 DCHECK(params->prefer_cache()); | 581 DCHECK(params->prefer_cache()); |
544 DCHECK(params->method() == "POST"); | 582 DCHECK(params->method() == "POST"); |
545 } | 583 } |
546 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( | 584 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
547 &BeginDownload, base::Passed(¶ms))); | 585 &BeginDownload, base::Passed(¶ms), DownloadId())); |
548 } | 586 } |
549 | 587 |
550 void DownloadManagerImpl::AddObserver(Observer* observer) { | 588 void DownloadManagerImpl::AddObserver(Observer* observer) { |
551 observers_.AddObserver(observer); | 589 observers_.AddObserver(observer); |
552 } | 590 } |
553 | 591 |
554 void DownloadManagerImpl::RemoveObserver(Observer* observer) { | 592 void DownloadManagerImpl::RemoveObserver(Observer* observer) { |
555 observers_.RemoveObserver(observer); | 593 observers_.RemoveObserver(observer); |
556 } | 594 } |
557 | 595 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 it != downloads_.end(); ++it) { | 665 it != downloads_.end(); ++it) { |
628 DownloadItemImpl* item = it->second; | 666 DownloadItemImpl* item = it->second; |
629 if (item->IsComplete() && | 667 if (item->IsComplete() && |
630 !item->GetOpened()) | 668 !item->GetOpened()) |
631 ++num_unopened; | 669 ++num_unopened; |
632 } | 670 } |
633 RecordOpensOutstanding(num_unopened); | 671 RecordOpensOutstanding(num_unopened); |
634 } | 672 } |
635 | 673 |
636 } // namespace content | 674 } // namespace content |
OLD | NEW |