Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / loader / detachable_resource_handler.cc
blob4b0641b30fc7dcdbec634593361b8bd82ed75637
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(status, std::string(), &defer_ignored);
48 DCHECK(!defer_ignored);
49 // If |next_handler_| were to defer its shutdown in OnResponseCompleted,
50 // this would destroy it anyway. Fortunately, AsyncResourceHandler never
51 // does this anyway, so DCHECK it. BufferedResourceHandler and RVH shutdown
52 // already ignore deferred ResourceHandler shutdown, but
53 // DetachableResourceHandler and the detach-on-renderer-cancel logic
54 // introduces a case where this occurs when the renderer cancels a resource.
56 // A OnWillRead / OnReadCompleted pair may still be in progress, but
57 // OnWillRead passes back a scoped_refptr, so downstream handler's buffer will
58 // survive long enough to complete that read. From there, future reads will
59 // drain into |read_buffer_|. (If |next_handler_| is an AsyncResourceHandler,
60 // the net::IOBuffer takes a reference to the ResourceBuffer which owns the
61 // shared memory.)
62 next_handler_.reset();
64 // Time the request out if it takes too long.
65 detached_timer_.reset(new base::OneShotTimer<DetachableResourceHandler>());
66 detached_timer_->Start(
67 FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel);
69 // Resume if necessary. The request may have been deferred, say, waiting on a
70 // full buffer in AsyncResourceHandler. Now that it has been detached, resume
71 // and drain it.
72 if (is_deferred_)
73 Resume();
76 void DetachableResourceHandler::SetController(ResourceController* controller) {
77 ResourceHandler::SetController(controller);
79 // Intercept the ResourceController for downstream handlers to keep track of
80 // whether the request is deferred.
81 if (next_handler_)
82 next_handler_->SetController(this);
85 bool DetachableResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
86 if (!next_handler_)
87 return true;
89 return next_handler_->OnUploadProgress(position, size);
92 bool DetachableResourceHandler::OnRequestRedirected(
93 const net::RedirectInfo& redirect_info,
94 ResourceResponse* response,
95 bool* defer) {
96 DCHECK(!is_deferred_);
98 if (!next_handler_)
99 return true;
101 bool ret = next_handler_->OnRequestRedirected(
102 redirect_info, response, &is_deferred_);
103 *defer = is_deferred_;
104 return ret;
107 bool DetachableResourceHandler::OnResponseStarted(ResourceResponse* response,
108 bool* defer) {
109 DCHECK(!is_deferred_);
111 if (!next_handler_)
112 return true;
114 bool ret =
115 next_handler_->OnResponseStarted(response, &is_deferred_);
116 *defer = is_deferred_;
117 return ret;
120 bool DetachableResourceHandler::OnWillStart(const GURL& url, bool* defer) {
121 DCHECK(!is_deferred_);
123 if (!next_handler_)
124 return true;
126 bool ret = next_handler_->OnWillStart(url, &is_deferred_);
127 *defer = is_deferred_;
128 return ret;
131 bool DetachableResourceHandler::OnBeforeNetworkStart(const GURL& url,
132 bool* defer) {
133 DCHECK(!is_deferred_);
135 if (!next_handler_)
136 return true;
138 bool ret =
139 next_handler_->OnBeforeNetworkStart(url, &is_deferred_);
140 *defer = is_deferred_;
141 return ret;
144 bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
145 int* buf_size,
146 int min_size) {
147 if (!next_handler_) {
148 DCHECK_EQ(-1, min_size);
149 if (!read_buffer_.get())
150 read_buffer_ = new net::IOBuffer(kReadBufSize);
151 *buf = read_buffer_;
152 *buf_size = kReadBufSize;
153 return true;
156 return next_handler_->OnWillRead(buf, buf_size, min_size);
159 bool DetachableResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
160 DCHECK(!is_deferred_);
162 if (!next_handler_)
163 return true;
165 bool ret =
166 next_handler_->OnReadCompleted(bytes_read, &is_deferred_);
167 *defer = is_deferred_;
168 return ret;
171 void DetachableResourceHandler::OnResponseCompleted(
172 const net::URLRequestStatus& status,
173 const std::string& security_info,
174 bool* defer) {
175 // No DCHECK(!is_deferred_) as the request may have been cancelled while
176 // deferred.
178 if (!next_handler_)
179 return;
181 is_finished_ = true;
183 next_handler_->OnResponseCompleted(status, security_info, &is_deferred_);
184 *defer = is_deferred_;
187 void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) {
188 if (!next_handler_)
189 return;
191 next_handler_->OnDataDownloaded(bytes_downloaded);
194 void DetachableResourceHandler::Resume() {
195 DCHECK(is_deferred_);
196 is_deferred_ = false;
197 controller()->Resume();
200 void DetachableResourceHandler::Cancel() {
201 controller()->Cancel();
204 void DetachableResourceHandler::CancelAndIgnore() {
205 controller()->CancelAndIgnore();
208 void DetachableResourceHandler::CancelWithError(int error_code) {
209 controller()->CancelWithError(error_code);
212 } // namespace content