Chromium Code Reviews| 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 | 69 |
| 70 const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024; | 70 const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024; |
| 71 | 71 |
| 72 DownloadResourceHandler::DownloadResourceHandler( | 72 DownloadResourceHandler::DownloadResourceHandler( |
| 73 uint32 id, | 73 uint32 id, |
| 74 net::URLRequest* request, | 74 net::URLRequest* request, |
| 75 const DownloadUrlParameters::OnStartedCallback& started_cb, | 75 const DownloadUrlParameters::OnStartedCallback& started_cb, |
| 76 scoped_ptr<DownloadSaveInfo> save_info) | 76 scoped_ptr<DownloadSaveInfo> save_info) |
| 77 : ResourceHandler(request), | 77 : ResourceHandler(request), |
| 78 download_id_(id), | 78 download_id_(id), |
| 79 content_length_(0), | |
| 80 started_cb_(started_cb), | 79 started_cb_(started_cb), |
| 81 save_info_(save_info.Pass()), | 80 save_info_(save_info.Pass()), |
| 82 last_buffer_size_(0), | 81 last_buffer_size_(0), |
| 83 bytes_read_(0), | 82 bytes_read_(0), |
| 84 pause_count_(0), | 83 pause_count_(0), |
| 85 was_deferred_(false), | 84 was_deferred_(false), |
| 86 on_response_started_called_(false) { | 85 on_response_started_called_(false) { |
| 87 RecordDownloadCount(UNTHROTTLED_COUNT); | 86 RecordDownloadCount(UNTHROTTLED_COUNT); |
| 88 } | 87 } |
| 89 | 88 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 118 << " request_id = " << request_id; | 117 << " request_id = " << request_id; |
| 119 download_start_time_ = base::TimeTicks::Now(); | 118 download_start_time_ = base::TimeTicks::Now(); |
| 120 | 119 |
| 121 // If it's a download, we don't want to poison the cache with it. | 120 // If it's a download, we don't want to poison the cache with it. |
| 122 request()->StopCaching(); | 121 request()->StopCaching(); |
| 123 | 122 |
| 124 // Lower priority as well, so downloads don't contend for resources | 123 // Lower priority as well, so downloads don't contend for resources |
| 125 // with main frames. | 124 // with main frames. |
| 126 request()->SetPriority(net::IDLE); | 125 request()->SetPriority(net::IDLE); |
| 127 | 126 |
| 128 std::string content_disposition; | 127 // If the content-length header is not present (or contains something other |
| 129 request()->GetResponseHeaderByName("content-disposition", | 128 // than numbers), the incoming content_length is -1 (unknown size). |
| 130 &content_disposition); | 129 // Set the content length to 0 to indicate unknown size to DownloadManager. |
| 131 SetContentDisposition(content_disposition); | 130 int64 content_length = |
| 132 SetContentLength(response->head.content_length); | 131 response->head.content_length > 0 ? response->head.content_length : 0; |
| 133 | 132 |
| 134 const ResourceRequestInfoImpl* request_info = GetRequestInfo(); | 133 const ResourceRequestInfoImpl* request_info = GetRequestInfo(); |
| 135 | 134 |
| 136 // Deleted in DownloadManager. | 135 // Deleted in DownloadManager. |
| 137 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo( | 136 scoped_ptr<DownloadCreateInfo> info( |
| 138 base::Time::Now(), content_length_, | 137 new DownloadCreateInfo(base::Time::Now(), |
| 139 request()->net_log(), request_info->HasUserGesture(), | 138 content_length, |
| 140 request_info->GetPageTransition())); | 139 request()->net_log(), |
| 140 request_info->HasUserGesture(), | |
| 141 request_info->GetPageTransition(), | |
| 142 save_info_.Pass())); | |
| 141 | 143 |
| 142 // Create the ByteStream for sending data to the download sink. | 144 // Create the ByteStream for sending data to the download sink. |
| 143 scoped_ptr<ByteStreamReader> stream_reader; | 145 scoped_ptr<ByteStreamReader> stream_reader; |
| 144 CreateByteStream( | 146 CreateByteStream( |
| 145 base::MessageLoopProxy::current(), | 147 base::MessageLoopProxy::current(), |
| 146 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | 148 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), |
| 147 kDownloadByteStreamSize, &stream_writer_, &stream_reader); | 149 kDownloadByteStreamSize, &stream_writer_, &stream_reader); |
| 148 stream_writer_->RegisterCallback( | 150 stream_writer_->RegisterCallback( |
| 149 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); | 151 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); |
| 150 | 152 |
| 151 info->download_id = download_id_; | 153 info->download_id = download_id_; |
| 152 info->url_chain = request()->url_chain(); | 154 info->url_chain = request()->url_chain(); |
| 153 info->referrer_url = GURL(request()->referrer()); | 155 info->referrer_url = GURL(request()->referrer()); |
| 154 info->start_time = base::Time::Now(); | |
| 155 info->total_bytes = content_length_; | |
| 156 info->has_user_gesture = request_info->HasUserGesture(); | |
| 157 info->content_disposition = content_disposition_; | |
| 158 info->mime_type = response->head.mime_type; | 156 info->mime_type = response->head.mime_type; |
| 159 info->remote_address = request()->GetSocketAddress().host(); | 157 info->remote_address = request()->GetSocketAddress().host(); |
| 158 request()->GetResponseHeaderByName("content-disposition", | |
| 159 &info->content_disposition); | |
| 160 RecordDownloadMimeType(info->mime_type); | 160 RecordDownloadMimeType(info->mime_type); |
| 161 RecordDownloadContentDisposition(info->content_disposition); | 161 RecordDownloadContentDisposition(info->content_disposition); |
| 162 | 162 |
| 163 info->request_handle = | 163 info->request_handle = |
| 164 DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(), | 164 DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(), |
| 165 request_info->GetRouteID(), | 165 request_info->GetRouteID(), |
| 166 request_info->GetRequestID()); | 166 request_info->GetRequestID()); |
| 167 | 167 |
| 168 // Get the last modified time and etag. | 168 // Get the last modified time and etag. |
| 169 const net::HttpResponseHeaders* headers = request()->response_headers(); | 169 const net::HttpResponseHeaders* headers = request()->response_headers(); |
| 170 if (headers) { | 170 if (headers) { |
| 171 std::string last_modified_hdr; | 171 // TODO(asanka): Only store these if headers->HasStrongValidators() is true. |
| 172 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) | 172 // See RFC 2616 section 13.3.3. |
| 173 info->last_modified = last_modified_hdr; | 173 headers->EnumerateHeader(NULL, "Last-Modified", &info->last_modified); |
| 174 if (headers->EnumerateHeader(NULL, "ETag", &etag_)) | 174 headers->EnumerateHeader(NULL, "ETag", &info->etag); |
|
Randy Smith (Not in Mondays)
2013/11/20 21:35:56
I'm feeling like if I objected to ignoring the ret
asanka
2013/11/21 17:30:21
Done. I chose to check the return value here as we
| |
| 175 info->etag = etag_; | |
| 176 | 175 |
| 177 int status = headers->response_code(); | 176 int status = headers->response_code(); |
| 178 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) { | 177 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) { |
| 179 // Success & not range response; if we asked for a range, we didn't | 178 // Success & not range response; if we asked for a range, we didn't |
| 180 // get it--reset the file pointers to reflect that. | 179 // get it--reset the file pointers to reflect that. |
| 181 save_info_->offset = 0; | 180 info->save_info->offset = 0; |
| 182 save_info_->hash_state = ""; | 181 info->save_info->hash_state = ""; |
| 183 } | 182 } |
| 183 | |
| 184 if (!headers->GetMimeType(&info->original_mime_type)) | |
| 185 info->original_mime_type.clear(); | |
| 184 } | 186 } |
| 185 | 187 |
| 186 std::string content_type_header; | |
| 187 if (!response->head.headers.get() || | |
| 188 !response->head.headers->GetMimeType(&content_type_header)) | |
| 189 content_type_header = ""; | |
| 190 info->original_mime_type = content_type_header; | |
| 191 | |
| 192 if (!response->head.headers.get() || | |
| 193 !response->head.headers->EnumerateHeader( | |
| 194 NULL, "Accept-Ranges", &accept_ranges_)) { | |
| 195 accept_ranges_ = ""; | |
| 196 } | |
| 197 | |
| 198 info->save_info = save_info_.Pass(); | |
| 199 | |
| 200 BrowserThread::PostTask( | 188 BrowserThread::PostTask( |
| 201 BrowserThread::UI, FROM_HERE, | 189 BrowserThread::UI, FROM_HERE, |
| 202 base::Bind(&StartOnUIThread, | 190 base::Bind(&StartOnUIThread, |
| 203 base::Passed(&info), | 191 base::Passed(&info), |
| 204 base::Passed(&stream_reader), | 192 base::Passed(&stream_reader), |
| 205 // Pass to StartOnUIThread so that variable | 193 // Pass to StartOnUIThread so that variable |
| 206 // access is always on IO thread but function | 194 // access is always on IO thread but function |
| 207 // is called on UI thread. | 195 // is called on UI thread. |
| 208 started_cb_)); | 196 started_cb_)); |
| 209 // Guaranteed to be called in StartOnUIThread | 197 // Guaranteed to be called in StartOnUIThread |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 default: // All other errors. | 354 default: // All other errors. |
| 367 // Redirection and informational codes should have been handled earlier | 355 // Redirection and informational codes should have been handled earlier |
| 368 // in the stack. | 356 // in the stack. |
| 369 DCHECK_NE(3, response_code / 100); | 357 DCHECK_NE(3, response_code / 100); |
| 370 DCHECK_NE(1, response_code / 100); | 358 DCHECK_NE(1, response_code / 100); |
| 371 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; | 359 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; |
| 372 break; | 360 break; |
| 373 } | 361 } |
| 374 } | 362 } |
| 375 | 363 |
| 376 RecordAcceptsRanges(accept_ranges_, bytes_read_, etag_); | 364 std::string accept_ranges; |
| 377 RecordNetworkBlockage( | 365 bool has_strong_validators = false; |
| 378 base::TimeTicks::Now() - download_start_time_, total_pause_time_); | 366 if (request()->response_headers()) { |
| 367 request()->response_headers()->EnumerateHeader( | |
| 368 NULL, "Accept-Ranges", &accept_ranges); | |
| 369 has_strong_validators = | |
| 370 request()->response_headers()->HasStrongValidators(); | |
| 371 } | |
| 372 RecordAcceptsRanges(accept_ranges, bytes_read_, has_strong_validators); | |
| 373 RecordNetworkBlockage(base::TimeTicks::Now() - download_start_time_, | |
| 374 total_pause_time_); | |
| 379 | 375 |
| 380 CallStartedCB(NULL, error_code); | 376 CallStartedCB(NULL, error_code); |
| 381 | 377 |
| 382 // Send the info down the stream. Conditional is in case we get | 378 // Send the info down the stream. Conditional is in case we get |
| 383 // OnResponseCompleted without OnResponseStarted. | 379 // OnResponseCompleted without OnResponseStarted. |
| 384 if (stream_writer_) | 380 if (stream_writer_) |
| 385 stream_writer_->Close(reason); | 381 stream_writer_->Close(reason); |
| 386 | 382 |
| 387 // If the error mapped to something unknown, record it so that | 383 // If the error mapped to something unknown, record it so that |
| 388 // we can drill down. | 384 // we can drill down. |
| 389 if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) { | 385 if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) { |
| 390 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.MapErrorNetworkFailed", | 386 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.MapErrorNetworkFailed", |
| 391 std::abs(status.error()), | 387 std::abs(status.error()), |
| 392 net::GetAllErrorCodesForUma()); | 388 net::GetAllErrorCodesForUma()); |
| 393 } | 389 } |
| 394 | 390 |
| 395 stream_writer_.reset(); // We no longer need the stream. | 391 stream_writer_.reset(); // We no longer need the stream. |
| 396 read_buffer_ = NULL; | 392 read_buffer_ = NULL; |
| 397 } | 393 } |
| 398 | 394 |
| 399 void DownloadResourceHandler::OnDataDownloaded( | 395 void DownloadResourceHandler::OnDataDownloaded( |
| 400 int request_id, | 396 int request_id, |
| 401 int bytes_downloaded) { | 397 int bytes_downloaded) { |
| 402 NOTREACHED(); | 398 NOTREACHED(); |
| 403 } | 399 } |
| 404 | 400 |
| 405 // If the content-length header is not present (or contains something other | |
| 406 // than numbers), the incoming content_length is -1 (unknown size). | |
| 407 // Set the content length to 0 to indicate unknown size to DownloadManager. | |
| 408 void DownloadResourceHandler::SetContentLength(const int64& content_length) { | |
| 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 410 content_length_ = 0; | |
| 411 if (content_length > 0) | |
| 412 content_length_ = content_length; | |
| 413 } | |
| 414 | |
| 415 void DownloadResourceHandler::SetContentDisposition( | |
| 416 const std::string& content_disposition) { | |
| 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 418 content_disposition_ = content_disposition; | |
| 419 } | |
| 420 | |
| 421 void DownloadResourceHandler::PauseRequest() { | 401 void DownloadResourceHandler::PauseRequest() { |
| 422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 423 | 403 |
| 424 ++pause_count_; | 404 ++pause_count_; |
| 425 } | 405 } |
| 426 | 406 |
| 427 void DownloadResourceHandler::ResumeRequest() { | 407 void DownloadResourceHandler::ResumeRequest() { |
| 428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 429 DCHECK_LT(0, pause_count_); | 409 DCHECK_LT(0, pause_count_); |
| 430 | 410 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 | 462 |
| 483 // Remove output stream callback if a stream exists. | 463 // Remove output stream callback if a stream exists. |
| 484 if (stream_writer_) | 464 if (stream_writer_) |
| 485 stream_writer_->RegisterCallback(base::Closure()); | 465 stream_writer_->RegisterCallback(base::Closure()); |
| 486 | 466 |
| 487 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", | 467 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", |
| 488 base::TimeTicks::Now() - download_start_time_); | 468 base::TimeTicks::Now() - download_start_time_); |
| 489 } | 469 } |
| 490 | 470 |
| 491 } // namespace content | 471 } // namespace content |
| OLD | NEW |