OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/loader/throttling_resource_handler.h" | 5 #include "content/browser/loader/throttling_resource_handler.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "content/browser/loader/resource_controller.h" | 9 #include "content/browser/loader/resource_controller.h" |
10 #include "content/public/common/resource_response.h" | 10 #include "content/public/common/resource_response.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 throttle->set_delegate(this); | 25 throttle->set_delegate(this); |
26 // Throttles must have a name, as otherwise, bugs where a throttle fails | 26 // Throttles must have a name, as otherwise, bugs where a throttle fails |
27 // to resume a request can be very difficult to debug. | 27 // to resume a request can be very difficult to debug. |
28 DCHECK(throttle->GetNameForLogging()); | 28 DCHECK(throttle->GetNameForLogging()); |
29 } | 29 } |
30 } | 30 } |
31 | 31 |
32 ThrottlingResourceHandler::~ThrottlingResourceHandler() { | 32 ThrottlingResourceHandler::~ThrottlingResourceHandler() { |
33 } | 33 } |
34 | 34 |
35 bool ThrottlingResourceHandler::OnRequestRedirected( | 35 void ThrottlingResourceHandler::OnRequestRedirected( |
36 const net::RedirectInfo& redirect_info, | 36 const net::RedirectInfo& redirect_info, |
37 ResourceResponse* response, | 37 ResourceResponse* response, |
38 bool* defer) { | 38 std::unique_ptr<ResourceController> controller) { |
| 39 DCHECK(!has_controller()); |
39 DCHECK(!cancelled_by_resource_throttle_); | 40 DCHECK(!cancelled_by_resource_throttle_); |
40 DCHECK(!*defer); | |
41 | 41 |
| 42 HoldController(std::move(controller)); |
42 while (next_index_ < throttles_.size()) { | 43 while (next_index_ < throttles_.size()) { |
43 int index = next_index_; | 44 int index = next_index_; |
44 throttles_[index]->WillRedirectRequest(redirect_info, defer); | 45 bool defer = false; |
| 46 throttles_[index]->WillRedirectRequest(redirect_info, &defer); |
45 next_index_++; | 47 next_index_++; |
46 if (cancelled_by_resource_throttle_) | 48 if (cancelled_by_resource_throttle_) |
47 return false; | 49 return; |
48 if (*defer) { | 50 |
| 51 if (defer) { |
49 OnRequestDeferred(index); | 52 OnRequestDeferred(index); |
50 deferred_stage_ = DEFERRED_REDIRECT; | 53 deferred_stage_ = DEFERRED_REDIRECT; |
51 deferred_redirect_ = redirect_info; | 54 deferred_redirect_ = redirect_info; |
52 deferred_response_ = response; | 55 deferred_response_ = response; |
53 return true; // Do not cancel. | 56 return; |
54 } | 57 } |
55 } | 58 } |
56 | 59 |
57 next_index_ = 0; // Reset for next time. | 60 next_index_ = 0; // Reset for next time. |
58 | 61 |
59 return next_handler_->OnRequestRedirected(redirect_info, response, defer); | 62 next_handler_->OnRequestRedirected(redirect_info, response, |
| 63 ReleaseController()); |
60 } | 64 } |
61 | 65 |
62 bool ThrottlingResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 66 void ThrottlingResourceHandler::OnWillStart( |
| 67 const GURL& url, |
| 68 std::unique_ptr<ResourceController> controller) { |
63 DCHECK(!cancelled_by_resource_throttle_); | 69 DCHECK(!cancelled_by_resource_throttle_); |
64 DCHECK(!*defer); | 70 DCHECK(!has_controller()); |
65 | 71 |
| 72 HoldController(std::move(controller)); |
66 while (next_index_ < throttles_.size()) { | 73 while (next_index_ < throttles_.size()) { |
67 int index = next_index_; | 74 int index = next_index_; |
68 throttles_[index]->WillStartRequest(defer); | 75 bool defer = false; |
| 76 throttles_[index]->WillStartRequest(&defer); |
69 next_index_++; | 77 next_index_++; |
70 if (cancelled_by_resource_throttle_) | 78 if (cancelled_by_resource_throttle_) |
71 return false; | 79 return; |
72 if (*defer) { | 80 if (defer) { |
73 OnRequestDeferred(index); | 81 OnRequestDeferred(index); |
74 deferred_stage_ = DEFERRED_START; | 82 deferred_stage_ = DEFERRED_START; |
75 deferred_url_ = url; | 83 deferred_url_ = url; |
76 return true; // Do not cancel. | 84 return; |
77 } | 85 } |
78 } | 86 } |
79 | 87 |
80 next_index_ = 0; // Reset for next time. | 88 next_index_ = 0; // Reset for next time. |
81 | 89 |
82 return next_handler_->OnWillStart(url, defer); | 90 return next_handler_->OnWillStart(url, ReleaseController()); |
83 } | 91 } |
84 | 92 |
85 bool ThrottlingResourceHandler::OnResponseStarted(ResourceResponse* response, | 93 void ThrottlingResourceHandler::OnResponseStarted( |
86 bool* defer) { | 94 ResourceResponse* response, |
| 95 std::unique_ptr<ResourceController> controller) { |
87 DCHECK(!cancelled_by_resource_throttle_); | 96 DCHECK(!cancelled_by_resource_throttle_); |
88 DCHECK(!*defer); | 97 DCHECK(!has_controller()); |
89 | 98 |
| 99 HoldController(std::move(controller)); |
90 while (next_index_ < throttles_.size()) { | 100 while (next_index_ < throttles_.size()) { |
91 int index = next_index_; | 101 int index = next_index_; |
92 throttles_[index]->WillProcessResponse(defer); | 102 bool defer = false; |
| 103 throttles_[index]->WillProcessResponse(&defer); |
93 next_index_++; | 104 next_index_++; |
94 if (cancelled_by_resource_throttle_) | 105 if (cancelled_by_resource_throttle_) |
95 return false; | 106 return; |
96 if (*defer) { | 107 if (defer) { |
97 OnRequestDeferred(index); | 108 OnRequestDeferred(index); |
98 deferred_stage_ = DEFERRED_RESPONSE; | 109 deferred_stage_ = DEFERRED_RESPONSE; |
99 deferred_response_ = response; | 110 deferred_response_ = response; |
100 return true; // Do not cancel. | 111 return; |
101 } | 112 } |
102 } | 113 } |
103 | 114 |
104 next_index_ = 0; // Reset for next time. | 115 next_index_ = 0; // Reset for next time. |
105 | 116 |
106 return next_handler_->OnResponseStarted(response, defer); | 117 return next_handler_->OnResponseStarted(response, ReleaseController()); |
107 } | 118 } |
108 | 119 |
109 void ThrottlingResourceHandler::Cancel() { | 120 void ThrottlingResourceHandler::Cancel() { |
| 121 if (!has_controller()) { |
| 122 OutOfBandCancel(net::ERR_ABORTED, false /* tell_renderer */); |
| 123 return; |
| 124 } |
110 cancelled_by_resource_throttle_ = true; | 125 cancelled_by_resource_throttle_ = true; |
111 controller()->Cancel(); | 126 ResourceHandler::Cancel(); |
112 } | 127 } |
113 | 128 |
114 void ThrottlingResourceHandler::CancelAndIgnore() { | 129 void ThrottlingResourceHandler::CancelAndIgnore() { |
| 130 if (!has_controller()) { |
| 131 OutOfBandCancel(net::ERR_ABORTED, false /* tell_renderer */); |
| 132 return; |
| 133 } |
115 cancelled_by_resource_throttle_ = true; | 134 cancelled_by_resource_throttle_ = true; |
116 controller()->CancelAndIgnore(); | 135 ResourceHandler::CancelAndIgnore(); |
117 } | 136 } |
118 | 137 |
119 void ThrottlingResourceHandler::CancelWithError(int error_code) { | 138 void ThrottlingResourceHandler::CancelWithError(int error_code) { |
| 139 if (!has_controller()) { |
| 140 OutOfBandCancel(error_code, false /* tell_renderer */); |
| 141 return; |
| 142 } |
120 cancelled_by_resource_throttle_ = true; | 143 cancelled_by_resource_throttle_ = true; |
121 controller()->CancelWithError(error_code); | 144 ResourceHandler::CancelWithError(error_code); |
122 } | 145 } |
123 | 146 |
124 void ThrottlingResourceHandler::Resume() { | 147 void ThrottlingResourceHandler::Resume() { |
125 // Throttles expect to be able to cancel requests out-of-band, so just do | 148 // Throttles expect to be able to cancel requests out-of-band, so just do |
126 // nothing if one request resumes after another cancels. Can't even recognize | 149 // nothing if one request resumes after another cancels. Can't even recognize |
127 // out-of-band cancels and for synchronous teardown, since don't know if the | 150 // out-of-band cancels and for synchronous teardown, since don't know if the |
128 // currently active throttle called Cancel() or if it was another one. | 151 // currently active throttle called Cancel() or if it was another one. |
129 if (cancelled_by_resource_throttle_) | 152 if (cancelled_by_resource_throttle_) |
130 return; | 153 return; |
131 | 154 |
| 155 DCHECK(has_controller()); |
| 156 |
132 DeferredStage last_deferred_stage = deferred_stage_; | 157 DeferredStage last_deferred_stage = deferred_stage_; |
133 deferred_stage_ = DEFERRED_NONE; | 158 deferred_stage_ = DEFERRED_NONE; |
134 // Clear information about the throttle that delayed the request. | 159 // Clear information about the throttle that delayed the request. |
135 request()->LogUnblocked(); | 160 request()->LogUnblocked(); |
136 switch (last_deferred_stage) { | 161 switch (last_deferred_stage) { |
137 case DEFERRED_NONE: | 162 case DEFERRED_NONE: |
138 NOTREACHED(); | 163 NOTREACHED(); |
139 break; | 164 break; |
140 case DEFERRED_START: | 165 case DEFERRED_START: |
141 ResumeStart(); | 166 ResumeStart(); |
142 break; | 167 break; |
143 case DEFERRED_REDIRECT: | 168 case DEFERRED_REDIRECT: |
144 ResumeRedirect(); | 169 ResumeRedirect(); |
145 break; | 170 break; |
146 case DEFERRED_RESPONSE: | 171 case DEFERRED_RESPONSE: |
147 ResumeResponse(); | 172 ResumeResponse(); |
148 break; | 173 break; |
149 } | 174 } |
150 } | 175 } |
151 | 176 |
152 void ThrottlingResourceHandler::ResumeStart() { | 177 void ThrottlingResourceHandler::ResumeStart() { |
153 DCHECK(!cancelled_by_resource_throttle_); | 178 DCHECK(!cancelled_by_resource_throttle_); |
| 179 DCHECK(has_controller()); |
154 | 180 |
155 GURL url = deferred_url_; | 181 GURL url = deferred_url_; |
156 deferred_url_ = GURL(); | 182 deferred_url_ = GURL(); |
157 | 183 |
158 bool defer = false; | 184 OnWillStart(url, ReleaseController()); |
159 if (!OnWillStart(url, &defer)) { | |
160 controller()->Cancel(); | |
161 } else if (!defer) { | |
162 controller()->Resume(); | |
163 } | |
164 } | 185 } |
165 | 186 |
166 void ThrottlingResourceHandler::ResumeRedirect() { | 187 void ThrottlingResourceHandler::ResumeRedirect() { |
167 DCHECK(!cancelled_by_resource_throttle_); | 188 DCHECK(!cancelled_by_resource_throttle_); |
| 189 DCHECK(has_controller()); |
168 | 190 |
169 net::RedirectInfo redirect_info = deferred_redirect_; | 191 net::RedirectInfo redirect_info = deferred_redirect_; |
170 deferred_redirect_ = net::RedirectInfo(); | 192 deferred_redirect_ = net::RedirectInfo(); |
171 scoped_refptr<ResourceResponse> response; | 193 scoped_refptr<ResourceResponse> response; |
172 deferred_response_.swap(response); | 194 deferred_response_.swap(response); |
173 | 195 |
174 bool defer = false; | 196 OnRequestRedirected(redirect_info, response.get(), ReleaseController()); |
175 if (!OnRequestRedirected(redirect_info, response.get(), &defer)) { | |
176 controller()->Cancel(); | |
177 } else if (!defer) { | |
178 controller()->Resume(); | |
179 } | |
180 } | 197 } |
181 | 198 |
182 void ThrottlingResourceHandler::ResumeResponse() { | 199 void ThrottlingResourceHandler::ResumeResponse() { |
183 DCHECK(!cancelled_by_resource_throttle_); | 200 DCHECK(!cancelled_by_resource_throttle_); |
| 201 DCHECK(has_controller()); |
184 | 202 |
185 scoped_refptr<ResourceResponse> response; | 203 scoped_refptr<ResourceResponse> response; |
186 deferred_response_.swap(response); | 204 deferred_response_.swap(response); |
187 | 205 |
188 bool defer = false; | 206 OnResponseStarted(response.get(), ReleaseController()); |
189 if (!OnResponseStarted(response.get(), &defer)) { | |
190 controller()->Cancel(); | |
191 } else if (!defer) { | |
192 controller()->Resume(); | |
193 } | |
194 } | 207 } |
195 | 208 |
196 void ThrottlingResourceHandler::OnRequestDeferred(int throttle_index) { | 209 void ThrottlingResourceHandler::OnRequestDeferred(int throttle_index) { |
197 request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging()); | 210 request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging()); |
198 } | 211 } |
199 | 212 |
200 } // namespace content | 213 } // namespace content |
OLD | NEW |