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