Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: content/browser/download/download_manager_impl.cc

Issue 148133007: [Downloads] Always call DM::StartDownload() for explicit downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 #include "url/origin.h" 48 #include "url/origin.h"
49 49
50 namespace content { 50 namespace content {
51 namespace { 51 namespace {
52 52
53 scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload( 53 scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
54 scoped_ptr<DownloadUrlParameters> params, 54 scoped_ptr<DownloadUrlParameters> params,
55 uint32_t download_id, 55 uint32_t download_id,
56 base::WeakPtr<DownloadManagerImpl> download_manager) { 56 base::WeakPtr<DownloadManagerImpl> download_manager) {
57 DCHECK_CURRENTLY_ON(BrowserThread::IO); 57 DCHECK_CURRENTLY_ON(BrowserThread::IO);
58 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and 58
59 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so 59 scoped_ptr<net::URLRequest> url_request =
60 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. 60 DownloadRequestCore::CreateRequestOnIOThread(download_id, params.get());
61 scoped_ptr<net::URLRequest> request( 61
62 params->resource_context()->GetRequestContext()->CreateRequest( 62 // If there's a valid renderer process associated with the request, then the
63 params->url(), net::DEFAULT_PRIORITY, NULL)); 63 // request should be driven by the ResourceLoader. Pass it over to the
64 request->set_method(params->method()); 64 // ResourceDispatcherHostImpl which will in turn pass it along to the
65 if (!params->post_body().empty()) { 65 // ResourceLoader.
66 const std::string& body = params->post_body(); 66 if (params->render_process_host_id() != -1) {
67 scoped_ptr<net::UploadElementReader> reader( 67 DownloadInterruptReason reason =
68 net::UploadOwnedBytesElementReader::CreateWithString(body)); 68 ResourceDispatcherHostImpl::Get()->BeginDownload(
69 request->set_upload( 69 std::move(url_request), params->referrer(),
70 net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0)); 70 params->content_initiated(), params->resource_context(),
71 } 71 params->render_process_host_id(),
72 if (params->post_id() >= 0) { 72 params->render_view_host_routing_id(),
73 // The POST in this case does not have an actual body, and only works 73 params->render_frame_host_routing_id(),
74 // when retrieving data from cache. This is done because we don't want 74 params->do_not_prompt_for_login());
75 // to do a re-POST without user consent, and currently don't have a good 75
76 // plan on how to display the UI for that. 76 // If the download was accepted, the DownloadResourceHandler is now
77 DCHECK(params->prefer_cache()); 77 // responsible for driving the request to completion.
78 DCHECK_EQ("POST", params->method()); 78 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
79 std::vector<scoped_ptr<net::UploadElementReader>> element_readers; 79 return nullptr;
80 request->set_upload(make_scoped_ptr(new net::ElementsUploadDataStream( 80
81 std::move(element_readers), params->post_id()))); 81 // Otherwise, create an interrupted download.
82 scoped_ptr<DownloadCreateInfo> failed_created_info(
83 new DownloadCreateInfo(base::Time::Now(), net::BoundNetLog(),
84 make_scoped_ptr(new DownloadSaveInfo)));
85 failed_created_info->url_chain.push_back(params->url());
86 failed_created_info->result = reason;
87 scoped_ptr<ByteStreamReader> empty_byte_stream;
88 BrowserThread::PostTask(
89 BrowserThread::UI, FROM_HERE,
90 base::Bind(&DownloadManager::StartDownload, download_manager,
91 base::Passed(&failed_created_info),
92 base::Passed(&empty_byte_stream), params->callback()));
93 return nullptr;
82 } 94 }
83 95
84 // If we're not at the beginning of the file, retrieve only the remaining
85 // portion.
86 bool has_last_modified = !params->last_modified().empty();
87 bool has_etag = !params->etag().empty();
88
89 // If we've asked for a range, we want to make sure that we only
90 // get that range if our current copy of the information is good.
91 // We shouldn't be asked to continue if we don't have a verifier.
92 DCHECK(params->offset() == 0 || has_etag || has_last_modified);
93
94 if (params->offset() > 0 && (has_etag || has_last_modified)) {
95 request->SetExtraRequestHeaderByName(
96 "Range",
97 base::StringPrintf("bytes=%" PRId64 "-", params->offset()),
98 true);
99
100 // In accordance with RFC 2616 Section 14.27, use If-Range to specify that
101 // the server return the entire entity if the validator doesn't match.
102 // Last-Modified can be used in the absence of ETag as a validator if the
103 // response headers satisfied the HttpUtil::HasStrongValidators() predicate.
104 //
105 // This function assumes that HasStrongValidators() was true and that the
106 // ETag and Last-Modified header values supplied are valid.
107 request->SetExtraRequestHeaderByName(
108 "If-Range", has_etag ? params->etag() : params->last_modified(), true);
109 }
110
111 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter
112 = params->request_headers_begin();
113 iter != params->request_headers_end();
114 ++iter) {
115 request->SetExtraRequestHeaderByName(
116 iter->first, iter->second, false /*overwrite*/);
117 }
118
119 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
120 save_info->file_path = params->file_path();
121 save_info->suggested_name = params->suggested_name();
122 save_info->offset = params->offset();
123 save_info->hash_state = params->hash_state();
124 save_info->prompt_for_save_location = params->prompt();
125 save_info->file = params->GetFile();
126
127 if (params->render_process_host_id() != -1) {
128 ResourceDispatcherHost::Get()->BeginDownload(
129 std::move(request), params->referrer(), params->content_initiated(),
130 params->resource_context(), params->render_process_host_id(),
131 params->render_view_host_routing_id(),
132 params->render_frame_host_routing_id(), params->prefer_cache(),
133 params->do_not_prompt_for_login(), std::move(save_info), download_id,
134 params->callback());
135 return nullptr;
136 }
137 return scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>( 96 return scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>(
138 UrlDownloader::BeginDownload(download_manager, std::move(request), 97 UrlDownloader::BeginDownload(download_manager, std::move(url_request),
139 params->referrer(), params->prefer_cache(), 98 params->referrer())
140 std::move(save_info), download_id,
141 params->callback())
142 .release()); 99 .release());
143 } 100 }
144 101
145 class DownloadItemFactoryImpl : public DownloadItemFactory { 102 class DownloadItemFactoryImpl : public DownloadItemFactory {
146 public: 103 public:
147 DownloadItemFactoryImpl() {} 104 DownloadItemFactoryImpl() {}
148 ~DownloadItemFactoryImpl() override {} 105 ~DownloadItemFactoryImpl() override {}
149 106
150 DownloadItemImpl* CreatePersistedItem( 107 DownloadItemImpl* CreatePersistedItem(
151 DownloadItemImplDelegate* delegate, 108 DownloadItemImplDelegate* delegate,
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 url_downloaders_.clear(); 289 url_downloaders_.clear();
333 290
334 // We'll have nothing more to report to the observers after this point. 291 // We'll have nothing more to report to the observers after this point.
335 observers_.Clear(); 292 observers_.Clear();
336 293
337 if (delegate_) 294 if (delegate_)
338 delegate_->Shutdown(); 295 delegate_->Shutdown();
339 delegate_ = NULL; 296 delegate_ = NULL;
340 } 297 }
341 298
342 void DownloadManagerImpl::StartDownload( 299 void DownloadManagerImpl::StartDownload(
Randy Smith (Not in Mondays) 2016/02/10 21:48:45 Suggestion: I find myself wondering if we should c
asanka 2016/02/11 03:43:07 DII::Start() is, I think, OK since it starts the s
343 scoped_ptr<DownloadCreateInfo> info, 300 scoped_ptr<DownloadCreateInfo> info,
344 scoped_ptr<ByteStreamReader> stream, 301 scoped_ptr<ByteStreamReader> stream,
345 const DownloadUrlParameters::OnStartedCallback& on_started) { 302 const DownloadUrlParameters::OnStartedCallback& on_started) {
346 DCHECK_CURRENTLY_ON(BrowserThread::UI); 303 DCHECK_CURRENTLY_ON(BrowserThread::UI);
347 DCHECK(info); 304 DCHECK(info);
305 // |stream| is only non-nil if the download request was successful.
306 DCHECK(info->result != DOWNLOAD_INTERRUPT_REASON_NONE || stream.get());
Randy Smith (Not in Mondays) 2016/02/05 00:51:41 Should this be an XOR? I..e shouldn't result != N
asanka 2016/02/11 03:43:07 Done.
307 DVLOG(20) << __FUNCTION__ << "()"
308 << " result=" << DownloadInterruptReasonToString(info->result);
348 uint32_t download_id = info->download_id; 309 uint32_t download_id = info->download_id;
349 const bool new_download = (download_id == content::DownloadItem::kInvalidId); 310 const bool new_download = (download_id == content::DownloadItem::kInvalidId);
350 base::Callback<void(uint32_t)> got_id(base::Bind( 311 base::Callback<void(uint32_t)> got_id(base::Bind(
351 &DownloadManagerImpl::StartDownloadWithId, weak_factory_.GetWeakPtr(), 312 &DownloadManagerImpl::StartDownloadWithId, weak_factory_.GetWeakPtr(),
352 base::Passed(&info), base::Passed(&stream), on_started, new_download)); 313 base::Passed(&info), base::Passed(&stream), on_started, new_download));
353 if (new_download) { 314 if (new_download) {
354 GetNextId(got_id); 315 GetNextId(got_id);
355 } else { 316 } else {
356 got_id.Run(download_id); 317 got_id.Run(download_id);
357 } 318 }
(...skipping 15 matching lines...) Expand all
373 // Trying to resume an interrupted download. 334 // Trying to resume an interrupted download.
374 if (item_iterator == downloads_.end() || 335 if (item_iterator == downloads_.end() ||
375 (item_iterator->second->GetState() == DownloadItem::CANCELLED)) { 336 (item_iterator->second->GetState() == DownloadItem::CANCELLED)) {
376 // If the download is no longer known to the DownloadManager, then it was 337 // If the download is no longer known to the DownloadManager, then it was
377 // removed after it was resumed. Ignore. If the download is cancelled 338 // removed after it was resumed. Ignore. If the download is cancelled
378 // while resuming, then also ignore the request. 339 // while resuming, then also ignore the request.
379 info->request_handle->CancelRequest(); 340 info->request_handle->CancelRequest();
380 if (!on_started.is_null()) 341 if (!on_started.is_null())
381 on_started.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); 342 on_started.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
382 // The ByteStreamReader lives and dies on the FILE thread. 343 // The ByteStreamReader lives and dies on the FILE thread.
383 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, 344 if (stream)
384 stream.release()); 345 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
346 stream.release());
385 return; 347 return;
386 } 348 }
387 download = item_iterator->second; 349 download = item_iterator->second;
388 DCHECK_EQ(download->GetState(), DownloadItem::IN_PROGRESS);
389 download->MergeOriginInfoOnResume(*info);
390 } 350 }
391 351
392 base::FilePath default_download_directory; 352 base::FilePath default_download_directory;
393 if (delegate_) { 353 if (delegate_) {
394 base::FilePath website_save_directory; // Unused 354 base::FilePath website_save_directory; // Unused
395 bool skip_dir_check = false; // Unused 355 bool skip_dir_check = false; // Unused
396 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, 356 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory,
397 &default_download_directory, &skip_dir_check); 357 &default_download_directory, &skip_dir_check);
398 } 358 }
399 359
400 // Create the download file and start the download. 360 scoped_ptr<DownloadFile> download_file;
401 scoped_ptr<DownloadFile> download_file(file_factory_->CreateFile(
402 std::move(info->save_info), default_download_directory, info->url(),
403 info->referrer_url, delegate_ && delegate_->GenerateFileHash(),
404 std::move(stream), download->GetBoundNetLog(),
405 download->DestinationObserverAsWeakPtr()));
406 361
407 // Attach the client ID identifying the app to the AV system. 362 if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
Randy Smith (Not in Mondays) 2016/02/05 00:51:41 nit, suggestion: I think this test is equivalent t
asanka 2016/02/11 03:43:07 Got it. Changed the other test to if(result == NON
408 if (download_file.get() && delegate_) { 363 DCHECK(stream.get());
Randy Smith (Not in Mondays) 2016/02/11 22:08:08 Hmmm. Was there a specific reason to removing thi
Randy Smith (Not in Mondays) 2016/02/12 18:01:18 Ping?
asanka 2016/02/12 18:31:46 It was redundant with the DCHECK at the top of the
Randy Smith (Not in Mondays) 2016/02/12 18:58:10 Nah, I'm good. Thanks for the pointer.
409 download_file->SetClientGuid( 364 // Create the download file and start the download.
Randy Smith (Not in Mondays) 2016/02/05 00:51:41 nit: The placement of this comment makes me feel l
asanka 2016/02/11 03:43:07 I removed the extra comments which I thought were
410 delegate_->ApplicationClientIdForFileScanning()); 365 download_file.reset(file_factory_->CreateFile(
366 *info->save_info, default_download_directory, info->url(),
367 info->referrer_url, delegate_ && delegate_->GenerateFileHash(),
368 std::move(info->save_info->file), std::move(stream),
369 download->GetBoundNetLog(), download->DestinationObserverAsWeakPtr()));
370
371 // Attach the client ID identifying the app to the AV system.
372 if (download_file.get() && delegate_) {
Randy Smith (Not in Mondays) 2016/02/11 22:08:08 nit: My understanding of the style guide is that c
Randy Smith (Not in Mondays) 2016/02/12 18:01:18 Ping?
asanka 2016/02/12 18:31:46 Ah. Done.
373 download_file->SetClientGuid(
374 delegate_->ApplicationClientIdForFileScanning());
375 }
411 } 376 }
412 377
413 download->Start(std::move(download_file), std::move(info->request_handle)); 378 download->Start(std::move(download_file), std::move(info->request_handle),
379 *info);
414 380
415 // For interrupted downloads, Start() will transition the state to 381 // For interrupted downloads, Start() will transition the state to
416 // IN_PROGRESS and consumers will be notified via OnDownloadUpdated(). 382 // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
417 // For new downloads, we notify here, rather than earlier, so that 383 // For new downloads, we notify here, rather than earlier, so that
418 // the download_file is bound to download and all the usual 384 // the download_file is bound to download and all the usual
419 // setters (e.g. Cancel) work. 385 // setters (e.g. Cancel) work.
420 if (new_download) 386 if (new_download)
421 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 387 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
422 388
423 if (!on_started.is_null()) 389 if (!on_started.is_null())
424 on_started.Run(download, DOWNLOAD_INTERRUPT_REASON_NONE); 390 on_started.Run(download, info->result);
425 } 391 }
426 392
427 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 393 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
428 DCHECK_CURRENTLY_ON(BrowserThread::UI); 394 DCHECK_CURRENTLY_ON(BrowserThread::UI);
429 for (DownloadMap::iterator it = downloads_.begin(); 395 for (DownloadMap::iterator it = downloads_.begin();
430 it != downloads_.end(); ++it) { 396 it != downloads_.end(); ++it) {
431 DownloadItemImpl* item = it->second; 397 DownloadItemImpl* item = it->second;
432 CheckForFileRemoval(item); 398 CheckForFileRemoval(item);
433 } 399 }
434 } 400 }
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 if (delegate_) 705 if (delegate_)
740 delegate_->OpenDownload(download); 706 delegate_->OpenDownload(download);
741 } 707 }
742 708
743 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl* download) { 709 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl* download) {
744 if (delegate_) 710 if (delegate_)
745 delegate_->ShowDownloadInShell(download); 711 delegate_->ShowDownloadInShell(download);
746 } 712 }
747 713
748 } // namespace content 714 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698