blob: df9c357a888bb0658eb769b392f5d06b62d8fa19 [file] [log] [blame]
[email protected]146b8b22013-11-20 03:59:181// 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.
4
5#include "content/browser/loader/detachable_resource_handler.h"
6
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"
mmenke5c270612014-09-09 00:46:4512#include "net/url_request/url_request.h"
[email protected]146b8b22013-11-20 03:59:1813#include "net/url_request/url_request_status.h"
14
15namespace {
16// This matches the maximum allocation size of AsyncResourceHandler.
17const int kReadBufSize = 32 * 1024;
[email protected]f8453512014-04-17 01:12:4218}
[email protected]146b8b22013-11-20 03:59:1819
20namespace content {
21
22DetachableResourceHandler::DetachableResourceHandler(
23 net::URLRequest* request,
24 base::TimeDelta cancel_delay,
25 scoped_ptr<ResourceHandler> next_handler)
26 : ResourceHandler(request),
27 next_handler_(next_handler.Pass()),
28 cancel_delay_(cancel_delay),
29 is_deferred_(false),
[email protected]f8453512014-04-17 01:12:4230 is_finished_(false) {
[email protected]146b8b22013-11-20 03:59:1831 GetRequestInfo()->set_detachable_handler(this);
32}
33
34DetachableResourceHandler::~DetachableResourceHandler() {
35 // Cleanup back-pointer stored on the request info.
36 GetRequestInfo()->set_detachable_handler(NULL);
37}
38
39void DetachableResourceHandler::Detach() {
40 if (is_detached())
41 return;
42
43 if (!is_finished_) {
44 // Simulate a cancel on the next handler before destroying it.
45 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
46 net::ERR_ABORTED);
47 bool defer_ignored = false;
[email protected]d22e800e2014-05-28 21:55:5748 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
[email protected]146b8b22013-11-20 03:59:1849 DCHECK(!defer_ignored);
50 // If |next_handler_| were to defer its shutdown in OnResponseCompleted,
51 // this would destroy it anyway. Fortunately, AsyncResourceHandler never
mmenke664a8fd2015-06-13 00:08:5152 // does this anyway, so DCHECK it. MimeTypeResourceHandler and RVH shutdown
[email protected]146b8b22013-11-20 03:59:1853 // 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.
56 }
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();
64
65 // Time the request out if it takes too long.
danakj8c3eb802015-09-24 07:53:0066 detached_timer_.reset(new base::OneShotTimer());
[email protected]146b8b22013-11-20 03:59:1867 detached_timer_->Start(
[email protected]f8453512014-04-17 01:12:4268 FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel);
[email protected]146b8b22013-11-20 03:59:1869
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.
mmenke5c270612014-09-09 00:46:4573 if (is_deferred_) {
74 // The nested ResourceHandler may have logged that it's blocking the
75 // request. Log it as no longer doing so, to avoid a DCHECK on resume.
76 request()->LogUnblocked();
[email protected]146b8b22013-11-20 03:59:1877 Resume();
mmenke5c270612014-09-09 00:46:4578 }
[email protected]146b8b22013-11-20 03:59:1879}
80
81void DetachableResourceHandler::SetController(ResourceController* controller) {
82 ResourceHandler::SetController(controller);
83
84 // Intercept the ResourceController for downstream handlers to keep track of
85 // whether the request is deferred.
86 if (next_handler_)
87 next_handler_->SetController(this);
88}
89
[email protected]cba24642014-08-15 20:49:5990bool DetachableResourceHandler::OnRequestRedirected(
91 const net::RedirectInfo& redirect_info,
92 ResourceResponse* response,
93 bool* defer) {
[email protected]146b8b22013-11-20 03:59:1894 DCHECK(!is_deferred_);
95
96 if (!next_handler_)
97 return true;
98
[email protected]cba24642014-08-15 20:49:5999 bool ret = next_handler_->OnRequestRedirected(
100 redirect_info, response, &is_deferred_);
[email protected]146b8b22013-11-20 03:59:18101 *defer = is_deferred_;
102 return ret;
103}
104
[email protected]d22e800e2014-05-28 21:55:57105bool DetachableResourceHandler::OnResponseStarted(ResourceResponse* response,
[email protected]146b8b22013-11-20 03:59:18106 bool* defer) {
107 DCHECK(!is_deferred_);
108
109 if (!next_handler_)
110 return true;
111
112 bool ret =
[email protected]d22e800e2014-05-28 21:55:57113 next_handler_->OnResponseStarted(response, &is_deferred_);
[email protected]146b8b22013-11-20 03:59:18114 *defer = is_deferred_;
115 return ret;
116}
117
[email protected]d22e800e2014-05-28 21:55:57118bool DetachableResourceHandler::OnWillStart(const GURL& url, bool* defer) {
[email protected]146b8b22013-11-20 03:59:18119 DCHECK(!is_deferred_);
120
121 if (!next_handler_)
122 return true;
123
[email protected]d22e800e2014-05-28 21:55:57124 bool ret = next_handler_->OnWillStart(url, &is_deferred_);
[email protected]146b8b22013-11-20 03:59:18125 *defer = is_deferred_;
126 return ret;
127}
128
[email protected]d22e800e2014-05-28 21:55:57129bool DetachableResourceHandler::OnBeforeNetworkStart(const GURL& url,
[email protected]5584eab2014-01-09 22:16:15130 bool* defer) {
131 DCHECK(!is_deferred_);
132
133 if (!next_handler_)
134 return true;
135
136 bool ret =
[email protected]d22e800e2014-05-28 21:55:57137 next_handler_->OnBeforeNetworkStart(url, &is_deferred_);
[email protected]5584eab2014-01-09 22:16:15138 *defer = is_deferred_;
139 return ret;
140}
141
[email protected]d22e800e2014-05-28 21:55:57142bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
[email protected]146b8b22013-11-20 03:59:18143 int* buf_size,
144 int min_size) {
145 if (!next_handler_) {
146 DCHECK_EQ(-1, min_size);
dcheng67769df52014-08-26 19:43:51147 if (!read_buffer_.get())
[email protected]146b8b22013-11-20 03:59:18148 read_buffer_ = new net::IOBuffer(kReadBufSize);
149 *buf = read_buffer_;
150 *buf_size = kReadBufSize;
151 return true;
152 }
153
[email protected]d22e800e2014-05-28 21:55:57154 return next_handler_->OnWillRead(buf, buf_size, min_size);
[email protected]146b8b22013-11-20 03:59:18155}
156
[email protected]d22e800e2014-05-28 21:55:57157bool DetachableResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
[email protected]146b8b22013-11-20 03:59:18158 DCHECK(!is_deferred_);
159
160 if (!next_handler_)
161 return true;
162
163 bool ret =
[email protected]d22e800e2014-05-28 21:55:57164 next_handler_->OnReadCompleted(bytes_read, &is_deferred_);
[email protected]146b8b22013-11-20 03:59:18165 *defer = is_deferred_;
166 return ret;
167}
168
169void DetachableResourceHandler::OnResponseCompleted(
[email protected]146b8b22013-11-20 03:59:18170 const net::URLRequestStatus& status,
171 const std::string& security_info,
172 bool* defer) {
173 // No DCHECK(!is_deferred_) as the request may have been cancelled while
174 // deferred.
175
176 if (!next_handler_)
177 return;
178
179 is_finished_ = true;
180
[email protected]d22e800e2014-05-28 21:55:57181 next_handler_->OnResponseCompleted(status, security_info, &is_deferred_);
[email protected]146b8b22013-11-20 03:59:18182 *defer = is_deferred_;
183}
184
[email protected]d22e800e2014-05-28 21:55:57185void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) {
[email protected]146b8b22013-11-20 03:59:18186 if (!next_handler_)
187 return;
188
[email protected]d22e800e2014-05-28 21:55:57189 next_handler_->OnDataDownloaded(bytes_downloaded);
[email protected]146b8b22013-11-20 03:59:18190}
191
192void DetachableResourceHandler::Resume() {
193 DCHECK(is_deferred_);
194 is_deferred_ = false;
195 controller()->Resume();
196}
197
198void DetachableResourceHandler::Cancel() {
199 controller()->Cancel();
200}
201
202void DetachableResourceHandler::CancelAndIgnore() {
203 controller()->CancelAndIgnore();
204}
205
206void DetachableResourceHandler::CancelWithError(int error_code) {
207 controller()->CancelWithError(error_code);
208}
209
[email protected]146b8b22013-11-20 03:59:18210} // namespace content