| 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/mime_sniffing_resource_handler.h" | 5 #include "content/browser/loader/mime_sniffing_resource_handler.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 7 #include <utility> | 8 #include <utility> |
| 8 #include <vector> | 9 #include <vector> |
| 9 | 10 |
| 10 #include "base/bind.h" | 11 #include "base/bind.h" |
| 11 #include "base/location.h" | 12 #include "base/location.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 16 #include "base/threading/thread_task_runner_handle.h" | 17 #include "base/threading/thread_task_runner_handle.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 : LayeredResourceHandler(request, std::move(next_handler)), | 119 : LayeredResourceHandler(request, std::move(next_handler)), |
| 119 state_(STATE_STARTING), | 120 state_(STATE_STARTING), |
| 120 host_(host), | 121 host_(host), |
| 121 #if BUILDFLAG(ENABLE_PLUGINS) | 122 #if BUILDFLAG(ENABLE_PLUGINS) |
| 122 plugin_service_(plugin_service), | 123 plugin_service_(plugin_service), |
| 123 #endif | 124 #endif |
| 124 must_download_(false), | 125 must_download_(false), |
| 125 must_download_is_set_(false), | 126 must_download_is_set_(false), |
| 126 read_buffer_size_(0), | 127 read_buffer_size_(0), |
| 127 bytes_read_(0), | 128 bytes_read_(0), |
| 128 parent_read_buffer_(nullptr), | 129 bytes_replayed_(0), |
| 129 parent_read_buffer_size_(nullptr), | 130 out_buffer_size_(0), |
| 130 intercepting_handler_(intercepting_handler), | 131 intercepting_handler_(intercepting_handler), |
| 131 request_context_type_(request_context_type), | 132 request_context_type_(request_context_type), |
| 132 in_state_loop_(false), | 133 in_state_loop_(false), |
| 133 advance_state_(false), | 134 advance_state_(false), |
| 134 weak_ptr_factory_(this) { | 135 weak_ptr_factory_(this) { |
| 135 } | 136 } |
| 136 | 137 |
| 137 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {} | 138 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {} |
| 138 | 139 |
| 139 void MimeSniffingResourceHandler::OnWillStart( | 140 void MimeSniffingResourceHandler::OnWillStart( |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 HoldController(std::move(controller)); | 217 HoldController(std::move(controller)); |
| 217 AdvanceState(); | 218 AdvanceState(); |
| 218 } | 219 } |
| 219 | 220 |
| 220 void MimeSniffingResourceHandler::OnWillRead( | 221 void MimeSniffingResourceHandler::OnWillRead( |
| 221 scoped_refptr<net::IOBuffer>* buf, | 222 scoped_refptr<net::IOBuffer>* buf, |
| 222 int* buf_size, | 223 int* buf_size, |
| 223 std::unique_ptr<ResourceController> controller) { | 224 std::unique_ptr<ResourceController> controller) { |
| 224 DCHECK(buf); | 225 DCHECK(buf); |
| 225 DCHECK(buf_size); | 226 DCHECK(buf_size); |
| 226 DCHECK(!parent_read_buffer_); | |
| 227 DCHECK(!parent_read_buffer_size_); | |
| 228 | 227 |
| 229 if (state_ == STATE_STREAMING) { | 228 if (state_ == STATE_STREAMING) { |
| 230 next_handler_->OnWillRead(buf, buf_size, std::move(controller)); | 229 next_handler_->OnWillRead(buf, buf_size, std::move(controller)); |
| 231 return; | 230 return; |
| 232 } | 231 } |
| 233 | 232 |
| 234 DCHECK_EQ(State::STATE_BUFFERING, state_); | 233 DCHECK_EQ(State::STATE_BUFFERING, state_); |
| 235 | 234 |
| 236 if (read_buffer_.get()) { | 235 if (read_buffer_.get()) { |
| 237 CHECK_LT(bytes_read_, read_buffer_size_); | 236 CHECK_LT(bytes_read_, read_buffer_size_); |
| 238 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_); | 237 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_); |
| 239 *buf_size = read_buffer_size_ - bytes_read_; | 238 *buf_size = read_buffer_size_ - bytes_read_; |
| 240 controller->Resume(); | 239 controller->Resume(); |
| 241 return; | 240 } else { |
| 241 *buf_size = read_buffer_size_ = net::kMaxBytesToSniff * 2; |
| 242 *buf = read_buffer_ = new net::IOBuffer(read_buffer_size_); |
| 243 controller->Resume(); |
| 242 } | 244 } |
| 243 | 245 |
| 244 DCHECK(!read_buffer_size_); | 246 return; |
| 245 | |
| 246 parent_read_buffer_ = buf; | |
| 247 parent_read_buffer_size_ = buf_size; | |
| 248 | |
| 249 HoldController(std::move(controller)); | |
| 250 | |
| 251 // Have to go through AdvanceState here so that if OnWillRead completes | |
| 252 // synchronously, won't post a task. | |
| 253 state_ = State::STATE_CALLING_ON_WILL_READ; | |
| 254 AdvanceState(); | |
| 255 } | 247 } |
| 256 | 248 |
| 257 void MimeSniffingResourceHandler::OnReadCompleted( | 249 void MimeSniffingResourceHandler::OnReadCompleted( |
| 258 int bytes_read, | 250 int bytes_read, |
| 259 std::unique_ptr<ResourceController> controller) { | 251 std::unique_ptr<ResourceController> controller) { |
| 260 DCHECK(!has_controller()); | 252 DCHECK(!has_controller()); |
| 261 | 253 |
| 262 if (state_ == STATE_STREAMING) { | 254 if (state_ == STATE_STREAMING) { |
| 263 next_handler_->OnReadCompleted(bytes_read, std::move(controller)); | 255 next_handler_->OnReadCompleted(bytes_read, std::move(controller)); |
| 264 return; | 256 return; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 320 |
| 329 base::AutoReset<bool> auto_in_state_loop(&in_state_loop_, true); | 321 base::AutoReset<bool> auto_in_state_loop(&in_state_loop_, true); |
| 330 advance_state_ = true; | 322 advance_state_ = true; |
| 331 while (advance_state_) { | 323 while (advance_state_) { |
| 332 advance_state_ = false; | 324 advance_state_ = false; |
| 333 | 325 |
| 334 switch (state_) { | 326 switch (state_) { |
| 335 case STATE_BUFFERING: | 327 case STATE_BUFFERING: |
| 336 MaybeIntercept(); | 328 MaybeIntercept(); |
| 337 break; | 329 break; |
| 338 case STATE_CALLING_ON_WILL_READ: | |
| 339 CallOnWillRead(); | |
| 340 break; | |
| 341 case STATE_WAITING_FOR_BUFFER: | |
| 342 BufferReceived(); | |
| 343 break; | |
| 344 case STATE_INTERCEPTION_CHECK_DONE: | 330 case STATE_INTERCEPTION_CHECK_DONE: |
| 345 ReplayResponseReceived(); | 331 ReplayResponseReceived(); |
| 346 break; | 332 break; |
| 347 case STATE_REPLAYING_RESPONSE_RECEIVED: | 333 case STATE_REPLAYING_RESPONSE_RECEIVED: |
| 334 ReplayGetBuffer(); |
| 335 break; |
| 336 case STATE_REPLAYING_WAIT_FOR_WILL_READ: |
| 348 ReplayReadCompleted(); | 337 ReplayReadCompleted(); |
| 349 break; | 338 break; |
| 350 case STATE_STARTING: | 339 case STATE_STARTING: |
| 351 case STATE_STREAMING: | 340 case STATE_STREAMING: |
| 352 Resume(); | 341 Resume(); |
| 353 return; | 342 return; |
| 354 default: | 343 default: |
| 355 NOTREACHED(); | 344 NOTREACHED(); |
| 356 break; | 345 break; |
| 357 } | 346 } |
| 358 } | 347 } |
| 359 | 348 |
| 360 DCHECK(in_state_loop_); | 349 DCHECK(in_state_loop_); |
| 361 in_state_loop_ = false; | 350 in_state_loop_ = false; |
| 362 } | 351 } |
| 363 | 352 |
| 364 void MimeSniffingResourceHandler::MaybeIntercept() { | 353 void MimeSniffingResourceHandler::MaybeIntercept() { |
| 365 DCHECK_EQ(STATE_BUFFERING, state_); | 354 DCHECK_EQ(STATE_BUFFERING, state_); |
| 366 // If a request that can be intercepted failed the check for interception | 355 // If a request that can be intercepted failed the check for interception |
| 367 // step, it should be canceled. | 356 // step, it should be canceled. |
| 368 if (!MaybeStartInterception()) | 357 if (!MaybeStartInterception()) |
| 369 return; | 358 return; |
| 370 | 359 |
| 371 state_ = STATE_INTERCEPTION_CHECK_DONE; | 360 state_ = STATE_INTERCEPTION_CHECK_DONE; |
| 372 ResumeInternal(); | 361 ResumeInternal(); |
| 373 } | 362 } |
| 374 | 363 |
| 375 void MimeSniffingResourceHandler::CallOnWillRead() { | |
| 376 DCHECK_EQ(STATE_CALLING_ON_WILL_READ, state_); | |
| 377 | |
| 378 state_ = STATE_WAITING_FOR_BUFFER; | |
| 379 next_handler_->OnWillRead(&read_buffer_, &read_buffer_size_, | |
| 380 base::MakeUnique<Controller>(this)); | |
| 381 } | |
| 382 | |
| 383 void MimeSniffingResourceHandler::BufferReceived() { | |
| 384 DCHECK_EQ(STATE_WAITING_FOR_BUFFER, state_); | |
| 385 | |
| 386 DCHECK(read_buffer_); | |
| 387 DCHECK(parent_read_buffer_); | |
| 388 DCHECK(parent_read_buffer_size_); | |
| 389 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); | |
| 390 | |
| 391 *parent_read_buffer_ = read_buffer_; | |
| 392 *parent_read_buffer_size_ = read_buffer_size_; | |
| 393 | |
| 394 parent_read_buffer_ = nullptr; | |
| 395 parent_read_buffer_size_ = nullptr; | |
| 396 | |
| 397 state_ = State::STATE_BUFFERING; | |
| 398 Resume(); | |
| 399 } | |
| 400 | |
| 401 void MimeSniffingResourceHandler::ReplayResponseReceived() { | 364 void MimeSniffingResourceHandler::ReplayResponseReceived() { |
| 402 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_); | 365 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_); |
| 403 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; | 366 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; |
| 404 next_handler_->OnResponseStarted(response_.get(), | 367 next_handler_->OnResponseStarted(response_.get(), |
| 405 base::MakeUnique<Controller>(this)); | 368 base::MakeUnique<Controller>(this)); |
| 406 } | 369 } |
| 407 | 370 |
| 408 void MimeSniffingResourceHandler::ReplayReadCompleted() { | 371 void MimeSniffingResourceHandler::ReplayGetBuffer() { |
| 409 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_); | 372 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_); |
| 410 | 373 |
| 411 state_ = STATE_STREAMING; | 374 if (bytes_read_ == bytes_replayed_) { |
| 375 read_buffer_ = nullptr; |
| 376 read_buffer_size_ = 0; |
| 377 bytes_read_ = bytes_replayed_ = 0; |
| 412 | 378 |
| 413 if (!read_buffer_.get()) { | 379 state_ = STATE_STREAMING; |
| 380 |
| 414 ResumeInternal(); | 381 ResumeInternal(); |
| 415 return; | 382 return; |
| 416 } | 383 } |
| 417 | 384 |
| 418 int bytes_read = bytes_read_; | 385 state_ = STATE_REPLAYING_WAIT_FOR_WILL_READ; |
| 419 | 386 |
| 420 read_buffer_ = nullptr; | 387 out_buffer_ = nullptr; |
| 421 read_buffer_size_ = 0; | 388 out_buffer_size_ = 0; |
| 422 bytes_read_ = 0; | 389 next_handler_->OnWillRead(&out_buffer_, &out_buffer_size_, |
| 390 base::MakeUnique<Controller>(this)); |
| 391 } |
| 423 | 392 |
| 424 next_handler_->OnReadCompleted(bytes_read, | 393 void MimeSniffingResourceHandler::ReplayReadCompleted() { |
| 394 DCHECK_EQ(STATE_REPLAYING_WAIT_FOR_WILL_READ, state_); |
| 395 DCHECK(out_buffer_.get()); |
| 396 DCHECK_LT(0, out_buffer_size_); |
| 397 |
| 398 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; |
| 399 int bytes_to_copy = std::min(bytes_read_ - bytes_replayed_, out_buffer_size_); |
| 400 memcpy(out_buffer_->data(), read_buffer_->data() + bytes_replayed_, |
| 401 bytes_to_copy); |
| 402 bytes_replayed_ += bytes_to_copy; |
| 403 |
| 404 next_handler_->OnReadCompleted(bytes_to_copy, |
| 425 base::MakeUnique<Controller>(this)); | 405 base::MakeUnique<Controller>(this)); |
| 426 } | 406 } |
| 427 | 407 |
| 428 bool MimeSniffingResourceHandler::ShouldSniffContent() { | 408 bool MimeSniffingResourceHandler::ShouldSniffContent() { |
| 429 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) { | 409 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) { |
| 430 // MIME sniffing should be disabled for a request initiated by fetch(). | 410 // MIME sniffing should be disabled for a request initiated by fetch(). |
| 431 return false; | 411 return false; |
| 432 } | 412 } |
| 433 | 413 |
| 434 const std::string& mime_type = response_->head.mime_type; | 414 const std::string& mime_type = response_->head.mime_type; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 | 585 |
| 606 void MimeSniffingResourceHandler::OnPluginsLoaded( | 586 void MimeSniffingResourceHandler::OnPluginsLoaded( |
| 607 const std::vector<WebPluginInfo>& plugins) { | 587 const std::vector<WebPluginInfo>& plugins) { |
| 608 // No longer blocking on the plugins being loaded. | 588 // No longer blocking on the plugins being loaded. |
| 609 request()->LogUnblocked(); | 589 request()->LogUnblocked(); |
| 610 if (state_ == STATE_BUFFERING) | 590 if (state_ == STATE_BUFFERING) |
| 611 AdvanceState(); | 591 AdvanceState(); |
| 612 } | 592 } |
| 613 | 593 |
| 614 } // namespace content | 594 } // namespace content |
| OLD | NEW |