IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / loader / detachable_resource_handler.cc
blob42c7d1f191d5a6261dfbc2bf265d689b313886f9
1 // Copyright 2013 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.
5 #include "content/browser/loader/detachable_resource_handler.h"
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "content/browser/loader/resource_request_info_impl.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "net/url_request/url_request_status.h"
14 namespace {
15 // This matches the maximum allocation size of AsyncResourceHandler.
16 const int kReadBufSize = 32 * 1024;
19 namespace content {
21 DetachableResourceHandler::DetachableResourceHandler(
22 net::URLRequest* request,
23 base::TimeDelta cancel_delay,
24 scoped_ptr<ResourceHandler> next_handler)
25 : ResourceHandler(request),
26 next_handler_(next_handler.Pass()),
27 cancel_delay_(cancel_delay),
28 is_deferred_(false),
29 is_finished_(false) {
30 GetRequestInfo()->set_detachable_handler(this);
33 DetachableResourceHandler::~DetachableResourceHandler() {
34 // Cleanup back-pointer stored on the request info.
35 GetRequestInfo()->set_detachable_handler(NULL);
38 void DetachableResourceHandler::Detach() {
39 if (is_detached())
40 return;
42 if (!is_finished_) {
43 // Simulate a cancel on the next handler before destroying it.
44 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
45 net::ERR_ABORTED);
46 bool defer_ignored = false;
47 next_handler_->OnResponseCompleted(GetRequestID(), status, std::string(),
48 &defer_ignored);
49 DCHECK(!defer_ignored);
50 // If |next_handler_| were to defer its shutdown in OnResponseCompleted,
51 // this would destroy it anyway. Fortunately, AsyncResourceHandler never
52 // does this anyway, so DCHECK it. BufferedResourceHandler and RVH shutdown
53 // already ignore deferred ResourceHandler shutdown, but
54 // DetachableResourceHandler and the detach-on-renderer-cancel logic
55 // introduces a case where this occurs when the renderer cancels a resource.
57 // A OnWillRead / OnReadCompleted pair may still be in progress, but
58 // OnWillRead passes back a scoped_refptr, so downstream handler's buffer will
59 // survive long enough to complete that read. From there, future reads will
60 // drain into |read_buffer_|. (If |next_handler_| is an AsyncResourceHandler,
61 // the net::IOBuffer takes a reference to the ResourceBuffer which owns the
62 // shared memory.)
63 next_handler_.reset();
65 // Time the request out if it takes too long.
66 detached_timer_.reset(new base::OneShotTimer<DetachableResourceHandler>());
67 detached_timer_->Start(
68 FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel);
70 // Resume if necessary. The request may have been deferred, say, waiting on a
71 // full buffer in AsyncResourceHandler. Now that it has been detached, resume
72 // and drain it.
73 if (is_deferred_)
74 Resume();
77 void DetachableResourceHandler::SetController(ResourceController* controller) {
78 ResourceHandler::SetController(controller);
80 // Intercept the ResourceController for downstream handlers to keep track of
81 // whether the request is deferred.
82 if (next_handler_)
83 next_handler_->SetController(this);
86 bool DetachableResourceHandler::OnUploadProgress(int request_id,
87 uint64 position,
88 uint64 size) {
89 if (!next_handler_)
90 return true;
92 return next_handler_->OnUploadProgress(request_id, position, size);
95 bool DetachableResourceHandler::OnRequestRedirected(int request_id,
96 const GURL& url,
97 ResourceResponse* response,
98 bool* defer) {
99 DCHECK(!is_deferred_);
101 if (!next_handler_)
102 return true;
104 bool ret = next_handler_->OnRequestRedirected(request_id, url, response,
105 &is_deferred_);
106 *defer = is_deferred_;
107 return ret;
110 bool DetachableResourceHandler::OnResponseStarted(int request_id,
111 ResourceResponse* response,
112 bool* defer) {
113 DCHECK(!is_deferred_);
115 if (!next_handler_)
116 return true;
118 bool ret =
119 next_handler_->OnResponseStarted(request_id, response, &is_deferred_);
120 *defer = is_deferred_;
121 return ret;
124 bool DetachableResourceHandler::OnWillStart(int request_id, const GURL& url,
125 bool* defer) {
126 DCHECK(!is_deferred_);
128 if (!next_handler_)
129 return true;
131 bool ret = next_handler_->OnWillStart(request_id, url, &is_deferred_);
132 *defer = is_deferred_;
133 return ret;
136 bool DetachableResourceHandler::OnBeforeNetworkStart(int request_id,
137 const GURL& url,
138 bool* defer) {
139 DCHECK(!is_deferred_);
141 if (!next_handler_)
142 return true;
144 bool ret =
145 next_handler_->OnBeforeNetworkStart(request_id, url, &is_deferred_);
146 *defer = is_deferred_;
147 return ret;
150 bool DetachableResourceHandler::OnWillRead(int request_id,
151 scoped_refptr<net::IOBuffer>* buf,
152 int* buf_size,
153 int min_size) {
154 if (!next_handler_) {
155 DCHECK_EQ(-1, min_size);
156 if (!read_buffer_)
157 read_buffer_ = new net::IOBuffer(kReadBufSize);
158 *buf = read_buffer_;
159 *buf_size = kReadBufSize;
160 return true;
163 return next_handler_->OnWillRead(request_id, buf, buf_size, min_size);
166 bool DetachableResourceHandler::OnReadCompleted(int request_id, int bytes_read,
167 bool* defer) {
168 DCHECK(!is_deferred_);
170 if (!next_handler_)
171 return true;
173 bool ret =
174 next_handler_->OnReadCompleted(request_id, bytes_read, &is_deferred_);
175 *defer = is_deferred_;
176 return ret;
179 void DetachableResourceHandler::OnResponseCompleted(
180 int request_id,
181 const net::URLRequestStatus& status,
182 const std::string& security_info,
183 bool* defer) {
184 // No DCHECK(!is_deferred_) as the request may have been cancelled while
185 // deferred.
187 if (!next_handler_)
188 return;
190 is_finished_ = true;
192 next_handler_->OnResponseCompleted(request_id, status, security_info,
193 &is_deferred_);
194 *defer = is_deferred_;
197 void DetachableResourceHandler::OnDataDownloaded(int request_id,
198 int bytes_downloaded) {
199 if (!next_handler_)
200 return;
202 next_handler_->OnDataDownloaded(request_id, bytes_downloaded);
205 void DetachableResourceHandler::Resume() {
206 DCHECK(is_deferred_);
207 is_deferred_ = false;
208 controller()->Resume();
211 void DetachableResourceHandler::Cancel() {
212 controller()->Cancel();
215 void DetachableResourceHandler::CancelAndIgnore() {
216 controller()->CancelAndIgnore();
219 void DetachableResourceHandler::CancelWithError(int error_code) {
220 controller()->CancelWithError(error_code);
223 } // namespace content