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

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

Issue 11571025: Initial CL for Downloads resumption. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated comments. Created 7 years, 11 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_resource_handler.h" 5 #include "content/browser/download/download_resource_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 10 matching lines...) Expand all
21 #include "content/browser/loader/resource_dispatcher_host_impl.h" 21 #include "content/browser/loader/resource_dispatcher_host_impl.h"
22 #include "content/browser/loader/resource_request_info_impl.h" 22 #include "content/browser/loader/resource_request_info_impl.h"
23 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/download_interrupt_reasons.h" 24 #include "content/public/browser/download_interrupt_reasons.h"
25 #include "content/public/browser/download_item.h" 25 #include "content/public/browser/download_item.h"
26 #include "content/public/browser/download_manager_delegate.h" 26 #include "content/public/browser/download_manager_delegate.h"
27 #include "content/public/common/resource_response.h" 27 #include "content/public/common/resource_response.h"
28 #include "net/base/io_buffer.h" 28 #include "net/base/io_buffer.h"
29 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
30 #include "net/http/http_response_headers.h" 30 #include "net/http/http_response_headers.h"
31 #include "net/http/http_status_code.h"
31 #include "net/url_request/url_request_context.h" 32 #include "net/url_request/url_request_context.h"
32 33
33 namespace content { 34 namespace content {
34 namespace { 35 namespace {
35 36
36 static const int kDownloadByteStreamSize = 100 * 1024; 37 static const int kDownloadByteStreamSize = 100 * 1024;
37 38
38 void CallStartedCBOnUIThread( 39 void CallStartedCBOnUIThread(
39 const DownloadResourceHandler::OnStartedCallback& started_cb, 40 const DownloadResourceHandler::OnStartedCallback& started_cb,
40 DownloadItem* item, 41 DownloadItem* item,
(...skipping 25 matching lines...) Expand all
66 DownloadItem* item = download_manager->StartDownload( 67 DownloadItem* item = download_manager->StartDownload(
67 info.Pass(), stream.Pass()); 68 info.Pass(), stream.Pass());
68 69
69 if (!started_cb.is_null()) 70 if (!started_cb.is_null())
70 started_cb.Run(item, net::OK); 71 started_cb.Run(item, net::OK);
71 } 72 }
72 73
73 } // namespace 74 } // namespace
74 75
75 DownloadResourceHandler::DownloadResourceHandler( 76 DownloadResourceHandler::DownloadResourceHandler(
77 DownloadId id,
76 net::URLRequest* request, 78 net::URLRequest* request,
77 const DownloadResourceHandler::OnStartedCallback& started_cb, 79 const DownloadResourceHandler::OnStartedCallback& started_cb,
78 scoped_ptr<DownloadSaveInfo> save_info) 80 scoped_ptr<DownloadSaveInfo> save_info)
79 : render_view_id_(0), // Actually initialized below. 81 : download_id_(id),
82 render_view_id_(0), // Actually initialized below.
80 content_length_(0), 83 content_length_(0),
81 request_(request), 84 request_(request),
82 started_cb_(started_cb), 85 started_cb_(started_cb),
83 save_info_(save_info.Pass()), 86 save_info_(save_info.Pass()),
84 last_buffer_size_(0), 87 last_buffer_size_(0),
85 bytes_read_(0), 88 bytes_read_(0),
86 pause_count_(0), 89 pause_count_(0),
87 was_deferred_(false), 90 was_deferred_(false),
88 on_response_started_called_(false) { 91 on_response_started_called_(false) {
89 ResourceRequestInfoImpl* info(ResourceRequestInfoImpl::ForRequest(request)); 92 ResourceRequestInfoImpl* info(ResourceRequestInfoImpl::ForRequest(request));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 145
143 // Create the ByteStream for sending data to the download sink. 146 // Create the ByteStream for sending data to the download sink.
144 scoped_ptr<ByteStreamReader> stream_reader; 147 scoped_ptr<ByteStreamReader> stream_reader;
145 CreateByteStream( 148 CreateByteStream(
146 base::MessageLoopProxy::current(), 149 base::MessageLoopProxy::current(),
147 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), 150 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
148 kDownloadByteStreamSize, &stream_writer_, &stream_reader); 151 kDownloadByteStreamSize, &stream_writer_, &stream_reader);
149 stream_writer_->RegisterCallback( 152 stream_writer_->RegisterCallback(
150 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); 153 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr()));
151 154
155 info->download_id = download_id_;
152 info->url_chain = request_->url_chain(); 156 info->url_chain = request_->url_chain();
153 info->referrer_url = GURL(request_->referrer()); 157 info->referrer_url = GURL(request_->referrer());
154 info->start_time = base::Time::Now(); 158 info->start_time = base::Time::Now();
155 info->total_bytes = content_length_; 159 info->total_bytes = content_length_;
156 info->has_user_gesture = request_info->HasUserGesture(); 160 info->has_user_gesture = request_info->HasUserGesture();
157 info->content_disposition = content_disposition_; 161 info->content_disposition = content_disposition_;
158 info->mime_type = response->head.mime_type; 162 info->mime_type = response->head.mime_type;
159 info->remote_address = request_->GetSocketAddress().host(); 163 info->remote_address = request_->GetSocketAddress().host();
160 RecordDownloadMimeType(info->mime_type); 164 RecordDownloadMimeType(info->mime_type);
161 RecordDownloadContentDisposition(info->content_disposition); 165 RecordDownloadContentDisposition(info->content_disposition);
162 166
163 info->request_handle = 167 info->request_handle =
164 DownloadRequestHandle(AsWeakPtr(), global_id_.child_id, 168 DownloadRequestHandle(AsWeakPtr(), global_id_.child_id,
165 render_view_id_, global_id_.request_id); 169 render_view_id_, global_id_.request_id);
166 170
167 // Get the last modified time and etag. 171 // Get the last modified time and etag.
168 const net::HttpResponseHeaders* headers = request_->response_headers(); 172 const net::HttpResponseHeaders* headers = request_->response_headers();
169 if (headers) { 173 if (headers) {
170 std::string last_modified_hdr; 174 std::string last_modified_hdr;
171 std::string etag; 175 std::string etag;
172 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) 176 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr))
173 info->last_modified = last_modified_hdr; 177 info->last_modified = last_modified_hdr;
174 if (headers->EnumerateHeader(NULL, "ETag", &etag)) 178 if (headers->EnumerateHeader(NULL, "ETag", &etag))
175 info->etag = etag; 179 info->etag = etag;
180
181 int status = headers->response_code();
182 if (2 == status / 100 && status != 206) { // Success & not range response
benjhayden 2013/01/08 16:41:17 net::HTTP_PARTIAL_CONTENT
benjhayden 2013/01/08 16:41:17 2 spaces before line comments?
Randy Smith (Not in Mondays) 2013/01/09 22:34:37 Done.
Randy Smith (Not in Mondays) 2013/01/09 22:34:37 Moot; moved into conditional to deal with > 80 cha
183 // Downloading the full file. If we asked for a range, we didn't
184 // get it--reset the file pointers to reflect that.
185 save_info_->offset = 0;
186 save_info_->hash_state = "";
187 }
176 } 188 }
177 189
178 std::string content_type_header; 190 std::string content_type_header;
179 if (!response->head.headers || 191 if (!response->head.headers ||
180 !response->head.headers->GetMimeType(&content_type_header)) 192 !response->head.headers->GetMimeType(&content_type_header))
181 content_type_header = ""; 193 content_type_header = "";
182 info->original_mime_type = content_type_header; 194 info->original_mime_type = content_type_header;
183 195
184 if (!response->head.headers || 196 if (!response->head.headers ||
185 !response->head.headers->EnumerateHeader( 197 !response->head.headers->EnumerateHeader(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 *defer = was_deferred_ = true; 287 *defer = was_deferred_ = true;
276 288
277 return true; 289 return true;
278 } 290 }
279 291
280 bool DownloadResourceHandler::OnResponseCompleted( 292 bool DownloadResourceHandler::OnResponseCompleted(
281 int request_id, 293 int request_id,
282 const net::URLRequestStatus& status, 294 const net::URLRequestStatus& status,
283 const std::string& security_info) { 295 const std::string& security_info) {
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
297 int response_code = status.is_success() ? request_->GetResponseCode() : 0;
285 VLOG(20) << __FUNCTION__ << "()" << DebugString() 298 VLOG(20) << __FUNCTION__ << "()" << DebugString()
286 << " request_id = " << request_id 299 << " request_id = " << request_id
287 << " status.status() = " << status.status() 300 << " status.status() = " << status.status()
288 << " status.error() = " << status.error(); 301 << " status.error() = " << status.error()
289 int response_code = status.is_success() ? request_->GetResponseCode() : 0; 302 << " response_code = " << response_code;
290 303
291 net::Error error_code = net::OK; 304 net::Error error_code = net::OK;
292 if (status.status() == net::URLRequestStatus::FAILED || 305 if (status.status() == net::URLRequestStatus::FAILED ||
293 // Note cancels as failures too. 306 // Note cancels as failures too.
294 status.status() == net::URLRequestStatus::CANCELED) { 307 status.status() == net::URLRequestStatus::CANCELED) {
295 error_code = static_cast<net::Error>(status.error()); // Normal case. 308 error_code = static_cast<net::Error>(status.error()); // Normal case.
296 // Make sure that at least the fact of failure comes through. 309 // Make sure that at least the fact of failure comes through.
297 if (error_code == net::OK) 310 if (error_code == net::OK)
298 error_code = net::ERR_FAILED; 311 error_code = net::ERR_FAILED;
299 } 312 }
(...skipping 16 matching lines...) Expand all
316 // stack cancelled the request. There aren't that many things that 329 // stack cancelled the request. There aren't that many things that
317 // could do this to a download request (whose lifetime is separated from 330 // could do this to a download request (whose lifetime is separated from
318 // the tab from which it came). We map this to USER_CANCELLED as the 331 // the tab from which it came). We map this to USER_CANCELLED as the
319 // case we know about (system suspend because of laptop close) corresponds 332 // case we know about (system suspend because of laptop close) corresponds
320 // to a user action. 333 // to a user action.
321 // TODO(ahendrickson) -- Find a better set of codes to use here, as 334 // TODO(ahendrickson) -- Find a better set of codes to use here, as
322 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. 335 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel.
323 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; 336 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
324 } 337 }
325 338
326 if (status.is_success()) { 339 if (status.is_success() &&
327 if (response_code >= 400) { 340 reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
328 switch(response_code) { 341 request_->response_headers()) {
329 case 404: // File Not Found. 342 // Handle server's response codes.
330 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; 343 switch(response_code) {
331 break; 344 case -1: // Non-HTTP request.
332 case 416: // Range Not Satisfiable. 345 case net::HTTP_OK:
333 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; 346 case net::HTTP_PARTIAL_CONTENT:
334 break; 347 // Expected successful codes.
335 case 412: // Precondition Failed. 348 break;
336 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION; 349 case net::HTTP_NO_CONTENT:
337 break; 350 case net::HTTP_NOT_FOUND:
338 default: 351 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
339 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; 352 break;
340 break; 353 case net::HTTP_PRECONDITION_FAILED:
341 } 354 // Failed our 'If-Unmodified-Since' or 'If-Match'; see
355 // download_manager_impl.cc BeginDownload()
356 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION;
357 break;
358 case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
359 // Retry by downloading from the start automatically:
360 // If we haven't received data when we get this error, we won't.
361 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
362 break;
363 default: // All other errors.
364 // Redirection should have been handled earlier in the stack.
365 DCHECK(3 != response_code / 100);
366
367 // Informational codes should have been handled earlier in the
368 // stack.
369 DCHECK(1 != response_code / 100);
370 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
371 break;
342 } 372 }
343 } 373 }
344 374
345 RecordAcceptsRanges(accept_ranges_, bytes_read_); 375 RecordAcceptsRanges(accept_ranges_, bytes_read_);
346 RecordNetworkBlockage( 376 RecordNetworkBlockage(
347 base::TimeTicks::Now() - download_start_time_, total_pause_time_); 377 base::TimeTicks::Now() - download_start_time_, total_pause_time_);
348 378
349 CallStartedCB(NULL, error_code); 379 CallStartedCB(NULL, error_code);
350 380
351 // Send the info down the stream. Conditional is in case we get 381 // Send the info down the stream. Conditional is in case we get
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 481
452 // Remove output stream callback if a stream exists. 482 // Remove output stream callback if a stream exists.
453 if (stream_writer_.get()) 483 if (stream_writer_.get())
454 stream_writer_->RegisterCallback(base::Closure()); 484 stream_writer_->RegisterCallback(base::Closure());
455 485
456 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", 486 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
457 base::TimeTicks::Now() - download_start_time_); 487 base::TimeTicks::Now() - download_start_time_);
458 } 488 }
459 489
460 } // namespace content 490 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698