1 // Copyright (c) 2012 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/throttling_resource_handler.h"
7 #include "content/browser/loader/resource_request_info_impl.h"
8 #include "content/public/browser/resource_throttle.h"
9 #include "content/public/common/resource_response.h"
10 #include "net/url_request/url_request.h"
14 ThrottlingResourceHandler::ThrottlingResourceHandler(
15 scoped_ptr
<ResourceHandler
> next_handler
,
16 net::URLRequest
* request
,
17 ScopedVector
<ResourceThrottle
> throttles
)
18 : LayeredResourceHandler(request
, next_handler
.Pass()),
19 deferred_stage_(DEFERRED_NONE
),
20 throttles_(throttles
.Pass()),
22 cancelled_by_resource_throttle_(false) {
23 for (size_t i
= 0; i
< throttles_
.size(); ++i
) {
24 throttles_
[i
]->set_controller(this);
25 // Throttles must have a name, as otherwise, bugs where a throttle fails
26 // to resume a request can be very difficult to debug.
27 DCHECK(throttles_
[i
]->GetNameForLogging());
31 ThrottlingResourceHandler::~ThrottlingResourceHandler() {
34 bool ThrottlingResourceHandler::OnRequestRedirected(
35 const net::RedirectInfo
& redirect_info
,
36 ResourceResponse
* response
,
38 DCHECK(!cancelled_by_resource_throttle_
);
41 while (next_index_
< throttles_
.size()) {
42 int index
= next_index_
;
43 throttles_
[index
]->WillRedirectRequest(redirect_info
.new_url
, defer
);
45 if (cancelled_by_resource_throttle_
)
48 OnRequestDefered(index
);
49 deferred_stage_
= DEFERRED_REDIRECT
;
50 deferred_redirect_
= redirect_info
;
51 deferred_response_
= response
;
52 return true; // Do not cancel.
56 next_index_
= 0; // Reset for next time.
58 return next_handler_
->OnRequestRedirected(redirect_info
, response
, defer
);
61 bool ThrottlingResourceHandler::OnWillStart(const GURL
& url
, bool* defer
) {
62 DCHECK(!cancelled_by_resource_throttle_
);
65 while (next_index_
< throttles_
.size()) {
66 int index
= next_index_
;
67 throttles_
[index
]->WillStartRequest(defer
);
69 if (cancelled_by_resource_throttle_
)
72 OnRequestDefered(index
);
73 deferred_stage_
= DEFERRED_START
;
75 return true; // Do not cancel.
79 next_index_
= 0; // Reset for next time.
81 return next_handler_
->OnWillStart(url
, defer
);
84 bool ThrottlingResourceHandler::OnBeforeNetworkStart(const GURL
& url
,
86 DCHECK(!cancelled_by_resource_throttle_
);
89 while (next_index_
< throttles_
.size()) {
90 int index
= next_index_
;
91 throttles_
[index
]->WillStartUsingNetwork(defer
);
93 if (cancelled_by_resource_throttle_
)
96 OnRequestDefered(index
);
97 deferred_stage_
= DEFERRED_NETWORK_START
;
99 return true; // Do not cancel.
103 next_index_
= 0; // Reset for next time.
105 return next_handler_
->OnBeforeNetworkStart(url
, defer
);
108 bool ThrottlingResourceHandler::OnResponseStarted(ResourceResponse
* response
,
110 DCHECK(!cancelled_by_resource_throttle_
);
112 while (next_index_
< throttles_
.size()) {
113 int index
= next_index_
;
114 throttles_
[index
]->WillProcessResponse(defer
);
116 if (cancelled_by_resource_throttle_
)
119 OnRequestDefered(index
);
120 deferred_stage_
= DEFERRED_RESPONSE
;
121 deferred_response_
= response
;
122 return true; // Do not cancel.
126 next_index_
= 0; // Reset for next time.
128 return next_handler_
->OnResponseStarted(response
, defer
);
131 void ThrottlingResourceHandler::Cancel() {
132 cancelled_by_resource_throttle_
= true;
133 controller()->Cancel();
136 void ThrottlingResourceHandler::CancelAndIgnore() {
137 cancelled_by_resource_throttle_
= true;
138 controller()->CancelAndIgnore();
141 void ThrottlingResourceHandler::CancelWithError(int error_code
) {
142 cancelled_by_resource_throttle_
= true;
143 controller()->CancelWithError(error_code
);
146 void ThrottlingResourceHandler::Resume() {
147 DCHECK(!cancelled_by_resource_throttle_
);
149 DeferredStage last_deferred_stage
= deferred_stage_
;
150 deferred_stage_
= DEFERRED_NONE
;
151 // Clear information about the throttle that delayed the request.
152 request()->LogUnblocked();
153 switch (last_deferred_stage
) {
160 case DEFERRED_NETWORK_START
:
161 ResumeNetworkStart();
163 case DEFERRED_REDIRECT
:
166 case DEFERRED_RESPONSE
:
172 void ThrottlingResourceHandler::ResumeStart() {
173 DCHECK(!cancelled_by_resource_throttle_
);
175 GURL url
= deferred_url_
;
176 deferred_url_
= GURL();
179 if (!OnWillStart(url
, &defer
)) {
180 controller()->Cancel();
182 controller()->Resume();
186 void ThrottlingResourceHandler::ResumeNetworkStart() {
187 DCHECK(!cancelled_by_resource_throttle_
);
189 GURL url
= deferred_url_
;
190 deferred_url_
= GURL();
193 if (!OnBeforeNetworkStart(url
, &defer
)) {
194 controller()->Cancel();
196 controller()->Resume();
200 void ThrottlingResourceHandler::ResumeRedirect() {
201 DCHECK(!cancelled_by_resource_throttle_
);
203 net::RedirectInfo redirect_info
= deferred_redirect_
;
204 deferred_redirect_
= net::RedirectInfo();
205 scoped_refptr
<ResourceResponse
> response
;
206 deferred_response_
.swap(response
);
209 if (!OnRequestRedirected(redirect_info
, response
.get(), &defer
)) {
210 controller()->Cancel();
212 controller()->Resume();
216 void ThrottlingResourceHandler::ResumeResponse() {
217 DCHECK(!cancelled_by_resource_throttle_
);
219 scoped_refptr
<ResourceResponse
> response
;
220 deferred_response_
.swap(response
);
223 if (!OnResponseStarted(response
.get(), &defer
)) {
224 controller()->Cancel();
226 controller()->Resume();
230 void ThrottlingResourceHandler::OnRequestDefered(int throttle_index
) {
231 request()->LogBlockedBy(throttles_
[throttle_index
]->GetNameForLogging());
234 } // namespace content