OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/intercepting_resource_handler.h" | 5 #include "content/browser/loader/intercepting_resource_handler.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 response_ = response; | 85 response_ = response; |
86 | 86 |
87 // Otherwise, switch handlers. First, inform the original ResourceHandler | 87 // Otherwise, switch handlers. First, inform the original ResourceHandler |
88 // that this will be handled entirely by the new ResourceHandler. | 88 // that this will be handled entirely by the new ResourceHandler. |
89 HoldController(std::move(controller)); | 89 HoldController(std::move(controller)); |
90 state_ = State::SWAPPING_HANDLERS; | 90 state_ = State::SWAPPING_HANDLERS; |
91 | 91 |
92 DoLoop(); | 92 DoLoop(); |
93 } | 93 } |
94 | 94 |
95 bool InterceptingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 95 void InterceptingResourceHandler::OnWillRead( |
96 int* buf_size) { | 96 scoped_refptr<net::IOBuffer>* buf, |
97 if (state_ == State::PASS_THROUGH) | 97 int* buf_size, |
98 return next_handler_->OnWillRead(buf, buf_size); | 98 std::unique_ptr<ResourceController> controller) { |
99 if (state_ == State::PASS_THROUGH) { | |
100 next_handler_->OnWillRead(buf, buf_size, std::move(controller)); | |
101 return; | |
102 } | |
99 | 103 |
100 DCHECK_EQ(State::STARTING, state_); | 104 DCHECK_EQ(State::STARTING, state_); |
105 DCHECK(!first_read_buffer_); | |
106 DCHECK_EQ(0, first_read_buffer_size_); | |
107 DCHECK(!parent_read_buffer_); | |
108 DCHECK(!parent_read_buffer_size_); | |
101 | 109 |
102 if (!next_handler_->OnWillRead(buf, buf_size)) | 110 parent_read_buffer_ = buf; |
103 return false; | 111 parent_read_buffer_size_ = buf_size; |
104 | 112 |
105 first_read_buffer_ = *buf; | 113 state_ = State::SENDING_ON_WILL_READ_TO_OLD_HANDLER; |
106 first_read_buffer_size_ = *buf_size; | 114 HoldController(std::move(controller)); |
107 first_read_buffer_double_ = new net::IOBuffer(static_cast<size_t>(*buf_size)); | 115 DoLoop(); |
108 *buf = first_read_buffer_double_; | |
109 return true; | |
110 } | 116 } |
111 | 117 |
112 void InterceptingResourceHandler::OnReadCompleted( | 118 void InterceptingResourceHandler::OnReadCompleted( |
113 int bytes_read, | 119 int bytes_read, |
114 std::unique_ptr<ResourceController> controller) { | 120 std::unique_ptr<ResourceController> controller) { |
115 DCHECK(!has_controller()); | 121 DCHECK(!has_controller()); |
116 | 122 |
117 DCHECK_GE(bytes_read, 0); | 123 DCHECK_GE(bytes_read, 0); |
118 if (state_ == State::PASS_THROUGH) { | 124 if (state_ == State::PASS_THROUGH) { |
119 if (first_read_buffer_double_) { | 125 if (first_read_buffer_double_) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 | 190 |
185 while (advance_to_next_state_) { | 191 while (advance_to_next_state_) { |
186 advance_to_next_state_ = false; | 192 advance_to_next_state_ = false; |
187 | 193 |
188 switch (state_) { | 194 switch (state_) { |
189 case State::STARTING: | 195 case State::STARTING: |
190 case State::WAITING_FOR_ON_READ_COMPLETED: | 196 case State::WAITING_FOR_ON_READ_COMPLETED: |
191 case State::PASS_THROUGH: | 197 case State::PASS_THROUGH: |
192 NOTREACHED(); | 198 NOTREACHED(); |
193 break; | 199 break; |
200 case State::SENDING_ON_WILL_READ_TO_OLD_HANDLER: | |
201 SendOnWillReadToOldHandler(); | |
202 break; | |
203 case State::WAITING_FOR_OLD_HANDLERS_BUFFER: | |
204 OnBufferReceived(); | |
205 break; | |
194 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER: | 206 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER: |
195 SendOnResponseStartedToNewHandler(); | 207 SendOnResponseStartedToNewHandler(); |
196 break; | 208 break; |
197 case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER: | 209 case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER: |
198 if (first_read_buffer_double_) { | 210 if (first_read_buffer_double_) { |
199 // OnWillRead has been called, so copying the data from | 211 // OnWillRead has been called, so copying the data from |
200 // |first_read_buffer_double_| to |first_read_buffer_| will be needed | 212 // |first_read_buffer_double_| to |first_read_buffer_| will be needed |
201 // when OnReadCompleted is called. | 213 // when OnReadCompleted is called. |
202 state_ = State::WAITING_FOR_ON_READ_COMPLETED; | 214 state_ = State::WAITING_FOR_ON_READ_COMPLETED; |
203 } else { | 215 } else { |
204 // OnWillRead has not been called, so no special handling will be | 216 // OnWillRead has not been called, so no special handling will be |
205 // needed from now on. | 217 // needed from now on. |
206 state_ = State::PASS_THROUGH; | 218 state_ = State::PASS_THROUGH; |
207 } | 219 } |
208 ResumeInternal(); | 220 ResumeInternal(); |
209 break; | 221 break; |
210 case State::SWAPPING_HANDLERS: | 222 case State::SWAPPING_HANDLERS: |
211 SendOnResponseStartedToOldHandler(); | 223 SendOnResponseStartedToOldHandler(); |
212 break; | 224 break; |
213 case State::SENDING_PAYLOAD_TO_OLD_HANDLER: | 225 case State::SENDING_PAYLOAD_TO_OLD_HANDLER: |
214 SendPayloadToOldHandler(); | 226 SendPayloadToOldHandler(); |
215 break; | 227 break; |
228 case State::RECEIVING_BUFFER_FROM_OLD_HANDLER: | |
229 ReceivedBufferFromOldHandler(); | |
230 break; | |
216 case State::SENDING_BUFFER_TO_NEW_HANDLER: | 231 case State::SENDING_BUFFER_TO_NEW_HANDLER: |
217 SendFirstReadBufferToNewHandler(); | 232 SendFirstReadBufferToNewHandler(); |
218 break; | 233 break; |
234 case State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER: | |
235 ReceivedBufferFromNewHandler(); | |
236 break; | |
219 } | 237 } |
220 } | 238 } |
221 } | 239 } |
222 | 240 |
223 void InterceptingResourceHandler::ResumeInternal() { | 241 void InterceptingResourceHandler::ResumeInternal() { |
224 DCHECK(has_controller()); | 242 DCHECK(has_controller()); |
225 if (state_ == State::STARTING || | 243 if (state_ == State::STARTING || |
226 state_ == State::WAITING_FOR_ON_READ_COMPLETED || | 244 state_ == State::WAITING_FOR_ON_READ_COMPLETED || |
227 state_ == State::PASS_THROUGH) { | 245 state_ == State::PASS_THROUGH) { |
228 // Uninteresting Resume: just delegate to the original resource controller. | 246 // Uninteresting Resume: just delegate to the original resource controller. |
229 Resume(); | 247 Resume(); |
230 return; | 248 return; |
231 } | 249 } |
232 | 250 |
233 // If called recusively from a DoLoop, advance state when returning to the | 251 // If called recusively from a DoLoop, advance state when returning to the |
234 // loop. | 252 // loop. |
235 if (in_do_loop_) { | 253 if (in_do_loop_) { |
236 DCHECK(!advance_to_next_state_); | 254 DCHECK(!advance_to_next_state_); |
237 advance_to_next_state_ = true; | 255 advance_to_next_state_ = true; |
238 return; | 256 return; |
239 } | 257 } |
240 | 258 |
241 // Can't call DoLoop synchronously, as it may call into |next_handler_| | 259 // Can't call DoLoop synchronously, as it may call into |next_handler_| |
242 // synchronously, which is what called Resume(). | 260 // synchronously, which is what called Resume(). |
243 base::ThreadTaskRunnerHandle::Get()->PostTask( | 261 base::ThreadTaskRunnerHandle::Get()->PostTask( |
244 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop, | 262 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop, |
245 weak_ptr_factory_.GetWeakPtr())); | 263 weak_ptr_factory_.GetWeakPtr())); |
246 } | 264 } |
247 | 265 |
266 void InterceptingResourceHandler::SendOnWillReadToOldHandler() { | |
267 DCHECK_EQ(State::SENDING_ON_WILL_READ_TO_OLD_HANDLER, state_); | |
268 | |
269 state_ = State::WAITING_FOR_OLD_HANDLERS_BUFFER; | |
270 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_, | |
271 base::MakeUnique<Controller>(this)); | |
272 } | |
273 | |
274 void InterceptingResourceHandler::OnBufferReceived() { | |
275 DCHECK_EQ(State::WAITING_FOR_OLD_HANDLERS_BUFFER, state_); | |
276 | |
277 // TODO(mmenke): If this method is just going to allocate a double buffer | |
278 // anyways, can the call to the old handler's OnWillRead be removed? That | |
279 // would mean handling replaying data in the case that |next_handler_|'s | |
280 // buffer is smaller than the double buffer, but SendPayloadToOldHandler | |
281 // already handles that case, anyways, so could share that code with the | |
282 // no-swap path as well. Or better, just have MimeSniffingResourceHandler | |
283 // create and manage the buffer itself. | |
284 first_read_buffer_double_ = | |
285 new net::IOBuffer(static_cast<size_t>(first_read_buffer_size_)); | |
286 *parent_read_buffer_ = first_read_buffer_double_; | |
287 *parent_read_buffer_size_ = first_read_buffer_size_; | |
288 | |
289 parent_read_buffer_ = nullptr; | |
290 parent_read_buffer_size_ = nullptr; | |
291 | |
292 state_ = State::STARTING; | |
293 Resume(); | |
294 } | |
295 | |
248 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() { | 296 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() { |
249 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; | 297 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; |
250 next_handler_->OnResponseStarted(response_.get(), | 298 next_handler_->OnResponseStarted(response_.get(), |
251 base::MakeUnique<Controller>(this)); | 299 base::MakeUnique<Controller>(this)); |
252 } | 300 } |
253 | 301 |
254 void InterceptingResourceHandler::SendPayloadToOldHandler() { | 302 void InterceptingResourceHandler::SendPayloadToOldHandler() { |
255 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_); | 303 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_); |
256 if (payload_bytes_written_ == payload_for_old_handler_.size()) { | 304 |
305 if (static_cast<size_t>(payload_bytes_written_) == | |
306 payload_for_old_handler_.size()) { | |
257 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); | 307 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); |
258 if (payload_for_old_handler_.empty()) { | 308 if (payload_for_old_handler_.empty()) { |
259 // If there is no payload, just finalize the request on the old handler. | 309 // If there is no payload, just finalize the request on the old handler. |
260 status = net::URLRequestStatus::FromError(net::ERR_ABORTED); | 310 status = net::URLRequestStatus::FromError(net::ERR_ABORTED); |
261 } | 311 } |
262 bool was_resumed = false; | 312 bool was_resumed = false; |
263 // TODO(mmenke): Get rid of NullResourceController and do something more | 313 // TODO(mmenke): Get rid of NullResourceController and do something more |
264 // reasonable. | 314 // reasonable. |
265 next_handler_->OnResponseCompleted( | 315 next_handler_->OnResponseCompleted( |
266 status, base::MakeUnique<NullResourceController>(&was_resumed)); | 316 status, base::MakeUnique<NullResourceController>(&was_resumed)); |
267 DCHECK(was_resumed); | 317 DCHECK(was_resumed); |
268 | 318 |
269 next_handler_ = std::move(new_handler_); | 319 next_handler_ = std::move(new_handler_); |
270 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER; | 320 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER; |
271 next_handler_->OnWillStart(request()->url(), | 321 next_handler_->OnWillStart(request()->url(), |
272 base::MakeUnique<Controller>(this)); | 322 base::MakeUnique<Controller>(this)); |
273 return; | 323 return; |
274 } | 324 } |
275 | 325 |
326 state_ = State::RECEIVING_BUFFER_FROM_OLD_HANDLER; | |
327 | |
276 scoped_refptr<net::IOBuffer> buffer; | 328 scoped_refptr<net::IOBuffer> buffer; |
277 int size = 0; | 329 // If |first_read_buffer_| is non-NULL, it was already received from |
330 // |next_handler_| via OnWillRead. Can just use the buffer. | |
278 if (first_read_buffer_) { | 331 if (first_read_buffer_) { |
279 // |first_read_buffer_| is a buffer gotten from |next_handler_| via | 332 DCHECK_GT(first_read_buffer_size_, 0); |
280 // OnWillRead. Use the buffer. | |
281 buffer = first_read_buffer_; | |
282 size = first_read_buffer_size_; | |
283 | 333 |
284 first_read_buffer_ = nullptr; | 334 ResumeInternal(); |
285 first_read_buffer_size_ = 0; | 335 return; |
286 } else { | |
287 if (!next_handler_->OnWillRead(&buffer, &size)) { | |
288 Cancel(); | |
289 return; | |
290 } | |
291 } | 336 } |
292 | 337 |
293 size = std::min(size, static_cast<int>(payload_for_old_handler_.size() - | 338 DCHECK(!first_read_buffer_size_); |
294 payload_bytes_written_)); | 339 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_, |
295 memcpy(buffer->data(), | 340 base::MakeUnique<Controller>(this)); |
296 payload_for_old_handler_.data() + payload_bytes_written_, size); | 341 } |
297 payload_bytes_written_ += size; | 342 |
298 next_handler_->OnReadCompleted(size, base::MakeUnique<Controller>(this)); | 343 void InterceptingResourceHandler::ReceivedBufferFromOldHandler() { |
344 DCHECK_EQ(State::RECEIVING_BUFFER_FROM_OLD_HANDLER, state_); | |
345 DCHECK(first_read_buffer_); | |
346 DCHECK_GT(first_read_buffer_size_, 0); | |
347 | |
348 int bytes_to_copy = | |
349 std::min(first_read_buffer_size_, | |
350 static_cast<int>(payload_for_old_handler_.size() - | |
351 payload_bytes_written_)); | |
352 memcpy(first_read_buffer_->data(), | |
353 payload_for_old_handler_.data() + payload_bytes_written_, | |
354 bytes_to_copy); | |
355 payload_bytes_written_ += bytes_to_copy; | |
356 | |
357 first_read_buffer_ = nullptr; | |
358 first_read_buffer_size_ = 0; | |
359 | |
360 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; | |
361 next_handler_->OnReadCompleted(bytes_to_copy, | |
362 base::MakeUnique<Controller>(this)); | |
299 } | 363 } |
300 | 364 |
301 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() { | 365 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() { |
302 state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER; | 366 state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER; |
303 next_handler_->OnResponseStarted(response_.get(), | 367 next_handler_->OnResponseStarted(response_.get(), |
304 base::MakeUnique<Controller>(this)); | 368 base::MakeUnique<Controller>(this)); |
305 } | 369 } |
306 | 370 |
307 void InterceptingResourceHandler::SendFirstReadBufferToNewHandler() { | 371 void InterceptingResourceHandler::SendFirstReadBufferToNewHandler() { |
308 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER); | 372 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER); |
373 DCHECK(!new_handler_read_buffer_); | |
374 DCHECK(!new_handler_read_buffer_size_); | |
309 | 375 |
310 if (first_read_buffer_bytes_written_ == first_read_buffer_bytes_read_) { | 376 if (first_read_buffer_bytes_written_ == first_read_buffer_bytes_read_) { |
311 state_ = State::PASS_THROUGH; | 377 state_ = State::PASS_THROUGH; |
312 first_read_buffer_double_ = nullptr; | 378 first_read_buffer_double_ = nullptr; |
313 ResumeInternal(); | 379 ResumeInternal(); |
314 return; | 380 return; |
315 } | 381 } |
316 | 382 |
317 scoped_refptr<net::IOBuffer> buf; | 383 next_handler_->OnWillRead(&new_handler_read_buffer_, |
318 int size = 0; | 384 &new_handler_read_buffer_size_, |
319 if (!next_handler_->OnWillRead(&buf, &size)) { | 385 base::MakeUnique<Controller>(this)); |
320 Cancel(); | 386 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER; |
Charlie Harrison
2017/02/16 21:25:04
Shouldn't this go above the OnWillReadCall?
mmenke
2017/03/08 19:16:07
Done. Doesn't matter for correctness, but it's mo
| |
321 return; | 387 } |
322 } | 388 |
323 size = std::min(size, static_cast<int>(first_read_buffer_bytes_read_ - | 389 void InterceptingResourceHandler::ReceivedBufferFromNewHandler() { |
324 first_read_buffer_bytes_written_)); | 390 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER); |
325 memcpy(buf->data(), | 391 DCHECK(new_handler_read_buffer_); |
392 DCHECK(new_handler_read_buffer_size_); | |
393 | |
394 int bytes_to_copy = | |
395 std::min(new_handler_read_buffer_size_, | |
396 static_cast<int>(first_read_buffer_bytes_read_ - | |
397 first_read_buffer_bytes_written_)); | |
398 memcpy(new_handler_read_buffer_->data(), | |
326 first_read_buffer_double_->data() + first_read_buffer_bytes_written_, | 399 first_read_buffer_double_->data() + first_read_buffer_bytes_written_, |
327 size); | 400 bytes_to_copy); |
328 first_read_buffer_bytes_written_ += size; | 401 first_read_buffer_bytes_written_ += bytes_to_copy; |
329 next_handler_->OnReadCompleted(size, base::MakeUnique<Controller>(this)); | 402 |
403 new_handler_read_buffer_ = nullptr; | |
404 new_handler_read_buffer_size_ = 0; | |
405 | |
406 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER; | |
407 next_handler_->OnReadCompleted(bytes_to_copy, | |
408 base::MakeUnique<Controller>(this)); | |
330 } | 409 } |
331 | 410 |
332 } // namespace content | 411 } // namespace content |
OLD | NEW |