summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/renderer/render_view.cc21
-rw-r--r--chrome/renderer/renderer_glue.cc1
-rw-r--r--webkit/glue/media/buffered_data_source.cc26
-rw-r--r--webkit/glue/media/buffered_data_source.h4
-rw-r--r--webkit/glue/media/simple_data_source.cc72
-rw-r--r--webkit/glue/media/simple_data_source.h7
-rw-r--r--webkit/glue/media/simple_data_source_unittest.cc84
-rw-r--r--webkit/tools/test_shell/test_shell.cc5
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.cc13
9 files changed, 159 insertions, 74 deletions
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 89d67f8..31c449b 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1789,15 +1789,20 @@ WebMediaPlayer* RenderView::createMediaPlayer(
appcache::kNoHostId,
routing_id());
- if (!cmd_line->HasSwitch(switches::kSimpleDataSource)) {
- // Add the chrome specific media data source.
- factory->AddFactory(
- webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(),
- bridge_factory));
+ // A simple data source that keeps all data in memory.
+ media::FilterFactory* simple_data_source_factory =
+ webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(),
+ bridge_factory);
+ // A sophisticated data source that does memory caching.
+ media::FilterFactory* buffered_data_source_factory =
+ webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(),
+ bridge_factory);
+ if (cmd_line->HasSwitch(switches::kSimpleDataSource)) {
+ factory->AddFactory(simple_data_source_factory);
+ factory->AddFactory(buffered_data_source_factory);
} else {
- factory->AddFactory(
- webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(),
- bridge_factory));
+ factory->AddFactory(buffered_data_source_factory);
+ factory->AddFactory(simple_data_source_factory);
}
return new webkit_glue::WebMediaPlayerImpl(client, factory);
}
diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc
index 1410376..43012e9 100644
--- a/chrome/renderer/renderer_glue.cc
+++ b/chrome/renderer/renderer_glue.cc
@@ -218,6 +218,7 @@ bool IsProtocolSupportedForMedia(const GURL& url) {
// validated accordingly in the media engine.
if (url.SchemeIsFile() || url.SchemeIs(chrome::kHttpScheme) ||
url.SchemeIs(chrome::kHttpsScheme) ||
+ url.SchemeIs(chrome::kDataScheme) ||
url.SchemeIs(chrome::kExtensionScheme))
return true;
return false;
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
index 34924c9..48df614 100644
--- a/webkit/glue/media/buffered_data_source.cc
+++ b/webkit/glue/media/buffered_data_source.cc
@@ -9,6 +9,7 @@
#include "base/string_util.h"
#include "chrome/common/extensions/url_pattern.h"
#include "media/base/filter_host.h"
+#include "media/base/media_format.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
@@ -19,6 +20,7 @@ namespace {
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
+const char kDataScheme[] = "data";
const int64 kPositionNotSpecified = -1;
const int kHttpOK = 200;
const int kHttpPartialContent = 206;
@@ -42,14 +44,12 @@ const int kForwardWaitThreshold = 2 * kMegabyte;
// Defines how long we should wait for more data before we declare a connection
// timeout and start a new request.
-// TODO(hclam): Use this value when retry is implemented.
// TODO(hclam): Set it to 5s, calibrate this value later.
const int kTimeoutMilliseconds = 5000;
// Defines how many times we should try to read from a buffered resource loader
// before we declare a read error. After each failure of read from a buffered
// resource loader, a new one is created to be read.
-// TODO(hclam): Use this value when retry is implemented.
const int kReadTrials = 3;
// BufferedDataSource has an intermediate buffer, this value governs the initial
@@ -62,6 +62,10 @@ bool IsHttpProtocol(const GURL& url) {
return url.SchemeIs(kHttpScheme) || url.SchemeIs(kHttpsScheme);
}
+bool IsDataProtocol(const GURL& url) {
+ return url.SchemeIs(kDataScheme);
+}
+
} // namespace
namespace webkit_glue {
@@ -493,6 +497,24 @@ void BufferedResourceLoader::NotifyNetworkEvent() {
}
/////////////////////////////////////////////////////////////////////////////
+// BufferedDataSource, static methods
+bool BufferedDataSource::IsMediaFormatSupported(
+ const media::MediaFormat& media_format) {
+ std::string mime_type;
+ std::string url;
+ if (media_format.GetAsString(media::MediaFormat::kMimeType, &mime_type) &&
+ media_format.GetAsString(media::MediaFormat::kURL, &url)) {
+ GURL gurl(url);
+
+ // This data source doesn't support data:// protocol, so reject it
+ // explicitly.
+ if (IsProtocolSupportedForMedia(gurl) && !IsDataProtocol(gurl))
+ return true;
+ }
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
// BufferedDataSource, protected
BufferedDataSource::BufferedDataSource(
MessageLoop* render_loop,
diff --git a/webkit/glue/media/buffered_data_source.h b/webkit/glue/media/buffered_data_source.h
index dbbb54c..59c511b 100644
--- a/webkit/glue/media/buffered_data_source.h
+++ b/webkit/glue/media/buffered_data_source.h
@@ -216,6 +216,10 @@ class BufferedDataSource : public media::DataSource {
message_loop, bridge_factory);
}
+ // media::FilterFactoryImpl2 implementation.
+ static bool IsMediaFormatSupported(
+ const media::MediaFormat& media_format);
+
// media::MediaFilter implementation.
virtual void Initialize(const std::string& url,
media::FilterCallback* callback);
diff --git a/webkit/glue/media/simple_data_source.cc b/webkit/glue/media/simple_data_source.cc
index b2b9f32..ab6cfea 100644
--- a/webkit/glue/media/simple_data_source.cc
+++ b/webkit/glue/media/simple_data_source.cc
@@ -6,29 +6,41 @@
#include "base/process_util.h"
#include "media/base/filter_host.h"
#include "net/base/load_flags.h"
+#include "net/base/data_url.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_status.h"
#include "webkit/glue/media/simple_data_source.h"
#include "webkit/glue/resource_loader_bridge.h"
+#include "webkit/glue/webkit_glue.h"
namespace {
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
-const char kFtpScheme[] = "ftp";
+const char kDataScheme[] = "data";
// A helper method that accepts only HTTP, HTTPS and FILE protocol.
-bool IsSchemeSupported(const GURL& url) {
- return url.SchemeIs(kHttpScheme) ||
- url.SchemeIs(kHttpsScheme) ||
- url.SchemeIs(kFtpScheme) ||
- url.SchemeIsFile();
+bool IsDataProtocol(const GURL& url) {
+ return url.SchemeIs(kDataScheme);
}
} // namespace
namespace webkit_glue {
+bool SimpleDataSource::IsMediaFormatSupported(
+ const media::MediaFormat& media_format) {
+ std::string mime_type;
+ std::string url;
+ if (media_format.GetAsString(media::MediaFormat::kMimeType, &mime_type) &&
+ media_format.GetAsString(media::MediaFormat::kURL, &url)) {
+ GURL gurl(url);
+ if (IsProtocolSupportedForMedia(gurl))
+ return true;
+ }
+ return false;
+}
+
SimpleDataSource::SimpleDataSource(
MessageLoop* render_loop,
webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory)
@@ -63,15 +75,13 @@ void SimpleDataSource::Initialize(const std::string& url,
// Validate the URL.
SetURL(GURL(url));
- if (!url_.is_valid() || !IsSchemeSupported(url_)) {
+ if (!url_.is_valid() || !IsProtocolSupportedForMedia(url_)) {
host()->SetError(media::PIPELINE_ERROR_NETWORK);
initialize_callback_->Run();
initialize_callback_.reset();
return;
}
- host()->SetLoaded(url_.SchemeIsFile());
-
// Post a task to the render thread to start loading the resource.
render_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &SimpleDataSource::StartTask));
@@ -148,16 +158,7 @@ void SimpleDataSource::OnCompletedRequest(const URLRequestStatus& status,
size_ = data_.length();
}
- // We're initialized!
- if (status.is_success()) {
- state_ = INITIALIZED;
- host()->SetTotalBytes(size_);
- host()->SetBufferedBytes(size_);
- } else {
- host()->SetError(media::PIPELINE_ERROR_NETWORK);
- }
- initialize_callback_->Run();
- initialize_callback_.reset();
+ DoneInitialization_Locked(status.is_success());
}
std::string SimpleDataSource::GetURLForDebugging() {
@@ -182,10 +183,20 @@ void SimpleDataSource::StartTask() {
DCHECK_EQ(state_, INITIALIZING);
- // Create our bridge and start loading the resource.
- bridge_.reset(bridge_factory_->CreateBridge(
- url_, net::LOAD_BYPASS_CACHE, -1, -1));
- bridge_->Start(this);
+ if (IsDataProtocol(url_)) {
+ // If this using data protocol, we just need to decode it.
+ std::string mime_type, charset;
+ bool success = net::DataURL::Parse(url_, &mime_type, &charset, &data_);
+
+ // Don't care about the mime-type just proceed if decoding was successful.
+ size_ = data_.length();
+ DoneInitialization_Locked(success);
+ } else {
+ // Create our bridge and start loading the resource.
+ bridge_.reset(bridge_factory_->CreateBridge(
+ url_, net::LOAD_BYPASS_CACHE, -1, -1));
+ bridge_->Start(this);
+ }
}
void SimpleDataSource::CancelTask() {
@@ -199,4 +210,19 @@ void SimpleDataSource::CancelTask() {
}
}
+void SimpleDataSource::DoneInitialization_Locked(bool success) {
+ lock_.AssertAcquired();
+ if (success) {
+ state_ = INITIALIZED;
+ host()->SetTotalBytes(size_);
+ host()->SetBufferedBytes(size_);
+ // If scheme is file or data, say we are loaded.
+ host()->SetLoaded(url_.SchemeIsFile() || IsDataProtocol(url_));
+ } else {
+ host()->SetError(media::PIPELINE_ERROR_NETWORK);
+ }
+ initialize_callback_->Run();
+ initialize_callback_.reset();
+}
+
} // namespace webkit_glue
diff --git a/webkit/glue/media/simple_data_source.h b/webkit/glue/media/simple_data_source.h
index e458c57..faf889d 100644
--- a/webkit/glue/media/simple_data_source.h
+++ b/webkit/glue/media/simple_data_source.h
@@ -34,6 +34,10 @@ class SimpleDataSource : public media::DataSource,
bridge_factory);
}
+ // media::FilterFactoryImpl2 implementation.
+ static bool IsMediaFormatSupported(
+ const media::MediaFormat& media_format);
+
// MediaFilter implementation.
virtual void Stop();
@@ -79,6 +83,9 @@ class SimpleDataSource : public media::DataSource,
// Cancels and deletes the resource loading on the render thread.
void CancelTask();
+ // Perform initialization completion tasks under a lock.
+ void DoneInitialization_Locked(bool success);
+
// Primarily used for asserting the bridge is loading on the render thread.
MessageLoop* render_loop_;
diff --git a/webkit/glue/media/simple_data_source_unittest.cc b/webkit/glue/media/simple_data_source_unittest.cc
index eb5cd78..30e1403 100644
--- a/webkit/glue/media/simple_data_source_unittest.cc
+++ b/webkit/glue/media/simple_data_source_unittest.cc
@@ -13,6 +13,7 @@ using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
+using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArgumentPointee;
@@ -23,9 +24,11 @@ namespace {
const int kDataSize = 1024;
const char kHttpUrl[] = "http://test";
-const char kFtpUrl[] = "ftp://test";
const char kHttpsUrl[] = "https://test";
const char kFileUrl[] = "file://test";
+const char kDataUrl[] =
+ "data:text/plain;base64,YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoK";
+const char kDataUrlDecoded[] = "abcdefghijklmnopqrstuvwxyz";
const char kInvalidUrl[] = "whatever://test";
} // namespace
@@ -36,8 +39,8 @@ class SimpleDataSourceTest : public testing::Test {
public:
SimpleDataSourceTest() {
bridge_factory_.reset(
- new StrictMock<MockMediaResourceLoaderBridgeFactory>());
- bridge_.reset(new StrictMock<MockResourceLoaderBridge>());
+ new NiceMock<MockMediaResourceLoaderBridgeFactory>());
+ bridge_.reset(new NiceMock<MockResourceLoaderBridge>());
factory_ = SimpleDataSource::CreateFactory(MessageLoop::current(),
bridge_factory_.get());
@@ -52,7 +55,7 @@ class SimpleDataSourceTest : public testing::Test {
}
}
- void InitializeDataSource(const char* url, bool is_loaded) {
+ void InitializeDataSource(const char* url) {
media::MediaFormat url_format;
url_format.SetAsString(media::MediaFormat::kMimeType,
media::mime_type::kURL);
@@ -63,8 +66,6 @@ class SimpleDataSourceTest : public testing::Test {
// There is no need to provide a message loop to data source.
data_source_->set_host(&host_);
- EXPECT_CALL(host_, SetLoaded(is_loaded));
-
// First a bridge is created.
InSequence s;
EXPECT_CALL(*bridge_factory_, CreateBridge(GURL(url), _, -1, -1))
@@ -72,13 +73,12 @@ class SimpleDataSourceTest : public testing::Test {
EXPECT_CALL(*bridge_, Start(data_source_.get()))
.WillOnce(Return(true));
- // TODO(hclam): need to add expectations to initialization callback.
data_source_->Initialize(url, callback_.NewCallback());
MessageLoop::current()->RunAllPending();
}
- void RequestSucceeded() {
+ void RequestSucceeded(bool is_loaded) {
ResourceLoaderBridge::ResponseInfo info;
info.content_length = kDataSize;
@@ -90,6 +90,8 @@ class SimpleDataSourceTest : public testing::Test {
for (int i = 0; i < kDataSize; ++i)
data_source_->OnReceivedData(data_ + i, 1);
+ EXPECT_CALL(host_, SetLoaded(is_loaded));
+
InSequence s;
EXPECT_CALL(*bridge_, OnDestroy())
.WillOnce(Invoke(this, &SimpleDataSourceTest::ReleaseBridge));
@@ -158,8 +160,8 @@ class SimpleDataSourceTest : public testing::Test {
protected:
scoped_ptr<MessageLoop> message_loop_;
- scoped_ptr<StrictMock<MockMediaResourceLoaderBridgeFactory> > bridge_factory_;
- scoped_ptr<StrictMock<MockResourceLoaderBridge> > bridge_;
+ scoped_ptr<NiceMock<MockMediaResourceLoaderBridgeFactory> > bridge_factory_;
+ scoped_ptr<NiceMock<MockResourceLoaderBridge> > bridge_;
scoped_refptr<media::FilterFactory> factory_;
scoped_refptr<SimpleDataSource> data_source_;
StrictMock<media::MockFilterHost> host_;
@@ -170,62 +172,70 @@ class SimpleDataSourceTest : public testing::Test {
};
TEST_F(SimpleDataSourceTest, InitializeHTTP) {
- InitializeDataSource(kHttpUrl, false);
- RequestSucceeded();
+ InitializeDataSource(kHttpUrl);
+ RequestSucceeded(false);
DestroyDataSource();
}
TEST_F(SimpleDataSourceTest, InitializeHTTPS) {
- InitializeDataSource(kHttpsUrl, false);
- RequestSucceeded();
- DestroyDataSource();
-}
-
-TEST_F(SimpleDataSourceTest, InitializeFTP) {
- InitializeDataSource(kFtpUrl, false);
- RequestSucceeded();
+ InitializeDataSource(kHttpsUrl);
+ RequestSucceeded(false);
DestroyDataSource();
}
TEST_F(SimpleDataSourceTest, InitializeFile) {
- InitializeDataSource(kFileUrl, true);
- RequestSucceeded();
+ InitializeDataSource(kFileUrl);
+ RequestSucceeded(true);
DestroyDataSource();
}
-TEST_F(SimpleDataSourceTest, InitializeInvalid) {
- StrictMock<media::MockFilterCallback> callback;
+TEST_F(SimpleDataSourceTest, InitializeData) {
+ // Bridge is not used at all.
+ ReleaseBridge();
+
media::MediaFormat url_format;
url_format.SetAsString(media::MediaFormat::kMimeType,
media::mime_type::kURL);
- url_format.SetAsString(media::MediaFormat::kURL, kInvalidUrl);
+ url_format.SetAsString(media::MediaFormat::kURL, kDataUrl);
data_source_ = factory_->Create<SimpleDataSource>(url_format);
CHECK(data_source_);
// There is no need to provide a message loop to data source.
data_source_->set_host(&host_);
- EXPECT_CALL(host_, SetError(media::PIPELINE_ERROR_NETWORK));
- EXPECT_CALL(callback, OnFilterCallback());
- EXPECT_CALL(callback, OnCallbackDestroyed());
+ EXPECT_CALL(host_, SetLoaded(true));
+ EXPECT_CALL(host_, SetTotalBytes(sizeof(kDataUrlDecoded)));
+ EXPECT_CALL(host_, SetBufferedBytes(sizeof(kDataUrlDecoded)));
+ EXPECT_CALL(callback_, OnFilterCallback());
+ EXPECT_CALL(callback_, OnCallbackDestroyed());
- data_source_->Initialize(kInvalidUrl, callback.NewCallback());
- data_source_->Stop();
+ data_source_->Initialize(kDataUrl, callback_.NewCallback());
MessageLoop::current()->RunAllPending();
- EXPECT_CALL(*bridge_factory_, OnDestroy())
- .WillOnce(Invoke(this, &SimpleDataSourceTest::ReleaseBridgeFactory));
- data_source_ = NULL;
+ DestroyDataSource();
+}
+
+TEST_F(SimpleDataSourceTest, InitializeInvalid) {
+ // They are not used at all.
+ ReleaseBridge();
+ ReleaseBridgeFactory();
+
+ media::MediaFormat url_format;
+ url_format.SetAsString(media::MediaFormat::kMimeType,
+ media::mime_type::kURL);
+ url_format.SetAsString(media::MediaFormat::kURL, kInvalidUrl);
+ data_source_ = factory_->Create<SimpleDataSource>(url_format);
+ EXPECT_FALSE(data_source_);
}
TEST_F(SimpleDataSourceTest, RequestFailed) {
- InitializeDataSource(kHttpUrl, false);
+ InitializeDataSource(kHttpUrl);
RequestFailed();
DestroyDataSource();
}
TEST_F(SimpleDataSourceTest, StopWhenDownloading) {
- InitializeDataSource(kHttpUrl, false);
+ InitializeDataSource(kHttpUrl);
EXPECT_CALL(*bridge_, Cancel());
EXPECT_CALL(*bridge_, OnDestroy())
@@ -235,8 +245,8 @@ TEST_F(SimpleDataSourceTest, StopWhenDownloading) {
}
TEST_F(SimpleDataSourceTest, AsyncRead) {
- InitializeDataSource(kFileUrl, true);
- RequestSucceeded();
+ InitializeDataSource(kFileUrl);
+ RequestSucceeded(true);
AsyncRead();
DestroyDataSource();
}
diff --git a/webkit/tools/test_shell/test_shell.cc b/webkit/tools/test_shell/test_shell.cc
index 5c28287..6691f85 100644
--- a/webkit/tools/test_shell/test_shell.cc
+++ b/webkit/tools/test_shell/test_shell.cc
@@ -690,7 +690,10 @@ bool IsDefaultPluginEnabled() {
}
bool IsProtocolSupportedForMedia(const GURL& url) {
- if (url.SchemeIsFile() || url.SchemeIs("http") || url.SchemeIs("https"))
+ if (url.SchemeIsFile() ||
+ url.SchemeIs("http") ||
+ url.SchemeIs("https") ||
+ url.SchemeIs("data"))
return true;
return false;
}
diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc
index 48fe80f..a05551b 100644
--- a/webkit/tools/test_shell/test_webview_delegate.cc
+++ b/webkit/tools/test_shell/test_webview_delegate.cc
@@ -613,9 +613,16 @@ WebMediaPlayer* TestWebViewDelegate::createMediaPlayer(
base::GetCurrentProcId(),
appcache::kNoHostId,
0);
- factory->AddFactory(webkit_glue::BufferedDataSource::CreateFactory(
- MessageLoop::current(), bridge_factory));
- // TODO(hclam): Use command line switch to determine which data source to use.
+ // A simple data source that keeps all data in memory.
+ media::FilterFactory* simple_data_source_factory =
+ webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(),
+ bridge_factory);
+ // A sophisticated data source that does memory caching.
+ media::FilterFactory* buffered_data_source_factory =
+ webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(),
+ bridge_factory);
+ factory->AddFactory(buffered_data_source_factory);
+ factory->AddFactory(simple_data_source_factory);
return new webkit_glue::WebMediaPlayerImpl(client, factory);
}