summaryrefslogtreecommitdiffstats
path: root/webkit/glue/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-19 17:48:43 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-19 17:48:43 +0000
commit272c3c15fa918060027b63a160d2e170c9088cf5 (patch)
tree7aa9aec33ab00415d9d9d68ba99a3757654ec8bb /webkit/glue/media
parent570575f6a60d7fad9a5c9e190b3300b176e34f0f (diff)
downloadchromium_src-272c3c15fa918060027b63a160d2e170c9088cf5.zip
chromium_src-272c3c15fa918060027b63a160d2e170c9088cf5.tar.gz
chromium_src-272c3c15fa918060027b63a160d2e170c9088cf5.tar.bz2
Added fallback code for servers that don't support Range requests properly
This change issues a request without a Range header if the first request with a Range header fails. This allows us to play files from servers that don't properly implement responses to Range requests. Patch by acolwell@chromium.org: http://codereview.chromium.org/3796007/show BUG=39048 TEST=BufferedDataSourceTest.MissingContentRange git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63065 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/media')
-rw-r--r--webkit/glue/media/buffered_data_source.cc14
-rw-r--r--webkit/glue/media/buffered_data_source.h4
-rw-r--r--webkit/glue/media/buffered_data_source_unittest.cc66
3 files changed, 66 insertions, 18 deletions
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
index 4feb0e6..3456e3a 100644
--- a/webkit/glue/media/buffered_data_source.cc
+++ b/webkit/glue/media/buffered_data_source.cc
@@ -560,7 +560,8 @@ BufferedDataSource::BufferedDataSource(
render_loop_(render_loop),
stop_signal_received_(false),
stopped_on_render_loop_(false),
- media_is_paused_(true) {
+ media_is_paused_(true),
+ using_range_request_(true) {
}
BufferedDataSource::~BufferedDataSource() {
@@ -879,6 +880,17 @@ void BufferedDataSource::HttpInitialStartCallback(int error) {
loader_->Stop();
}
+ if (error == net::ERR_INVALID_RESPONSE && using_range_request_) {
+ // Assuming that the Range header was causing the problem. Retry without
+ // the Range header.
+ using_range_request_ = false;
+ loader_ = CreateResourceLoader(-1, -1);
+ loader_->Start(
+ NewCallback(this, &BufferedDataSource::HttpInitialStartCallback),
+ NewCallback(this, &BufferedDataSource::NetworkEventCallback));
+ return;
+ }
+
// 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
diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h
index d07eb01..e7b2e47 100644
--- a/webkit/glue/media/buffered_data_source.h
+++ b/webkit/glue/media/buffered_data_source.h
@@ -406,6 +406,10 @@ class BufferedDataSource : public media::DataSource {
// the message loop doesn't hold a reference for the watch dog task.
base::RepeatingTimer<BufferedDataSource> watch_dog_timer_;
+ // Keeps track of whether we used a Range header in the initialization
+ // request.
+ bool using_range_request_;
+
DISALLOW_COPY_AND_ASSIGN(BufferedDataSource);
};
diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc
index 2ba0087..f032595 100644
--- a/webkit/glue/media/buffered_data_source_unittest.cc
+++ b/webkit/glue/media/buffered_data_source_unittest.cc
@@ -29,6 +29,7 @@ using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;
+using ::testing::NiceMock;
using ::testing::WithArgs;
namespace {
@@ -597,6 +598,17 @@ class BufferedDataSourceTest : public testing::Test {
}
}
+ void ExpectCreateAndStartResourceLoader(int start_error) {
+ EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
+ .WillOnce(Return(loader_.get()));
+
+ EXPECT_CALL(*loader_, Start(NotNull(), NotNull()))
+ .WillOnce(
+ DoAll(Assign(&error_, start_error),
+ Invoke(this,
+ &BufferedDataSourceTest::InvokeStartCallback)));
+ }
+
void InitializeDataSource(const char* url, int error,
bool partial_response, int64 instance_size,
NetworkState networkState) {
@@ -613,21 +625,34 @@ class BufferedDataSourceTest : public testing::Test {
// There is no need to provide a message loop to data source.
data_source_->set_host(&host_);
+ scoped_refptr<NiceMock<MockBufferedResourceLoader> > first_loader =
+ new NiceMock<MockBufferedResourceLoader>();
+
// Creates the mock loader to be injected.
- loader_ = new StrictMock<MockBufferedResourceLoader>();
+ loader_ = first_loader;
+ bool initialized_ok = (error == net::OK);
bool loaded = networkState == LOADED;
{
InSequence s;
- EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
- .WillOnce(Return(loader_.get()));
-
- // The initial response loader will be started.
- EXPECT_CALL(*loader_, Start(NotNull(), NotNull()))
- .WillOnce(
- DoAll(Assign(&error_, error),
- Invoke(this,
- &BufferedDataSourceTest::InvokeStartCallback)));
+ ExpectCreateAndStartResourceLoader(error);
+
+ // In the case of an invalid partial response we expect a second loader
+ // to be created.
+ if (partial_response && (error == net::ERR_INVALID_RESPONSE)) {
+ // Verify that the initial loader is stopped.
+ EXPECT_CALL(*loader_, Stop());
+
+ // Replace loader_ with a new instance.
+ loader_ = new NiceMock<MockBufferedResourceLoader>();
+
+ // Create and start Make sure Start() is called the new loader.
+ ExpectCreateAndStartResourceLoader(net::OK);
+
+ // Update initialization variable since we know the second loader will
+ // return OK.
+ initialized_ok = true;
+ }
}
StrictMock<media::MockFilterCallback> callback;
@@ -635,7 +660,7 @@ class BufferedDataSourceTest : public testing::Test {
.WillRepeatedly(Return(instance_size));
EXPECT_CALL(*loader_, partial_response())
.WillRepeatedly(Return(partial_response));
- if (error == net::OK) {
+ if (initialized_ok) {
// Expected loaded or not.
EXPECT_CALL(host_, SetLoaded(loaded));
@@ -663,7 +688,7 @@ class BufferedDataSourceTest : public testing::Test {
data_source_->Initialize(url, callback.NewCallback());
message_loop_->RunAllPending();
- if (error == net::OK) {
+ if (initialized_ok) {
// Verify the size of the data source.
int64 size;
if (instance_size != -1 && (loaded || partial_response)) {
@@ -746,8 +771,8 @@ class BufferedDataSourceTest : public testing::Test {
}
// 2. Then the current loader will be stop and destroyed.
- StrictMock<MockBufferedResourceLoader> *new_loader =
- new StrictMock<MockBufferedResourceLoader>();
+ NiceMock<MockBufferedResourceLoader> *new_loader =
+ new NiceMock<MockBufferedResourceLoader>();
EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
.WillOnce(Return(new_loader));
@@ -810,8 +835,8 @@ class BufferedDataSourceTest : public testing::Test {
}
// 2. Then the current loader will be stop and destroyed.
- StrictMock<MockBufferedResourceLoader> *new_loader =
- new StrictMock<MockBufferedResourceLoader>();
+ NiceMock<MockBufferedResourceLoader> *new_loader =
+ new NiceMock<MockBufferedResourceLoader>();
EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
.WillOnce(Return(new_loader));
@@ -853,7 +878,7 @@ class BufferedDataSourceTest : public testing::Test {
scoped_ptr<StrictMock<MockMediaResourceLoaderBridgeFactory> >
bridge_factory_;
- scoped_refptr<StrictMock<MockBufferedResourceLoader> > loader_;
+ scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_;
scoped_refptr<MockBufferedDataSource> data_source_;
scoped_refptr<media::FilterFactory> factory_;
@@ -889,6 +914,13 @@ TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) {
StopDataSource();
}
+// Test the case where we get a 206 response, but no Content-Range header.
+TEST_F(BufferedDataSourceTest, MissingContentRange) {
+ InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024,
+ LOADING);
+ StopDataSource();
+}
+
TEST_F(BufferedDataSourceTest,
MissingContentLengthAndRangeRequestNotSupported) {
InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING);