diff options
author | ddorwin@chromium.org <ddorwin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-19 09:45:56 +0000 |
---|---|---|
committer | ddorwin@chromium.org <ddorwin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-19 09:45:56 +0000 |
commit | f7a6b9990c8770ebce219a863b156b7c8e150f60 (patch) | |
tree | fb400719a0292f67ba4c4e4353a4ec6aa65d750d | |
parent | bec20dd23bdd936f7dea25da7367432a26d4f7a9 (diff) | |
download | chromium_src-f7a6b9990c8770ebce219a863b156b7c8e150f60.zip chromium_src-f7a6b9990c8770ebce219a863b156b7c8e150f60.tar.gz chromium_src-f7a6b9990c8770ebce219a863b156b7c8e150f60.tar.bz2 |
Initial implementation of Encrypted Media Extensions in Chrome.
The new encrypted-media layout tests pass, but the key is not used by the media stack yet.
BUG=119668
TEST=LayoutTests/media/encrypted-media/
R=scherkus@chromium.org
Review URL: http://codereview.chromium.org/10020053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132973 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/worker/worker_webkitplatformsupport_impl.cc | 7 | ||||
-rw-r--r-- | content/worker/worker_webkitplatformsupport_impl.h | 5 | ||||
-rw-r--r-- | webkit/glue/simple_webmimeregistry_impl.cc | 41 | ||||
-rw-r--r-- | webkit/glue/simple_webmimeregistry_impl.h | 5 | ||||
-rw-r--r-- | webkit/media/key_systems.cc | 78 | ||||
-rw-r--r-- | webkit/media/key_systems.h | 30 | ||||
-rw-r--r-- | webkit/media/webkit_media.gypi | 2 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.cc | 100 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.h | 17 | ||||
-rw-r--r-- | webkit/tools/layout_tests/test_expectations.txt | 1 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc | 6 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_webmimeregistry_impl.h | 1 |
12 files changed, 283 insertions, 10 deletions
diff --git a/content/worker/worker_webkitplatformsupport_impl.cc b/content/worker/worker_webkitplatformsupport_impl.cc index daa80504..45a2552 100644 --- a/content/worker/worker_webkitplatformsupport_impl.cc +++ b/content/worker/worker_webkitplatformsupport_impl.cc @@ -242,6 +242,13 @@ WorkerWebKitPlatformSupportImpl::supportsMediaMIMEType( } WebMimeRegistry::SupportsType +WorkerWebKitPlatformSupportImpl::supportsMediaMIMEType( + const WebString&, const WebString&, const WebString&) { + NOTREACHED(); + return WebMimeRegistry::IsSupported; +} + +WebMimeRegistry::SupportsType WorkerWebKitPlatformSupportImpl::supportsNonImageMIMEType( const WebString&) { NOTREACHED(); diff --git a/content/worker/worker_webkitplatformsupport_impl.h b/content/worker/worker_webkitplatformsupport_impl.h index 69aea47..339146c 100644 --- a/content/worker/worker_webkitplatformsupport_impl.h +++ b/content/worker/worker_webkitplatformsupport_impl.h @@ -72,8 +72,13 @@ class WorkerWebKitPlatformSupportImpl const WebKit::WebString&); virtual WebKit::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType( const WebKit::WebString&); + // TODO(ddorwin): Remove after http://webk.it/82983 lands. virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( const WebKit::WebString&, const WebKit::WebString&); + virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( + const WebKit::WebString&, + const WebKit::WebString&, + const WebKit::WebString&); virtual WebKit::WebMimeRegistry::SupportsType supportsNonImageMIMEType( const WebKit::WebString&); virtual WebKit::WebString mimeTypeForExtension(const WebKit::WebString&); diff --git a/webkit/glue/simple_webmimeregistry_impl.cc b/webkit/glue/simple_webmimeregistry_impl.cc index 1bc28fa..9a8d212 100644 --- a/webkit/glue/simple_webmimeregistry_impl.cc +++ b/webkit/glue/simple_webmimeregistry_impl.cc @@ -10,6 +10,7 @@ #include "net/base/mime_util.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/media/key_systems.h" using WebKit::WebString; using WebKit::WebMimeRegistry; @@ -45,25 +46,49 @@ WebMimeRegistry::SupportsType WebMimeRegistry::IsSupported : WebMimeRegistry::IsNotSupported; } +// When debugging layout tests failures in the test shell, +// see TestShellWebMimeRegistryImpl. +WebMimeRegistry::SupportsType SimpleWebMimeRegistryImpl::supportsMediaMIMEType( + const WebString& mime_type, const WebString& codecs) { + return supportsMediaMIMEType(mime_type, codecs, WebString()); +} + WebMimeRegistry::SupportsType SimpleWebMimeRegistryImpl::supportsMediaMIMEType( const WebString& mime_type, - const WebString& codecs) { + const WebString& codecs, + const WebString& key_system) { + const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type); // Not supporting the container is a flat-out no. - if (!net::IsSupportedMediaMimeType(ToASCIIOrEmpty(mime_type))) + if (!net::IsSupportedMediaMimeType(mime_type_ascii)) return IsNotSupported; + if (!key_system.isEmpty()) { + // Check whether the key system is supported with the mime_type and codecs. + + // Not supporting the key system is a flat-out no. + if (!webkit_media::IsSupportedKeySystem(key_system)) + return IsNotSupported; + + std::vector<std::string> strict_codecs; + net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, false); + + if (!webkit_media::IsSupportedKeySystemWithMediaMimeType( + mime_type_ascii, strict_codecs, ToASCIIOrEmpty(key_system))) + return IsNotSupported; + + // Continue processing the mime_type and codecs. + } + // Check list of strict codecs to see if it is supported. - if (net::IsStrictMediaMimeType(ToASCIIOrEmpty(mime_type))) { + if (net::IsStrictMediaMimeType(mime_type_ascii)) { // We support the container, but no codecs were specified. if (codecs.isNull()) return MayBeSupported; // Check if the codecs are a perfect match. std::vector<std::string> strict_codecs; - net::ParseCodecString(ToASCIIOrEmpty(codecs).c_str(), &strict_codecs, - false); - if (!net::IsSupportedStrictMediaMimeType(ToASCIIOrEmpty(mime_type), - strict_codecs)) + net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, false); + if (!net::IsSupportedStrictMediaMimeType(mime_type_ascii, strict_codecs)) return IsNotSupported; // Good to go! @@ -72,7 +97,7 @@ WebMimeRegistry::SupportsType SimpleWebMimeRegistryImpl::supportsMediaMIMEType( // If we don't recognize the codec, it's possible we support it. std::vector<std::string> parsed_codecs; - net::ParseCodecString(ToASCIIOrEmpty(codecs).c_str(), &parsed_codecs, true); + net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codecs, true); if (!net::AreSupportedMediaCodecs(parsed_codecs)) return MayBeSupported; diff --git a/webkit/glue/simple_webmimeregistry_impl.h b/webkit/glue/simple_webmimeregistry_impl.h index c106dff..a3a0608 100644 --- a/webkit/glue/simple_webmimeregistry_impl.h +++ b/webkit/glue/simple_webmimeregistry_impl.h @@ -24,8 +24,13 @@ class WEBKIT_GLUE_EXPORT SimpleWebMimeRegistryImpl : const WebKit::WebString&); virtual WebKit::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType( const WebKit::WebString&); + // TODO(ddorwin): Remove after http://webk.it/82983 lands. virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( const WebKit::WebString&, const WebKit::WebString&); + virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( + const WebKit::WebString&, + const WebKit::WebString&, + const WebKit::WebString&); virtual WebKit::WebMimeRegistry::SupportsType supportsNonImageMIMEType( const WebKit::WebString&); virtual WebKit::WebString mimeTypeForExtension(const WebKit::WebString&); diff --git a/webkit/media/key_systems.cc b/webkit/media/key_systems.cc new file mode 100644 index 0000000..7efbb9e --- /dev/null +++ b/webkit/media/key_systems.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/media/key_systems.h" + +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" + +namespace webkit_media { + +namespace { + +const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey"; + +struct MediaFormatAndKeySystem { + const char* mime_type; + const char* codec; + const char* key_system; +}; + +static const MediaFormatAndKeySystem +supported_format_key_system_combinations[] = { + // TODO(ddorwin): Reconsider based on how usage of this class evolves. + // For now, this class is stateless, so we do not have the opportunity to + // build a list using ParseCodecString() like + // net::MimeUtil::InitializeMimeTypeMaps(). Therfore, the following line must + // be separate entries. + // { "video/webm", "vorbis,vp8,vp8.0", kClearKeyKeySystem }, + { "video/webm", "vorbis", kClearKeyKeySystem }, + { "video/webm", "vp8", kClearKeyKeySystem }, + { "video/webm", "vp8.0", kClearKeyKeySystem }, + { "audio/webm", "vorbis", kClearKeyKeySystem }, + { "video/webm", "", kClearKeyKeySystem }, + { "audio/webm", "", kClearKeyKeySystem } +}; + +bool IsSupportedKeySystemWithContainerAndCodec(const std::string& mime_type, + const std::string& codec, + const std::string& key_system) { + for (size_t i = 0; + i < arraysize(supported_format_key_system_combinations); + ++i) { + const MediaFormatAndKeySystem& combination = + supported_format_key_system_combinations[i]; + if (combination.mime_type == mime_type && + combination.codec == codec && + combination.key_system == key_system) + return true; + } + + return false; +} + +} // namespace + +bool IsSupportedKeySystem(const WebKit::WebString& key_system) { + if (key_system == kClearKeyKeySystem) + return true; + return false; +} + +bool IsSupportedKeySystemWithMediaMimeType( + const std::string& mime_type, + const std::vector<std::string>& codecs, + const std::string& key_system) { + if (codecs.empty()) + return IsSupportedKeySystemWithContainerAndCodec(mime_type, "", key_system); + + for (size_t i = 0; i < codecs.size(); ++i) { + if (!IsSupportedKeySystemWithContainerAndCodec( + mime_type, codecs[i], key_system)) + return false; + } + + return true; +} + +} // namespace webkit_media diff --git a/webkit/media/key_systems.h b/webkit/media/key_systems.h new file mode 100644 index 0000000..dedd279 --- /dev/null +++ b/webkit/media/key_systems.h @@ -0,0 +1,30 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_MEDIA_KEY_SYSTEMS_H_ +#define WEBKIT_MEDIA_KEY_SYSTEMS_H_ + +#include <string> +#include <vector> + +namespace WebKit { +class WebString; +} + +namespace webkit_media { + +// Returns whether |key_sytem| is supported at all. +// Call IsSupportedKeySystemWithMediaMimeType() to determine whether a +// |key_system| supports a specific type of media. +bool IsSupportedKeySystem(const WebKit::WebString& key_system); + +// Returns whether |key_sytem| supports the specified media type and codec(s). +bool IsSupportedKeySystemWithMediaMimeType( + const std::string& mime_type, + const std::vector<std::string>& codecs, + const std::string& key_system); + +} // namespace webkit_media + +#endif // WEBKIT_MEDIA_KEY_SYSTEMS_H_ diff --git a/webkit/media/webkit_media.gypi b/webkit/media/webkit_media.gypi index fb62d19..879a423 100644 --- a/webkit/media/webkit_media.gypi +++ b/webkit/media/webkit_media.gypi @@ -25,6 +25,8 @@ 'buffered_resource_loader.h', 'filter_helpers.cc', 'filter_helpers.h', + 'key_systems.cc', + 'key_systems.h', 'media_stream_client.h', 'preload.h', 'skcanvas_video_renderer.cc', diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 2835799..ad74c22 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/message_loop_proxy.h" #include "base/metrics/histogram.h" +#include "base/string_number_conversions.h" #include "base/synchronization/waitable_event.h" #include "media/audio/null_audio_sink.h" #include "media/base/filter_collection.h" @@ -26,10 +27,12 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" #include "v8/include/v8.h" #include "webkit/media/buffered_data_source.h" #include "webkit/media/filter_helpers.h" +#include "webkit/media/key_systems.h" #include "webkit/media/webmediaplayer_delegate.h" #include "webkit/media/webmediaplayer_proxy.h" #include "webkit/media/webvideoframe_impl.h" @@ -38,6 +41,7 @@ using WebKit::WebCanvas; using WebKit::WebMediaPlayer; using WebKit::WebRect; using WebKit::WebSize; +using WebKit::WebString; using media::NetworkEvent; using media::PipelineStatus; @@ -668,6 +672,102 @@ void WebMediaPlayerImpl::sourceEndOfStream( proxy_->DemuxerEndOfStream(pipeline_status); } +WebKit::WebMediaPlayer::MediaKeyException +WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, + const unsigned char* init_data, + unsigned init_data_length) { + if (!IsSupportedKeySystem(key_system)) + return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + // Every request call creates a unique ID. + // TODO(ddorwin): Move this to the CDM implementations since the CDMs may + // create their own IDs and since CDMs supporting multiple renderer processes + // need globally unique IDs. + // Everything from here until the return should probably be handled by + // the decrypter - see http://crbug.com/123260. + static uint32_t next_available_session_id = 1; + uint32_t session_id = next_available_session_id++; + + WebString session_id_string(base::UintToString16(session_id)); + + DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " + << std::string(reinterpret_cast<const char*>(init_data), + static_cast<size_t>(init_data_length)) + << " [" << session_id_string.utf8().data() << "]"; + + // TODO(ddorwin): Generate a key request in the decrypter and fire + // keyMessage when it completes. + // For now, just fire the event with the init_data as the request. + const unsigned char* message = init_data; + unsigned message_length = init_data_length; + + MessageLoop::current()->PostTask(FROM_HERE, base::Bind( + &WebKit::WebMediaPlayerClient::keyMessage, + base::Unretained(GetClient()), + key_system, + session_id_string, + message, + message_length)); + + return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; +} + +WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( + const WebString& key_system, + const unsigned char* key, + unsigned key_length, + const unsigned char* init_data, + unsigned init_data_length, + const WebString& session_id) { + if (!IsSupportedKeySystem(key_system)) + return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + + DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " + << std::string(reinterpret_cast<const char*>(key), + static_cast<size_t>(key_length)) << ", " + << std::string(reinterpret_cast<const char*>(init_data), + static_cast<size_t>(init_data_length)) + << " [" << session_id.utf8().data() << "]"; + + // TODO(ddorwin): Add the key to the decrypter and fire keyAdded when it + // completes. Check the key length there. + // Everything from here until the return should probably be handled by + // the decrypter - see http://crbug.com/123260. + // Temporarily, fire an error for invalid key length so we can test the error + // event and fire the keyAdded event in all other cases. + const unsigned kSupportedKeyLength = 16; // 128-bit key. + if (key_length != kSupportedKeyLength) { + DLOG(ERROR) << "addKey: invalid key length: " << key_length; + MessageLoop::current()->PostTask(FROM_HERE, base::Bind( + &WebKit::WebMediaPlayerClient::keyError, + base::Unretained(GetClient()), + key_system, + session_id, + WebKit::WebMediaPlayerClient::MediaKeyErrorCodeUnknown, + 0)); + } else { + MessageLoop::current()->PostTask(FROM_HERE, base::Bind( + &WebKit::WebMediaPlayerClient::keyAdded, + base::Unretained(GetClient()), + key_system, + session_id)); + } + + return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; +} + +WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( + const WebString& key_system, + const WebString& session_id) { + if (!IsSupportedKeySystem(key_system)) + return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; + + // TODO(ddorwin): Cancel the key request in the decrypter. + + return WebKit::WebMediaPlayer::MediaKeyExceptionNoError; +} + void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { Destroy(); main_loop_ = NULL; diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h index fc803a3..ae1e889 100644 --- a/webkit/media/webmediaplayer_impl.h +++ b/webkit/media/webmediaplayer_impl.h @@ -184,6 +184,23 @@ class WebMediaPlayerImpl virtual bool sourceAppend(const unsigned char* data, unsigned length); virtual void sourceEndOfStream(EndOfStreamStatus status); + virtual MediaKeyException generateKeyRequest( + const WebKit::WebString& key_system, + const unsigned char* init_data, + unsigned init_data_length); + + virtual MediaKeyException addKey(const WebKit::WebString& key_system, + const unsigned char* key, + unsigned key_length, + const unsigned char* init_data, + unsigned init_data_length, + const WebKit::WebString& session_id); + + virtual MediaKeyException cancelKeyRequest( + const WebKit::WebString& key_system, + const WebKit::WebString& session_id); + + // As we are closing the tab or even the browser, |main_loop_| is destroyed // even before this object gets destructed, so we need to know when // |main_loop_| is being destroyed and we can stop posting repaint task diff --git a/webkit/tools/layout_tests/test_expectations.txt b/webkit/tools/layout_tests/test_expectations.txt index 9d262f1..0ed3dbcf 100644 --- a/webkit/tools/layout_tests/test_expectations.txt +++ b/webkit/tools/layout_tests/test_expectations.txt @@ -54,3 +54,4 @@ BUGCR123680 : fast/repaint/shadow-multiple-vertical.html = IMAGE BUGCR123680 : svg/W3C-SVG-1.1/masking-intro-01-f.svg = IMAGE BUGCR123809 : fast/borders/border-radius-groove-02.html = IMAGE +BUGWK82983 : media/encrypted-media/ = PASS diff --git a/webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc b/webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc index ebc19e2..e08842b 100644 --- a/webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc +++ b/webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc @@ -35,7 +35,8 @@ TestShellWebMimeRegistryImpl::~TestShellWebMimeRegistryImpl() {} WebMimeRegistry::SupportsType TestShellWebMimeRegistryImpl::supportsMediaMIMEType( const WebString& mime_type, - const WebString& codecs) { + const WebString& codecs, + const WebKit::WebString& key_system) { if (IsBlacklistedMediaMimeType(ToASCIIOrEmpty(mime_type))) return IsNotSupported; @@ -44,7 +45,8 @@ TestShellWebMimeRegistryImpl::supportsMediaMIMEType( if (HasBlacklistedMediaCodecs(parsed_codecs)) return IsNotSupported; - return SimpleWebMimeRegistryImpl::supportsMediaMIMEType(mime_type, codecs); + return SimpleWebMimeRegistryImpl::supportsMediaMIMEType( + mime_type, codecs, key_system); } bool TestShellWebMimeRegistryImpl::IsBlacklistedMediaMimeType( diff --git a/webkit/tools/test_shell/test_shell_webmimeregistry_impl.h b/webkit/tools/test_shell/test_shell_webmimeregistry_impl.h index 40ac863..6fcff259 100644 --- a/webkit/tools/test_shell/test_shell_webmimeregistry_impl.h +++ b/webkit/tools/test_shell/test_shell_webmimeregistry_impl.h @@ -29,6 +29,7 @@ class TestShellWebMimeRegistryImpl // layout tests. virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( const WebKit::WebString&, + const WebKit::WebString&, const WebKit::WebString&) OVERRIDE; private: |