Apply _RELATIVE relocations ahead of others.
[chromium-blink-merge.git] / content / browser / loader / throttling_resource_handler.cc
blob1f17d336b6d6207522be03a543a2e8a8c197f952
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"
12 namespace content {
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()),
21 next_index_(0),
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,
37 bool* defer) {
38 DCHECK(!cancelled_by_resource_throttle_);
40 *defer = false;
41 while (next_index_ < throttles_.size()) {
42 int index = next_index_;
43 throttles_[index]->WillRedirectRequest(redirect_info.new_url, defer);
44 next_index_++;
45 if (cancelled_by_resource_throttle_)
46 return false;
47 if (*defer) {
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_);
64 *defer = false;
65 while (next_index_ < throttles_.size()) {
66 int index = next_index_;
67 throttles_[index]->WillStartRequest(defer);
68 next_index_++;
69 if (cancelled_by_resource_throttle_)
70 return false;
71 if (*defer) {
72 OnRequestDefered(index);
73 deferred_stage_ = DEFERRED_START;
74 deferred_url_ = url;
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,
85 bool* defer) {
86 DCHECK(!cancelled_by_resource_throttle_);
88 *defer = false;
89 while (next_index_ < throttles_.size()) {
90 int index = next_index_;
91 throttles_[index]->WillStartUsingNetwork(defer);
92 next_index_++;
93 if (cancelled_by_resource_throttle_)
94 return false;
95 if (*defer) {
96 OnRequestDefered(index);
97 deferred_stage_ = DEFERRED_NETWORK_START;
98 deferred_url_ = url;
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,
109 bool* defer) {
110 DCHECK(!cancelled_by_resource_throttle_);
112 while (next_index_ < throttles_.size()) {
113 int index = next_index_;
114 throttles_[index]->WillProcessResponse(defer);
115 next_index_++;
116 if (cancelled_by_resource_throttle_)
117 return false;
118 if (*defer) {
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) {
154 case DEFERRED_NONE:
155 NOTREACHED();
156 break;
157 case DEFERRED_START:
158 ResumeStart();
159 break;
160 case DEFERRED_NETWORK_START:
161 ResumeNetworkStart();
162 break;
163 case DEFERRED_REDIRECT:
164 ResumeRedirect();
165 break;
166 case DEFERRED_RESPONSE:
167 ResumeResponse();
168 break;
172 void ThrottlingResourceHandler::ResumeStart() {
173 DCHECK(!cancelled_by_resource_throttle_);
175 GURL url = deferred_url_;
176 deferred_url_ = GURL();
178 bool defer = false;
179 if (!OnWillStart(url, &defer)) {
180 controller()->Cancel();
181 } else if (!defer) {
182 controller()->Resume();
186 void ThrottlingResourceHandler::ResumeNetworkStart() {
187 DCHECK(!cancelled_by_resource_throttle_);
189 GURL url = deferred_url_;
190 deferred_url_ = GURL();
192 bool defer = false;
193 if (!OnBeforeNetworkStart(url, &defer)) {
194 controller()->Cancel();
195 } else if (!defer) {
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);
208 bool defer = false;
209 if (!OnRequestRedirected(redirect_info, response.get(), &defer)) {
210 controller()->Cancel();
211 } else if (!defer) {
212 controller()->Resume();
216 void ThrottlingResourceHandler::ResumeResponse() {
217 DCHECK(!cancelled_by_resource_throttle_);
219 scoped_refptr<ResourceResponse> response;
220 deferred_response_.swap(response);
222 bool defer = false;
223 if (!OnResponseStarted(response.get(), &defer)) {
224 controller()->Cancel();
225 } else if (!defer) {
226 controller()->Resume();
230 void ThrottlingResourceHandler::OnRequestDefered(int throttle_index) {
231 request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging());
234 } // namespace content