Chromium Code Reviews| Index: webkit/glue/media/buffered_data_source.cc |
| diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc |
| index 36e43d0035298633268a96bde15c43784248c652..6efaa8ce15d25feb52bd646aa9ea355c0ab95be4 100644 |
| --- a/webkit/glue/media/buffered_data_source.cc |
| +++ b/webkit/glue/media/buffered_data_source.cc |
| @@ -72,6 +72,7 @@ BufferedResourceLoader::BufferedResourceLoader( |
| deferred_(false), |
| completed_(false), |
| range_requested_(false), |
| + partial_response_(false), |
| bridge_factory_(bridge_factory), |
| url_(url), |
| first_byte_position_(first_byte_position), |
| @@ -235,14 +236,19 @@ void BufferedResourceLoader::OnReceivedResponse( |
| // We expect to receive headers because this is a HTTP or HTTPS protocol, |
| // if not report failure. |
| error = net::ERR_INVALID_RESPONSE; |
| - } else if (range_requested_) { |
| - // If we have verified the partial response and it is correct, we will |
| - // return net::OK. |
| - if (!VerifyPartialResponse(info)) |
| - error = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; |
| - } else if (info.headers->response_code() != kHttpOK) { |
| - // We didn't request a range but server didn't reply with "200 OK". |
| - error = net::ERR_FAILED; |
| + } else { |
| + if (info.headers->response_code() == kHttpPartialContent) |
| + partial_response_ = true; |
| + |
| + if (range_requested_ && partial_response_) { |
| + // If we have verified the partial response and it is correct, we will |
| + // return net::OK. |
| + if (!VerifyPartialResponse(info)) |
| + error = net::ERR_INVALID_RESPONSE; |
| + } else if (info.headers->response_code() != kHttpOK) { |
| + // We didn't request a range but server didn't reply with "200 OK". |
| + error = net::ERR_FAILED; |
| + } |
| } |
| if (error != net::OK) { |
| @@ -250,6 +256,10 @@ void BufferedResourceLoader::OnReceivedResponse( |
| Stop(); |
| return; |
| } |
| + } else { |
| + // For any protocol other than HTTP and HTTPS, assume range request is |
| + // always fulfilled. |
| + partial_response_ = range_requested_; |
| } |
| // |info.content_length| can be -1, in that case |content_length_| is |
| @@ -258,7 +268,7 @@ void BufferedResourceLoader::OnReceivedResponse( |
| // If we have not requested a range, then the size of the instance is equal |
| // to the content length. |
| - if (!range_requested_) |
| + if (!partial_response_) |
| instance_size_ = content_length_; |
| // Calls with a successful response. |
| @@ -418,9 +428,6 @@ void BufferedResourceLoader::DoneStart(int error) { |
| bool BufferedResourceLoader::VerifyPartialResponse( |
| const ResourceLoaderBridge::ResponseInfo& info) { |
| - if (info.headers->response_code() != kHttpPartialContent) |
| - return false; |
| - |
| int64 first_byte_position, last_byte_position, instance_size; |
| if (!info.headers->GetContentRange(&first_byte_position, |
| &last_byte_position, |
| @@ -455,8 +462,6 @@ BufferedDataSource::BufferedDataSource( |
| read_position_(0), |
| read_size_(0), |
| read_buffer_(NULL), |
| - initial_response_received_(false), |
| - probe_response_received_(false), |
| intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), |
| intermediate_read_buffer_size_(kInitialReadBufferSize), |
| render_loop_(render_loop), |
| @@ -551,7 +556,6 @@ bool BufferedDataSource::IsStreaming() { |
| void BufferedDataSource::InitializeTask() { |
| DCHECK(MessageLoop::current() == render_loop_); |
| DCHECK(!loader_.get()); |
| - DCHECK(!probe_loader_.get()); |
| // Kick starts the watch dog task that will handle connection timeout. |
| // We run the watch dog 2 times faster the actual timeout so as to catch |
| @@ -561,18 +565,13 @@ void BufferedDataSource::InitializeTask() { |
| this, |
| &BufferedDataSource::WatchDogTask); |
| - // Creates a new resource loader with the full range and a probe resource |
| - // loader. Creates a probe resource loader to make sure the server supports |
| - // partial range request. |
| - // TODO(hclam): Only request 1 byte for this probe request, it may be useful |
| - // that we perform a suffix range request and fetch the index. That way we |
| - // can minimize the number of requests made. |
| - loader_ = CreateLoader(-1, -1); |
| - probe_loader_ = CreateLoader(1, 1); |
| - |
| + // Fetch only first 1024 bytes as this usually covers the header portion |
| + // of a media file that gives enough information about the codecs, etc. |
| + // This also serve as a probe to determine server capability to serve |
| + // range request. |
| + // TODO(hclam): Do some experiments for the best approach. |
| + loader_ = CreateLoader(0, 1024); |
|
scherkus (not reviewing)
2009/09/29 23:10:34
ok.. might have to request this be made a constant
|
| loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback)); |
| - probe_loader_->Start( |
| - NewCallback(this, &BufferedDataSource::ProbeStartCallback)); |
| } |
| void BufferedDataSource::ReadTask( |
| @@ -612,10 +611,6 @@ void BufferedDataSource::StopTask() { |
| if (loader_.get()) |
| loader_->Stop(); |
| - // If the probe request is still active, stop it too. |
| - if (probe_loader_.get()) |
| - probe_loader_->Stop(); |
| - |
| // Reset the parameters of the current read request. |
| read_callback_.reset(); |
| read_position_ = 0; |
| @@ -731,21 +726,21 @@ void BufferedDataSource::InitialStartCallback(int error) { |
| // TODO(hclam): In case of failure, we can retry several times. |
| host()->SetError(media::PIPELINE_ERROR_NETWORK); |
| DCHECK(loader_.get()); |
| - DCHECK(probe_loader_.get()); |
| loader_->Stop(); |
| - probe_loader_->Stop(); |
| DoneInitialization(); |
| return; |
| } |
| + // TODO(hclam): Needs more thinking about supporting servers without range |
| + // request or their partial response is not complete. |
| total_bytes_ = loader_->instance_size(); |
| - if (total_bytes_ >= 0) { |
| + if (total_bytes_ >= 0 && loader_->partial_response()) { |
| // This value governs the range that we can seek to. |
| // TODO(hclam): Report the correct value of buffered bytes. |
| host()->SetTotalBytes(total_bytes_); |
| host()->SetBufferedBytes(total_bytes_); |
| } else { |
| - // If the server didn't reply with a content length, it is likely this |
| + // If the server didn't reply with an instance size, it is likely this |
| // is a streaming response. |
| streaming_ = true; |
| host()->SetStreaming(true); |
| @@ -753,45 +748,18 @@ void BufferedDataSource::InitialStartCallback(int error) { |
| // Currently, only files can be used reliably w/o a network. |
| host()->SetLoaded(url_.SchemeIsFile()); |
| - |
| - initial_response_received_ = true; |
| - if (probe_response_received_) |
| - DoneInitialization(); |
| -} |
| - |
| -void BufferedDataSource::ProbeStartCallback(int error) { |
| - DCHECK(MessageLoop::current() == render_loop_); |
| - |
| - // We need to prevent calling to filter host and running the callback if |
| - // we have received the stop signal. We need to lock down the whole callback |
| - // method to prevent bad things from happening. The reason behind this is |
| - // that we cannot guarantee tasks on render thread have completely stopped |
| - // when we receive the Stop() method call. The only way to solve this is to |
| - // let tasks on render thread to run but make sure they don't call outside |
| - // this object when Stop() method is ever called. Locking this method is safe |
| - // because |lock_| is only acquired in tasks on render thread. |
| - AutoLock auto_lock(lock_); |
| - if (stopped_) |
| - return; |
| - |
| - if (error != net::OK) { |
| - streaming_ = true; |
| - host()->SetStreaming(true); |
| - } |
| - |
| - DCHECK(probe_loader_.get()); |
| - probe_loader_->Stop(); |
| - probe_response_received_ = true; |
| - if (initial_response_received_) |
| - DoneInitialization(); |
| + DoneInitialization(); |
| } |
| void BufferedDataSource::PartialReadStartCallback(int error) { |
| DCHECK(MessageLoop::current() == render_loop_); |
| DCHECK(loader_.get()); |
| - if (error == net::OK) { |
| - // Once the range request has start successfully, we can proceed with |
| + // This callback method is invoked after we have verified the server has |
| + // range request capability, so as a safety guard verify again the response |
| + // is partial. |
| + if (error == net::OK && loader_->partial_response()) { |
| + // Once the range request has started successfully, we can proceed with |
| // reading from it. |
| ReadInternal(); |
| } else { |