| 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 | 67 |
| 68 } // namespace | 68 } // namespace |
| 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 : download_id_(id), |
| 78 download_id_(id), | |
| 79 content_length_(0), | 78 content_length_(0), |
| 79 request_(request), |
| 80 started_cb_(started_cb), | 80 started_cb_(started_cb), |
| 81 save_info_(save_info.Pass()), | 81 save_info_(save_info.Pass()), |
| 82 last_buffer_size_(0), | 82 last_buffer_size_(0), |
| 83 bytes_read_(0), | 83 bytes_read_(0), |
| 84 pause_count_(0), | 84 pause_count_(0), |
| 85 was_deferred_(false), | 85 was_deferred_(false), |
| 86 on_response_started_called_(false) { | 86 on_response_started_called_(false) { |
| 87 RecordDownloadCount(UNTHROTTLED_COUNT); | 87 RecordDownloadCount(UNTHROTTLED_COUNT); |
| 88 } | 88 } |
| 89 | 89 |
| 90 bool DownloadResourceHandler::OnUploadProgress(int request_id, | 90 bool DownloadResourceHandler::OnUploadProgress(int request_id, |
| 91 uint64 position, | 91 uint64 position, |
| 92 uint64 size) { | 92 uint64 size) { |
| 93 return true; | 93 return true; |
| 94 } | 94 } |
| 95 | 95 |
| 96 bool DownloadResourceHandler::OnRequestRedirected( | 96 bool DownloadResourceHandler::OnRequestRedirected( |
| 97 int request_id, | 97 int request_id, |
| 98 const GURL& url, | 98 const GURL& url, |
| 99 ResourceResponse* response, | 99 ResourceResponse* response, |
| 100 bool* defer) { | 100 bool* defer) { |
| 101 // We treat a download as a main frame load, and thus update the policy URL | 101 // We treat a download as a main frame load, and thus update the policy URL |
| 102 // on redirects. | 102 // on redirects. |
| 103 request()->set_first_party_for_cookies(url); | 103 request_->set_first_party_for_cookies(url); |
| 104 return true; | 104 return true; |
| 105 } | 105 } |
| 106 | 106 |
| 107 // Send the download creation information to the download thread. | 107 // Send the download creation information to the download thread. |
| 108 bool DownloadResourceHandler::OnResponseStarted( | 108 bool DownloadResourceHandler::OnResponseStarted( |
| 109 int request_id, | 109 int request_id, |
| 110 ResourceResponse* response, | 110 ResourceResponse* response, |
| 111 bool* defer) { | 111 bool* defer) { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 113 // There can be only one (call) | 113 // There can be only one (call) |
| 114 DCHECK(!on_response_started_called_); | 114 DCHECK(!on_response_started_called_); |
| 115 on_response_started_called_ = true; | 115 on_response_started_called_ = true; |
| 116 | 116 |
| 117 VLOG(20) << __FUNCTION__ << "()" << DebugString() | 117 VLOG(20) << __FUNCTION__ << "()" << DebugString() |
| 118 << " request_id = " << request_id; | 118 << " request_id = " << request_id; |
| 119 download_start_time_ = base::TimeTicks::Now(); | 119 download_start_time_ = base::TimeTicks::Now(); |
| 120 | 120 |
| 121 // If it's a download, we don't want to poison the cache with it. | 121 // If it's a download, we don't want to poison the cache with it. |
| 122 request()->StopCaching(); | 122 request_->StopCaching(); |
| 123 | 123 |
| 124 // Lower priority as well, so downloads don't contend for resources | 124 // Lower priority as well, so downloads don't contend for resources |
| 125 // with main frames. | 125 // with main frames. |
| 126 request()->SetPriority(net::IDLE); | 126 request_->SetPriority(net::IDLE); |
| 127 | 127 |
| 128 std::string content_disposition; | 128 std::string content_disposition; |
| 129 request()->GetResponseHeaderByName("content-disposition", | 129 request_->GetResponseHeaderByName("content-disposition", |
| 130 &content_disposition); | 130 &content_disposition); |
| 131 SetContentDisposition(content_disposition); | 131 SetContentDisposition(content_disposition); |
| 132 SetContentLength(response->head.content_length); | 132 SetContentLength(response->head.content_length); |
| 133 | 133 |
| 134 const ResourceRequestInfoImpl* request_info = GetRequestInfo(); | 134 const ResourceRequestInfoImpl* request_info = |
| 135 ResourceRequestInfoImpl::ForRequest(request_); |
| 135 | 136 |
| 136 // Deleted in DownloadManager. | 137 // Deleted in DownloadManager. |
| 137 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo( | 138 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo( |
| 138 base::Time::Now(), content_length_, | 139 base::Time::Now(), content_length_, |
| 139 request()->net_log(), request_info->HasUserGesture(), | 140 request_->net_log(), request_info->HasUserGesture(), |
| 140 request_info->GetPageTransition())); | 141 request_info->GetPageTransition())); |
| 141 | 142 |
| 142 // Create the ByteStream for sending data to the download sink. | 143 // Create the ByteStream for sending data to the download sink. |
| 143 scoped_ptr<ByteStreamReader> stream_reader; | 144 scoped_ptr<ByteStreamReader> stream_reader; |
| 144 CreateByteStream( | 145 CreateByteStream( |
| 145 base::MessageLoopProxy::current(), | 146 base::MessageLoopProxy::current(), |
| 146 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | 147 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), |
| 147 kDownloadByteStreamSize, &stream_writer_, &stream_reader); | 148 kDownloadByteStreamSize, &stream_writer_, &stream_reader); |
| 148 stream_writer_->RegisterCallback( | 149 stream_writer_->RegisterCallback( |
| 149 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); | 150 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr())); |
| 150 | 151 |
| 151 info->download_id = download_id_; | 152 info->download_id = download_id_; |
| 152 info->url_chain = request()->url_chain(); | 153 info->url_chain = request_->url_chain(); |
| 153 info->referrer_url = GURL(request()->referrer()); | 154 info->referrer_url = GURL(request_->referrer()); |
| 154 info->start_time = base::Time::Now(); | 155 info->start_time = base::Time::Now(); |
| 155 info->total_bytes = content_length_; | 156 info->total_bytes = content_length_; |
| 156 info->has_user_gesture = request_info->HasUserGesture(); | 157 info->has_user_gesture = request_info->HasUserGesture(); |
| 157 info->content_disposition = content_disposition_; | 158 info->content_disposition = content_disposition_; |
| 158 info->mime_type = response->head.mime_type; | 159 info->mime_type = response->head.mime_type; |
| 159 info->remote_address = request()->GetSocketAddress().host(); | 160 info->remote_address = request_->GetSocketAddress().host(); |
| 160 RecordDownloadMimeType(info->mime_type); | 161 RecordDownloadMimeType(info->mime_type); |
| 161 RecordDownloadContentDisposition(info->content_disposition); | 162 RecordDownloadContentDisposition(info->content_disposition); |
| 162 | 163 |
| 163 info->request_handle = | 164 info->request_handle = |
| 164 DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(), | 165 DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(), |
| 165 request_info->GetRouteID(), | 166 request_info->GetRouteID(), |
| 166 request_info->GetRequestID()); | 167 request_info->GetRequestID()); |
| 167 | 168 |
| 168 // Get the last modified time and etag. | 169 // Get the last modified time and etag. |
| 169 const net::HttpResponseHeaders* headers = request()->response_headers(); | 170 const net::HttpResponseHeaders* headers = request_->response_headers(); |
| 170 if (headers) { | 171 if (headers) { |
| 171 std::string last_modified_hdr; | 172 std::string last_modified_hdr; |
| 172 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) | 173 if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr)) |
| 173 info->last_modified = last_modified_hdr; | 174 info->last_modified = last_modified_hdr; |
| 174 if (headers->EnumerateHeader(NULL, "ETag", &etag_)) | 175 if (headers->EnumerateHeader(NULL, "ETag", &etag_)) |
| 175 info->etag = etag_; | 176 info->etag = etag_; |
| 176 | 177 |
| 177 int status = headers->response_code(); | 178 int status = headers->response_code(); |
| 178 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) { | 179 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) { |
| 179 // Success & not range response; if we asked for a range, we didn't | 180 // Success & not range response; if we asked for a range, we didn't |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 225 } |
| 225 | 226 |
| 226 bool DownloadResourceHandler::OnWillStart(int request_id, | 227 bool DownloadResourceHandler::OnWillStart(int request_id, |
| 227 const GURL& url, | 228 const GURL& url, |
| 228 bool* defer) { | 229 bool* defer) { |
| 229 return true; | 230 return true; |
| 230 } | 231 } |
| 231 | 232 |
| 232 // Create a new buffer, which will be handed to the download thread for file | 233 // Create a new buffer, which will be handed to the download thread for file |
| 233 // writing and deletion. | 234 // writing and deletion. |
| 234 bool DownloadResourceHandler::OnWillRead(int request_id, | 235 bool DownloadResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, |
| 235 scoped_refptr<net::IOBuffer>* buf, | 236 int* buf_size, int min_size) { |
| 236 int* buf_size, | |
| 237 int min_size) { | |
| 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 239 DCHECK(buf && buf_size); | 238 DCHECK(buf && buf_size); |
| 240 DCHECK(!read_buffer_.get()); | 239 DCHECK(!read_buffer_.get()); |
| 241 | 240 |
| 242 *buf_size = min_size < 0 ? kReadBufSize : min_size; | 241 *buf_size = min_size < 0 ? kReadBufSize : min_size; |
| 243 last_buffer_size_ = *buf_size; | 242 last_buffer_size_ = *buf_size; |
| 244 read_buffer_ = new net::IOBuffer(*buf_size); | 243 read_buffer_ = new net::IOBuffer(*buf_size); |
| 245 *buf = read_buffer_.get(); | 244 *buf = read_buffer_.get(); |
| 246 return true; | 245 return true; |
| 247 } | 246 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 *defer = was_deferred_ = true; | 284 *defer = was_deferred_ = true; |
| 286 | 285 |
| 287 return true; | 286 return true; |
| 288 } | 287 } |
| 289 | 288 |
| 290 bool DownloadResourceHandler::OnResponseCompleted( | 289 bool DownloadResourceHandler::OnResponseCompleted( |
| 291 int request_id, | 290 int request_id, |
| 292 const net::URLRequestStatus& status, | 291 const net::URLRequestStatus& status, |
| 293 const std::string& security_info) { | 292 const std::string& security_info) { |
| 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 295 int response_code = status.is_success() ? request()->GetResponseCode() : 0; | 294 int response_code = status.is_success() ? request_->GetResponseCode() : 0; |
| 296 VLOG(20) << __FUNCTION__ << "()" << DebugString() | 295 VLOG(20) << __FUNCTION__ << "()" << DebugString() |
| 297 << " request_id = " << request_id | 296 << " request_id = " << request_id |
| 298 << " status.status() = " << status.status() | 297 << " status.status() = " << status.status() |
| 299 << " status.error() = " << status.error() | 298 << " status.error() = " << status.error() |
| 300 << " response_code = " << response_code; | 299 << " response_code = " << response_code; |
| 301 | 300 |
| 302 net::Error error_code = net::OK; | 301 net::Error error_code = net::OK; |
| 303 if (status.status() == net::URLRequestStatus::FAILED || | 302 if (status.status() == net::URLRequestStatus::FAILED || |
| 304 // Note cancels as failures too. | 303 // Note cancels as failures too. |
| 305 status.status() == net::URLRequestStatus::CANCELED) { | 304 status.status() == net::URLRequestStatus::CANCELED) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 329 // the tab from which it came). We map this to USER_CANCELLED as the | 328 // the tab from which it came). We map this to USER_CANCELLED as the |
| 330 // case we know about (system suspend because of laptop close) corresponds | 329 // case we know about (system suspend because of laptop close) corresponds |
| 331 // to a user action. | 330 // to a user action. |
| 332 // TODO(ahendrickson) -- Find a better set of codes to use here, as | 331 // TODO(ahendrickson) -- Find a better set of codes to use here, as |
| 333 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. | 332 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. |
| 334 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; | 333 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; |
| 335 } | 334 } |
| 336 | 335 |
| 337 if (status.is_success() && | 336 if (status.is_success() && |
| 338 reason == DOWNLOAD_INTERRUPT_REASON_NONE && | 337 reason == DOWNLOAD_INTERRUPT_REASON_NONE && |
| 339 request()->response_headers()) { | 338 request_->response_headers()) { |
| 340 // Handle server's response codes. | 339 // Handle server's response codes. |
| 341 switch(response_code) { | 340 switch(response_code) { |
| 342 case -1: // Non-HTTP request. | 341 case -1: // Non-HTTP request. |
| 343 case net::HTTP_OK: | 342 case net::HTTP_OK: |
| 344 case net::HTTP_CREATED: | 343 case net::HTTP_CREATED: |
| 345 case net::HTTP_ACCEPTED: | 344 case net::HTTP_ACCEPTED: |
| 346 case net::HTTP_NON_AUTHORITATIVE_INFORMATION: | 345 case net::HTTP_NON_AUTHORITATIVE_INFORMATION: |
| 347 case net::HTTP_RESET_CONTENT: | 346 case net::HTTP_RESET_CONTENT: |
| 348 case net::HTTP_PARTIAL_CONTENT: | 347 case net::HTTP_PARTIAL_CONTENT: |
| 349 // Expected successful codes. | 348 // Expected successful codes. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 total_pause_time_ += (base::TimeTicks::Now() - last_stream_pause_time_); | 440 total_pause_time_ += (base::TimeTicks::Now() - last_stream_pause_time_); |
| 442 last_stream_pause_time_ = base::TimeTicks(); | 441 last_stream_pause_time_ = base::TimeTicks(); |
| 443 } | 442 } |
| 444 | 443 |
| 445 controller()->Resume(); | 444 controller()->Resume(); |
| 446 } | 445 } |
| 447 | 446 |
| 448 void DownloadResourceHandler::CancelRequest() { | 447 void DownloadResourceHandler::CancelRequest() { |
| 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 450 | 449 |
| 451 const ResourceRequestInfo* info = GetRequestInfo(); | 450 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); |
| 452 ResourceDispatcherHostImpl::Get()->CancelRequest( | 451 ResourceDispatcherHostImpl::Get()->CancelRequest( |
| 453 info->GetChildID(), | 452 info->GetChildID(), |
| 454 info->GetRequestID(), | 453 info->GetRequestID(), |
| 455 false); | 454 false); |
| 456 } | 455 } |
| 457 | 456 |
| 458 std::string DownloadResourceHandler::DebugString() const { | 457 std::string DownloadResourceHandler::DebugString() const { |
| 459 const ResourceRequestInfo* info = GetRequestInfo(); | 458 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); |
| 460 return base::StringPrintf("{" | 459 return base::StringPrintf("{" |
| 461 " url_ = " "\"%s\"" | 460 " url_ = " "\"%s\"" |
| 462 " info = {" | 461 " info = {" |
| 463 " child_id = " "%d" | 462 " child_id = " "%d" |
| 464 " request_id = " "%d" | 463 " request_id = " "%d" |
| 465 " route_id = " "%d" | 464 " route_id = " "%d" |
| 466 " }" | 465 " }" |
| 467 " }", | 466 " }", |
| 468 request() ? | 467 request_ ? |
| 469 request()->url().spec().c_str() : | 468 request_->url().spec().c_str() : |
| 470 "<NULL request>", | 469 "<NULL request>", |
| 471 info->GetChildID(), | 470 info->GetChildID(), |
| 472 info->GetRequestID(), | 471 info->GetRequestID(), |
| 473 info->GetRouteID()); | 472 info->GetRouteID()); |
| 474 } | 473 } |
| 475 | 474 |
| 476 DownloadResourceHandler::~DownloadResourceHandler() { | 475 DownloadResourceHandler::~DownloadResourceHandler() { |
| 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 478 | 477 |
| 479 // This won't do anything if the callback was called before. | 478 // This won't do anything if the callback was called before. |
| 480 // If it goes through, it will likely be because OnWillStart() returned | 479 // If it goes through, it will likely be because OnWillStart() returned |
| 481 // false somewhere in the chain of resource handlers. | 480 // false somewhere in the chain of resource handlers. |
| 482 CallStartedCB(NULL, net::ERR_ACCESS_DENIED); | 481 CallStartedCB(NULL, net::ERR_ACCESS_DENIED); |
| 483 | 482 |
| 484 // Remove output stream callback if a stream exists. | 483 // Remove output stream callback if a stream exists. |
| 485 if (stream_writer_) | 484 if (stream_writer_) |
| 486 stream_writer_->RegisterCallback(base::Closure()); | 485 stream_writer_->RegisterCallback(base::Closure()); |
| 487 | 486 |
| 488 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", | 487 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", |
| 489 base::TimeTicks::Now() - download_start_time_); | 488 base::TimeTicks::Now() - download_start_time_); |
| 490 } | 489 } |
| 491 | 490 |
| 492 } // namespace content | 491 } // namespace content |
| OLD | NEW |