diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 17:49:41 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 17:49:41 +0000 |
commit | 3979b7df049bbcf8197cfe0849c1f526795b7c56 (patch) | |
tree | 80735491fbc9220a449133ce4064bfa645f128c5 | |
parent | 09642233be151b5dc640043e594b043850cbac69 (diff) | |
download | chromium_src-3979b7df049bbcf8197cfe0849c1f526795b7c56.zip chromium_src-3979b7df049bbcf8197cfe0849c1f526795b7c56.tar.gz chromium_src-3979b7df049bbcf8197cfe0849c1f526795b7c56.tar.bz2 |
Enable <video> using cache
Retrying the following two patches:
http://codereview.chromium.org/253001/show
http://codereview.chromium.org/248012/show
TBR=scherkus
Review URL: http://codereview.chromium.org/242073
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27632 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.cc | 1 | ||||
-rw-r--r-- | chrome/renderer/render_process.cc | 4 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source.cc | 132 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source.h | 37 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source_unittest.cc | 196 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.cc | 10 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.h | 5 |
7 files changed, 209 insertions, 176 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 159a190..b0ec310 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -331,6 +331,7 @@ bool BrowserRenderProcessHost::Init() { switches::kEnableBenchmarking, switches::kInternalNaCl, switches::kEnableDatabases, + switches::kEnableByteRangeSupport, }; for (size_t i = 0; i < arraysize(switch_names); ++i) { diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index 0c579ea..fbe38cf 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -85,6 +85,10 @@ RenderProcess::RenderProcess() if (command_line.HasSwitch(switches::kInternalNaCl)) RegisterInternalNaClPlugin(RenderProcess::LaunchNaClProcess); + if (command_line.HasSwitch(switches::kEnableByteRangeSupport)) { + webkit_glue::SetMediaCacheEnabled(true); + } + FilePath module_path; initialized_media_library_ = PathService::Get(base::DIR_MODULE, &module_path) && diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc index 36e43d0..0bc57f0 100644 --- a/webkit/glue/media/buffered_data_source.cc +++ b/webkit/glue/media/buffered_data_source.cc @@ -57,6 +57,11 @@ const int kReadTrials = 3; // of FFmpeg. const int kInitialReadBufferSize = 32768; +// Returns true if |url| operates on HTTP protocol. +bool IsHttpProtocol(const GURL& url) { + return url.SchemeIs(kHttpScheme) || url.SchemeIs(kHttpsScheme); +} + } // namespace namespace webkit_glue { @@ -72,6 +77,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), @@ -109,10 +115,12 @@ void BufferedResourceLoader::Start(net::CompletionCallback* start_callback) { // Creates the bridge on render thread since we can only access // ResourceDispatcher on this thread. - bridge_.reset(bridge_factory_->CreateBridge(url_, - net::LOAD_BYPASS_CACHE, - first_byte_position_, - last_byte_position_)); + bridge_.reset( + bridge_factory_->CreateBridge( + url_, + IsMediaCacheEnabled() ? net::LOAD_NORMAL : net::LOAD_BYPASS_CACHE, + first_byte_position_, + last_byte_position_)); // Increment the reference count right before we start the request. This // reference will be release when this request has ended. @@ -229,20 +237,25 @@ void BufferedResourceLoader::OnReceivedResponse( // received a response from HTTP/HTTPS protocol or the request was // successful (in particular range request). So we only verify the partial // response for HTTP and HTTPS protocol. - if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { + if (IsHttpProtocol(url_)) { int error = net::OK; if (!info.headers) { // 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 +263,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 +275,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 +435,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 +469,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 +563,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 +572,25 @@ 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); - - loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback)); - probe_loader_->Start( - NewCallback(this, &BufferedDataSource::ProbeStartCallback)); + if (IsHttpProtocol(url_)) { + // 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::HttpInitialStartCallback)); + } else { + // For all other protocols, assume they support range request. We fetch + // the full range of the resource to obtain the instance size because + // we won't be served HTTP headers. + loader_ = CreateLoader(-1, -1); + loader_->Start( + NewCallback(this, + &BufferedDataSource::NonHttpInitialStartCallback)); + } } void BufferedDataSource::ReadTask( @@ -612,10 +630,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; @@ -712,7 +726,7 @@ void BufferedDataSource::DoneInitialization() { // BufferedDataSource, callback methods. // These methods are called on the render thread for the events reported by // BufferedResourceLoader. -void BufferedDataSource::InitialStartCallback(int error) { +void BufferedDataSource::HttpInitialStartCallback(int error) { DCHECK(MessageLoop::current() == render_loop_); // We need to prevent calling to filter host and running the callback if @@ -731,35 +745,32 @@ 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); } // Currently, only files can be used reliably w/o a network. - host()->SetLoaded(url_.SchemeIsFile()); - - initial_response_received_ = true; - if (probe_response_received_) - DoneInitialization(); + host()->SetLoaded(false); + DoneInitialization(); } -void BufferedDataSource::ProbeStartCallback(int error) { +void BufferedDataSource::NonHttpInitialStartCallback(int error) { DCHECK(MessageLoop::current() == render_loop_); // We need to prevent calling to filter host and running the callback if @@ -774,24 +785,31 @@ void BufferedDataSource::ProbeStartCallback(int error) { if (stopped_) return; - if (error != net::OK) { - streaming_ = true; - host()->SetStreaming(true); - } + DCHECK(loader_.get()); - DCHECK(probe_loader_.get()); - probe_loader_->Stop(); - probe_response_received_ = true; - if (initial_response_received_) + if (error != net::OK || loader_->instance_size() == kPositionNotSpecified) { + host()->SetError(media::PIPELINE_ERROR_NETWORK); + loader_->Stop(); DoneInitialization(); + return; + } + + total_bytes_ = loader_->instance_size(); + host()->SetTotalBytes(total_bytes_); + host()->SetBufferedBytes(total_bytes_); + host()->SetLoaded(true); + 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..532fa56 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_; @@ -253,13 +263,15 @@ class BufferedDataSource : public media::DataSource { // Calls |initialize_callback_| and reset it. void DoneInitialization(); - // Callback method for |loader_|. This method is called when response for - // initial request is received. - void InitialStartCallback(int error); + // Callback method for |loader_| if URL for the resource requested is using + // HTTP protocol. This method is called when response for initial request is + // received. + void HttpInitialStartCallback(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 for |loader_| if URL for the resource requested is using + // a non-HTTP protocol, e.g. local files. This method is called when response + // for initial request is received. + void NonHttpInitialStartCallback(int error); // Callback method to be passed to BufferedResourceLoader during range // request. Once a resource request has started, this method will be called @@ -293,9 +305,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 +316,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..c05c9b9 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,60 @@ 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>(); - if (networkState == LOADED) { - EXPECT_CALL(host_, SetLoaded(true)); - } else if (networkState == LOADING) { - EXPECT_CALL(host_, SetLoaded(false)); + bool loaded = networkState == LOADED; + { + InSequence s; + EXPECT_CALL(*data_source_, CreateLoader(_, _)) + .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))); } - // 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())); - - // Then another resource loader with a small partial range is created. - EXPECT_CALL(*data_source_, CreateLoader(1, 1)) - .WillOnce(Return(probe_loader_.get())); - - // The initial response loader will be started. - EXPECT_CALL(*loader_, Start(NotNull())) - .WillOnce(DoAll(Assign(&error_, error), - Invoke(this, - &BufferedDataSourceTest::InvokeStartCallback))); - if (error == net::OK) { + // Expected loaded or not. + EXPECT_CALL(host_, SetLoaded(loaded)); 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 && (loaded || 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 && (loaded || 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 +516,6 @@ class BufferedDataSourceTest : public testing::Test { if (loader_) { InSequence s; EXPECT_CALL(*loader_, Stop()); - EXPECT_CALL(*probe_loader_, Stop()); } data_source_->Stop(); @@ -578,17 +565,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 +586,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 +611,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 +631,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 +684,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 +700,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 +738,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(); } diff --git a/webkit/glue/webkit_glue.cc b/webkit/glue/webkit_glue.cc index 0e61b6f..2136b22 100644 --- a/webkit/glue/webkit_glue.cc +++ b/webkit/glue/webkit_glue.cc @@ -479,4 +479,14 @@ int GetGlyphPageCount() { return WebCore::GlyphPageTreeNode::treeGlyphPageCount(); } +bool g_enable_media_cache = false; + +bool IsMediaCacheEnabled() { + return g_enable_media_cache; +} + +void SetMediaCacheEnabled(bool enabled) { + g_enable_media_cache = enabled; +} + } // namespace webkit_glue diff --git a/webkit/glue/webkit_glue.h b/webkit/glue/webkit_glue.h index 73fbe6b..1874510 100644 --- a/webkit/glue/webkit_glue.h +++ b/webkit/glue/webkit_glue.h @@ -122,6 +122,11 @@ WebKit::WebCanvas* ToWebCanvas(skia::PlatformCanvas*); // used to get memory usage statistics. int GetGlyphPageCount(); +// Methods to query and enable media cache. +// TODO(hclam): Remove these methods when the cache is stable enough. +bool IsMediaCacheEnabled(); +void SetMediaCacheEnabled(bool enabled); + //---- END FUNCTIONS IMPLEMENTED BY WEBKIT/GLUE ------------------------------- |