| 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_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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 DownloadItem* item = download_manager->StartDownload( | 66 DownloadItem* item = download_manager->StartDownload( |
| 67 info.Pass(), stream.Pass()); | 67 info.Pass(), stream.Pass()); |
| 68 | 68 |
| 69 if (!started_cb.is_null()) | 69 if (!started_cb.is_null()) |
| 70 started_cb.Run(item, net::OK); | 70 started_cb.Run(item, net::OK); |
| 71 } | 71 } |
| 72 | 72 |
| 73 } // namespace | 73 } // namespace |
| 74 | 74 |
| 75 DownloadResourceHandler::DownloadResourceHandler( | 75 DownloadResourceHandler::DownloadResourceHandler( |
| 76 DownloadId id, |
| 76 net::URLRequest* request, | 77 net::URLRequest* request, |
| 77 const DownloadResourceHandler::OnStartedCallback& started_cb, | 78 const DownloadResourceHandler::OnStartedCallback& started_cb, |
| 78 scoped_ptr<DownloadSaveInfo> save_info) | 79 scoped_ptr<DownloadSaveInfo> save_info) |
| 79 : render_view_id_(0), // Actually initialized below. | 80 : download_id_(id), |
| 81 render_view_id_(0), // Actually initialized below. |
| 80 content_length_(0), | 82 content_length_(0), |
| 81 request_(request), | 83 request_(request), |
| 82 started_cb_(started_cb), | 84 started_cb_(started_cb), |
| 83 save_info_(save_info.Pass()), | 85 save_info_(save_info.Pass()), |
| 84 last_buffer_size_(0), | 86 last_buffer_size_(0), |
| 85 bytes_read_(0), | 87 bytes_read_(0), |
| 86 pause_count_(0), | 88 pause_count_(0), |
| 87 was_deferred_(false), | 89 was_deferred_(false), |
| 88 on_response_started_called_(false) { | 90 on_response_started_called_(false) { |
| 89 ResourceRequestInfoImpl* info(ResourceRequestInfoImpl::ForRequest(request)); | 91 ResourceRequestInfoImpl* info(ResourceRequestInfoImpl::ForRequest(request)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 | 144 |
| 143 // Create the ByteStream for sending data to the download sink. | 145 // Create the ByteStream for sending data to the download sink. |
| 144 scoped_ptr<ByteStreamReader> stream_reader; | 146 scoped_ptr<ByteStreamReader> stream_reader; |
| 145 CreateByteStream( | 147 CreateByteStream( |
| 146 base::MessageLoopProxy::current(), | 148 base::MessageLoopProxy::current(), |
| 147 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | 149 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), |
| 148 kDownloadByteStreamSize, &stream_writer_, &stream_reader); | 150 kDownloadByteStreamSize, &stream_writer_, &stream_reader); |
| 149 stream_writer_->RegisterCallback( | 151 stream_writer_->RegisterCallback( |
| 150 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); | 152 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); |
| 151 | 153 |
| 154 info->download_id = download_id_; |
| 152 info->url_chain = request_->url_chain(); | 155 info->url_chain = request_->url_chain(); |
| 153 info->referrer_url = GURL(request_->referrer()); | 156 info->referrer_url = GURL(request_->referrer()); |
| 154 info->start_time = base::Time::Now(); | 157 info->start_time = base::Time::Now(); |
| 155 info->total_bytes = content_length_; | 158 info->total_bytes = content_length_; |
| 156 info->has_user_gesture = request_info->HasUserGesture(); | 159 info->has_user_gesture = request_info->HasUserGesture(); |
| 157 info->content_disposition = content_disposition_; | 160 info->content_disposition = content_disposition_; |
| 158 info->mime_type = response->head.mime_type; | 161 info->mime_type = response->head.mime_type; |
| 159 info->remote_address = request_->GetSocketAddress().host(); | 162 info->remote_address = request_->GetSocketAddress().host(); |
| 160 RecordDownloadMimeType(info->mime_type); | 163 RecordDownloadMimeType(info->mime_type); |
| 161 RecordDownloadContentDisposition(info->content_disposition); | 164 RecordDownloadContentDisposition(info->content_disposition); |
| 162 | 165 |
| 163 info->request_handle = | 166 info->request_handle = |
| 164 DownloadRequestHandle(AsWeakPtr(), global_id_.child_id, | 167 DownloadRequestHandle(AsWeakPtr(), global_id_.child_id, |
| 165 render_view_id_, global_id_.request_id); | 168 render_view_id_, global_id_.request_id); |
| 166 | 169 |
| 167 // Get the last modified time and etag. | 170 // Get the last modified time and etag. |
| 168 const net::HttpResponseHeaders* headers = request_->response_headers(); | 171 const net::HttpResponseHeaders* headers = request_->response_headers(); |
| 169 if (headers) { | 172 if (headers) { |
| 170 std::string last_modified_hdr; | 173 std::string last_modified_hdr; |
| 171 std::string etag; | 174 std::string etag; |
| 172 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) | 175 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) |
| 173 info->last_modified = last_modified_hdr; | 176 info->last_modified = last_modified_hdr; |
| 174 if (headers->EnumerateHeader(NULL, "ETag", &etag)) | 177 if (headers->EnumerateHeader(NULL, "ETag", &etag)) |
| 175 info->etag = etag; | 178 info->etag = etag; |
| 179 |
| 180 int status = headers->response_code(); |
| 181 if (status == 200) { // Continue with download: |
| 182 // Downloading the full file. If we asked for a range, we didn't |
| 183 // get it--reset the file pointers to reflect that. |
| 184 save_info_->offset = 0; |
| 185 save_info_->hash_state = ""; |
| 186 } |
| 176 } | 187 } |
| 177 | 188 |
| 178 std::string content_type_header; | 189 std::string content_type_header; |
| 179 if (!response->head.headers || | 190 if (!response->head.headers || |
| 180 !response->head.headers->GetMimeType(&content_type_header)) | 191 !response->head.headers->GetMimeType(&content_type_header)) |
| 181 content_type_header = ""; | 192 content_type_header = ""; |
| 182 info->original_mime_type = content_type_header; | 193 info->original_mime_type = content_type_header; |
| 183 | 194 |
| 184 if (!response->head.headers || | 195 if (!response->head.headers || |
| 185 !response->head.headers->EnumerateHeader( | 196 !response->head.headers->EnumerateHeader( |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 // stack cancelled the request. There aren't that many things that | 327 // stack cancelled the request. There aren't that many things that |
| 317 // could do this to a download request (whose lifetime is separated from | 328 // 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 | 329 // 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 | 330 // case we know about (system suspend because of laptop close) corresponds |
| 320 // to a user action. | 331 // to a user action. |
| 321 // TODO(ahendrickson) -- Find a better set of codes to use here, as | 332 // TODO(ahendrickson) -- Find a better set of codes to use here, as |
| 322 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. | 333 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. |
| 323 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; | 334 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; |
| 324 } | 335 } |
| 325 | 336 |
| 326 if (status.is_success()) { | 337 if (status.is_success() && |
| 327 if (response_code >= 400) { | 338 (reason == DOWNLOAD_INTERRUPT_REASON_NONE) && |
| 339 request_->response_headers()) { |
| 340 // Handle server's response codes. |
| 341 if ((response_code >= 0) && ((response_code % 100) != 2)) { |
| 328 switch(response_code) { | 342 switch(response_code) { |
| 329 case 404: // File Not Found. | 343 // Continue with download: |
| 344 case 200: // Downloading the full file, even if we asked for a |
| 345 // range. |
| 346 case 206: // Partial content. Leave alone. |
| 347 break; |
| 348 case 204: // No content. File not present. |
| 349 case 404: // File Not Found. |
| 330 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; | 350 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; |
| 331 break; | 351 break; |
| 352 case 412: // Precondition failed. Fails 'If-Unmodified-Since' or |
| 353 // 'If-Match'. |
| 354 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION; |
| 355 break; |
| 332 case 416: // Range Not Satisfiable. | 356 case 416: // Range Not Satisfiable. |
| 357 // Retry by downloading from the start automatically: |
| 358 // If we haven't received data when we get this error, we won't. |
| 333 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; | 359 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; |
| 334 break; | 360 break; |
| 335 case 412: // Precondition Failed. | 361 default: // All other errors. |
| 336 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION; | |
| 337 break; | |
| 338 default: | |
| 339 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; | 362 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; |
| 340 break; | 363 break; |
| 341 } | 364 } |
| 342 } | 365 } |
| 343 } | 366 } |
| 344 | 367 |
| 345 RecordAcceptsRanges(accept_ranges_, bytes_read_); | 368 RecordAcceptsRanges(accept_ranges_, bytes_read_); |
| 346 RecordNetworkBlockage( | 369 RecordNetworkBlockage( |
| 347 base::TimeTicks::Now() - download_start_time_, total_pause_time_); | 370 base::TimeTicks::Now() - download_start_time_, total_pause_time_); |
| 348 | 371 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 | 468 |
| 446 // Remove output stream callback if a stream exists. | 469 // Remove output stream callback if a stream exists. |
| 447 if (stream_writer_.get()) | 470 if (stream_writer_.get()) |
| 448 stream_writer_->RegisterCallback(base::Closure()); | 471 stream_writer_->RegisterCallback(base::Closure()); |
| 449 | 472 |
| 450 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", | 473 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", |
| 451 base::TimeTicks::Now() - download_start_time_); | 474 base::TimeTicks::Now() - download_start_time_); |
| 452 } | 475 } |
| 453 | 476 |
| 454 } // namespace content | 477 } // namespace content |
| OLD | NEW |