Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2011 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/download/download_util.h"
      9 #include "chrome/browser/renderer_host/download_resource_handler.h"
     10 #include "content/browser/renderer_host/resource_dispatcher_host.h"
     11 #include "content/common/resource_response.h"
     12 #include "net/base/io_buffer.h"
     13 #include "net/base/mime_sniffer.h"
     14 
     15 DownloadThrottlingResourceHandler::DownloadThrottlingResourceHandler(
     16     ResourceDispatcherHost* host,
     17     net::URLRequest* request,
     18     const GURL& url,
     19     int render_process_host_id,
     20     int render_view_id,
     21     int request_id,
     22     bool in_complete)
     23     : host_(host),
     24       request_(request),
     25       url_(url),
     26       render_process_host_id_(render_process_host_id),
     27       render_view_id_(render_view_id),
     28       request_id_(request_id),
     29       tmp_buffer_length_(0),
     30       ignore_on_read_complete_(in_complete),
     31       request_closed_(false) {
     32   download_util::RecordDownloadCount(
     33       download_util::INITIATED_BY_NAVIGATION_COUNT);
     34 
     35   // Pause the request.
     36   host_->PauseRequest(render_process_host_id_, request_id_, true);
     37 
     38   // Add a reference to ourselves to keep this object alive until we
     39   // receive a callback from DownloadRequestLimiter. The reference is
     40   // released in ContinueDownload() and CancelDownload().
     41   AddRef();
     42 
     43   host_->download_request_limiter()->CanDownloadOnIOThread(
     44       render_process_host_id_, render_view_id, request_id, this);
     45   BrowserThread::PostTask(
     46       BrowserThread::UI, FROM_HERE,
     47       NewRunnableFunction(&download_util::NotifyDownloadInitiated,
     48                           render_process_host_id_, render_view_id_));
     49 }
     50 
     51 DownloadThrottlingResourceHandler::~DownloadThrottlingResourceHandler() {
     52 }
     53 
     54 bool DownloadThrottlingResourceHandler::OnUploadProgress(int request_id,
     55                                                          uint64 position,
     56                                                          uint64 size) {
     57   DCHECK(!request_closed_);
     58   if (download_handler_.get())
     59     return download_handler_->OnUploadProgress(request_id, position, size);
     60   return true;
     61 }
     62 
     63 bool DownloadThrottlingResourceHandler::OnRequestRedirected(
     64     int request_id,
     65     const GURL& url,
     66     ResourceResponse* response,
     67     bool* defer) {
     68   DCHECK(!request_closed_);
     69   if (download_handler_.get()) {
     70     return download_handler_->OnRequestRedirected(
     71         request_id, url, response, defer);
     72   }
     73   url_ = url;
     74   return true;
     75 }
     76 
     77 bool DownloadThrottlingResourceHandler::OnResponseStarted(
     78     int request_id,
     79     ResourceResponse* response) {
     80   DCHECK(!request_closed_);
     81   if (download_handler_.get())
     82     return download_handler_->OnResponseStarted(request_id, response);
     83   response_ = response;
     84   return true;
     85 }
     86 
     87 bool DownloadThrottlingResourceHandler::OnWillStart(int request_id,
     88                                                     const GURL& url,
     89                                                     bool* defer) {
     90   DCHECK(!request_closed_);
     91   if (download_handler_.get())
     92     return download_handler_->OnWillStart(request_id, url, defer);
     93   return true;
     94 }
     95 
     96 bool DownloadThrottlingResourceHandler::OnWillRead(int request_id,
     97                                                    net::IOBuffer** buf,
     98                                                    int* buf_size,
     99                                                    int min_size) {
    100   DCHECK(!request_closed_);
    101   if (download_handler_.get())
    102     return download_handler_->OnWillRead(request_id, buf, buf_size, min_size);
    103 
    104   // We should only have this invoked once, as such we only deal with one
    105   // tmp buffer.
    106   DCHECK(!tmp_buffer_.get());
    107   // If the caller passed a negative |min_size| then chose an appropriate
    108   // default. The BufferedResourceHandler requires this to be at least 2 times
    109   // the size required for mime detection.
    110   if (min_size < 0)
    111     min_size = 2 * net::kMaxBytesToSniff;
    112   tmp_buffer_ = new net::IOBuffer(min_size);
    113   *buf = tmp_buffer_.get();
    114   *buf_size = min_size;
    115   return true;
    116 }
    117 
    118 bool DownloadThrottlingResourceHandler::OnReadCompleted(int request_id,
    119                                                         int* bytes_read) {
    120   DCHECK(!request_closed_);
    121   if (ignore_on_read_complete_) {
    122     // See comments above definition for details on this.
    123     ignore_on_read_complete_ = false;
    124     return true;
    125   }
    126   if (!*bytes_read)
    127     return true;
    128 
    129   if (tmp_buffer_.get()) {
    130     DCHECK(!tmp_buffer_length_);
    131     tmp_buffer_length_ = *bytes_read;
    132     if (download_handler_.get())
    133       CopyTmpBufferToDownloadHandler();
    134     return true;
    135   }
    136   if (download_handler_.get())
    137     return download_handler_->OnReadCompleted(request_id, bytes_read);
    138   return true;
    139 }
    140 
    141 bool DownloadThrottlingResourceHandler::OnResponseCompleted(
    142     int request_id,
    143     const net::URLRequestStatus& status,
    144     const std::string& security_info) {
    145   DCHECK(!request_closed_);
    146   if (download_handler_.get())
    147     return download_handler_->OnResponseCompleted(request_id, status,
    148                                                   security_info);
    149 
    150   // For a download, if ResourceDispatcher::Read() fails,
    151   // ResourceDispatcher::OnresponseStarted() will call
    152   // OnResponseCompleted(), and we will end up here with an error
    153   // status.
    154   if (!status.is_success())
    155     return false;
    156   NOTREACHED();
    157   return true;
    158 }
    159 
    160 void DownloadThrottlingResourceHandler::OnRequestClosed() {
    161   DCHECK(!request_closed_);
    162   if (download_handler_.get())
    163     download_handler_->OnRequestClosed();
    164   request_closed_ = true;
    165 }
    166 
    167 void DownloadThrottlingResourceHandler::CancelDownload() {
    168   if (!request_closed_)
    169     host_->CancelRequest(render_process_host_id_, request_id_, false);
    170   Release();  // Release the additional reference from constructor.
    171 }
    172 
    173 void DownloadThrottlingResourceHandler::ContinueDownload() {
    174   DCHECK(!download_handler_.get());
    175   if (!request_closed_) {
    176     download_handler_ =
    177         new DownloadResourceHandler(host_,
    178                                     render_process_host_id_,
    179                                     render_view_id_,
    180                                     request_id_,
    181                                     url_,
    182                                     host_->download_file_manager(),
    183                                     request_,
    184                                     false,
    185                                     DownloadSaveInfo());
    186     if (response_.get())
    187       download_handler_->OnResponseStarted(request_id_, response_.get());
    188 
    189     if (tmp_buffer_length_)
    190       CopyTmpBufferToDownloadHandler();
    191 
    192     // And let the request continue.
    193     host_->PauseRequest(render_process_host_id_, request_id_, false);
    194   }
    195   Release();  // Release the addtional reference from constructor.
    196 }
    197 
    198 void DownloadThrottlingResourceHandler::CopyTmpBufferToDownloadHandler() {
    199   // Copy over the tmp buffer.
    200   net::IOBuffer* buffer;
    201   int buf_size;
    202   if (download_handler_->OnWillRead(request_id_, &buffer, &buf_size,
    203                                     tmp_buffer_length_)) {
    204     CHECK(buf_size >= tmp_buffer_length_);
    205     memcpy(buffer->data(), tmp_buffer_->data(), tmp_buffer_length_);
    206     download_handler_->OnReadCompleted(request_id_, &tmp_buffer_length_);
    207   }
    208   tmp_buffer_length_ = 0;
    209   tmp_buffer_ = NULL;
    210 }
    211