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(int request_id
,
36 ResourceResponse
* response
,
38 DCHECK(!cancelled_by_resource_throttle_
);
41 while (next_index_
< throttles_
.size()) {
42 int index
= next_index_
;
43 throttles_
[index
]->WillRedirectRequest(new_url
, defer
);
45 if (cancelled_by_resource_throttle_
)
48 OnRequestDefered(index
);
49 deferred_stage_
= DEFERRED_REDIRECT
;
50 deferred_url_
= new_url
;
51 deferred_response_
= response
;
52 return true; // Do not cancel.
56 next_index_
= 0; // Reset for next time.
58 return next_handler_
->OnRequestRedirected(request_id
, new_url
, response
,
62 bool ThrottlingResourceHandler::OnWillStart(int request_id
,
65 DCHECK(!cancelled_by_resource_throttle_
);
68 while (next_index_
< throttles_
.size()) {
69 int index
= next_index_
;
70 throttles_
[index
]->WillStartRequest(defer
);
72 if (cancelled_by_resource_throttle_
)
75 OnRequestDefered(index
);
76 deferred_stage_
= DEFERRED_START
;
78 return true; // Do not cancel.
82 next_index_
= 0; // Reset for next time.
84 return next_handler_
->OnWillStart(request_id
, url
, defer
);
87 bool ThrottlingResourceHandler::OnBeforeNetworkStart(int request_id
,
90 DCHECK(!cancelled_by_resource_throttle_
);
93 while (next_index_
< throttles_
.size()) {
94 int index
= next_index_
;
95 throttles_
[index
]->OnBeforeNetworkStart(defer
);
97 if (cancelled_by_resource_throttle_
)
100 OnRequestDefered(index
);
101 deferred_stage_
= DEFERRED_NETWORK_START
;
103 return true; // Do not cancel.
107 next_index_
= 0; // Reset for next time.
109 return next_handler_
->OnBeforeNetworkStart(request_id
, url
, defer
);
112 bool ThrottlingResourceHandler::OnResponseStarted(int request_id
,
113 ResourceResponse
* response
,
115 DCHECK(!cancelled_by_resource_throttle_
);
117 while (next_index_
< throttles_
.size()) {
118 int index
= next_index_
;
119 throttles_
[index
]->WillProcessResponse(defer
);
121 if (cancelled_by_resource_throttle_
)
124 OnRequestDefered(index
);
125 deferred_stage_
= DEFERRED_RESPONSE
;
126 deferred_response_
= response
;
127 return true; // Do not cancel.
131 next_index_
= 0; // Reset for next time.
133 return next_handler_
->OnResponseStarted(request_id
, response
, defer
);
136 void ThrottlingResourceHandler::Cancel() {
137 cancelled_by_resource_throttle_
= true;
138 controller()->Cancel();
141 void ThrottlingResourceHandler::CancelAndIgnore() {
142 cancelled_by_resource_throttle_
= true;
143 controller()->CancelAndIgnore();
146 void ThrottlingResourceHandler::CancelWithError(int error_code
) {
147 cancelled_by_resource_throttle_
= true;
148 controller()->CancelWithError(error_code
);
151 void ThrottlingResourceHandler::Resume() {
152 DCHECK(!cancelled_by_resource_throttle_
);
154 DeferredStage last_deferred_stage
= deferred_stage_
;
155 deferred_stage_
= DEFERRED_NONE
;
156 // Clear information about the throttle that delayed the request.
157 request()->LogUnblocked();
158 switch (last_deferred_stage
) {
165 case DEFERRED_NETWORK_START
:
166 ResumeNetworkStart();
168 case DEFERRED_REDIRECT
:
171 case DEFERRED_RESPONSE
:
177 void ThrottlingResourceHandler::ResumeStart() {
178 DCHECK(!cancelled_by_resource_throttle_
);
180 GURL url
= deferred_url_
;
181 deferred_url_
= GURL();
184 if (!OnWillStart(GetRequestID(), url
, &defer
)) {
185 controller()->Cancel();
187 controller()->Resume();
191 void ThrottlingResourceHandler::ResumeNetworkStart() {
192 DCHECK(!cancelled_by_resource_throttle_
);
194 GURL url
= deferred_url_
;
195 deferred_url_
= GURL();
198 if (!OnBeforeNetworkStart(GetRequestID(), url
, &defer
)) {
199 controller()->Cancel();
201 controller()->Resume();
205 void ThrottlingResourceHandler::ResumeRedirect() {
206 DCHECK(!cancelled_by_resource_throttle_
);
208 GURL new_url
= deferred_url_
;
209 deferred_url_
= GURL();
210 scoped_refptr
<ResourceResponse
> response
;
211 deferred_response_
.swap(response
);
214 if (!OnRequestRedirected(GetRequestID(), new_url
, response
.get(), &defer
)) {
215 controller()->Cancel();
217 controller()->Resume();
221 void ThrottlingResourceHandler::ResumeResponse() {
222 DCHECK(!cancelled_by_resource_throttle_
);
224 scoped_refptr
<ResourceResponse
> response
;
225 deferred_response_
.swap(response
);
228 if (!OnResponseStarted(GetRequestID(), response
.get(), &defer
)) {
229 controller()->Cancel();
231 controller()->Resume();
235 void ThrottlingResourceHandler::OnRequestDefered(int throttle_index
) {
236 request()->LogBlockedBy(throttles_
[throttle_index
]->GetNameForLogging());
239 } // namespace content