Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/glue/media/buffered_resource_loader.h" | 5 #include "webkit/glue/media/buffered_resource_loader.h" |
| 6 | 6 |
| 7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" | 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 // number to be 2MB. | 43 // number to be 2MB. |
| 44 // TODO(hclam): determine a better value for this. | 44 // TODO(hclam): determine a better value for this. |
| 45 static const int kForwardWaitThreshold = 2 * kMegabyte; | 45 static const int kForwardWaitThreshold = 2 * kMegabyte; |
| 46 | 46 |
| 47 BufferedResourceLoader::BufferedResourceLoader( | 47 BufferedResourceLoader::BufferedResourceLoader( |
| 48 const GURL& url, | 48 const GURL& url, |
| 49 int64 first_byte_position, | 49 int64 first_byte_position, |
| 50 int64 last_byte_position) | 50 int64 last_byte_position) |
| 51 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), | 51 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), |
| 52 deferred_(false), | 52 deferred_(false), |
| 53 defer_allowed_(true), | 53 defer_strategy_(kReadThenDefer), |
| 54 completed_(false), | 54 completed_(false), |
| 55 range_requested_(false), | 55 range_requested_(false), |
| 56 partial_response_(false), | 56 partial_response_(false), |
| 57 url_(url), | 57 url_(url), |
| 58 first_byte_position_(first_byte_position), | 58 first_byte_position_(first_byte_position), |
| 59 last_byte_position_(last_byte_position), | 59 last_byte_position_(last_byte_position), |
| 60 single_origin_(true), | 60 single_origin_(true), |
| 61 start_callback_(NULL), | 61 start_callback_(NULL), |
| 62 offset_(0), | 62 offset_(0), |
| 63 content_length_(kPositionNotSpecified), | 63 content_length_(kPositionNotSpecified), |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 return; | 173 return; |
| 174 } | 174 } |
| 175 | 175 |
| 176 // Prepare the parameters. | 176 // Prepare the parameters. |
| 177 first_offset_ = static_cast<int>(read_position_ - offset_); | 177 first_offset_ = static_cast<int>(read_position_ - offset_); |
| 178 last_offset_ = first_offset_ + read_size_; | 178 last_offset_ = first_offset_ + read_size_; |
| 179 | 179 |
| 180 // If we can serve the request now, do the actual read. | 180 // If we can serve the request now, do the actual read. |
| 181 if (CanFulfillRead()) { | 181 if (CanFulfillRead()) { |
| 182 ReadInternal(); | 182 ReadInternal(); |
| 183 DisableDeferIfNeeded(); | 183 UpdateDeferBehavior(); |
| 184 return; | 184 return; |
| 185 } | 185 } |
| 186 | 186 |
| 187 // If you're deferred and you can't fulfill the read because you don't have | |
| 188 // enough data, you will never fulfill the read. | |
| 189 // Update defer behavior to re-enable deferring if need be. | |
| 190 UpdateDeferBehavior(); | |
| 191 | |
| 187 // If we expected the read request to be fulfilled later, returns | 192 // If we expected the read request to be fulfilled later, returns |
| 188 // immediately and let more data to flow in. | 193 // immediately and let more data to flow in. |
| 189 if (WillFulfillRead()) | 194 if (WillFulfillRead()) |
| 190 return; | 195 return; |
| 191 | 196 |
| 192 // Make a callback to report failure. | 197 // Make a callback to report failure. |
| 193 DoneRead(net::ERR_CACHE_MISS); | 198 DoneRead(net::ERR_CACHE_MISS); |
| 194 } | 199 } |
| 195 | 200 |
| 196 int64 BufferedResourceLoader::GetBufferedPosition() { | 201 int64 BufferedResourceLoader::GetBufferedPosition() { |
| 197 if (buffer_.get()) | 202 if (buffer_.get()) |
| 198 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; | 203 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; |
| 199 return kPositionNotSpecified; | 204 return kPositionNotSpecified; |
| 200 } | 205 } |
| 201 | 206 |
| 202 void BufferedResourceLoader::SetAllowDefer(bool is_allowed) { | |
| 203 defer_allowed_ = is_allowed; | |
| 204 DisableDeferIfNeeded(); | |
| 205 } | |
| 206 | |
| 207 int64 BufferedResourceLoader::content_length() { | 207 int64 BufferedResourceLoader::content_length() { |
| 208 return content_length_; | 208 return content_length_; |
| 209 } | 209 } |
| 210 | 210 |
| 211 int64 BufferedResourceLoader::instance_size() { | 211 int64 BufferedResourceLoader::instance_size() { |
| 212 return instance_size_; | 212 return instance_size_; |
| 213 } | 213 } |
| 214 | 214 |
| 215 bool BufferedResourceLoader::partial_response() { | 215 bool BufferedResourceLoader::partial_response() { |
| 216 return partial_response_; | 216 return partial_response_; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 | 327 |
| 328 // If this loader has been stopped, |buffer_| would be destroyed. | 328 // If this loader has been stopped, |buffer_| would be destroyed. |
| 329 // In this case we shouldn't do anything. | 329 // In this case we shouldn't do anything. |
| 330 if (!buffer_.get()) | 330 if (!buffer_.get()) |
| 331 return; | 331 return; |
| 332 | 332 |
| 333 // Writes more data to |buffer_|. | 333 // Writes more data to |buffer_|. |
| 334 buffer_->Append(reinterpret_cast<const uint8*>(data), data_length); | 334 buffer_->Append(reinterpret_cast<const uint8*>(data), data_length); |
| 335 | 335 |
| 336 // If there is an active read request, try to fulfill the request. | 336 // If there is an active read request, try to fulfill the request. |
| 337 if (HasPendingRead() && CanFulfillRead()) { | 337 if (HasPendingRead() && CanFulfillRead()) |
| 338 ReadInternal(); | 338 ReadInternal(); |
| 339 } else if (!defer_allowed_) { | |
| 340 // If we're not allowed to defer, slide the buffer window forward instead | |
| 341 // of deferring. | |
| 342 if (buffer_->forward_bytes() > buffer_->forward_capacity()) { | |
| 343 size_t excess = buffer_->forward_bytes() - buffer_->forward_capacity(); | |
| 344 bool success = buffer_->Seek(excess); | |
| 345 DCHECK(success); | |
| 346 offset_ += first_offset_ + excess; | |
| 347 } | |
| 348 } | |
| 349 | 339 |
| 350 // At last see if the buffer is full and we need to defer the downloading. | 340 // At last see if the buffer is full and we need to defer the downloading. |
| 351 EnableDeferIfNeeded(); | 341 UpdateDeferBehavior(); |
| 342 | |
| 343 // Consume excess bytes from our in-memory buffer if necessary. | |
| 344 if (buffer_->forward_bytes() > buffer_->forward_capacity()) { | |
| 345 size_t excess = buffer_->forward_bytes() - buffer_->forward_capacity(); | |
| 346 bool success = buffer_->Seek(excess); | |
| 347 DCHECK(success); | |
| 348 offset_ += first_offset_ + excess; | |
| 349 } | |
| 352 | 350 |
| 353 // Notify that we have received some data. | 351 // Notify that we have received some data. |
| 354 NotifyNetworkEvent(); | 352 NotifyNetworkEvent(); |
| 355 } | 353 } |
| 356 | 354 |
| 357 void BufferedResourceLoader::didDownloadData( | 355 void BufferedResourceLoader::didDownloadData( |
| 358 WebKit::WebURLLoader* loader, | 356 WebKit::WebURLLoader* loader, |
| 359 int dataLength) { | 357 int dataLength) { |
| 360 NOTIMPLEMENTED(); | 358 NOTIMPLEMENTED(); |
| 361 } | 359 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 url_loader_.reset(); | 422 url_loader_.reset(); |
| 425 Release(); | 423 Release(); |
| 426 } | 424 } |
| 427 | 425 |
| 428 bool BufferedResourceLoader::HasSingleOrigin() const { | 426 bool BufferedResourceLoader::HasSingleOrigin() const { |
| 429 return single_origin_; | 427 return single_origin_; |
| 430 } | 428 } |
| 431 | 429 |
| 432 ///////////////////////////////////////////////////////////////////////////// | 430 ///////////////////////////////////////////////////////////////////////////// |
| 433 // Helper methods. | 431 // Helper methods. |
| 434 void BufferedResourceLoader::EnableDeferIfNeeded() { | 432 void BufferedResourceLoader::UpdateDeferBehavior() { |
| 435 if (!defer_allowed_) | 433 if (!url_loader_.get() || !buffer_.get()) |
| 436 return; | 434 return; |
| 437 | 435 |
| 438 if (!deferred_ && | 436 if ((deferred_ && ShouldDisableDefer()) || |
| 439 buffer_->forward_bytes() >= buffer_->forward_capacity()) { | 437 (!deferred_ && ShouldEnableDefer())) { |
| 440 deferred_ = true; | 438 bool eventOccurred = ToggleDeferring(); |
| 441 | 439 if (eventOccurred) |
| 442 if (url_loader_.get()) | 440 NotifyNetworkEvent(); |
| 443 url_loader_->setDefersLoading(true); | |
| 444 | |
| 445 NotifyNetworkEvent(); | |
| 446 } | 441 } |
| 447 } | 442 } |
| 448 | 443 |
| 449 void BufferedResourceLoader::DisableDeferIfNeeded() { | 444 void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) { |
| 450 if (deferred_ && | 445 defer_strategy_ = strategy; |
| 451 (!defer_allowed_ || | 446 UpdateDeferBehavior(); |
| 452 buffer_->forward_bytes() < buffer_->forward_capacity() / 2)) { | 447 } |
| 453 deferred_ = false; | |
| 454 | 448 |
| 455 if (url_loader_.get()) | 449 bool BufferedResourceLoader::ShouldEnableDefer() { |
| 456 url_loader_->setDefersLoading(false); | 450 // If we're already deferring, then enabling makes no sense. |
| 451 if (deferred_) | |
| 452 return false; | |
| 457 | 453 |
| 458 NotifyNetworkEvent(); | 454 switch(defer_strategy_) { |
| 455 // Never defer at all, so never enable defer. | |
| 456 case kNeverDefer: | |
| 457 return false; | |
| 458 | |
| 459 // Defer if nothing is being requested. | |
| 460 case kReadThenDefer: | |
| 461 return !read_callback_.get(); | |
| 462 | |
| 463 // Defer if we've reached the max capacity of the threshold. | |
| 464 case kThresholdDefer: | |
| 465 return buffer_->forward_bytes() >= buffer_->forward_capacity(); | |
| 459 } | 466 } |
| 467 // Otherwise no longer defer. | |
| 468 return false; | |
| 469 } | |
| 470 | |
| 471 bool BufferedResourceLoader::ShouldDisableDefer() { | |
| 472 // If we're not deferring, then disabling makes no sense. | |
| 473 if (!deferred_) | |
| 474 return false; | |
| 475 | |
| 476 switch(defer_strategy_) { | |
| 477 // Always disable deferring. | |
| 478 case kNeverDefer: | |
| 479 return true; | |
| 480 | |
| 481 // We have an outstanding read request, and we have not buffered enough | |
| 482 // yet to fulfill the request; disable defer to get more data. | |
| 483 case kReadThenDefer: { | |
| 484 size_t amount_buffered = buffer_->forward_bytes(); | |
| 485 size_t amount_to_read = static_cast<size_t>(read_size_); | |
| 486 return read_callback_.get() && amount_buffered < amount_to_read; | |
| 487 } | |
| 488 | |
| 489 // We have less than half the capacity of our threshold, so | |
| 490 // disable defer to get more data. | |
| 491 case kThresholdDefer: { | |
| 492 size_t amount_buffered = buffer_->forward_bytes(); | |
| 493 size_t half_capacity = buffer_->forward_capacity() / 2; | |
| 494 return amount_buffered < half_capacity; | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 // Otherwise keep deferring. | |
| 499 return false; | |
| 500 } | |
| 501 | |
| 502 bool BufferedResourceLoader::ToggleDeferring() { | |
| 503 deferred_ = !deferred_; | |
|
scherkus (not reviewing)
2011/03/31 23:40:21
nit: over-indented by 2 spaces
vrk (LEFT CHROMIUM)
2011/04/01 22:52:12
Done.
| |
| 504 if (url_loader_.get()) { | |
| 505 url_loader_->setDefersLoading(deferred_); | |
| 506 return true; | |
| 507 } | |
| 508 return false; | |
| 460 } | 509 } |
| 461 | 510 |
| 462 bool BufferedResourceLoader::CanFulfillRead() { | 511 bool BufferedResourceLoader::CanFulfillRead() { |
| 463 // If we are reading too far in the backward direction. | 512 // If we are reading too far in the backward direction. |
| 464 if (first_offset_ < 0 && | 513 if (first_offset_ < 0 && |
| 465 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0) | 514 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0) |
| 466 return false; | 515 return false; |
| 467 | 516 |
| 468 // If the start offset is too far ahead. | 517 // If the start offset is too far ahead. |
| 469 if (first_offset_ >= static_cast<int>(buffer_->forward_bytes())) | 518 if (first_offset_ >= static_cast<int>(buffer_->forward_bytes())) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 start_callback_->RunWithParams(Tuple1<int>(error)); | 622 start_callback_->RunWithParams(Tuple1<int>(error)); |
| 574 start_callback_.reset(); | 623 start_callback_.reset(); |
| 575 } | 624 } |
| 576 | 625 |
| 577 void BufferedResourceLoader::NotifyNetworkEvent() { | 626 void BufferedResourceLoader::NotifyNetworkEvent() { |
| 578 if (event_callback_.get()) | 627 if (event_callback_.get()) |
| 579 event_callback_->Run(); | 628 event_callback_->Run(); |
| 580 } | 629 } |
| 581 | 630 |
| 582 } // namespace webkit_glue | 631 } // namespace webkit_glue |
| OLD | NEW |