diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 02:46:29 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 02:46:29 +0000 |
commit | 84b0cbf0fc3b8eafa444be319fd10bb33b5f0f79 (patch) | |
tree | f75771ca6eb4a2f09d1ba1d89cee20671edc0faa /webkit/glue | |
parent | c0222007b5c580f0d5b8332e491c12918c9bad04 (diff) | |
download | chromium_src-84b0cbf0fc3b8eafa444be319fd10bb33b5f0f79.zip chromium_src-84b0cbf0fc3b8eafa444be319fd10bb33b5f0f79.tar.gz chromium_src-84b0cbf0fc3b8eafa444be319fd10bb33b5f0f79.tar.bz2 |
Change how <video> fetch a resource to make it friendly to sparse caching
BUG=16013
TEST=test_shell_tests --gtest_filter=Buffered*
Also video on a server that doesn't support range request will still work.
How <video> used to fetch a resource:
1. Fetch the whole file to get the header
2. Fetch a small range (1, 1) to determine if server supports range request
3. If [2] was successful, then fetch the file with range request if necessary
If [2] failed, prevent range request by telling ffmpeg this is streaming
New way of fetching a resource for <video>:
1. Fetch (0, 1023) to get the header (This needs more experiment).
2. If [1] was successful, then request later on will be made partial
If [1] failed, prevent range request by telling ffmpeg this is streaming
By doing this change we can eliminate one request before we can start the
file. And with the help of sparse cache, we would be able to reuse the first
1KB fetched even we need to fetch the index at the end of file.
Review URL: http://codereview.chromium.org/248012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27587 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/media/buffered_data_source.cc | 102 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source.h | 27 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source_unittest.cc | 190 |
3 files changed, 141 insertions, 178 deletions
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc index 36e43d0..6efaa8c 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); 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 { diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h index f3282cc..e160c60 100644 --- a/webkit/glue/media/buffered_data_source.h +++ b/webkit/glue/media/buffered_data_source.h @@ -51,8 +51,6 @@ class BufferedResourceLoader : // |callback| is called with the following values: // - net::OK // The request has started successfully. - // - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE - // A range request was made to the server but the server doesn't support it. // - net::ERR_FAILED // The request has failed because of an error with the network. // - net::ERR_INVALID_RESPONSE @@ -85,6 +83,10 @@ class BufferedResourceLoader : // the size is unknown. virtual int64 instance_size() { return instance_size_; } + // Returns true if the response for this loader is a partial response. + // It means a 206 response in HTTP/HTTPS protocol. + virtual bool partial_response() { return partial_response_; } + ///////////////////////////////////////////////////////////////////////////// // webkit_glue::ResourceLoaderBridge::Peer implementations. virtual void OnUploadProgress(uint64 position, uint64 size) {} @@ -137,10 +139,18 @@ class BufferedResourceLoader : // A sliding window of buffer. scoped_ptr<media::SeekableBuffer> buffer_; + // True if resource loading was deferred. bool deferred_; + + // True if resource loading has completed. bool completed_; + + // True if a range request was made. bool range_requested_; + // True if response data received is a partial range. + bool partial_response_; + webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory_; GURL url_; int64 first_byte_position_; @@ -257,10 +267,6 @@ class BufferedDataSource : public media::DataSource { // initial request is received. void InitialStartCallback(int error); - // Callback method for |probe_loader_|. This method is called when the - // response for probe request is received. - void ProbeStartCallback(int error); - // Callback method to be passed to BufferedResourceLoader during range // request. Once a resource request has started, this method will be called // with the error code. This method will be executed on the thread @@ -293,9 +299,6 @@ class BufferedDataSource : public media::DataSource { // A resource loader for the media resource. scoped_refptr<BufferedResourceLoader> loader_; - // A resource loader that probes the server's ability to serve range requests. - scoped_refptr<BufferedResourceLoader> probe_loader_; - // Callback method from the pipeline for initialization. scoped_ptr<media::FilterCallback> initialize_callback_; @@ -307,12 +310,6 @@ class BufferedDataSource : public media::DataSource { base::Time read_submitted_time_; int read_attempts_; - // This flag is set to true if the initial request has started. - bool initial_response_received_; - - // This flag is set to true if the probe request has started. - bool probe_response_received_; - // This buffer is intermediate, we use it for BufferedResourceLoader to write // to. And when read in BufferedResourceLoader is done, we copy data from // this buffer to |read_buffer_|. The reason for an additional copy is that diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc index 003313c..8c72120 100644 --- a/webkit/glue/media/buffered_data_source_unittest.cc +++ b/webkit/glue/media/buffered_data_source_unittest.cc @@ -97,16 +97,18 @@ class BufferedResourceLoaderTest : public testing::Test { loader_->OnReceivedResponse(info, false); EXPECT_EQ(instance_size, loader_->content_length()); EXPECT_EQ(instance_size, loader_->instance_size()); + EXPECT_FALSE(loader_->partial_response()); } - void PartialResponse(int64 instance_size) { + void PartialResponse(int64 first_position, int64 last_position, + int64 instance_size) { EXPECT_CALL(*this, StartCallback(net::OK)); - int64 content_length = last_position_ - first_position_ + 1; + int64 content_length = last_position - first_position + 1; ResourceLoaderBridge::ResponseInfo info; std::string header = StringPrintf("HTTP/1.1 206 Partial Content\n" "Content-Range: bytes %lld-%lld/%lld", - first_position_, - last_position_, + first_position, + last_position, instance_size); replace(header.begin(), header.end(), '\n', '\0'); info.headers = new net::HttpResponseHeaders(header); @@ -114,6 +116,7 @@ class BufferedResourceLoaderTest : public testing::Test { loader_->OnReceivedResponse(info, false); EXPECT_EQ(content_length, loader_->content_length()); EXPECT_EQ(instance_size, loader_->instance_size()); + EXPECT_TRUE(loader_->partial_response()); } void StopWhenLoad() { @@ -196,24 +199,16 @@ TEST_F(BufferedResourceLoaderTest, BadHttpResponse) { .WillOnce(Invoke(this, &BufferedResourceLoaderTest::ReleaseBridge)); ResourceLoaderBridge::ResponseInfo info; - info.headers = new net::HttpResponseHeaders("HTTP/1.1 404 Bot Found\n"); + info.headers = new net::HttpResponseHeaders("HTTP/1.1 404 Not Found\n"); loader_->OnReceivedResponse(info, false); } // Tests that partial content is requested but not fulfilled. -TEST_F(BufferedResourceLoaderTest, NotPartialRange) { +TEST_F(BufferedResourceLoaderTest, NotPartialResponse) { Initialize(kHttpUrl, 100, -1); Start(); - - EXPECT_CALL(*this, StartCallback(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); - EXPECT_CALL(*bridge_, Cancel()) - .WillOnce(RequestCanceled(loader_)); - EXPECT_CALL(*bridge_, OnDestroy()) - .WillOnce(Invoke(this, &BufferedResourceLoaderTest::ReleaseBridge)); - - ResourceLoaderBridge::ResponseInfo info; - info.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK\n"); - loader_->OnReceivedResponse(info, false); + FullResponse(1024); + StopWhenLoad(); } // Tests that a 200 response is received. @@ -228,15 +223,36 @@ TEST_F(BufferedResourceLoaderTest, FullResponse) { TEST_F(BufferedResourceLoaderTest, PartialResponse) { Initialize(kHttpUrl, 100, 200); Start(); - PartialResponse(1024); + PartialResponse(100, 200, 1024); StopWhenLoad(); } +// Tests that an invalid partial response is received. +TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) { + Initialize(kHttpUrl, 0, 10); + Start(); + + EXPECT_CALL(*this, StartCallback(net::ERR_INVALID_RESPONSE)); + EXPECT_CALL(*bridge_, Cancel()) + .WillOnce(RequestCanceled(loader_)); + EXPECT_CALL(*bridge_, OnDestroy()) + .WillOnce(Invoke(this, &BufferedResourceLoaderTest::ReleaseBridge)); + + ResourceLoaderBridge::ResponseInfo info; + std::string header = StringPrintf("HTTP/1.1 206 Partial Content\n" + "Content-Range: bytes %d-%d/%d", + 1, 10, 1024); + replace(header.begin(), header.end(), '\n', '\0'); + info.headers = new net::HttpResponseHeaders(header); + info.content_length = 10; + loader_->OnReceivedResponse(info, false); +} + // Tests the logic of sliding window for data buffering and reading. TEST_F(BufferedResourceLoaderTest, BufferAndRead) { Initialize(kHttpUrl, 10, 29); Start(); - PartialResponse(30); + PartialResponse(10, 29, 30); uint8 buffer[10]; InSequence s; @@ -289,7 +305,7 @@ TEST_F(BufferedResourceLoaderTest, BufferAndRead) { TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) { Initialize(kHttpUrl, 10, 0x00FFFFFF); Start(); - PartialResponse(0x01000000); + PartialResponse(10, 0x00FFFFFF, 0x01000000); uint8 buffer[10]; InSequence s; @@ -321,7 +337,7 @@ TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) { TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) { Initialize(kHttpUrl, 10, 29); Start(); - PartialResponse(30); + PartialResponse(10, 29, 30); uint8 buffer[10]; InSequence s; @@ -348,6 +364,7 @@ class MockBufferedResourceLoader : public BufferedResourceLoader { net::CompletionCallback* callback)); MOCK_METHOD0(content_length, int64()); MOCK_METHOD0(instance_size, int64()); + MOCK_METHOD0(partial_response, bool()); private: DISALLOW_COPY_AND_ASSIGN(MockBufferedResourceLoader); @@ -420,8 +437,9 @@ class BufferedDataSourceTest : public testing::Test { message_loop_.release(); } - void InitializeDataSource(const char* url, int error, int probe_error, - int64 instance_size, NetworkState networkState) { + void InitializeDataSource(const char* url, int error, + bool partial_response, int64 instance_size, + NetworkState networkState) { // Saves the url first. gurl_ = GURL(url); @@ -435,90 +453,66 @@ class BufferedDataSourceTest : public testing::Test { // There is no need to provide a message loop to data source. data_source_->set_host(&host_); - // Creates the first mock loader to be injected. + // Creates the mock loader to be injected. loader_ = new StrictMock<MockBufferedResourceLoader>(); - probe_loader_ = new StrictMock<MockBufferedResourceLoader>(); + // Expected loaded or not. if (networkState == LOADED) { EXPECT_CALL(host_, SetLoaded(true)); } else if (networkState == LOADING) { EXPECT_CALL(host_, SetLoaded(false)); } - // TODO(ajwong): This mock is too strict. We do not need to guarantee a - // full sequencing each of these expectations. - InSequence s; - StrictMock<media::MockFilterCallback> callback; - - // There is one resource loader with full range will be created. - EXPECT_CALL(*data_source_, CreateLoader(-1, -1)) - .WillOnce(Return(loader_.get())); + { + InSequence s; - // Then another resource loader with a small partial range is created. - EXPECT_CALL(*data_source_, CreateLoader(1, 1)) - .WillOnce(Return(probe_loader_.get())); + // There is one resource loader that request the first 1KB. + EXPECT_CALL(*data_source_, CreateLoader(0, 1024)) + .WillOnce(Return(loader_.get())); - // The initial response loader will be started. - EXPECT_CALL(*loader_, Start(NotNull())) - .WillOnce(DoAll(Assign(&error_, error), - Invoke(this, - &BufferedDataSourceTest::InvokeStartCallback))); + // The initial response loader will be started. + EXPECT_CALL(*loader_, Start(NotNull())) + .WillOnce( + DoAll(Assign(&error_, error), + Invoke(this, + &BufferedDataSourceTest::InvokeStartCallback))); + } + StrictMock<media::MockFilterCallback> callback; if (error == net::OK) { EXPECT_CALL(*loader_, instance_size()) - .WillOnce(Return(instance_size)); - if (instance_size != -1) { + .WillRepeatedly(Return(instance_size)); + EXPECT_CALL(*loader_, partial_response()) + .WillRepeatedly(Return(partial_response)); + + // TODO(hclam): The condition for streaming needs to be adjusted. + if (instance_size != -1 && partial_response) { EXPECT_CALL(host_, SetTotalBytes(instance_size)); EXPECT_CALL(host_, SetBufferedBytes(instance_size)); } else { EXPECT_CALL(host_, SetStreaming(true)); } - // Then the probe resource loader will start. - EXPECT_CALL(*probe_loader_, Start(NotNull())) - .WillOnce(DoAll(Assign(&error_, probe_error), - Invoke(this, - &BufferedDataSourceTest::InvokeStartCallback))); - if (probe_error != net::OK) - EXPECT_CALL(host_, SetStreaming(true)); - EXPECT_CALL(*probe_loader_, Stop()); EXPECT_CALL(callback, OnFilterCallback()); EXPECT_CALL(callback, OnCallbackDestroyed()); } else { EXPECT_CALL(host_, SetError(media::PIPELINE_ERROR_NETWORK)); EXPECT_CALL(*loader_, Stop()); - EXPECT_CALL(*probe_loader_, Stop()); EXPECT_CALL(callback, OnFilterCallback()); EXPECT_CALL(callback, OnCallbackDestroyed()); - - // This expectation looks a little strange, but this is actually what - // will happen since we are not running a message loop. So simply - // delete the callback. - EXPECT_CALL(*probe_loader_, Start(NotNull())) - .WillOnce(DeleteArg<0>()); } + // Actual initialization of the data source. data_source_->Initialize(url, callback.NewCallback()); message_loop_->RunAllPending(); if (error == net::OK) { // Verify the size of the data source. int64 size; - if (instance_size != -1) { + if (instance_size != -1 && partial_response) { EXPECT_TRUE(data_source_->GetSize(&size)); EXPECT_EQ(instance_size, size); - - if (probe_error == net::OK) { - EXPECT_FALSE(data_source_->IsStreaming()); - } } else { - EXPECT_FALSE(data_source_->GetSize(&size)); - EXPECT_EQ(0, size); - EXPECT_TRUE(data_source_->IsStreaming()); - } - - // Verify the data source is streamed if the probe has received an error. - if (probe_error != net::OK) { EXPECT_TRUE(data_source_->IsStreaming()); } } @@ -528,7 +522,6 @@ class BufferedDataSourceTest : public testing::Test { if (loader_) { InSequence s; EXPECT_CALL(*loader_, Stop()); - EXPECT_CALL(*probe_loader_, Stop()); } data_source_->Stop(); @@ -578,17 +571,19 @@ class BufferedDataSourceTest : public testing::Test { void ReadDataSourceMiss(int64 position, int size) { EXPECT_TRUE(loader_); - InSequence s; // 1. Reply with a cache miss for the read. - EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull())) - .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS), - Invoke(this, - &BufferedDataSourceTest::InvokeReadCallback))); + { + InSequence s; + EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull())) + .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS), + Invoke(this, + &BufferedDataSourceTest::InvokeReadCallback))); + EXPECT_CALL(*loader_, Stop()); + } // 2. Then the current loader will be stop and destroyed. StrictMock<MockBufferedResourceLoader> *new_loader = new StrictMock<MockBufferedResourceLoader>(); - EXPECT_CALL(*loader_, Stop()); EXPECT_CALL(*data_source_, CreateLoader(position, -1)) .WillOnce(Return(new_loader)); @@ -597,6 +592,8 @@ class BufferedDataSourceTest : public testing::Test { .WillOnce(DoAll(Assign(&error_, net::OK), Invoke(this, &BufferedDataSourceTest::InvokeStartCallback))); + EXPECT_CALL(*new_loader, partial_response()) + .WillRepeatedly(Return(loader_->partial_response())); // 4. Then again a read request is made to the new loader. EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull())) @@ -620,7 +617,6 @@ class BufferedDataSourceTest : public testing::Test { void ReadDataSourceFailed(int64 position, int size, int error) { EXPECT_TRUE(loader_); - InSequence s; // 1. Expect the read is delegated to the resource loader. EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull())) .WillOnce(DoAll(Assign(&error_, error), @@ -641,23 +637,29 @@ class BufferedDataSourceTest : public testing::Test { } void ReadDataSourceTimesOut(int64 position, int size) { - InSequence s; // 1. Drop the request and let it times out. - EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull())) - .WillOnce(DeleteArg<3>()); + { + InSequence s; + EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull())) + .WillOnce(DeleteArg<3>()); + EXPECT_CALL(*loader_, Stop()); + } // 2. Then the current loader will be stop and destroyed. StrictMock<MockBufferedResourceLoader> *new_loader = new StrictMock<MockBufferedResourceLoader>(); - EXPECT_CALL(*loader_, Stop()); EXPECT_CALL(*data_source_, CreateLoader(position, -1)) .WillOnce(Return(new_loader)); - // 3. Then the new loader will be started. + // 3. Then the new loader will be started and respond to queries about + // whether this is a partial response using the value of the previous + // loader. EXPECT_CALL(*new_loader, Start(NotNull())) .WillOnce(DoAll(Assign(&error_, net::OK), Invoke(this, &BufferedDataSourceTest::InvokeStartCallback))); + EXPECT_CALL(*new_loader, partial_response()) + .WillRepeatedly(Return(loader_->partial_response())); // 4. Then again a read request is made to the new loader. EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull())) @@ -688,7 +690,6 @@ class BufferedDataSourceTest : public testing::Test { scoped_ptr<StrictMock<MockMediaResourceLoaderBridgeFactory> > bridge_factory_; scoped_refptr<StrictMock<MockBufferedResourceLoader> > loader_; - scoped_refptr<StrictMock<MockBufferedResourceLoader> > probe_loader_; scoped_refptr<MockBufferedDataSource > data_source_; scoped_refptr<media::FilterFactory> factory_; @@ -705,36 +706,33 @@ class BufferedDataSourceTest : public testing::Test { }; TEST_F(BufferedDataSourceTest, InitializationSuccess) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, InitiailizationFailed) { - InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, - net::ERR_FILE_NOT_FOUND, 0, NONE); + InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE); StopDataSource(); } TEST_F(BufferedDataSourceTest, MissingContentLength) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, -1, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) { - InitializeDataSource(kHttpUrl, net::OK, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, 1024, LOADING); + InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, MissingContentLengthAndRangeRequestNotSupported) { - InitializeDataSource(kHttpUrl, net::OK, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, -1, LOADING); + InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadCacheHit) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 25, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); // Performs read with cache hit. ReadDataSourceHit(10, 10, 10); @@ -746,27 +744,27 @@ TEST_F(BufferedDataSourceTest, ReadCacheHit) { } TEST_F(BufferedDataSourceTest, ReadCacheMiss) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); ReadDataSourceMiss(1000, 10); ReadDataSourceMiss(20, 10); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadFailed) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); ReadDataSourceHit(10, 10, 10); ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadTimesOut) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); + InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); ReadDataSourceTimesOut(20, 10); StopDataSource(); } TEST_F(BufferedDataSourceTest, FileHasLoadedState) { - InitializeDataSource(kFileUrl, net::OK, net::OK, 1024, LOADED); + InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); ReadDataSourceTimesOut(20, 10); StopDataSource(); } |