summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-30 17:49:41 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-30 17:49:41 +0000
commit3979b7df049bbcf8197cfe0849c1f526795b7c56 (patch)
tree80735491fbc9220a449133ce4064bfa645f128c5
parent09642233be151b5dc640043e594b043850cbac69 (diff)
downloadchromium_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.cc1
-rw-r--r--chrome/renderer/render_process.cc4
-rw-r--r--webkit/glue/media/buffered_data_source.cc132
-rw-r--r--webkit/glue/media/buffered_data_source.h37
-rw-r--r--webkit/glue/media/buffered_data_source_unittest.cc196
-rw-r--r--webkit/glue/webkit_glue.cc10
-rw-r--r--webkit/glue/webkit_glue.h5
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 -------------------------------