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 |