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