summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-14 21:22:05 +0000
committerxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-14 21:22:05 +0000
commita941d4e57a9c663e2c9feb3779fef16f8f3f7457 (patch)
tree943ddcf1cce5dfa16131ce1bead16b0955895c38
parentb6b41cca31a6742abf132d4175befa81d359c639 (diff)
downloadchromium_src-a941d4e57a9c663e2c9feb3779fef16f8f3f7457.zip
chromium_src-a941d4e57a9c663e2c9feb3779fef16f8f3f7457.tar.gz
chromium_src-a941d4e57a9c663e2c9feb3779fef16f8f3f7457.tar.bz2
Handle CdmWrapper::Initialize() failure gracefully.
Since CdmWrapper::Initialize() doesn't report error, GenerateKeyRequest() et al can be called even if Initialize() failed previously. For MediaKeys calls, we should fire KeyError when they are called without valid |cdm_|. For Decryptor calls, we should fire the callback with error code. Also added EncryptedMediaTest.ExternalClearKeyInitializeCDMFail test to cover this case. Chrome will claim that the ClearKey CDM supports key system "org.chromium.externalclearkey.fail". But actually ClearKey CDM will return NULL for this key system in CreateCdmInstance(); BUG=306241,179570 TEST=Unit tests added. Review URL: https://codereview.chromium.org/27030007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@228528 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/media/encrypted_media_browsertest.cc11
-rw-r--r--chrome/renderer/media/chrome_key_systems.cc7
-rw-r--r--media/cdm/ppapi/cdm_wrapper.cc41
-rw-r--r--media/cdm/ppapi/clear_key_cdm.cc6
4 files changed, 43 insertions, 22 deletions
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 850d16c..e1e68aa 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -306,3 +306,14 @@ IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, WVParentThrowsException) {
kWebMAudioOnly, "com.widevine", SRC, kEmeGkrException);
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
+
+#if defined(ENABLE_PEPPER_CDMS)
+IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, ExternalClearKeyInitializeCDMFail) {
+ RunEncryptedMediaTest("encrypted_media_player.html",
+ "bear-a-enc_a.webm",
+ kWebMAudioOnly,
+ "org.chromium.externalclearkey.initializefail",
+ SRC,
+ kEmeKeyError);
+}
+#endif // defined(ENABLE_PEPPER_CDMS)
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index 014035d..12dfa92 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -69,10 +69,15 @@ static void AddExternalClearKey(
info.supported_types.push_back(std::make_pair(kAudioMp4, kMp4a));
info.supported_types.push_back(std::make_pair(kVideoMp4, kMp4aAvc1));
#endif // defined(USE_PROPRIETARY_CODECS)
-
info.pepper_type = kExternalClearKeyPepperType;
concrete_key_systems->push_back(info);
+
+ // A key system that Chrome thinks is supported by ClearKeyCdm, but actually
+ // will be refused by ClearKeyCdm. This is to test the CDM initialization
+ // failure case.
+ info.key_system += ".initializefail";
+ concrete_key_systems->push_back(info);
}
#endif // defined(ENABLE_PEPPER_CDMS)
diff --git a/media/cdm/ppapi/cdm_wrapper.cc b/media/cdm/ppapi/cdm_wrapper.cc
index 6d8a788..60a8e44 100644
--- a/media/cdm/ppapi/cdm_wrapper.cc
+++ b/media/cdm/ppapi/cdm_wrapper.cc
@@ -586,6 +586,7 @@ class CdmWrapper : public pp::Instance,
void SendKeyAdded(const std::string& key_system,
const std::string& session_id);
+ // TODO(jrummell): Drop the |key_system| parameter.
void SendKeyErrorInternal(const std::string& key_system,
const std::string& session_id,
cdm::MediaKeyError error_code,
@@ -707,25 +708,29 @@ bool CdmWrapper::CreateCdmInstance(const std::string& key_system) {
return (cdm_ != NULL);
}
+// No KeyErrors should be reported in this function because they cannot be
+// bubbled up in the WD EME API. Those errors will be reported during session
+// creation (aka GenerateKeyRequest).
void CdmWrapper::Initialize(const std::string& key_system,
bool can_challenge_platform) {
PP_DCHECK(!key_system.empty());
PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_));
- if (!cdm_) {
- if (!CreateCdmInstance(key_system)) {
- // TODO(jrummell): Is UnknownKeyError the correct response?
- SendUnknownKeyError(key_system, std::string());
- return;
- }
- }
+ if (!cdm_ && !CreateCdmInstance(key_system))
+ return;
+
PP_DCHECK(cdm_);
key_system_ = key_system;
}
void CdmWrapper::GenerateKeyRequest(const std::string& type,
pp::VarArrayBuffer init_data) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
+ // Initialize() doesn't report an error, so GenerateKeyRequest() can be called
+ // even if Initialize() failed.
+ if (!cdm_) {
+ SendUnknownKeyError(key_system_, std::string());
+ return;
+ }
#if defined(CHECK_DOCUMENT_URL)
PP_URLComponents_Dev url_components = {};
@@ -749,7 +754,8 @@ void CdmWrapper::GenerateKeyRequest(const std::string& type,
void CdmWrapper::AddKey(const std::string& session_id,
pp::VarArrayBuffer key,
pp::VarArrayBuffer init_data) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
+ // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
+ // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
if (!cdm_) {
SendUnknownKeyError(key_system_, session_id);
return;
@@ -779,7 +785,8 @@ void CdmWrapper::AddKey(const std::string& session_id,
}
void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
+ // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
+ // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
if (!cdm_) {
SendUnknownKeyError(key_system_, session_id);
return;
@@ -797,7 +804,6 @@ void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
const PP_EncryptedBlockInfo& encrypted_block_info) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
PP_DCHECK(!encrypted_buffer.is_null());
// Release a buffer that the caller indicated it is finished with.
@@ -827,8 +833,6 @@ void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
void CdmWrapper::InitializeAudioDecoder(
const PP_AudioDecoderConfig& decoder_config,
pp::Buffer_Dev extra_data_buffer) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
-
cdm::Status status = cdm::kSessionError;
if (cdm_) {
cdm::AudioDecoderConfig cdm_decoder_config;
@@ -854,8 +858,6 @@ void CdmWrapper::InitializeAudioDecoder(
void CdmWrapper::InitializeVideoDecoder(
const PP_VideoDecoderConfig& decoder_config,
pp::Buffer_Dev extra_data_buffer) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
-
cdm::Status status = cdm::kSessionError;
if (cdm_) {
cdm::VideoDecoderConfig cdm_decoder_config;
@@ -883,7 +885,7 @@ void CdmWrapper::InitializeVideoDecoder(
void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
uint32_t request_id) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
+ PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
if (cdm_) {
cdm_->DeinitializeDecoder(
PpDecryptorStreamTypeToCdmStreamType(decoder_type));
@@ -897,7 +899,7 @@ void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
uint32_t request_id) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
+ PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
if (cdm_)
cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
@@ -910,8 +912,7 @@ void CdmWrapper::DecryptAndDecode(
PP_DecryptorStreamType decoder_type,
pp::Buffer_Dev encrypted_buffer,
const PP_EncryptedBlockInfo& encrypted_block_info) {
- PP_DCHECK(cdm_); // Initialize() should have succeeded.
-
+ PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
// Release a buffer that the caller indicated it is finished with.
allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
@@ -1027,7 +1028,6 @@ void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
const std::string& session_id,
cdm::MediaKeyError error_code,
uint32_t system_code) {
- PP_DCHECK(!key_system.empty());
PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
SessionInfo(key_system_, session_id),
error_code,
@@ -1063,7 +1063,6 @@ void CdmWrapper::KeyError(int32_t result,
cdm::MediaKeyError error_code,
uint32_t system_code) {
PP_DCHECK(result == PP_OK);
- PP_DCHECK(!session_info.key_system.empty());
pp::ContentDecryptor_Private::KeyError(
session_info.key_system, session_info.session_id,
error_code, system_code);
diff --git a/media/cdm/ppapi/clear_key_cdm.cc b/media/cdm/ppapi/clear_key_cdm.cc
index d6702ca..6ab0773 100644
--- a/media/cdm/ppapi/clear_key_cdm.cc
+++ b/media/cdm/ppapi/clear_key_cdm.cc
@@ -60,6 +60,7 @@ static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries();
#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
const char kClearKeyCdmVersion[] = "0.1.0.1";
+const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
const int64 kSecondsPerMinute = 60;
const int64 kMsPerSecond = 1000;
const int64 kInitialTimerDelayMs = 200;
@@ -130,6 +131,11 @@ void* CreateCdmInstance(
GetCdmHostFunc get_cdm_host_func, void* user_data) {
DVLOG(1) << "CreateCdmInstance()";
+ if (std::string(key_system, key_system_size) != kExternalClearKeyKeySystem) {
+ DVLOG(1) << "Unsupported key system.";
+ return NULL;
+ }
+
if (cdm_interface_version != cdm::kCdmInterfaceVersion)
return NULL;