download_throttling_resource_handler.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/renderer_host/download_throttling_resource_handler.h" 6 7#include "base/logging.h" 8#include "chrome/browser/renderer_host/download_resource_handler.h" 9#include "chrome/browser/renderer_host/resource_dispatcher_host.h" 10#include "chrome/common/resource_response.h" 11#include "net/base/io_buffer.h" 12#include "net/base/mime_sniffer.h" 13 14DownloadThrottlingResourceHandler::DownloadThrottlingResourceHandler( 15 ResourceDispatcherHost* host, 16 net::URLRequest* request, 17 const GURL& url, 18 int render_process_host_id, 19 int render_view_id, 20 int request_id, 21 bool in_complete) 22 : host_(host), 23 request_(request), 24 url_(url), 25 render_process_host_id_(render_process_host_id), 26 render_view_id_(render_view_id), 27 request_id_(request_id), 28 tmp_buffer_length_(0), 29 ignore_on_read_complete_(in_complete) { 30 // Pause the request. 31 host_->PauseRequest(render_process_host_id_, request_id_, true); 32 host_->download_request_limiter()->CanDownloadOnIOThread( 33 render_process_host_id_, render_view_id, this); 34 } 35 36DownloadThrottlingResourceHandler::~DownloadThrottlingResourceHandler() { 37} 38 39bool DownloadThrottlingResourceHandler::OnUploadProgress(int request_id, 40 uint64 position, 41 uint64 size) { 42 if (download_handler_.get()) 43 return download_handler_->OnUploadProgress(request_id, position, size); 44 return true; 45} 46 47bool DownloadThrottlingResourceHandler::OnRequestRedirected( 48 int request_id, 49 const GURL& url, 50 ResourceResponse* response, 51 bool* defer) { 52 if (download_handler_.get()) { 53 return download_handler_->OnRequestRedirected( 54 request_id, url, response, defer); 55 } 56 url_ = url; 57 return true; 58} 59 60bool DownloadThrottlingResourceHandler::OnResponseStarted( 61 int request_id, 62 ResourceResponse* response) { 63 if (download_handler_.get()) 64 return download_handler_->OnResponseStarted(request_id, response); 65 response_ = response; 66 return true; 67} 68 69bool DownloadThrottlingResourceHandler::OnWillStart(int request_id, 70 const GURL& url, 71 bool* defer) { 72 if (download_handler_.get()) 73 return download_handler_->OnWillStart(request_id, url, defer); 74 return true; 75} 76 77bool DownloadThrottlingResourceHandler::OnWillRead(int request_id, 78 net::IOBuffer** buf, 79 int* buf_size, 80 int min_size) { 81 if (download_handler_.get()) 82 return download_handler_->OnWillRead(request_id, buf, buf_size, min_size); 83 84 // We should only have this invoked once, as such we only deal with one 85 // tmp buffer. 86 DCHECK(!tmp_buffer_.get()); 87 // If the caller passed a negative |min_size| then chose an appropriate 88 // default. The BufferedResourceHandler requires this to be at least 2 times 89 // the size required for mime detection. 90 if (min_size < 0) 91 min_size = 2 * net::kMaxBytesToSniff; 92 tmp_buffer_ = new net::IOBuffer(min_size); 93 *buf = tmp_buffer_.get(); 94 *buf_size = min_size; 95 return true; 96} 97 98bool DownloadThrottlingResourceHandler::OnReadCompleted(int request_id, 99 int* bytes_read) { 100 if (ignore_on_read_complete_) { 101 // See comments above definition for details on this. 102 ignore_on_read_complete_ = false; 103 return true; 104 } 105 if (!*bytes_read) 106 return true; 107 108 if (tmp_buffer_.get()) { 109 DCHECK(!tmp_buffer_length_); 110 tmp_buffer_length_ = *bytes_read; 111 if (download_handler_.get()) 112 CopyTmpBufferToDownloadHandler(); 113 return true; 114 } 115 if (download_handler_.get()) 116 return download_handler_->OnReadCompleted(request_id, bytes_read); 117 return true; 118} 119 120bool DownloadThrottlingResourceHandler::OnResponseCompleted( 121 int request_id, 122 const URLRequestStatus& status, 123 const std::string& security_info) { 124 if (download_handler_.get()) 125 return download_handler_->OnResponseCompleted(request_id, status, 126 security_info); 127 128 // For a download, if ResourceDispatcher::Read() fails, 129 // ResourceDispatcher::OnresponseStarted() will call 130 // OnResponseCompleted(), and we will end up here with an error 131 // status. 132 if (!status.is_success()) 133 return false; 134 NOTREACHED(); 135 return true; 136} 137 138void DownloadThrottlingResourceHandler::OnRequestClosed() { 139 if (download_handler_.get()) 140 download_handler_->OnRequestClosed(); 141} 142 143void DownloadThrottlingResourceHandler::CancelDownload() { 144 host_->CancelRequest(render_process_host_id_, request_id_, false); 145} 146 147void DownloadThrottlingResourceHandler::ContinueDownload() { 148 DCHECK(!download_handler_.get()); 149 download_handler_ = 150 new DownloadResourceHandler(host_, 151 render_process_host_id_, 152 render_view_id_, 153 request_id_, 154 url_, 155 host_->download_file_manager(), 156 request_, 157 false, 158 DownloadSaveInfo()); 159 if (response_.get()) 160 download_handler_->OnResponseStarted(request_id_, response_.get()); 161 162 if (tmp_buffer_length_) 163 CopyTmpBufferToDownloadHandler(); 164 165 // And let the request continue. 166 host_->PauseRequest(render_process_host_id_, request_id_, false); 167} 168 169int DownloadThrottlingResourceHandler::GetRequestId() { 170 return request_id_; 171} 172 173void DownloadThrottlingResourceHandler::CopyTmpBufferToDownloadHandler() { 174 // Copy over the tmp buffer. 175 net::IOBuffer* buffer; 176 int buf_size; 177 if (download_handler_->OnWillRead(request_id_, &buffer, &buf_size, 178 tmp_buffer_length_)) { 179 CHECK(buf_size >= tmp_buffer_length_); 180 memcpy(buffer->data(), tmp_buffer_->data(), tmp_buffer_length_); 181 download_handler_->OnReadCompleted(request_id_, &tmp_buffer_length_); 182 } 183 tmp_buffer_length_ = 0; 184 tmp_buffer_ = NULL; 185} 186