Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "base/compiler_specific.h" | 5 #include "base/compiler_specific.h" |
| 6 #include "base/message_loop.h" | 6 #include "base/message_loop.h" |
| 7 #include "base/process_util.h" | 7 #include "base/process_util.h" |
| 8 #include "base/stl_util-inl.h" | 8 #include "base/stl_util-inl.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "chrome/common/extensions/url_pattern.h" | 10 #include "chrome/common/extensions/url_pattern.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 // BufferedResourceLoader | 65 // BufferedResourceLoader |
| 66 BufferedResourceLoader::BufferedResourceLoader( | 66 BufferedResourceLoader::BufferedResourceLoader( |
| 67 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, | 67 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, |
| 68 const GURL& url, | 68 const GURL& url, |
| 69 int64 first_byte_position, | 69 int64 first_byte_position, |
| 70 int64 last_byte_position) | 70 int64 last_byte_position) |
| 71 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), | 71 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), |
| 72 deferred_(false), | 72 deferred_(false), |
| 73 completed_(false), | 73 completed_(false), |
| 74 range_requested_(false), | 74 range_requested_(false), |
| 75 partial_response_(false), | |
| 75 bridge_factory_(bridge_factory), | 76 bridge_factory_(bridge_factory), |
| 76 url_(url), | 77 url_(url), |
| 77 first_byte_position_(first_byte_position), | 78 first_byte_position_(first_byte_position), |
| 78 last_byte_position_(last_byte_position), | 79 last_byte_position_(last_byte_position), |
| 79 start_callback_(NULL), | 80 start_callback_(NULL), |
| 80 bridge_(NULL), | 81 bridge_(NULL), |
| 81 offset_(0), | 82 offset_(0), |
| 82 content_length_(kPositionNotSpecified), | 83 content_length_(kPositionNotSpecified), |
| 83 instance_size_(kPositionNotSpecified), | 84 instance_size_(kPositionNotSpecified), |
| 84 read_callback_(NULL), | 85 read_callback_(NULL), |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 // We make a strong assumption that when we reach here we have either | 229 // We make a strong assumption that when we reach here we have either |
| 229 // received a response from HTTP/HTTPS protocol or the request was | 230 // received a response from HTTP/HTTPS protocol or the request was |
| 230 // successful (in particular range request). So we only verify the partial | 231 // successful (in particular range request). So we only verify the partial |
| 231 // response for HTTP and HTTPS protocol. | 232 // response for HTTP and HTTPS protocol. |
| 232 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { | 233 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { |
| 233 int error = net::OK; | 234 int error = net::OK; |
| 234 if (!info.headers) { | 235 if (!info.headers) { |
| 235 // We expect to receive headers because this is a HTTP or HTTPS protocol, | 236 // We expect to receive headers because this is a HTTP or HTTPS protocol, |
| 236 // if not report failure. | 237 // if not report failure. |
| 237 error = net::ERR_INVALID_RESPONSE; | 238 error = net::ERR_INVALID_RESPONSE; |
| 238 } else if (range_requested_) { | 239 } else { |
| 239 // If we have verified the partial response and it is correct, we will | 240 if (info.headers->response_code() == kHttpPartialContent) |
| 240 // return net::OK. | 241 partial_response_ = true; |
| 241 if (!VerifyPartialResponse(info)) | 242 |
| 242 error = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; | 243 if (range_requested_ && partial_response_) { |
| 243 } else if (info.headers->response_code() != kHttpOK) { | 244 // If we have verified the partial response and it is correct, we will |
| 244 // We didn't request a range but server didn't reply with "200 OK". | 245 // return net::OK. |
| 245 error = net::ERR_FAILED; | 246 if (!VerifyPartialResponse(info)) |
| 247 error = net::ERR_INVALID_RESPONSE; | |
| 248 } else if (info.headers->response_code() != kHttpOK) { | |
| 249 // We didn't request a range but server didn't reply with "200 OK". | |
| 250 error = net::ERR_FAILED; | |
| 251 } | |
| 246 } | 252 } |
| 247 | 253 |
| 248 if (error != net::OK) { | 254 if (error != net::OK) { |
| 249 DoneStart(error); | 255 DoneStart(error); |
| 250 Stop(); | 256 Stop(); |
| 251 return; | 257 return; |
| 252 } | 258 } |
| 259 } else { | |
| 260 // For any protocol other than HTTP and HTTPS, assume range request is | |
| 261 // always fulfilled. | |
| 262 partial_response_ = range_requested_; | |
| 253 } | 263 } |
| 254 | 264 |
| 255 // |info.content_length| can be -1, in that case |content_length_| is | 265 // |info.content_length| can be -1, in that case |content_length_| is |
| 256 // not specified and this is a streaming response. | 266 // not specified and this is a streaming response. |
| 257 content_length_ = info.content_length; | 267 content_length_ = info.content_length; |
| 258 | 268 |
| 259 // If we have not requested a range, then the size of the instance is equal | 269 // If we have not requested a range, then the size of the instance is equal |
| 260 // to the content length. | 270 // to the content length. |
| 261 if (!range_requested_) | 271 if (!partial_response_) |
| 262 instance_size_ = content_length_; | 272 instance_size_ = content_length_; |
| 263 | 273 |
| 264 // Calls with a successful response. | 274 // Calls with a successful response. |
| 265 DoneStart(net::OK); | 275 DoneStart(net::OK); |
| 266 } | 276 } |
| 267 | 277 |
| 268 void BufferedResourceLoader::OnReceivedData(const char* data, int len) { | 278 void BufferedResourceLoader::OnReceivedData(const char* data, int len) { |
| 269 DCHECK(bridge_.get()); | 279 DCHECK(bridge_.get()); |
| 270 | 280 |
| 271 // If this loader has been stopped, |buffer_| would be destroyed. | 281 // If this loader has been stopped, |buffer_| would be destroyed. |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 last_offset_ = 0; | 421 last_offset_ = 0; |
| 412 } | 422 } |
| 413 | 423 |
| 414 void BufferedResourceLoader::DoneStart(int error) { | 424 void BufferedResourceLoader::DoneStart(int error) { |
| 415 start_callback_->RunWithParams(Tuple1<int>(error)); | 425 start_callback_->RunWithParams(Tuple1<int>(error)); |
| 416 start_callback_.reset(); | 426 start_callback_.reset(); |
| 417 } | 427 } |
| 418 | 428 |
| 419 bool BufferedResourceLoader::VerifyPartialResponse( | 429 bool BufferedResourceLoader::VerifyPartialResponse( |
| 420 const ResourceLoaderBridge::ResponseInfo& info) { | 430 const ResourceLoaderBridge::ResponseInfo& info) { |
| 421 if (info.headers->response_code() != kHttpPartialContent) | |
| 422 return false; | |
| 423 | |
| 424 int64 first_byte_position, last_byte_position, instance_size; | 431 int64 first_byte_position, last_byte_position, instance_size; |
| 425 if (!info.headers->GetContentRange(&first_byte_position, | 432 if (!info.headers->GetContentRange(&first_byte_position, |
| 426 &last_byte_position, | 433 &last_byte_position, |
| 427 &instance_size)) { | 434 &instance_size)) { |
| 428 return false; | 435 return false; |
| 429 } | 436 } |
| 430 | 437 |
| 431 if (instance_size != kPositionNotSpecified) | 438 if (instance_size != kPositionNotSpecified) |
| 432 instance_size_ = instance_size; | 439 instance_size_ = instance_size; |
| 433 | 440 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 448 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) | 455 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) |
| 449 : total_bytes_(kPositionNotSpecified), | 456 : total_bytes_(kPositionNotSpecified), |
| 450 streaming_(false), | 457 streaming_(false), |
| 451 bridge_factory_(bridge_factory), | 458 bridge_factory_(bridge_factory), |
| 452 loader_(NULL), | 459 loader_(NULL), |
| 453 initialize_callback_(NULL), | 460 initialize_callback_(NULL), |
| 454 read_callback_(NULL), | 461 read_callback_(NULL), |
| 455 read_position_(0), | 462 read_position_(0), |
| 456 read_size_(0), | 463 read_size_(0), |
| 457 read_buffer_(NULL), | 464 read_buffer_(NULL), |
| 458 initial_response_received_(false), | |
| 459 probe_response_received_(false), | |
| 460 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), | 465 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), |
| 461 intermediate_read_buffer_size_(kInitialReadBufferSize), | 466 intermediate_read_buffer_size_(kInitialReadBufferSize), |
| 462 render_loop_(render_loop), | 467 render_loop_(render_loop), |
| 463 stopped_(false), | 468 stopped_(false), |
| 464 stop_task_finished_(false) { | 469 stop_task_finished_(false) { |
| 465 } | 470 } |
| 466 | 471 |
| 467 BufferedDataSource::~BufferedDataSource() { | 472 BufferedDataSource::~BufferedDataSource() { |
| 468 } | 473 } |
| 469 | 474 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 544 | 549 |
| 545 bool BufferedDataSource::IsStreaming() { | 550 bool BufferedDataSource::IsStreaming() { |
| 546 return streaming_; | 551 return streaming_; |
| 547 } | 552 } |
| 548 | 553 |
| 549 ///////////////////////////////////////////////////////////////////////////// | 554 ///////////////////////////////////////////////////////////////////////////// |
| 550 // BufferedDataSource, render thread tasks | 555 // BufferedDataSource, render thread tasks |
| 551 void BufferedDataSource::InitializeTask() { | 556 void BufferedDataSource::InitializeTask() { |
| 552 DCHECK(MessageLoop::current() == render_loop_); | 557 DCHECK(MessageLoop::current() == render_loop_); |
| 553 DCHECK(!loader_.get()); | 558 DCHECK(!loader_.get()); |
| 554 DCHECK(!probe_loader_.get()); | |
| 555 | 559 |
| 556 // Kick starts the watch dog task that will handle connection timeout. | 560 // Kick starts the watch dog task that will handle connection timeout. |
| 557 // We run the watch dog 2 times faster the actual timeout so as to catch | 561 // We run the watch dog 2 times faster the actual timeout so as to catch |
| 558 // the timeout more accurately. | 562 // the timeout more accurately. |
| 559 watch_dog_timer_.Start( | 563 watch_dog_timer_.Start( |
| 560 GetTimeoutMilliseconds() / 2, | 564 GetTimeoutMilliseconds() / 2, |
| 561 this, | 565 this, |
| 562 &BufferedDataSource::WatchDogTask); | 566 &BufferedDataSource::WatchDogTask); |
| 563 | 567 |
| 564 // Creates a new resource loader with the full range and a probe resource | 568 // Fetch only first 1024 bytes as this usually covers the header portion |
| 565 // loader. Creates a probe resource loader to make sure the server supports | 569 // of a media file that gives enough information about the codecs, etc. |
| 566 // partial range request. | 570 // This also serve as a probe to determine server capability to serve |
| 567 // TODO(hclam): Only request 1 byte for this probe request, it may be useful | 571 // range request. |
| 568 // that we perform a suffix range request and fetch the index. That way we | 572 // TODO(hclam): Do some experiments for the best approach. |
| 569 // can minimize the number of requests made. | 573 loader_ = CreateLoader(0, 1024); |
|
scherkus (not reviewing)
2009/09/29 23:10:34
ok.. might have to request this be made a constant
| |
| 570 loader_ = CreateLoader(-1, -1); | |
| 571 probe_loader_ = CreateLoader(1, 1); | |
| 572 | |
| 573 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback)); | 574 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback)); |
| 574 probe_loader_->Start( | |
| 575 NewCallback(this, &BufferedDataSource::ProbeStartCallback)); | |
| 576 } | 575 } |
| 577 | 576 |
| 578 void BufferedDataSource::ReadTask( | 577 void BufferedDataSource::ReadTask( |
| 579 int64 position, int read_size, uint8* buffer, | 578 int64 position, int read_size, uint8* buffer, |
| 580 media::DataSource::ReadCallback* read_callback) { | 579 media::DataSource::ReadCallback* read_callback) { |
| 581 DCHECK(MessageLoop::current() == render_loop_); | 580 DCHECK(MessageLoop::current() == render_loop_); |
| 582 | 581 |
| 583 // If StopTask() was executed we should return immediately. We check this | 582 // If StopTask() was executed we should return immediately. We check this |
| 584 // variable to prevent doing any actual work after clean up was done. We do | 583 // variable to prevent doing any actual work after clean up was done. We do |
| 585 // not check |stopped_| because anything use of it has to be within |lock_| | 584 // not check |stopped_| because anything use of it has to be within |lock_| |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 605 void BufferedDataSource::StopTask() { | 604 void BufferedDataSource::StopTask() { |
| 606 DCHECK(MessageLoop::current() == render_loop_); | 605 DCHECK(MessageLoop::current() == render_loop_); |
| 607 | 606 |
| 608 // Stop the watch dog. | 607 // Stop the watch dog. |
| 609 watch_dog_timer_.Stop(); | 608 watch_dog_timer_.Stop(); |
| 610 | 609 |
| 611 // We just need to stop the loader, so it stops activity. | 610 // We just need to stop the loader, so it stops activity. |
| 612 if (loader_.get()) | 611 if (loader_.get()) |
| 613 loader_->Stop(); | 612 loader_->Stop(); |
| 614 | 613 |
| 615 // If the probe request is still active, stop it too. | |
| 616 if (probe_loader_.get()) | |
| 617 probe_loader_->Stop(); | |
| 618 | |
| 619 // Reset the parameters of the current read request. | 614 // Reset the parameters of the current read request. |
| 620 read_callback_.reset(); | 615 read_callback_.reset(); |
| 621 read_position_ = 0; | 616 read_position_ = 0; |
| 622 read_size_ = 0; | 617 read_size_ = 0; |
| 623 read_buffer_ = 0; | 618 read_buffer_ = 0; |
| 624 read_submitted_time_ = base::Time(); | 619 read_submitted_time_ = base::Time(); |
| 625 read_attempts_ = 0; | 620 read_attempts_ = 0; |
| 626 | 621 |
| 627 // Signal that stop task has finished execution. | 622 // Signal that stop task has finished execution. |
| 628 stop_task_finished_ = true; | 623 stop_task_finished_ = true; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 // this object when Stop() method is ever called. Locking this method is safe | 719 // this object when Stop() method is ever called. Locking this method is safe |
| 725 // because |lock_| is only acquired in tasks on render thread. | 720 // because |lock_| is only acquired in tasks on render thread. |
| 726 AutoLock auto_lock(lock_); | 721 AutoLock auto_lock(lock_); |
| 727 if (stopped_) | 722 if (stopped_) |
| 728 return; | 723 return; |
| 729 | 724 |
| 730 if (error != net::OK) { | 725 if (error != net::OK) { |
| 731 // TODO(hclam): In case of failure, we can retry several times. | 726 // TODO(hclam): In case of failure, we can retry several times. |
| 732 host()->SetError(media::PIPELINE_ERROR_NETWORK); | 727 host()->SetError(media::PIPELINE_ERROR_NETWORK); |
| 733 DCHECK(loader_.get()); | 728 DCHECK(loader_.get()); |
| 734 DCHECK(probe_loader_.get()); | |
| 735 loader_->Stop(); | 729 loader_->Stop(); |
| 736 probe_loader_->Stop(); | |
| 737 DoneInitialization(); | 730 DoneInitialization(); |
| 738 return; | 731 return; |
| 739 } | 732 } |
| 740 | 733 |
| 734 // TODO(hclam): Needs more thinking about supporting servers without range | |
| 735 // request or their partial response is not complete. | |
| 741 total_bytes_ = loader_->instance_size(); | 736 total_bytes_ = loader_->instance_size(); |
| 742 if (total_bytes_ >= 0) { | 737 if (total_bytes_ >= 0 && loader_->partial_response()) { |
| 743 // This value governs the range that we can seek to. | 738 // This value governs the range that we can seek to. |
| 744 // TODO(hclam): Report the correct value of buffered bytes. | 739 // TODO(hclam): Report the correct value of buffered bytes. |
| 745 host()->SetTotalBytes(total_bytes_); | 740 host()->SetTotalBytes(total_bytes_); |
| 746 host()->SetBufferedBytes(total_bytes_); | 741 host()->SetBufferedBytes(total_bytes_); |
| 747 } else { | 742 } else { |
| 748 // If the server didn't reply with a content length, it is likely this | 743 // If the server didn't reply with an instance size, it is likely this |
| 749 // is a streaming response. | 744 // is a streaming response. |
| 750 streaming_ = true; | 745 streaming_ = true; |
| 751 host()->SetStreaming(true); | 746 host()->SetStreaming(true); |
| 752 } | 747 } |
| 753 | 748 |
| 754 // Currently, only files can be used reliably w/o a network. | 749 // Currently, only files can be used reliably w/o a network. |
| 755 host()->SetLoaded(url_.SchemeIsFile()); | 750 host()->SetLoaded(url_.SchemeIsFile()); |
| 756 | 751 DoneInitialization(); |
| 757 initial_response_received_ = true; | |
| 758 if (probe_response_received_) | |
| 759 DoneInitialization(); | |
| 760 } | |
| 761 | |
| 762 void BufferedDataSource::ProbeStartCallback(int error) { | |
| 763 DCHECK(MessageLoop::current() == render_loop_); | |
| 764 | |
| 765 // We need to prevent calling to filter host and running the callback if | |
| 766 // we have received the stop signal. We need to lock down the whole callback | |
| 767 // method to prevent bad things from happening. The reason behind this is | |
| 768 // that we cannot guarantee tasks on render thread have completely stopped | |
| 769 // when we receive the Stop() method call. The only way to solve this is to | |
| 770 // let tasks on render thread to run but make sure they don't call outside | |
| 771 // this object when Stop() method is ever called. Locking this method is safe | |
| 772 // because |lock_| is only acquired in tasks on render thread. | |
| 773 AutoLock auto_lock(lock_); | |
| 774 if (stopped_) | |
| 775 return; | |
| 776 | |
| 777 if (error != net::OK) { | |
| 778 streaming_ = true; | |
| 779 host()->SetStreaming(true); | |
| 780 } | |
| 781 | |
| 782 DCHECK(probe_loader_.get()); | |
| 783 probe_loader_->Stop(); | |
| 784 probe_response_received_ = true; | |
| 785 if (initial_response_received_) | |
| 786 DoneInitialization(); | |
| 787 } | 752 } |
| 788 | 753 |
| 789 void BufferedDataSource::PartialReadStartCallback(int error) { | 754 void BufferedDataSource::PartialReadStartCallback(int error) { |
| 790 DCHECK(MessageLoop::current() == render_loop_); | 755 DCHECK(MessageLoop::current() == render_loop_); |
| 791 DCHECK(loader_.get()); | 756 DCHECK(loader_.get()); |
| 792 | 757 |
| 793 if (error == net::OK) { | 758 // This callback method is invoked after we have verified the server has |
| 794 // Once the range request has start successfully, we can proceed with | 759 // range request capability, so as a safety guard verify again the response |
| 760 // is partial. | |
| 761 if (error == net::OK && loader_->partial_response()) { | |
| 762 // Once the range request has started successfully, we can proceed with | |
| 795 // reading from it. | 763 // reading from it. |
| 796 ReadInternal(); | 764 ReadInternal(); |
| 797 } else { | 765 } else { |
| 798 loader_->Stop(); | 766 loader_->Stop(); |
| 799 | 767 |
| 800 // We need to prevent calling to filter host and running the callback if | 768 // We need to prevent calling to filter host and running the callback if |
| 801 // we have received the stop signal. We need to lock down the whole callback | 769 // we have received the stop signal. We need to lock down the whole callback |
| 802 // method to prevent bad things from happening. The reason behind this is | 770 // method to prevent bad things from happening. The reason behind this is |
| 803 // that we cannot guarantee tasks on render thread have completely stopped | 771 // that we cannot guarantee tasks on render thread have completely stopped |
| 804 // when we receive the Stop() method call. So only way to solve this is to | 772 // when we receive the Stop() method call. So only way to solve this is to |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 render_loop_->PostTask(FROM_HERE, | 818 render_loop_->PostTask(FROM_HERE, |
| 851 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask, | 819 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask, |
| 852 CreateLoader(read_position_, -1))); | 820 CreateLoader(read_position_, -1))); |
| 853 } else { | 821 } else { |
| 854 loader_->Stop(); | 822 loader_->Stop(); |
| 855 DoneRead(error); | 823 DoneRead(error); |
| 856 } | 824 } |
| 857 } | 825 } |
| 858 | 826 |
| 859 } // namespace webkit_glue | 827 } // namespace webkit_glue |
| OLD | NEW |