Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Side by Side Diff: content/browser/loader/mime_sniffing_resource_handler.cc

Issue 2743723003: Add buffering to MimeSniffingResourceHandler.
Patch Set: Remove unused 'first_call' variable. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698