diff options
Diffstat (limited to 'chromium/content/renderer/media/crypto')
19 files changed, 640 insertions, 3148 deletions
diff --git a/chromium/content/renderer/media/crypto/cdm_initialized_promise.cc b/chromium/content/renderer/media/crypto/cdm_initialized_promise.cc new file mode 100644 index 00000000000..8d9b7afd631 --- /dev/null +++ b/chromium/content/renderer/media/crypto/cdm_initialized_promise.cc @@ -0,0 +1,30 @@ +// Copyright 2015 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 "content/renderer/media/crypto/cdm_initialized_promise.h" + +namespace content { + +CdmInitializedPromise::CdmInitializedPromise( + const media::CdmCreatedCB& cdm_created_cb, + scoped_ptr<media::MediaKeys> cdm) + : cdm_created_cb_(cdm_created_cb), cdm_(cdm.Pass()) { +} + +CdmInitializedPromise::~CdmInitializedPromise() { +} + +void CdmInitializedPromise::resolve() { + MarkPromiseSettled(); + cdm_created_cb_.Run(cdm_.Pass(), ""); +} + +void CdmInitializedPromise::reject(media::MediaKeys::Exception exception_code, + uint32 system_code, + const std::string& error_message) { + MarkPromiseSettled(); + cdm_created_cb_.Run(nullptr, error_message); +} + +} // namespace content diff --git a/chromium/content/renderer/media/crypto/cdm_initialized_promise.h b/chromium/content/renderer/media/crypto/cdm_initialized_promise.h new file mode 100644 index 00000000000..7c3d4c38116 --- /dev/null +++ b/chromium/content/renderer/media/crypto/cdm_initialized_promise.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CONTENT_RENDERER_MEDIA_CRYPTO_CDM_INITIALIZED_PROMISE_H_ +#define CONTENT_RENDERER_MEDIA_CRYPTO_CDM_INITIALIZED_PROMISE_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "media/base/cdm_factory.h" +#include "media/base/cdm_promise.h" +#include "media/base/media_keys.h" + +namespace content { + +// Promise to be resolved when the CDM is initialized. It owns the MediaKeys +// object until the initialization completes, which it then passes to +// |cdm_created_cb|. +class CdmInitializedPromise : public media::SimpleCdmPromise { + public: + CdmInitializedPromise(const media::CdmCreatedCB& cdm_created_cb, + scoped_ptr<media::MediaKeys> cdm); + ~CdmInitializedPromise() override; + + // SimpleCdmPromise implementation. + void resolve() override; + void reject(media::MediaKeys::Exception exception_code, + uint32 system_code, + const std::string& error_message) override; + + private: + media::CdmCreatedCB cdm_created_cb_; + scoped_ptr<media::MediaKeys> cdm_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_CRYPTO_CDM_INITIALIZED_PROMISE_H_ diff --git a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc deleted file mode 100644 index cf24056f14f..00000000000 --- a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc +++ /dev/null @@ -1,475 +0,0 @@ -// Copyright 2014 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 "content/renderer/media/crypto/encrypted_media_player_support_impl.h" - -#include <string> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "content/renderer/media/crypto/key_systems.h" -#include "content/renderer/media/crypto/render_cdm_factory.h" -#include "content/renderer/media/webcontentdecryptionmodule_impl.h" -#include "media/base/bind_to_current_loop.h" -#include "media/blink/encrypted_media_player_support.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" -#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" - -#if defined(ENABLE_PEPPER_CDMS) -#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h" -#elif defined(ENABLE_BROWSER_CDMS) -#error Browser side CDM in WMPI for prefixed EME API not supported yet. -#endif - -using blink::WebMediaPlayer; -using blink::WebMediaPlayerClient; -using blink::WebString; - -namespace content { - -#define BIND_TO_RENDER_LOOP(function) \ - (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) - -#define BIND_TO_RENDER_LOOP1(function, arg1) \ - (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) - -// Prefix for histograms related to Encrypted Media Extensions. -static const char* kMediaEme = "Media.EME."; - -// Used for calls to decryptor_ready_cb where the result can be ignored. -static void DoNothing(bool success) { -} - -// Convert a WebString to ASCII, falling back on an empty string in the case -// of a non-ASCII string. -static std::string ToASCIIOrEmpty(const WebString& string) { - return base::IsStringASCII(string) ? base::UTF16ToASCII(string) - : std::string(); -} - -// Helper functions to report media EME related stats to UMA. They follow the -// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and -// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is -// that UMA_* macros require the names to be constant throughout the process' -// lifetime. -static void EmeUMAHistogramEnumeration(const std::string& key_system, - const std::string& method, - int sample, - int boundary_value) { - base::LinearHistogram::FactoryGet( - kMediaEme + KeySystemNameForUMA(key_system) + "." + method, - 1, boundary_value, boundary_value + 1, - base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); -} - -static void EmeUMAHistogramCounts(const std::string& key_system, - const std::string& method, - int sample) { - // Use the same parameters as UMA_HISTOGRAM_COUNTS. - base::Histogram::FactoryGet( - kMediaEme + KeySystemNameForUMA(key_system) + "." + method, - 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); -} - -// Helper enum for reporting generateKeyRequest/addKey histograms. -enum MediaKeyException { - kUnknownResultId, - kSuccess, - kKeySystemNotSupported, - kInvalidPlayerState, - kMaxMediaKeyException -}; - -static MediaKeyException MediaKeyExceptionForUMA( - WebMediaPlayer::MediaKeyException e) { - switch (e) { - case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported: - return kKeySystemNotSupported; - case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState: - return kInvalidPlayerState; - case WebMediaPlayer::MediaKeyExceptionNoError: - return kSuccess; - default: - return kUnknownResultId; - } -} - -// Helper for converting |key_system| name and exception |e| to a pair of enum -// values from above, for reporting to UMA. -static void ReportMediaKeyExceptionToUMA(const std::string& method, - const std::string& key_system, - WebMediaPlayer::MediaKeyException e) { - MediaKeyException result_id = MediaKeyExceptionForUMA(e); - DCHECK_NE(result_id, kUnknownResultId) << e; - EmeUMAHistogramEnumeration( - key_system, method, result_id, kMaxMediaKeyException); -} - -// Guess the type of |init_data|. This is only used to handle some corner cases -// so we keep it as simple as possible without breaking major use cases. -static std::string GuessInitDataType(const unsigned char* init_data, - unsigned init_data_length) { - // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes. - if (init_data_length == 16) - return "webm"; - - return "cenc"; -} - -scoped_ptr<media::EncryptedMediaPlayerSupport> -EncryptedMediaPlayerSupportImpl::Create(blink::WebMediaPlayerClient* client) { - return scoped_ptr<EncryptedMediaPlayerSupport>( - new EncryptedMediaPlayerSupportImpl(client)); -} - -EncryptedMediaPlayerSupportImpl::EncryptedMediaPlayerSupportImpl( - blink::WebMediaPlayerClient* client) - : client_(client), - web_cdm_(NULL) { -} - -EncryptedMediaPlayerSupportImpl::~EncryptedMediaPlayerSupportImpl() { -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::GenerateKeyRequest( - blink::WebLocalFrame* frame, - const WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": " - << std::string(reinterpret_cast<const char*>(init_data), - static_cast<size_t>(init_data_length)); - - std::string ascii_key_system = - GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - - WebMediaPlayer::MediaKeyException e = - GenerateKeyRequestInternal(frame, ascii_key_system, init_data, - init_data_length); - ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::GenerateKeyRequestInternal( - blink::WebLocalFrame* frame, - const std::string& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - if (!IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - // We do not support run-time switching between key systems for now. - if (current_key_system_.empty()) { - if (!proxy_decryptor_) { - proxy_decryptor_.reset(new ProxyDecryptor( - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyAdded), - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyError), - BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyMessage))); - } - - GURL security_origin(frame->document().securityOrigin().toString()); - -#if defined(ENABLE_PEPPER_CDMS) - RenderCdmFactory cdm_factory( - base::Bind(&PepperCdmWrapperImpl::Create, frame)); -#else - RenderCdmFactory cdm_factory; -#endif - - if (!proxy_decryptor_->InitializeCDM(&cdm_factory, key_system, - security_origin)) { - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - } - - if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing)); - } - - current_key_system_ = key_system; - } else if (key_system != current_key_system_) { - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - } - - std::string init_data_type = init_data_type_; - if (init_data_type.empty()) - init_data_type = GuessInitDataType(init_data, init_data_length); - - // TODO(xhwang): We assume all streams are from the same container (thus have - // the same "type") for now. In the future, the "type" should be passed down - // from the application. - if (!proxy_decryptor_->GenerateKeyRequest( - init_data_type, init_data, init_data_length)) { - current_key_system_.clear(); - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - } - - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -WebMediaPlayer::MediaKeyException EncryptedMediaPlayerSupportImpl::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) { - DVLOG(1) << "addKey: " << base::string16(key_system) << ": " - << 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)) << " [" - << base::string16(session_id) << "]"; - - std::string ascii_key_system = - GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - std::string ascii_session_id = ToASCIIOrEmpty(session_id); - - WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system, - key, - key_length, - init_data, - init_data_length, - ascii_session_id); - ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::AddKeyInternal( - const std::string& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const std::string& session_id) { - DCHECK(key); - DCHECK_GT(key_length, 0u); - - if (!IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - if (current_key_system_.empty() || key_system != current_key_system_) - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - - proxy_decryptor_->AddKey( - key, key_length, init_data, init_data_length, session_id); - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::CancelKeyRequest( - const WebString& key_system, - const WebString& session_id) { - DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": " - << " [" << base::string16(session_id) << "]"; - - std::string ascii_key_system = - GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system)); - std::string ascii_session_id = ToASCIIOrEmpty(session_id); - - WebMediaPlayer::MediaKeyException e = - CancelKeyRequestInternal(ascii_key_system, ascii_session_id); - ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e); - return e; -} - -WebMediaPlayer::MediaKeyException -EncryptedMediaPlayerSupportImpl::CancelKeyRequestInternal( - const std::string& key_system, - const std::string& session_id) { - if (!IsConcreteSupportedKeySystem(key_system)) - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; - - if (current_key_system_.empty() || key_system != current_key_system_) - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; - - proxy_decryptor_->CancelKeyRequest(session_id); - return WebMediaPlayer::MediaKeyExceptionNoError; -} - -void EncryptedMediaPlayerSupportImpl::SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) { - // Used when loading media and no pipeline/decoder attached yet. - DCHECK(decryptor_ready_cb_.is_null()); - - web_cdm_ = ToWebContentDecryptionModuleImpl(initial_cdm); -} - -void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) - return; - - web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); -} - -void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324 - if (!cdm) { - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Null MediaKeys object is not supported."); - return; - } - - web_cdm_ = ToWebContentDecryptionModuleImpl(cdm); - - if (web_cdm_ && !decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(web_cdm_->GetDecryptor(), BIND_TO_RENDER_LOOP1( - &EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached, - result)); - } else { - // No pipeline/decoder connected, so resolve the promise. When something - // is connected, setting the CDM will happen in SetDecryptorReadyCB(). - ContentDecryptionModuleAttached(result, true); - } -} - -void EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success) { - if (success) { - result.complete(); - return; - } - - result.completeWithError( - blink::WebContentDecryptionModuleExceptionNotSupportedError, - 0, - "Unable to set MediaKeys object"); -} - -media::SetDecryptorReadyCB -EncryptedMediaPlayerSupportImpl::CreateSetDecryptorReadyCB() { - return BIND_TO_RENDER_LOOP( - &EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB); -} - -media::Demuxer::NeedKeyCB -EncryptedMediaPlayerSupportImpl::CreateNeedKeyCB() { - return BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnNeedKey); -} - -void EncryptedMediaPlayerSupportImpl::OnPipelineDecryptError() { - EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1); -} - -void EncryptedMediaPlayerSupportImpl::OnNeedKey(const std::string& type, - const std::vector<uint8>& init_data) { - // Do not fire NeedKey event if encrypted media is not enabled. - if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() && - !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) { - return; - } - - UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1); - - DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); - if (init_data_type_.empty()) - init_data_type_ = type; - - const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; - client_->encrypted( - WebString::fromUTF8(type), init_data_ptr, init_data.size()); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyAdded( - const std::string& session_id) { - EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1); - client_->keyAdded( - WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id)); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code) { - EmeUMAHistogramEnumeration(current_key_system_, "KeyError", - error_code, media::MediaKeys::kMaxKeyError); - - uint16 short_system_code = 0; - if (system_code > std::numeric_limits<uint16>::max()) { - LOG(WARNING) << "system_code exceeds unsigned short limit."; - short_system_code = std::numeric_limits<uint16>::max(); - } else { - short_system_code = static_cast<uint16>(system_code); - } - - client_->keyError( - WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id), - static_cast<WebMediaPlayerClient::MediaKeyErrorCode>(error_code), - short_system_code); -} - -void EncryptedMediaPlayerSupportImpl::OnKeyMessage( - const std::string& session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { - DCHECK(destination_url.is_empty() || destination_url.is_valid()); - - client_->keyMessage( - WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)), - WebString::fromUTF8(session_id), - message.empty() ? NULL : &message[0], - message.size(), - destination_url); -} - -void EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB( - const media::DecryptorReadyCB& decryptor_ready_cb) { - // Cancels the previous decryptor request. - if (decryptor_ready_cb.is_null()) { - if (!decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&decryptor_ready_cb_) - .Run(NULL, base::Bind(DoNothing)); - } - return; - } - - // TODO(xhwang): Support multiple decryptor notification request (e.g. from - // video and audio). The current implementation is okay for the current - // media pipeline since we initialize audio and video decoders in sequence. - // But WebMediaPlayerImpl should not depend on media pipeline's implementation - // detail. - DCHECK(decryptor_ready_cb_.is_null()); - - // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink. - DCHECK(!proxy_decryptor_ || !web_cdm_); - - if (proxy_decryptor_) { - decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(), - base::Bind(DoNothing)); - return; - } - - if (web_cdm_) { - decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing)); - return; - } - - decryptor_ready_cb_ = decryptor_ready_cb; -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h deleted file mode 100644 index d68d40b7d5a..00000000000 --- a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2014 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 CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ - -#include <string> -#include <vector> - -#include "base/memory/weak_ptr.h" -#include "content/renderer/media/crypto/proxy_decryptor.h" -#include "media/blink/encrypted_media_player_support.h" - -namespace blink { -class WebMediaPlayerClient; -} - -namespace content { - -class WebContentDecryptionModuleImpl; - -class EncryptedMediaPlayerSupportImpl - : public media::EncryptedMediaPlayerSupport, - public base::SupportsWeakPtr<EncryptedMediaPlayerSupportImpl> { - public: - static scoped_ptr<EncryptedMediaPlayerSupport> Create( - blink::WebMediaPlayerClient* client); - - ~EncryptedMediaPlayerSupportImpl() override; - - // EncryptedMediaPlayerSupport implementation. - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( - blink::WebLocalFrame* frame, - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) override; - - blink::WebMediaPlayer::MediaKeyException AddKey( - const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id) override; - - blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id) override; - - void SetInitialContentDecryptionModule( - blink::WebContentDecryptionModule* initial_cdm) override; - - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) override; - void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) override; - - media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() override; - media::Demuxer::NeedKeyCB CreateNeedKeyCB() override; - - void OnPipelineDecryptError() override; - - private: - explicit EncryptedMediaPlayerSupportImpl(blink::WebMediaPlayerClient* client); - - // Requests that this object notifies when a decryptor is ready through the - // |decryptor_ready_cb| provided. - // If |decryptor_ready_cb| is null, the existing callback will be fired with - // NULL immediately and reset. - void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb); - - blink::WebMediaPlayer::MediaKeyException GenerateKeyRequestInternal( - blink::WebLocalFrame* frame, - const std::string& key_system, - const unsigned char* init_data, - unsigned init_data_length); - - blink::WebMediaPlayer::MediaKeyException AddKeyInternal( - const std::string& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const std::string& session_id); - - blink::WebMediaPlayer::MediaKeyException CancelKeyRequestInternal( - const std::string& key_system, - const std::string& session_id); - - void OnNeedKey(const std::string& type, - const std::vector<uint8>& init_data); - - void OnKeyAdded(const std::string& session_id); - void OnKeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code); - void OnKeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const GURL& destination_url); - - void ContentDecryptionModuleAttached( - blink::WebContentDecryptionModuleResult result, - bool success); - - blink::WebMediaPlayerClient* client_; - - // The currently selected key system. Empty string means that no key system - // has been selected. - std::string current_key_system_; - - // Temporary for EME v0.1. In the future the init data type should be passed - // through GenerateKeyRequest() directly from WebKit. - std::string init_data_type_; - - // Manages decryption keys and decrypts encrypted frames. - scoped_ptr<ProxyDecryptor> proxy_decryptor_; - - // Non-owned pointer to the CDM. Updated via calls to - // setContentDecryptionModule(). - WebContentDecryptionModuleImpl* web_cdm_; - - media::DecryptorReadyCB decryptor_ready_cb_; - - DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupportImpl); -}; -} - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_ diff --git a/chromium/content/renderer/media/crypto/key_systems.cc b/chromium/content/renderer/media/crypto/key_systems.cc deleted file mode 100644 index 9c3ce046ab6..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems.cc +++ /dev/null @@ -1,650 +0,0 @@ -// Copyright 2013 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 "content/renderer/media/crypto/key_systems.h" - -#include <string> - -#include "base/containers/hash_tables.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "content/public/common/content_client.h" -#include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/media/crypto/key_systems_support_uma.h" -#include "media/base/eme_constants.h" -#include "media/base/key_system_info.h" - -#if defined(OS_ANDROID) -#include "media/base/android/media_codec_bridge.h" -#endif - -#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. - -namespace content { - -using media::EmeCodec; -using media::EmeInitDataType; -using media::KeySystemInfo; -using media::SupportedInitDataTypes; -using media::SupportedCodecs; - -const char kClearKeyKeySystem[] = "org.w3.clearkey"; -const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey"; -const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey"; - -struct NamedInitDataType { - const char* name; - EmeInitDataType type; -}; - -// Mapping between initialization data types names and enum values. When adding -// entries, make sure to update IsSaneInitDataTypeWithContainer(). -static NamedInitDataType kInitDataTypeNames[] = { - {"webm", media::EME_INIT_DATA_TYPE_WEBM}, -#if defined(USE_PROPRIETARY_CODECS) - {"cenc", media::EME_INIT_DATA_TYPE_CENC} -#endif // defined(USE_PROPRIETARY_CODECS) -}; - -struct NamedCodec { - const char* name; - EmeCodec type; -}; - -// Mapping between containers and their codecs. -// Only audio codec can belong to a "audio/*" container. Both audio and video -// codecs can belong to a "video/*" container. -static NamedCodec kContainerToCodecMasks[] = { - {"audio/webm", media::EME_CODEC_WEBM_AUDIO_ALL}, - {"video/webm", media::EME_CODEC_WEBM_ALL}, -#if defined(USE_PROPRIETARY_CODECS) - {"audio/mp4", media::EME_CODEC_MP4_AUDIO_ALL}, - {"video/mp4", media::EME_CODEC_MP4_ALL} -#endif // defined(USE_PROPRIETARY_CODECS) -}; - -// Mapping between codec names and enum values. -static NamedCodec kCodecStrings[] = { - {"vorbis", media::EME_CODEC_WEBM_VORBIS}, - {"vp8", media::EME_CODEC_WEBM_VP8}, - {"vp8.0", media::EME_CODEC_WEBM_VP8}, - {"vp9", media::EME_CODEC_WEBM_VP9}, - {"vp9.0", media::EME_CODEC_WEBM_VP9}, -#if defined(USE_PROPRIETARY_CODECS) - {"mp4a", media::EME_CODEC_MP4_AAC}, - {"avc1", media::EME_CODEC_MP4_AVC1}, - {"avc3", media::EME_CODEC_MP4_AVC1} -#endif // defined(USE_PROPRIETARY_CODECS) -}; - -static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { - KeySystemInfo info(kClearKeyKeySystem); - - // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec: - // http://developer.android.com/guide/appendix/media-formats.html - // VP9 support is device dependent. - - info.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM; - info.supported_codecs = media::EME_CODEC_WEBM_ALL; - -#if defined(OS_ANDROID) - // Temporarily disable VP9 support for Android. - // TODO(xhwang): Use mime_util.h to query VP9 support on Android. - info.supported_codecs &= ~media::EME_CODEC_WEBM_VP9; -#endif // defined(OS_ANDROID) - -#if defined(USE_PROPRIETARY_CODECS) - info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC; - info.supported_codecs |= media::EME_CODEC_MP4_ALL; -#endif // defined(USE_PROPRIETARY_CODECS) - - info.use_aes_decryptor = true; - - concrete_key_systems->push_back(info); -} - -class KeySystems { - public: - static KeySystems& GetInstance(); - - void UpdateIfNeeded(); - - bool IsConcreteSupportedKeySystem(const std::string& key_system); - - bool IsSupportedKeySystem(const std::string& key_system); - - bool IsSupportedKeySystemWithInitDataType( - const std::string& key_system, - const std::string& init_data_type); - - bool IsSupportedKeySystemWithMediaMimeType( - const std::string& mime_type, - const std::vector<std::string>& codecs, - const std::string& key_system); - - bool UseAesDecryptor(const std::string& concrete_key_system); - -#if defined(ENABLE_PEPPER_CDMS) - std::string GetPepperType(const std::string& concrete_key_system); -#endif - - void AddContainerMask(const std::string& container, uint32 mask); - void AddCodecMask(const std::string& codec, uint32 mask); - - private: - void UpdateSupportedKeySystems(); - - void AddConcreteSupportedKeySystems( - const std::vector<KeySystemInfo>& concrete_key_systems); - - void AddConcreteSupportedKeySystem( - const std::string& key_system, - bool use_aes_decryptor, -#if defined(ENABLE_PEPPER_CDMS) - const std::string& pepper_type, -#endif - SupportedInitDataTypes supported_init_data_types, - SupportedCodecs supported_codecs, - const std::string& parent_key_system); - - friend struct base::DefaultLazyInstanceTraits<KeySystems>; - - struct KeySystemProperties { - KeySystemProperties() - : use_aes_decryptor(false), supported_codecs(media::EME_CODEC_NONE) {} - - bool use_aes_decryptor; -#if defined(ENABLE_PEPPER_CDMS) - std::string pepper_type; -#endif - SupportedInitDataTypes supported_init_data_types; - SupportedCodecs supported_codecs; - }; - - typedef base::hash_map<std::string, KeySystemProperties> - KeySystemPropertiesMap; - typedef base::hash_map<std::string, std::string> ParentKeySystemMap; - typedef base::hash_map<std::string, SupportedCodecs> ContainerCodecsMap; - typedef base::hash_map<std::string, EmeCodec> CodecsMap; - typedef base::hash_map<std::string, media::EmeInitDataType> InitDataTypesMap; - - KeySystems(); - ~KeySystems() {} - - EmeInitDataType GetInitDataTypeForName( - const std::string& init_data_type) const; - // TODO(sandersd): Separate container enum from codec mask value. - // http://crbug.com/417440 - SupportedCodecs GetCodecMaskForContainer( - const std::string& container) const; - EmeCodec GetCodecForString(const std::string& codec) const; - - const std::string& GetConcreteKeySystemName( - const std::string& key_system) const; - - // Returns whether a |container| type is supported by checking - // |key_system_supported_codecs|. - // TODO(xhwang): Update this to actually check initDataType support. - bool IsSupportedContainer(const std::string& container, - SupportedCodecs key_system_supported_codecs) const; - - // Returns true if all |codecs| are supported in |container| by checking - // |key_system_supported_codecs|. - bool IsSupportedContainerAndCodecs( - const std::string& container, - const std::vector<std::string>& codecs, - SupportedCodecs key_system_supported_codecs) const; - - // Map from key system string to capabilities. - KeySystemPropertiesMap concrete_key_system_map_; - - // Map from parent key system to the concrete key system that should be used - // to represent its capabilities. - ParentKeySystemMap parent_key_system_map_; - - KeySystemsSupportUMA key_systems_support_uma_; - - InitDataTypesMap init_data_type_name_map_; - ContainerCodecsMap container_to_codec_mask_map_; - CodecsMap codec_string_map_; - - bool needs_update_; - base::Time last_update_time_; - - // Makes sure all methods are called from the same thread. - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(KeySystems); -}; - -static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER; - -KeySystems& KeySystems::GetInstance() { - KeySystems& key_systems = g_key_systems.Get(); - key_systems.UpdateIfNeeded(); - return key_systems; -} - -// Because we use a LazyInstance, the key systems info must be populated when -// the instance is lazily initiated. -KeySystems::KeySystems() : needs_update_(true) { - for (size_t i = 0; i < arraysize(kInitDataTypeNames); ++i) { - const std::string& name = kInitDataTypeNames[i].name; - DCHECK(!init_data_type_name_map_.count(name)); - init_data_type_name_map_[name] = kInitDataTypeNames[i].type; - } - for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) { - const std::string& name = kContainerToCodecMasks[i].name; - DCHECK(!container_to_codec_mask_map_.count(name)); - container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type; - } - for (size_t i = 0; i < arraysize(kCodecStrings); ++i) { - const std::string& name = kCodecStrings[i].name; - DCHECK(!codec_string_map_.count(name)); - codec_string_map_[name] = kCodecStrings[i].type; - } - - UpdateSupportedKeySystems(); - -#if defined(WIDEVINE_CDM_AVAILABLE) - key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem); -#endif // defined(WIDEVINE_CDM_AVAILABLE) -} - -EmeInitDataType KeySystems::GetInitDataTypeForName( - const std::string& init_data_type) const { - InitDataTypesMap::const_iterator iter = - init_data_type_name_map_.find(init_data_type); - if (iter != init_data_type_name_map_.end()) - return iter->second; - return media::EME_INIT_DATA_TYPE_NONE; -} - -SupportedCodecs KeySystems::GetCodecMaskForContainer( - const std::string& container) const { - ContainerCodecsMap::const_iterator iter = - container_to_codec_mask_map_.find(container); - if (iter != container_to_codec_mask_map_.end()) - return iter->second; - return media::EME_CODEC_NONE; -} - -EmeCodec KeySystems::GetCodecForString(const std::string& codec) const { - CodecsMap::const_iterator iter = codec_string_map_.find(codec); - if (iter != codec_string_map_.end()) - return iter->second; - return media::EME_CODEC_NONE; -} - -const std::string& KeySystems::GetConcreteKeySystemName( - const std::string& key_system) const { - ParentKeySystemMap::const_iterator iter = - parent_key_system_map_.find(key_system); - if (iter != parent_key_system_map_.end()) - return iter->second; - return key_system; -} - -void KeySystems::UpdateIfNeeded() { -#if defined(WIDEVINE_CDM_AVAILABLE) - DCHECK(thread_checker_.CalledOnValidThread()); - if (!needs_update_) - return; - - // The update could involve a sync IPC to the browser process. Use a minimum - // update interval to avoid unnecessary frequent IPC to the browser. - static const int kMinUpdateIntervalInSeconds = 1; - base::Time now = base::Time::Now(); - if (now - last_update_time_ < - base::TimeDelta::FromSeconds(kMinUpdateIntervalInSeconds)) { - return; - } - - UpdateSupportedKeySystems(); -#endif -} - -void KeySystems::UpdateSupportedKeySystems() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(needs_update_); - concrete_key_system_map_.clear(); - parent_key_system_map_.clear(); - - // Build KeySystemInfo. - std::vector<KeySystemInfo> key_systems_info; - GetContentClient()->renderer()->AddKeySystems(&key_systems_info); - // Clear Key is always supported. - AddClearKey(&key_systems_info); - - AddConcreteSupportedKeySystems(key_systems_info); - -#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT) - if (IsConcreteSupportedKeySystem(kWidevineKeySystem)) - needs_update_ = false; -#endif - - last_update_time_ = base::Time::Now(); -} - -void KeySystems::AddConcreteSupportedKeySystems( - const std::vector<KeySystemInfo>& concrete_key_systems) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(concrete_key_system_map_.empty()); - DCHECK(parent_key_system_map_.empty()); - - for (size_t i = 0; i < concrete_key_systems.size(); ++i) { - const KeySystemInfo& key_system_info = concrete_key_systems[i]; - AddConcreteSupportedKeySystem(key_system_info.key_system, - key_system_info.use_aes_decryptor, -#if defined(ENABLE_PEPPER_CDMS) - key_system_info.pepper_type, -#endif - key_system_info.supported_init_data_types, - key_system_info.supported_codecs, - key_system_info.parent_key_system); - } -} - -void KeySystems::AddConcreteSupportedKeySystem( - const std::string& concrete_key_system, - bool use_aes_decryptor, -#if defined(ENABLE_PEPPER_CDMS) - const std::string& pepper_type, -#endif - SupportedInitDataTypes supported_init_data_types, - SupportedCodecs supported_codecs, - const std::string& parent_key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system)) - << "Key system '" << concrete_key_system << "' already registered"; - DCHECK(!parent_key_system_map_.count(concrete_key_system)) - << "'" << concrete_key_system << " is already registered as a parent"; - - KeySystemProperties properties; - properties.use_aes_decryptor = use_aes_decryptor; -#if defined(ENABLE_PEPPER_CDMS) - DCHECK_EQ(use_aes_decryptor, pepper_type.empty()); - properties.pepper_type = pepper_type; -#endif - - properties.supported_init_data_types = supported_init_data_types; - properties.supported_codecs = supported_codecs; - - concrete_key_system_map_[concrete_key_system] = properties; - - if (!parent_key_system.empty()) { - DCHECK(!IsConcreteSupportedKeySystem(parent_key_system)) - << "Parent '" << parent_key_system << "' already registered concrete"; - DCHECK(!parent_key_system_map_.count(parent_key_system)) - << "Parent '" << parent_key_system << "' already registered"; - parent_key_system_map_[parent_key_system] = concrete_key_system; - } -} - -bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - return concrete_key_system_map_.count(key_system) != 0; -} - -bool KeySystems::IsSupportedContainer( - const std::string& container, - SupportedCodecs key_system_supported_codecs) const { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!container.empty()); - - // When checking container support for EME, "audio/foo" should be treated the - // same as "video/foo". Convert the |container| to achieve this. - // TODO(xhwang): Replace this with real checks against supported initDataTypes - // combined with supported demuxers. - std::string canonical_container = container; - if (container.find("audio/") == 0) - canonical_container.replace(0, 6, "video/"); - - // A container is supported iif at least one codec in that container is - // supported. - SupportedCodecs supported_codecs = - GetCodecMaskForContainer(canonical_container); - return (supported_codecs & key_system_supported_codecs) != 0; -} - -bool KeySystems::IsSupportedContainerAndCodecs( - const std::string& container, - const std::vector<std::string>& codecs, - SupportedCodecs key_system_supported_codecs) const { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!container.empty()); - DCHECK(!codecs.empty()); - DCHECK(IsSupportedContainer(container, key_system_supported_codecs)); - - SupportedCodecs container_supported_codecs = - GetCodecMaskForContainer(container); - - for (size_t i = 0; i < codecs.size(); ++i) { - // TODO(sandersd): This should fail for isTypeSupported(). - // http://crbug.com/417461 - if (codecs[i].empty()) - continue; - - EmeCodec codec = GetCodecForString(codecs[i]); - - // Unsupported codec. - if (!(codec & key_system_supported_codecs)) - return false; - - // Unsupported codec/container combination, e.g. "video/webm" and "avc1". - if (!(codec & container_supported_codecs)) - return false; - } - - return true; -} - -bool KeySystems::IsSupportedKeySystem(const std::string& key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - return (concrete_key_system_map_.count(key_system) || - parent_key_system_map_.count(key_system)); -} - -bool KeySystems::IsSupportedKeySystemWithInitDataType( - const std::string& key_system, - const std::string& init_data_type) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // If |key_system| is a parent key system, use its concrete child. - const std::string& concrete_key_system = GetConcreteKeySystemName(key_system); - - // Locate |concrete_key_system|. - KeySystemPropertiesMap::const_iterator key_system_iter = - concrete_key_system_map_.find(concrete_key_system); - if (key_system_iter == concrete_key_system_map_.end()) - return false; - - // Check |init_data_type| and |key_system| x |init_data_type|. - const KeySystemProperties& properties = key_system_iter->second; - EmeInitDataType eme_init_data_type = GetInitDataTypeForName(init_data_type); - return (properties.supported_init_data_types & eme_init_data_type) != 0; -} - -// TODO(sandersd): Reorganize to be more similar to -// IsKeySystemSupportedWithInitDataType(). Note that a fork may still be -// required; http://crbug.com/417461. -bool KeySystems::IsSupportedKeySystemWithMediaMimeType( - const std::string& mime_type, - const std::vector<std::string>& codecs, - const std::string& key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // If |key_system| is a parent key system, use its concrete child. - const std::string& concrete_key_system = GetConcreteKeySystemName(key_system); - - bool has_type = !mime_type.empty(); - - key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type); - - // Check key system support. - KeySystemPropertiesMap::const_iterator key_system_iter = - concrete_key_system_map_.find(concrete_key_system); - if (key_system_iter == concrete_key_system_map_.end()) - return false; - - key_systems_support_uma_.ReportKeySystemSupport(key_system, false); - - if (!has_type) { - DCHECK(codecs.empty()); - return true; - } - - SupportedCodecs key_system_supported_codecs = - key_system_iter->second.supported_codecs; - - if (!IsSupportedContainer(mime_type, key_system_supported_codecs)) - return false; - - if (!codecs.empty() && - !IsSupportedContainerAndCodecs( - mime_type, codecs, key_system_supported_codecs)) { - return false; - } - - key_systems_support_uma_.ReportKeySystemSupport(key_system, true); - return true; -} - -bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - - KeySystemPropertiesMap::const_iterator key_system_iter = - concrete_key_system_map_.find(concrete_key_system); - if (key_system_iter == concrete_key_system_map_.end()) { - DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; - return false; - } - - return key_system_iter->second.use_aes_decryptor; -} - -#if defined(ENABLE_PEPPER_CDMS) -std::string KeySystems::GetPepperType(const std::string& concrete_key_system) { - DCHECK(thread_checker_.CalledOnValidThread()); - - KeySystemPropertiesMap::const_iterator key_system_iter = - concrete_key_system_map_.find(concrete_key_system); - if (key_system_iter == concrete_key_system_map_.end()) { - DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; - return std::string(); - } - - const std::string& type = key_system_iter->second.pepper_type; - DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based"; - return type; -} -#endif - -void KeySystems::AddContainerMask(const std::string& container, uint32 mask) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!container_to_codec_mask_map_.count(container)); - container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask); -} - -void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!codec_string_map_.count(codec)); - codec_string_map_[codec] = static_cast<EmeCodec>(mask); -} - -//------------------------------------------------------------------------------ - -std::string GetUnprefixedKeySystemName(const std::string& key_system) { - if (key_system == kClearKeyKeySystem) - return kUnsupportedClearKeyKeySystem; - - if (key_system == kPrefixedClearKeyKeySystem) - return kClearKeyKeySystem; - - return key_system; -} - -std::string GetPrefixedKeySystemName(const std::string& key_system) { - DCHECK_NE(key_system, kPrefixedClearKeyKeySystem); - - if (key_system == kClearKeyKeySystem) - return kPrefixedClearKeyKeySystem; - - return key_system; -} - -bool IsSaneInitDataTypeWithContainer( - const std::string& init_data_type, - const std::string& container) { - if (init_data_type == "cenc") { - return container == "audio/mp4" || container == "video/mp4"; - } else if (init_data_type == "webm") { - return container == "audio/webm" || container == "video/webm"; - } else { - return true; - } -} - -bool IsConcreteSupportedKeySystem(const std::string& key_system) { - return KeySystems::GetInstance().IsConcreteSupportedKeySystem(key_system); -} - -bool IsSupportedKeySystem(const std::string& key_system) { - return KeySystems::GetInstance().IsSupportedKeySystem(key_system); -} - -bool IsSupportedKeySystemWithInitDataType( - const std::string& key_system, - const std::string& init_data_type) { - return KeySystems::GetInstance().IsSupportedKeySystemWithInitDataType( - key_system, init_data_type); -} - -bool IsSupportedKeySystemWithMediaMimeType( - const std::string& mime_type, - const std::vector<std::string>& codecs, - const std::string& key_system) { - return KeySystems::GetInstance().IsSupportedKeySystemWithMediaMimeType( - mime_type, codecs, key_system); -} - -std::string KeySystemNameForUMA(const std::string& key_system) { - if (key_system == kClearKeyKeySystem) - return "ClearKey"; -#if defined(WIDEVINE_CDM_AVAILABLE) - if (key_system == kWidevineKeySystem) - return "Widevine"; -#endif // WIDEVINE_CDM_AVAILABLE - return "Unknown"; -} - -bool CanUseAesDecryptor(const std::string& concrete_key_system) { - return KeySystems::GetInstance().UseAesDecryptor(concrete_key_system); -} - -#if defined(ENABLE_PEPPER_CDMS) -std::string GetPepperType(const std::string& concrete_key_system) { - return KeySystems::GetInstance().GetPepperType(concrete_key_system); -} -#endif - -// These two functions are for testing purpose only. The declaration in the -// header file is guarded by "#if defined(UNIT_TEST)" so that they can be used -// by tests but not non-test code. However, this .cc file is compiled as part of -// "content" where "UNIT_TEST" is not defined. So we need to specify -// "CONTENT_EXPORT" here again so that they are visible to tests. - -CONTENT_EXPORT void AddContainerMask(const std::string& container, - uint32 mask) { - KeySystems::GetInstance().AddContainerMask(container, mask); -} - -CONTENT_EXPORT void AddCodecMask(const std::string& codec, uint32 mask) { - KeySystems::GetInstance().AddCodecMask(codec, mask); -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/key_systems.h b/chromium/content/renderer/media/crypto/key_systems.h deleted file mode 100644 index 03d40024579..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_H_ - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "content/common/content_export.h" - -namespace content { - -// Prefixed EME API only supports prefixed (webkit-) key system name for -// certain key systems. But internally only unprefixed key systems are -// supported. The following two functions help convert between prefixed and -// unprefixed key system names. - -// Gets the unprefixed key system name for |key_system|. -std::string GetUnprefixedKeySystemName(const std::string& key_system); - -// Gets the prefixed key system name for |key_system|. -std::string GetPrefixedKeySystemName(const std::string& key_system); - -// Returns false if a container-specific |init_data_type| is specified with an -// inappropriate container. -// TODO(sandersd): Remove this essentially internal detail if the spec is -// updated to not convolve the two in a single method call. -// TODO(sandersd): Use enum values instead of strings. http://crbug.com/417440 -bool IsSaneInitDataTypeWithContainer( - const std::string& init_data_type, - const std::string& container); - -// Note: Shouldn't be used for prefixed API as the original -// IsSupportedKeySystemWithMediaMimeType() path reports UMAs, but this path does -// not. -bool IsSupportedKeySystem(const std::string& key_system); - -bool IsSupportedKeySystemWithInitDataType( - const std::string& key_system, - const std::string& init_data_type); - -// Returns whether |key_system| is a real supported key system that can be -// instantiated. -// Abstract parent |key_system| strings will return false. -// Call IsSupportedKeySystemWithMediaMimeType() to determine whether a -// |key_system| supports a specific type of media or to check parent key -// systems. -CONTENT_EXPORT bool IsConcreteSupportedKeySystem(const std::string& key_system); - -// Returns whether |key_sytem| supports the specified media type and codec(s). -CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType( - const std::string& mime_type, - const std::vector<std::string>& codecs, - const std::string& key_system); - -// Returns a name for |key_system| suitable to UMA logging. -CONTENT_EXPORT std::string KeySystemNameForUMA(const std::string& key_system); - -// Returns whether AesDecryptor can be used for the given |concrete_key_system|. -CONTENT_EXPORT bool CanUseAesDecryptor(const std::string& concrete_key_system); - -#if defined(ENABLE_PEPPER_CDMS) -// Returns the Pepper MIME type for |concrete_key_system|. -// Returns empty string if |concrete_key_system| is unknown or not Pepper-based. -CONTENT_EXPORT std::string GetPepperType( - const std::string& concrete_key_system); -#endif - -#if defined(UNIT_TEST) -// Helper functions to add container/codec types for testing purposes. -CONTENT_EXPORT void AddContainerMask(const std::string& container, uint32 mask); -CONTENT_EXPORT void AddCodecMask(const std::string& codec, uint32 mask); -#endif // defined(UNIT_TEST) - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_H_ diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc deleted file mode 100644 index bd90aeb8bc9..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2013 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 "content/renderer/media/crypto/key_systems_support_uma.h" - -#include <string> - -#include "base/metrics/histogram.h" -#include "content/public/renderer/render_thread.h" -#include "content/renderer/media/crypto/key_systems.h" - -namespace content { - -namespace { - -const char kKeySystemSupportUMAPrefix[] = "Media.EME.KeySystemSupport."; - -// These values are reported to UMA. Do not change the existing values! -enum KeySystemSupportStatus { - KEY_SYSTEM_QUERIED = 0, - KEY_SYSTEM_SUPPORTED = 1, - KEY_SYSTEM_WITH_TYPE_QUERIED = 2, - KEY_SYSTEM_WITH_TYPE_SUPPORTED = 3, - KEY_SYSTEM_SUPPORT_STATUS_COUNT -}; - -// Reports an event only once. -class OneTimeReporter { - public: - OneTimeReporter(const std::string& key_system, KeySystemSupportStatus status); - ~OneTimeReporter(); - - void Report(); - - private: - bool is_reported_; - const std::string key_system_; - const KeySystemSupportStatus status_; -}; - -OneTimeReporter::OneTimeReporter(const std::string& key_system, - KeySystemSupportStatus status) - : is_reported_(false), key_system_(key_system), status_(status) { -} - -OneTimeReporter::~OneTimeReporter() {} - -void OneTimeReporter::Report() { - if (is_reported_) - return; - - // Not using UMA_HISTOGRAM_ENUMERATION directly because UMA_* macros require - // the names to be constant throughout the process' lifetime. - base::LinearHistogram::FactoryGet( - kKeySystemSupportUMAPrefix + KeySystemNameForUMA(key_system_), 1, - KEY_SYSTEM_SUPPORT_STATUS_COUNT, KEY_SYSTEM_SUPPORT_STATUS_COUNT + 1, - base::Histogram::kUmaTargetedHistogramFlag)->Add(status_); - - is_reported_ = true; -} - -} // namespace - -class KeySystemsSupportUMA::Reporter { - public: - explicit Reporter(const std::string& key_system); - ~Reporter(); - - void Report(bool has_type, bool is_supported); - - private: - const std::string key_system_; - - OneTimeReporter call_reporter_; - OneTimeReporter call_with_type_reporter_; - OneTimeReporter support_reporter_; - OneTimeReporter support_with_type_reporter_; -}; - -KeySystemsSupportUMA::Reporter::Reporter(const std::string& key_system) - : key_system_(key_system), - call_reporter_(key_system, KEY_SYSTEM_QUERIED), - call_with_type_reporter_(key_system, KEY_SYSTEM_WITH_TYPE_QUERIED), - support_reporter_(key_system, KEY_SYSTEM_SUPPORTED), - support_with_type_reporter_(key_system, KEY_SYSTEM_WITH_TYPE_SUPPORTED) {} - -KeySystemsSupportUMA::Reporter::~Reporter() {} - -void KeySystemsSupportUMA::Reporter::Report(bool has_type, bool is_supported) { - call_reporter_.Report(); - if (has_type) - call_with_type_reporter_.Report(); - - if (!is_supported) - return; - - support_reporter_.Report(); - if (has_type) - support_with_type_reporter_.Report(); -} - -KeySystemsSupportUMA::KeySystemsSupportUMA() {} - -KeySystemsSupportUMA::~KeySystemsSupportUMA() {} - -void KeySystemsSupportUMA::AddKeySystemToReport(const std::string& key_system) { - DCHECK(!GetReporter(key_system)); - reporters_.set(key_system, scoped_ptr<Reporter>(new Reporter(key_system))); -} - -void KeySystemsSupportUMA::ReportKeySystemQuery(const std::string& key_system, - bool has_type) { - Reporter* reporter = GetReporter(key_system); - if (!reporter) - return; - reporter->Report(has_type, false); -} - -void KeySystemsSupportUMA::ReportKeySystemSupport(const std::string& key_system, - bool has_type) { - Reporter* reporter = GetReporter(key_system); - if (!reporter) - return; - reporter->Report(has_type, true); -} - -KeySystemsSupportUMA::Reporter* KeySystemsSupportUMA::GetReporter( - const std::string& key_system) { - Reporters::iterator reporter = reporters_.find(key_system); - if (reporter == reporters_.end()) - return NULL; - return reporter->second; -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.h b/chromium/content/renderer/media/crypto/key_systems_support_uma.h deleted file mode 100644 index 95e1b02bcd4..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems_support_uma.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ - -#include <string> - -#include "base/containers/scoped_ptr_hash_map.h" - -namespace content { - -// Key system support UMA statistics for queried key systems. -// 1. The key system is queried (with or without a MIME type). -// 2. The key system is queried with a MIME type. -// 3. The queried key system is supported (with or without a MIME type). This is -// reported when the key system is supported when queried, regardless of -// whether a MIME type is specified. -// 4. The queried key system is supported with a MIME type. This is reported -// when the key system is supported when queried without a MIME type -// specified. -// Note: All 4 stats are only reported once per renderer process per key system. -class KeySystemsSupportUMA { - public: - KeySystemsSupportUMA(); - ~KeySystemsSupportUMA(); - - // Adds a |key_system| for which query/support statistics are reported. - // If you use this function to add key system to report, make sure to update - // AddKeySystemSupportActions() in tools/metrics/actions/extract_actions.py. - void AddKeySystemToReport(const std::string& key_system); - - // Reports that the |key_system| is queried. When |has_type|, also reports - // that the |key_system| with a MIME type is queried. - void ReportKeySystemQuery(const std::string& key_system, bool has_type); - - // Reports that the queried |key_system| is supported. When |has_type| (a - // a MIME type is specified in the query), also reports that the queried - // |key_system| is supported with that MIME type. - void ReportKeySystemSupport(const std::string& key_system, bool has_type); - - private: - class Reporter; - - // Returns the Reporter for |key_system|. Returns NULL if |key_system| was not - // added for UMA reporting. - Reporter* GetReporter(const std::string& key_system); - - // Key system <-> Reporter map. - typedef base::ScopedPtrHashMap<std::string, Reporter> Reporters; - Reporters reporters_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ diff --git a/chromium/content/renderer/media/crypto/key_systems_unittest.cc b/chromium/content/renderer/media/crypto/key_systems_unittest.cc deleted file mode 100644 index d7c980dd17f..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems_unittest.cc +++ /dev/null @@ -1,649 +0,0 @@ -// Copyright 2013 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 <string> -#include <vector> - -#include "content/public/common/content_client.h" -#include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/media/crypto/key_systems.h" -#include "content/test/test_content_client.h" -#include "media/base/eme_constants.h" -#include "media/base/key_system_info.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebString.h" - -#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. - -// Death tests are not always available, including on Android. -// EXPECT_DEBUG_DEATH_PORTABLE executes tests correctly except in the case that -// death tests are not available and NDEBUG is not defined. -#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) -#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ - EXPECT_DEBUG_DEATH(statement, regex) -#else -#if defined(NDEBUG) -#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ - do { statement; } while (false) -#else -#include "base/logging.h" -#define EXPECT_DEBUG_DEATH_PORTABLE(statement, regex) \ - LOG(WARNING) << "Death tests are not supported on this platform.\n" \ - << "Statement '" #statement "' cannot be verified."; -#endif // defined(NDEBUG) -#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) - -namespace content { - -using blink::WebString; -using media::KeySystemInfo; - -// These are the (fake) key systems that are registered for these tests. -// kUsesAes uses the AesDecryptor like Clear Key. -// kExternal uses an external CDM, such as Pepper-based or Android platform CDM. -const char kUsesAes[] = "org.example.clear"; -const char kUsesAesParent[] = "org.example"; // Not registered. -const char kExternal[] = "com.example.test"; -const char kExternalParent[] = "com.example"; - -const char kClearKey[] = "org.w3.clearkey"; -const char kPrefixedClearKey[] = "webkit-org.w3.clearkey"; -const char kExternalClearKey[] = "org.chromium.externalclearkey"; - -const char kAudioWebM[] = "audio/webm"; -const char kVideoWebM[] = "video/webm"; -const char kAudioFoo[] = "audio/foo"; -const char kVideoFoo[] = "video/foo"; - -// Pick some arbitrary bit fields as long as they are not in conflict with the -// real ones. -enum TestCodec { - TEST_CODEC_FOO_AUDIO = 1 << 10, // An audio codec for foo container. - TEST_CODEC_FOO_AUDIO_ALL = TEST_CODEC_FOO_AUDIO, - TEST_CODEC_FOO_VIDEO = 1 << 11, // A video codec for foo container. - TEST_CODEC_FOO_VIDEO_ALL = TEST_CODEC_FOO_VIDEO, - TEST_CODEC_FOO_ALL = TEST_CODEC_FOO_AUDIO_ALL | TEST_CODEC_FOO_VIDEO_ALL -}; - -COMPILE_ASSERT((TEST_CODEC_FOO_ALL & media::EME_CODEC_ALL) == - media::EME_CODEC_NONE, - test_codec_masks_should_only_use_invalid_codec_masks); - -// Adds test container and codec masks. -// This function must be called after SetContentClient() is called. -// More details: AddXxxMask() will create KeySystems if it hasn't been created. -// During KeySystems's construction GetContentClient() will be used to add key -// systems. In test code, the content client is set by SetContentClient(). -// Therefore, SetContentClient() must be called before this function to avoid -// access violation. -static void AddContainerAndCodecMasksForTest() { - // Since KeySystems is a singleton. Make sure we only add test container and - // codec masks once per process. - static bool is_test_masks_added = false; - - if (is_test_masks_added) - return; - - AddContainerMask("audio/foo", TEST_CODEC_FOO_AUDIO_ALL); - AddContainerMask("video/foo", TEST_CODEC_FOO_ALL); - AddCodecMask("fooaudio", TEST_CODEC_FOO_AUDIO); - AddCodecMask("foovideo", TEST_CODEC_FOO_VIDEO); - - is_test_masks_added = true; -} - -class TestContentRendererClient : public ContentRendererClient { - void AddKeySystems(std::vector<media::KeySystemInfo>* key_systems) override; -}; - -void TestContentRendererClient::AddKeySystems( - std::vector<media::KeySystemInfo>* key_systems) { - KeySystemInfo aes(kUsesAes); - aes.supported_codecs = media::EME_CODEC_WEBM_ALL; - aes.supported_codecs |= TEST_CODEC_FOO_ALL; - aes.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM; - aes.use_aes_decryptor = true; - key_systems->push_back(aes); - - KeySystemInfo ext(kExternal); - ext.supported_codecs = media::EME_CODEC_WEBM_ALL; - ext.supported_codecs |= TEST_CODEC_FOO_ALL; - ext.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM; - ext.parent_key_system = kExternalParent; -#if defined(ENABLE_PEPPER_CDMS) - ext.pepper_type = "application/x-ppapi-external-cdm"; -#endif // defined(ENABLE_PEPPER_CDMS) - key_systems->push_back(ext); -} - -// TODO(sandersd): Refactor. http://crbug.com/417444 -class KeySystemsTest : public testing::Test { - protected: - KeySystemsTest() { - vp8_codec_.push_back("vp8"); - - vp80_codec_.push_back("vp8.0"); - - vp9_codec_.push_back("vp9"); - - vp90_codec_.push_back("vp9.0"); - - vorbis_codec_.push_back("vorbis"); - - vp8_and_vorbis_codecs_.push_back("vp8"); - vp8_and_vorbis_codecs_.push_back("vorbis"); - - vp9_and_vorbis_codecs_.push_back("vp9"); - vp9_and_vorbis_codecs_.push_back("vorbis"); - - foovideo_codec_.push_back("foovideo"); - - foovideo_extended_codec_.push_back("foovideo.4D400C"); - - foovideo_dot_codec_.push_back("foovideo."); - - fooaudio_codec_.push_back("fooaudio"); - - foovideo_and_fooaudio_codecs_.push_back("foovideo"); - foovideo_and_fooaudio_codecs_.push_back("fooaudio"); - - unknown_codec_.push_back("unknown"); - - mixed_codecs_.push_back("vorbis"); - mixed_codecs_.push_back("foovideo"); - - // KeySystems requires a valid ContentRendererClient and thus ContentClient. - // The TestContentClient is not available inside Death Tests on some - // platforms (see below). Therefore, always provide a TestContentClient. - // Explanation: When Death Tests fork, there is a valid ContentClient. - // However, when they launch a new process instead of forking, the global - // variable is not copied and for some reason TestContentClientInitializer - // does not get created to set the global variable in the new process. - SetContentClient(&test_content_client_); - SetRendererClientForTesting(&content_renderer_client_); - } - - void SetUp() override { AddContainerAndCodecMasksForTest(); } - - ~KeySystemsTest() override { - // Clear the use of content_client_, which was set in SetUp(). - SetContentClient(NULL); - } - - typedef std::vector<std::string> CodecVector; - - const CodecVector& no_codecs() const { return no_codecs_; } - - const CodecVector& vp8_codec() const { return vp8_codec_; } - const CodecVector& vp80_codec() const { return vp80_codec_; } - const CodecVector& vp9_codec() const { return vp9_codec_; } - const CodecVector& vp90_codec() const { return vp90_codec_; } - - const CodecVector& vorbis_codec() const { return vorbis_codec_; } - - const CodecVector& vp8_and_vorbis_codecs() const { - return vp8_and_vorbis_codecs_; - } - const CodecVector& vp9_and_vorbis_codecs() const { - return vp9_and_vorbis_codecs_; - } - - const CodecVector& foovideo_codec() const { return foovideo_codec_; } - const CodecVector& foovideo_extended_codec() const { - return foovideo_extended_codec_; - } - const CodecVector& foovideo_dot_codec() const { return foovideo_dot_codec_; } - const CodecVector& fooaudio_codec() const { return fooaudio_codec_; } - const CodecVector& foovideo_and_fooaudio_codecs() const { - return foovideo_and_fooaudio_codecs_; - } - - const CodecVector& unknown_codec() const { return unknown_codec_; } - - const CodecVector& mixed_codecs() const { return mixed_codecs_; } - - private: - const CodecVector no_codecs_; - CodecVector vp8_codec_; - CodecVector vp80_codec_; - CodecVector vp9_codec_; - CodecVector vp90_codec_; - CodecVector vorbis_codec_; - CodecVector vp8_and_vorbis_codecs_; - CodecVector vp9_and_vorbis_codecs_; - - CodecVector foovideo_codec_; - CodecVector foovideo_extended_codec_; - CodecVector foovideo_dot_codec_; - CodecVector fooaudio_codec_; - CodecVector foovideo_and_fooaudio_codecs_; - - CodecVector unknown_codec_; - - CodecVector mixed_codecs_; - - TestContentClient test_content_client_; - TestContentRendererClient content_renderer_client_; -}; - -// TODO(ddorwin): Consider moving GetPepperType() calls out to their own test. - -TEST_F(KeySystemsTest, EmptyKeySystem) { - EXPECT_FALSE(IsConcreteSupportedKeySystem(std::string())); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), std::string())); - EXPECT_EQ("Unknown", KeySystemNameForUMA(std::string())); -} - -// Clear Key is the only key system registered in content. -TEST_F(KeySystemsTest, ClearKey) { - EXPECT_TRUE(IsConcreteSupportedKeySystem(kClearKey)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kClearKey)); - - EXPECT_EQ("ClearKey", KeySystemNameForUMA(kClearKey)); - - // Prefixed Clear Key is not supported internally. - EXPECT_FALSE(IsConcreteSupportedKeySystem(kPrefixedClearKey)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kPrefixedClearKey)); - EXPECT_EQ("Unknown", KeySystemNameForUMA(kPrefixedClearKey)); -} - -// The key system is not registered and therefore is unrecognized. -TEST_F(KeySystemsTest, Basic_UnrecognizedKeySystem) { - static const char* const kUnrecognized = "org.example.unrecognized"; - - EXPECT_FALSE(IsConcreteSupportedKeySystem(kUnrecognized)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kUnrecognized)); - - EXPECT_EQ("Unknown", KeySystemNameForUMA(kUnrecognized)); - - bool can_use = false; - EXPECT_DEBUG_DEATH_PORTABLE( - can_use = CanUseAesDecryptor(kUnrecognized), - "org.example.unrecognized is not a known concrete system"); - EXPECT_FALSE(can_use); - -#if defined(ENABLE_PEPPER_CDMS) - std::string type; - EXPECT_DEBUG_DEATH(type = GetPepperType(kUnrecognized), - "org.example.unrecognized is not a known concrete system"); - EXPECT_TRUE(type.empty()); -#endif -} - -TEST_F(KeySystemsTest, Basic_UsesAesDecryptor) { - EXPECT_TRUE(IsConcreteSupportedKeySystem(kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kUsesAes)); - - // No UMA value for this test key system. - EXPECT_EQ("Unknown", KeySystemNameForUMA(kUsesAes)); - - EXPECT_TRUE(CanUseAesDecryptor(kUsesAes)); -#if defined(ENABLE_PEPPER_CDMS) - std::string type; - EXPECT_DEBUG_DEATH(type = GetPepperType(kUsesAes), - "org.example.clear is not Pepper-based"); - EXPECT_TRUE(type.empty()); -#endif -} - -TEST_F(KeySystemsTest, - IsSupportedKeySystemWithMediaMimeType_UsesAesDecryptor_TypesContainer1) { - // Valid video types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_codec(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp80_codec(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_and_vorbis_codecs(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_codec(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp90_codec(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_and_vorbis_codecs(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vorbis_codec(), kUsesAes)); - - // Non-Webm codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, foovideo_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, unknown_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, mixed_codecs(), kUsesAes)); - - // Valid audio types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, no_codecs(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vorbis_codec(), kUsesAes)); - - // Non-audio codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp8_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp8_and_vorbis_codecs(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp9_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp9_and_vorbis_codecs(), kUsesAes)); - - // Non-Webm codec. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, fooaudio_codec(), kUsesAes)); -} - -// No parent is registered for UsesAes. -TEST_F(KeySystemsTest, Parent_NoParentRegistered) { - EXPECT_FALSE(IsConcreteSupportedKeySystem(kUsesAesParent)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kUsesAesParent)); - - // The parent is not supported for most things. - EXPECT_EQ("Unknown", KeySystemNameForUMA(kUsesAesParent)); - bool result = false; - EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kUsesAesParent), - "org.example is not a known concrete system"); - EXPECT_FALSE(result); -#if defined(ENABLE_PEPPER_CDMS) - std::string type; - EXPECT_DEBUG_DEATH(type = GetPepperType(kUsesAesParent), - "org.example is not a known concrete system"); - EXPECT_TRUE(type.empty()); -#endif -} - -TEST_F(KeySystemsTest, IsSupportedKeySystem_InvalidVariants) { - // Case sensitive. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.example.ClEaR")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.example.ClEaR")); - - // TLDs are not allowed. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.")); - EXPECT_FALSE(IsConcreteSupportedKeySystem("com")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "com")); - - // Extra period. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.example.")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.example.")); - - // Incomplete. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.example.clea")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.example.clea")); - - // Extra character. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.example.clearz")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.example.clearz")); - - // There are no child key systems for UsesAes. - EXPECT_FALSE(IsConcreteSupportedKeySystem("org.example.clear.foo")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), "org.example.clear.foo")); -} - -TEST_F(KeySystemsTest, IsSupportedKeySystemWithMediaMimeType_NoType) { - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - std::string(), no_codecs(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - std::string(), no_codecs(), kUsesAesParent)); - - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - std::string(), no_codecs(), "org.example.foo")); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - std::string(), no_codecs(), "org.example.clear.foo")); -} - -// Tests the second registered container type. -// TODO(ddorwin): Combined with TypesContainer1 in a future CL. -TEST_F(KeySystemsTest, - IsSupportedKeySystemWithMediaMimeType_UsesAesDecryptor_TypesContainer2) { - // Valid video types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, no_codecs(), kUsesAes)); - // The parent should be supported but is not. See http://crbug.com/164303. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, no_codecs(), kUsesAesParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_codec(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_and_fooaudio_codecs(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, fooaudio_codec(), kUsesAes)); - - // Extended codecs fail because this is handled by SimpleWebMimeRegistryImpl. - // They should really pass canPlayType(). - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_extended_codec(), kUsesAes)); - - // Invalid codec format. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_dot_codec(), kUsesAes)); - - // Non-container2 codec. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, vp8_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, unknown_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, mixed_codecs(), kUsesAes)); - - // Valid audio types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, no_codecs(), kUsesAes)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, fooaudio_codec(), kUsesAes)); - - // Non-audio codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, foovideo_codec(), kUsesAes)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, foovideo_and_fooaudio_codecs(), kUsesAes)); - - // Non-container2 codec. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, vorbis_codec(), kUsesAes)); -} - -// -// Non-AesDecryptor-based key system. -// - -TEST_F(KeySystemsTest, Basic_ExternalDecryptor) { - EXPECT_TRUE(IsConcreteSupportedKeySystem(kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kExternal)); - - EXPECT_FALSE(CanUseAesDecryptor(kExternal)); -#if defined(ENABLE_PEPPER_CDMS) - EXPECT_EQ("application/x-ppapi-external-cdm", GetPepperType(kExternal)); -#endif // defined(ENABLE_PEPPER_CDMS) - -} - -TEST_F(KeySystemsTest, Parent_ParentRegistered) { - // The parent system is not a concrete system but is supported. - EXPECT_FALSE(IsConcreteSupportedKeySystem(kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kExternalParent)); - - // The parent is not supported for most things. - EXPECT_EQ("Unknown", KeySystemNameForUMA(kExternalParent)); - bool result = false; - EXPECT_DEBUG_DEATH_PORTABLE(result = CanUseAesDecryptor(kExternalParent), - "com.example is not a known concrete system"); - EXPECT_FALSE(result); -#if defined(ENABLE_PEPPER_CDMS) - std::string type; - EXPECT_DEBUG_DEATH(type = GetPepperType(kExternalParent), - "com.example is not a known concrete system"); - EXPECT_TRUE(type.empty()); -#endif -} - -TEST_F( - KeySystemsTest, - IsSupportedKeySystemWithMediaMimeType_ExternalDecryptor_TypesContainer1) { - // Valid video types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_codec(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp80_codec(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_and_vorbis_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_codec(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp90_codec(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_and_vorbis_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vorbis_codec(), kExternal)); - - // Valid video types - parent key system. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, no_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_codec(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp80_codec(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp8_and_vorbis_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_codec(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp90_codec(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vp9_and_vorbis_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, vorbis_codec(), kExternalParent)); - - // Non-Webm codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, foovideo_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, unknown_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoWebM, mixed_codecs(), kExternal)); - - // Valid audio types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, no_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vorbis_codec(), kExternal)); - - // Valid audio types - parent key system. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, no_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vorbis_codec(), kExternalParent)); - - // Non-audio codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp8_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp8_and_vorbis_codecs(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp9_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, vp9_and_vorbis_codecs(), kExternal)); - - // Non-Webm codec. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioWebM, fooaudio_codec(), kExternal)); -} - -TEST_F( - KeySystemsTest, - IsSupportedKeySystemWithMediaMimeType_ExternalDecryptor_TypesContainer2) { - // Valid video types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, no_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_codec(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_and_fooaudio_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, fooaudio_codec(), kExternal)); - - // Valid video types - parent key system. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, no_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_codec(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_and_fooaudio_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, fooaudio_codec(), kExternalParent)); - - // Extended codecs fail because this is handled by SimpleWebMimeRegistryImpl. - // They should really pass canPlayType(). - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_extended_codec(), kExternal)); - - // Invalid codec format. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, foovideo_dot_codec(), kExternal)); - - // Non-container2 codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, vp8_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, unknown_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kVideoFoo, mixed_codecs(), kExternal)); - - // Valid audio types. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, no_codecs(), kExternal)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, fooaudio_codec(), kExternal)); - - // Valid audio types - parent key system. - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, no_codecs(), kExternalParent)); - EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, fooaudio_codec(), kExternalParent)); - - // Non-audio codecs. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, foovideo_codec(), kExternal)); - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, foovideo_and_fooaudio_codecs(), kExternal)); - - // Non-container2 codec. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( - kAudioFoo, vorbis_codec(), kExternal)); -} - -TEST_F(KeySystemsTest, KeySystemNameForUMA) { - EXPECT_EQ("ClearKey", KeySystemNameForUMA(kClearKey)); - // Prefixed is not supported internally. - EXPECT_EQ("Unknown", KeySystemNameForUMA(kPrefixedClearKey)); - - // External Clear Key never has a UMA name. - EXPECT_EQ("Unknown", KeySystemNameForUMA(kExternalClearKey)); - -#if defined(WIDEVINE_CDM_AVAILABLE) - const char* const kTestWidevineUmaName = "Widevine"; -#else - const char* const kTestWidevineUmaName = "Unknown"; -#endif - EXPECT_EQ(kTestWidevineUmaName, KeySystemNameForUMA("com.widevine.alpha")); -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc index 1af098c1fbe..b828de51d09 100644 --- a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc +++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc @@ -10,92 +10,103 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" -#include "content/renderer/media/crypto/key_systems.h" +#include "content/renderer/media/crypto/cdm_initialized_promise.h" #include "content/renderer/pepper/content_decryptor_delegate.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "media/base/audio_decoder_config.h" +#include "media/base/cdm_key_information.h" #include "media/base/data_buffer.h" #include "media/base/decoder_buffer.h" +#include "media/base/key_systems.h" #include "media/base/video_decoder_config.h" #include "media/base/video_frame.h" namespace content { -scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( +void PpapiDecryptor::Create( const std::string& key_system, const GURL& security_origin, + bool allow_distinctive_identifier, + bool allow_persistent_state, const CreatePepperCdmCB& create_pepper_cdm_cb, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb) { - std::string plugin_type = GetPepperType(key_system); + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb) { + std::string plugin_type = media::GetPepperType(key_system); DCHECK(!plugin_type.empty()); scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper = create_pepper_cdm_cb.Run(plugin_type, security_origin); if (!pepper_cdm_wrapper) { DLOG(ERROR) << "Plugin instance creation failed."; - return scoped_ptr<PpapiDecryptor>(); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(cdm_created_cb, nullptr, + "Plugin instance creation failed.")); + return; } - return scoped_ptr<PpapiDecryptor>( - new PpapiDecryptor(key_system, - pepper_cdm_wrapper.Pass(), - session_message_cb, - session_ready_cb, - session_closed_cb, - session_error_cb, - session_keys_change_cb, - session_expiration_update_cb)); + scoped_ptr<PpapiDecryptor> ppapi_decryptor( + new PpapiDecryptor(pepper_cdm_wrapper.Pass(), session_message_cb, + session_closed_cb, legacy_session_error_cb, + session_keys_change_cb, session_expiration_update_cb)); + + // PpapiDecryptor ownership passed to the promise, but keep a copy in order + // to call InitializeCdm(). + PpapiDecryptor* ppapi_decryptor_copy = ppapi_decryptor.get(); + scoped_ptr<CdmInitializedPromise> promise( + new CdmInitializedPromise(cdm_created_cb, ppapi_decryptor.Pass())); + ppapi_decryptor_copy->InitializeCdm(key_system, allow_distinctive_identifier, + allow_persistent_state, promise.Pass()); } PpapiDecryptor::PpapiDecryptor( - const std::string& key_system, scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, const media::SessionExpirationUpdateCB& session_expiration_update_cb) : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()), session_message_cb_(session_message_cb), - session_ready_cb_(session_ready_cb), session_closed_cb_(session_closed_cb), - session_error_cb_(session_error_cb), + legacy_session_error_cb_(legacy_session_error_cb), session_keys_change_cb_(session_keys_change_cb), session_expiration_update_cb_(session_expiration_update_cb), render_loop_proxy_(base::MessageLoopProxy::current()), weak_ptr_factory_(this) { DCHECK(pepper_cdm_wrapper_.get()); DCHECK(!session_message_cb_.is_null()); - DCHECK(!session_ready_cb_.is_null()); DCHECK(!session_closed_cb_.is_null()); - DCHECK(!session_error_cb_.is_null()); + DCHECK(!legacy_session_error_cb_.is_null()); DCHECK(!session_keys_change_cb.is_null()); DCHECK(!session_expiration_update_cb.is_null()); +} + +PpapiDecryptor::~PpapiDecryptor() { + pepper_cdm_wrapper_.reset(); +} +void PpapiDecryptor::InitializeCdm( + const std::string& key_system, + bool allow_distinctive_identifier, + bool allow_persistent_state, + scoped_ptr<media::SimpleCdmPromise> promise) { base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); CdmDelegate()->Initialize( - key_system, + key_system, allow_distinctive_identifier, allow_persistent_state, base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this), - base::Bind(&PpapiDecryptor::OnSessionReady, weak_this), base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this), - base::Bind(&PpapiDecryptor::OnSessionError, weak_this), + base::Bind(&PpapiDecryptor::OnLegacySessionError, weak_this), base::Bind(&PpapiDecryptor::OnSessionKeysChange, weak_this), base::Bind(&PpapiDecryptor::OnSessionExpirationUpdate, weak_this), - base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this)); -} - -PpapiDecryptor::~PpapiDecryptor() { - pepper_cdm_wrapper_.reset(); + base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this), + promise.Pass()); } void PpapiDecryptor::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -105,15 +116,13 @@ void PpapiDecryptor::SetServerCertificate( return; } - CdmDelegate()->SetServerCertificate( - certificate_data, certificate_data_length, promise.Pass()); + CdmDelegate()->SetServerCertificate(certificate, promise.Pass()); } -void PpapiDecryptor::CreateSession( - const std::string& init_data_type, - const uint8* init_data, - int init_data_length, +void PpapiDecryptor::CreateSessionAndGenerateRequest( SessionType session_type, + media::EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) { DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -123,15 +132,13 @@ void PpapiDecryptor::CreateSession( return; } - CdmDelegate()->CreateSession(init_data_type, - init_data, - init_data_length, - session_type, - promise.Pass()); + CdmDelegate()->CreateSessionAndGenerateRequest(session_type, init_data_type, + init_data, promise.Pass()); } void PpapiDecryptor::LoadSession( - const std::string& web_session_id, + SessionType session_type, + const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) { DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -140,13 +147,12 @@ void PpapiDecryptor::LoadSession( promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); return; } - CdmDelegate()->LoadSession(web_session_id, promise.Pass()); + CdmDelegate()->LoadSession(session_type, session_id, promise.Pass()); } void PpapiDecryptor::UpdateSession( - const std::string& web_session_id, - const uint8* response, - int response_length, + const std::string& session_id, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -154,11 +160,10 @@ void PpapiDecryptor::UpdateSession( promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); return; } - CdmDelegate()->UpdateSession(web_session_id, response, response_length, - promise.Pass()); + CdmDelegate()->UpdateSession(session_id, response, promise.Pass()); } -void PpapiDecryptor::CloseSession(const std::string& web_session_id, +void PpapiDecryptor::CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -167,11 +172,11 @@ void PpapiDecryptor::CloseSession(const std::string& web_session_id, return; } - CdmDelegate()->CloseSession(web_session_id, promise.Pass()); + CdmDelegate()->CloseSession(session_id, promise.Pass()); } void PpapiDecryptor::RemoveSession( - const std::string& web_session_id, + const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -180,25 +185,21 @@ void PpapiDecryptor::RemoveSession( return; } - CdmDelegate()->RemoveSession(web_session_id, promise.Pass()); + CdmDelegate()->RemoveSession(session_id, promise.Pass()); } -void PpapiDecryptor::GetUsableKeyIds(const std::string& web_session_id, - scoped_ptr<media::KeyIdsPromise> promise) { - DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - - if (!CdmDelegate()) { - promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); - return; - } - - CdmDelegate()->GetUsableKeyIds(web_session_id, promise.Pass()); +media::CdmContext* PpapiDecryptor::GetCdmContext() { + return this; } media::Decryptor* PpapiDecryptor::GetDecryptor() { return this; } +int PpapiDecryptor::GetCdmId() const { + return kInvalidCdmId; +} + void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, const NewKeyCB& new_key_cb) { if (!render_loop_proxy_->BelongsToCurrentThread()) { @@ -330,7 +331,7 @@ void PpapiDecryptor::DecryptAndDecodeAudio( DVLOG(3) << __FUNCTION__; if (!CdmDelegate() || !CdmDelegate()->DecryptAndDecodeAudio(encrypted, audio_decode_cb)) { - audio_decode_cb.Run(kError, AudioBuffers()); + audio_decode_cb.Run(kError, AudioFrames()); } } @@ -400,15 +401,18 @@ void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type, } } -void PpapiDecryptor::OnSessionMessage(const std::string& web_session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { +void PpapiDecryptor::OnSessionMessage(const std::string& session_id, + MessageType message_type, + const std::vector<uint8_t>& message, + const GURL& legacy_destination_url) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - session_message_cb_.Run(web_session_id, message, destination_url); + session_message_cb_.Run(session_id, message_type, message, + legacy_destination_url); } -void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id, - bool has_additional_usable_key) { +void PpapiDecryptor::OnSessionKeysChange(const std::string& session_id, + bool has_additional_usable_key, + media::CdmKeysInfo keys_info) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); // TODO(jrummell): Handling resume playback should be done in the media @@ -416,33 +420,30 @@ void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id, if (has_additional_usable_key) AttemptToResumePlayback(); - session_keys_change_cb_.Run(web_session_id, has_additional_usable_key); + session_keys_change_cb_.Run(session_id, has_additional_usable_key, + keys_info.Pass()); } void PpapiDecryptor::OnSessionExpirationUpdate( - const std::string& web_session_id, + const std::string& session_id, const base::Time& new_expiry_time) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - session_expiration_update_cb_.Run(web_session_id, new_expiry_time); -} - -void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) { - DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - session_ready_cb_.Run(web_session_id); + session_expiration_update_cb_.Run(session_id, new_expiry_time); } -void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) { +void PpapiDecryptor::OnSessionClosed(const std::string& session_id) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - session_closed_cb_.Run(web_session_id); + session_closed_cb_.Run(session_id); } -void PpapiDecryptor::OnSessionError(const std::string& web_session_id, - MediaKeys::Exception exception_code, - uint32 system_code, - const std::string& error_description) { +void PpapiDecryptor::OnLegacySessionError( + const std::string& session_id, + MediaKeys::Exception exception_code, + uint32_t system_code, + const std::string& error_description) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - session_error_cb_.Run( - web_session_id, exception_code, system_code, error_description); + legacy_session_error_cb_.Run(session_id, exception_code, system_code, + error_description); } void PpapiDecryptor::AttemptToResumePlayback() { diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.h b/chromium/content/renderer/media/crypto/ppapi_decryptor.h index 39c38c210f3..a4f26b5ac32 100644 --- a/chromium/content/renderer/media/crypto/ppapi_decryptor.h +++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.h @@ -12,6 +12,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/renderer/media/crypto/pepper_cdm_wrapper.h" +#include "media/base/cdm_context.h" +#include "media/base/cdm_factory.h" #include "media/base/decryptor.h" #include "media/base/media_keys.h" #include "media/base/video_decoder_config.h" @@ -29,44 +31,49 @@ class PepperPluginInstanceImpl; // PpapiDecryptor implements media::MediaKeys and media::Decryptor and forwards // all calls to the PluginInstance. // This class should always be created & destroyed on the main renderer thread. -class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { +class PpapiDecryptor : public media::MediaKeys, + public media::CdmContext, + public media::Decryptor { public: - static scoped_ptr<PpapiDecryptor> Create( + static void Create( const std::string& key_system, const GURL& security_origin, + bool allow_distinctive_identifier, + bool allow_persistent_state, const CreatePepperCdmCB& create_pepper_cdm_cb, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb); + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb); ~PpapiDecryptor() override; // media::MediaKeys implementation. void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) override; - void CreateSession(const std::string& init_data_type, - const uint8* init_data, - int init_data_length, - SessionType session_type, - scoped_ptr<media::NewSessionCdmPromise> promise) override; - void LoadSession(const std::string& web_session_id, + void CreateSessionAndGenerateRequest( + SessionType session_type, + media::EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, + scoped_ptr<media::NewSessionCdmPromise> promise) override; + void LoadSession(SessionType session_type, + const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) override; - void UpdateSession(const std::string& web_session_id, - const uint8* response, - int response_length, + void UpdateSession(const std::string& session_id, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) override; - void CloseSession(const std::string& web_session_id, + void CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override; - void RemoveSession(const std::string& web_session_id, + void RemoveSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override; - void GetUsableKeyIds(const std::string& web_session_id, - scoped_ptr<media::KeyIdsPromise> promise) override; + CdmContext* GetCdmContext() override; + + // media::CdmContext implementation. Decryptor* GetDecryptor() override; + int GetCdmId() const override; // media::Decryptor implementation. void RegisterNewKeyCB(StreamType stream_type, @@ -90,31 +97,35 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { private: PpapiDecryptor( - const std::string& key_system, scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, const media::SessionExpirationUpdateCB& session_expiration_update_cb); + void InitializeCdm(const std::string& key_system, + bool allow_distinctive_identifier, + bool allow_persistent_state, + scoped_ptr<media::SimpleCdmPromise> promise); + void OnDecoderInitialized(StreamType stream_type, bool success); // Callbacks for |plugin_cdm_delegate_| to fire session events. - void OnSessionMessage(const std::string& web_session_id, - const std::vector<uint8>& message, - const GURL& destination_url); - void OnSessionKeysChange(const std::string& web_session_id, - bool has_additional_usable_key); - void OnSessionExpirationUpdate(const std::string& web_session_id, + void OnSessionMessage(const std::string& session_id, + MediaKeys::MessageType message_type, + const std::vector<uint8_t>& message, + const GURL& legacy_destination_url); + void OnSessionKeysChange(const std::string& session_id, + bool has_additional_usable_key, + media::CdmKeysInfo keys_info); + void OnSessionExpirationUpdate(const std::string& session_id, const base::Time& new_expiry_time); - void OnSessionReady(const std::string& web_session_id); - void OnSessionClosed(const std::string& web_session_id); - void OnSessionError(const std::string& web_session_id, - MediaKeys::Exception exception_code, - uint32 system_code, - const std::string& error_description); + void OnSessionClosed(const std::string& session_id); + void OnLegacySessionError(const std::string& session_id, + MediaKeys::Exception exception_code, + uint32_t system_code, + const std::string& error_description); void AttemptToResumePlayback(); @@ -131,9 +142,8 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { // Callbacks for firing session events. media::SessionMessageCB session_message_cb_; - media::SessionReadyCB session_ready_cb_; media::SessionClosedCB session_closed_cb_; - media::SessionErrorCB session_error_cb_; + media::LegacySessionErrorCB legacy_session_error_cb_; media::SessionKeysChangeCB session_keys_change_cb_; media::SessionExpirationUpdateCB session_expiration_update_cb_; diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.cc b/chromium/content/renderer/media/crypto/proxy_decryptor.cc deleted file mode 100644 index 44a30fd1f84..00000000000 --- a/chromium/content/renderer/media/crypto/proxy_decryptor.cc +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2013 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 "content/renderer/media/crypto/proxy_decryptor.h" - -#include <cstring> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "media/base/cdm_callback_promise.h" -#include "media/base/cdm_factory.h" -#include "media/cdm/json_web_key.h" -#include "media/cdm/key_system_names.h" - -namespace content { - -// Special system code to signal a closed persistent session in a SessionError() -// call. This is needed because there is no SessionClosed() call in the prefixed -// EME API. -const int kSessionClosedSystemCode = 29127; - -ProxyDecryptor::ProxyDecryptor(const KeyAddedCB& key_added_cb, - const KeyErrorCB& key_error_cb, - const KeyMessageCB& key_message_cb) - : key_added_cb_(key_added_cb), - key_error_cb_(key_error_cb), - key_message_cb_(key_message_cb), - is_clear_key_(false), - weak_ptr_factory_(this) { - DCHECK(!key_added_cb_.is_null()); - DCHECK(!key_error_cb_.is_null()); - DCHECK(!key_message_cb_.is_null()); -} - -ProxyDecryptor::~ProxyDecryptor() { - // Destroy the decryptor explicitly before destroying the plugin. - media_keys_.reset(); -} - -media::Decryptor* ProxyDecryptor::GetDecryptor() { - return media_keys_ ? media_keys_->GetDecryptor() : NULL; -} - -#if defined(ENABLE_BROWSER_CDMS) -int ProxyDecryptor::GetCdmId() { - return media_keys_->GetCdmId(); -} -#endif - -bool ProxyDecryptor::InitializeCDM(media::CdmFactory* cdm_factory, - const std::string& key_system, - const GURL& security_origin) { - DVLOG(1) << "InitializeCDM: key_system = " << key_system; - - DCHECK(!media_keys_); - media_keys_ = CreateMediaKeys(cdm_factory, key_system, security_origin); - if (!media_keys_) - return false; - - is_clear_key_ = - media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); - return true; -} - -// Returns true if |data| is prefixed with |header| and has data after the -// |header|. -bool HasHeader(const uint8* data, int data_length, const std::string& header) { - return static_cast<size_t>(data_length) > header.size() && - std::equal(data, data + header.size(), header.begin()); -} - -// Removes the first |length| items from |data|. -void StripHeader(std::vector<uint8>& data, size_t length) { - data.erase(data.begin(), data.begin() + length); -} - -bool ProxyDecryptor::GenerateKeyRequest(const std::string& init_data_type, - const uint8* init_data, - int init_data_length) { - DVLOG(1) << "GenerateKeyRequest()"; - const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|"; - const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|"; - - SessionCreationType session_creation_type = TemporarySession; - std::vector<uint8> init_data_vector(init_data, init_data + init_data_length); - if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) { - session_creation_type = LoadSession; - StripHeader(init_data_vector, strlen(kPrefixedApiLoadSessionHeader)); - } else if (HasHeader(init_data, - init_data_length, - kPrefixedApiPersistentSessionHeader)) { - session_creation_type = PersistentSession; - StripHeader(init_data_vector, strlen(kPrefixedApiPersistentSessionHeader)); - } - - scoped_ptr<media::NewSessionCdmPromise> promise( - new media::CdmCallbackPromise<std::string>( - base::Bind(&ProxyDecryptor::SetSessionId, - weak_ptr_factory_.GetWeakPtr(), - session_creation_type), - base::Bind(&ProxyDecryptor::OnSessionError, - weak_ptr_factory_.GetWeakPtr(), - std::string()))); // No session id until created. - uint8* init_data_vector_data = - (init_data_vector.size() > 0) ? &init_data_vector[0] : nullptr; - - if (session_creation_type == LoadSession) { - media_keys_->LoadSession( - std::string(reinterpret_cast<const char*>(init_data_vector_data), - init_data_vector.size()), - promise.Pass()); - return true; - } - - media::MediaKeys::SessionType session_type = - session_creation_type == PersistentSession - ? media::MediaKeys::PERSISTENT_SESSION - : media::MediaKeys::TEMPORARY_SESSION; - - media_keys_->CreateSession(init_data_type, - init_data_vector_data, - init_data_vector.size(), - session_type, - promise.Pass()); - return true; -} - -void ProxyDecryptor::AddKey(const uint8* key, - int key_length, - const uint8* init_data, - int init_data_length, - const std::string& web_session_id) { - DVLOG(1) << "AddKey()"; - - // In the prefixed API, the session parameter provided to addKey() is - // optional, so use the single existing session if it exists. - // TODO(jrummell): remove when the prefixed API is removed. - std::string session_id(web_session_id); - if (session_id.empty()) { - if (active_sessions_.size() == 1) { - base::hash_map<std::string, bool>::iterator it = active_sessions_.begin(); - session_id = it->first; - } else { - OnSessionError(std::string(), - media::MediaKeys::NOT_SUPPORTED_ERROR, - 0, - "SessionId not specified."); - return; - } - } - - scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( - base::Bind(&ProxyDecryptor::OnSessionReady, - weak_ptr_factory_.GetWeakPtr(), - web_session_id), - base::Bind(&ProxyDecryptor::OnSessionError, - weak_ptr_factory_.GetWeakPtr(), - web_session_id))); - - // EME WD spec only supports a single array passed to the CDM. For - // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). - // Since the EME WD spec supports the key as a JSON Web Key, - // convert the 2 arrays to a JWK and pass it as the single array. - if (is_clear_key_) { - // Decryptor doesn't support empty key ID (see http://crbug.com/123265). - // So ensure a non-empty value is passed. - if (!init_data) { - static const uint8 kDummyInitData[1] = {0}; - init_data = kDummyInitData; - init_data_length = arraysize(kDummyInitData); - } - - std::string jwk = - media::GenerateJWKSet(key, key_length, init_data, init_data_length); - DCHECK(!jwk.empty()); - media_keys_->UpdateSession(session_id, - reinterpret_cast<const uint8*>(jwk.data()), - jwk.size(), - promise.Pass()); - return; - } - - media_keys_->UpdateSession(session_id, key, key_length, promise.Pass()); -} - -void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { - DVLOG(1) << "CancelKeyRequest()"; - - scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( - base::Bind(&ProxyDecryptor::OnSessionClosed, - weak_ptr_factory_.GetWeakPtr(), - web_session_id), - base::Bind(&ProxyDecryptor::OnSessionError, - weak_ptr_factory_.GetWeakPtr(), - web_session_id))); - media_keys_->RemoveSession(web_session_id, promise.Pass()); -} - -scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( - media::CdmFactory* cdm_factory, - const std::string& key_system, - const GURL& security_origin) { - base::WeakPtr<ProxyDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); - return cdm_factory->Create( - key_system, - security_origin, - base::Bind(&ProxyDecryptor::OnSessionMessage, weak_this), - base::Bind(&ProxyDecryptor::OnSessionReady, weak_this), - base::Bind(&ProxyDecryptor::OnSessionClosed, weak_this), - base::Bind(&ProxyDecryptor::OnSessionError, weak_this), - base::Bind(&ProxyDecryptor::OnSessionKeysChange, weak_this), - base::Bind(&ProxyDecryptor::OnSessionExpirationUpdate, weak_this)); -} - -void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { - // Assumes that OnSessionCreated() has been called before this. - - // For ClearKey, convert the message from JSON into just passing the key - // as the message. If unable to extract the key, return the message unchanged. - if (is_clear_key_) { - std::vector<uint8> key; - if (media::ExtractFirstKeyIdFromLicenseRequest(message, &key)) { - key_message_cb_.Run(web_session_id, key, destination_url); - return; - } - } - - key_message_cb_.Run(web_session_id, message, destination_url); -} - -void ProxyDecryptor::OnSessionKeysChange(const std::string& web_session_id, - bool has_additional_usable_key) { - // EME v0.1b doesn't support this event. -} - -void ProxyDecryptor::OnSessionExpirationUpdate( - const std::string& web_session_id, - const base::Time& new_expiry_time) { - // EME v0.1b doesn't support this event. -} - -void ProxyDecryptor::OnSessionReady(const std::string& web_session_id) { - key_added_cb_.Run(web_session_id); -} - -void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { - base::hash_map<std::string, bool>::iterator it = - active_sessions_.find(web_session_id); - - // Latest EME spec separates closing a session ("allows an application to - // indicate that it no longer needs the session") and actually closing the - // session (done by the CDM at any point "such as in response to a close() - // call, when the session is no longer needed, or when system resources are - // lost.") Thus the CDM may cause 2 close() events -- one to resolve the - // close() promise, and a second to actually close the session. Prefixed EME - // only expects 1 close event, so drop the second (and subsequent) events. - // However, this means we can't tell if the CDM is generating spurious close() - // events. - if (it == active_sessions_.end()) - return; - - if (it->second) { - OnSessionError(web_session_id, - media::MediaKeys::NOT_SUPPORTED_ERROR, - kSessionClosedSystemCode, - "Do not close persistent sessions."); - } - active_sessions_.erase(it); -} - -void ProxyDecryptor::OnSessionError(const std::string& web_session_id, - media::MediaKeys::Exception exception_code, - uint32 system_code, - const std::string& error_message) { - // Convert |error_name| back to MediaKeys::KeyError if possible. Prefixed - // EME has different error message, so all the specific error events will - // get lost. - media::MediaKeys::KeyError error_code; - switch (exception_code) { - case media::MediaKeys::CLIENT_ERROR: - error_code = media::MediaKeys::kClientError; - break; - case media::MediaKeys::OUTPUT_ERROR: - error_code = media::MediaKeys::kOutputError; - break; - default: - // This will include all other CDM4 errors and any error generated - // by CDM5 or later. - error_code = media::MediaKeys::kUnknownError; - break; - } - key_error_cb_.Run(web_session_id, error_code, system_code); -} - -void ProxyDecryptor::SetSessionId(SessionCreationType session_type, - const std::string& web_session_id) { - // Loaded sessions are considered persistent. - bool is_persistent = - session_type == PersistentSession || session_type == LoadSession; - active_sessions_.insert(std::make_pair(web_session_id, is_persistent)); - - // For LoadSession(), generate the SessionReady event. - if (session_type == LoadSession) - OnSessionReady(web_session_id); -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.h b/chromium/content/renderer/media/crypto/proxy_decryptor.h deleted file mode 100644 index 62f2e8eb884..00000000000 --- a/chromium/content/renderer/media/crypto/proxy_decryptor.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "media/base/decryptor.h" -#include "media/base/media_keys.h" - -class GURL; - -namespace media { -class CdmFactory; -} - -namespace content { - -// ProxyDecryptor is for EME v0.1b only. It should not be used for the WD API. -// A decryptor proxy that creates a real decryptor object on demand and -// forwards decryptor calls to it. -// -// TODO(xhwang): Currently we don't support run-time switching among decryptor -// objects. Fix this when needed. -// TODO(xhwang): The ProxyDecryptor is not a Decryptor. Find a better name! -class ProxyDecryptor { - public: - // These are similar to the callbacks in media_keys.h, but pass back the - // web session ID rather than the internal session ID. - typedef base::Callback<void(const std::string& session_id)> KeyAddedCB; - typedef base::Callback<void(const std::string& session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code)> KeyErrorCB; - typedef base::Callback<void(const std::string& session_id, - const std::vector<uint8>& message, - const GURL& destination_url)> KeyMessageCB; - - ProxyDecryptor(const KeyAddedCB& key_added_cb, - const KeyErrorCB& key_error_cb, - const KeyMessageCB& key_message_cb); - virtual ~ProxyDecryptor(); - - // Returns the Decryptor associated with this object. May be NULL if no - // Decryptor is associated. - media::Decryptor* GetDecryptor(); - -#if defined(ENABLE_BROWSER_CDMS) - // Returns the CDM ID associated with this object. May be kInvalidCdmId if no - // CDM ID is associated, such as when Clear Key is used. - int GetCdmId(); -#endif - - // Only call this once. - bool InitializeCDM(media::CdmFactory* cdm_factory, - const std::string& key_system, - const GURL& security_origin); - - // May only be called after InitializeCDM() succeeds. - bool GenerateKeyRequest(const std::string& init_data_type, - const uint8* init_data, - int init_data_length); - void AddKey(const uint8* key, int key_length, - const uint8* init_data, int init_data_length, - const std::string& session_id); - void CancelKeyRequest(const std::string& session_id); - - private: - // Helper function to create MediaKeys to handle the given |key_system|. - scoped_ptr<media::MediaKeys> CreateMediaKeys( - media::CdmFactory* cdm_factory, - const std::string& key_system, - const GURL& security_origin); - - // Callbacks for firing session events. - void OnSessionMessage(const std::string& web_session_id, - const std::vector<uint8>& message, - const GURL& default_url); - void OnSessionKeysChange(const std::string& web_session_id, - bool has_additional_usable_key); - void OnSessionExpirationUpdate(const std::string& web_session_id, - const base::Time& new_expiry_time); - void OnSessionReady(const std::string& web_session_id); - void OnSessionClosed(const std::string& web_session_id); - void OnSessionError(const std::string& web_session_id, - media::MediaKeys::Exception exception_code, - uint32 system_code, - const std::string& error_message); - - enum SessionCreationType { - TemporarySession, - PersistentSession, - LoadSession - }; - - // Called when a session is actually created or loaded. - void SetSessionId(SessionCreationType session_type, - const std::string& web_session_id); - - // The real MediaKeys that manages key operations for the ProxyDecryptor. - scoped_ptr<media::MediaKeys> media_keys_; - - // Callbacks for firing key events. - KeyAddedCB key_added_cb_; - KeyErrorCB key_error_cb_; - KeyMessageCB key_message_cb_; - - // Keep track of both persistent and non-persistent sessions. - base::hash_map<std::string, bool> active_sessions_; - - bool is_clear_key_; - -#if defined(ENABLE_BROWSER_CDMS) - int cdm_id_; -#endif - - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<ProxyDecryptor> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProxyDecryptor); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ diff --git a/chromium/content/renderer/media/crypto/proxy_media_keys.cc b/chromium/content/renderer/media/crypto/proxy_media_keys.cc index e62c6cea1fd..4092324d661 100644 --- a/chromium/content/renderer/media/crypto/proxy_media_keys.cc +++ b/chromium/content/renderer/media/crypto/proxy_media_keys.cc @@ -9,287 +9,207 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/stl_util.h" -#include "content/renderer/media/crypto/key_systems.h" +#include "content/renderer/media/crypto/cdm_initialized_promise.h" #include "content/renderer/media/crypto/renderer_cdm_manager.h" +#include "media/base/cdm_key_information.h" #include "media/base/cdm_promise.h" +#include "media/base/key_systems.h" namespace content { -scoped_ptr<ProxyMediaKeys> ProxyMediaKeys::Create( +void ProxyMediaKeys::Create( const std::string& key_system, const GURL& security_origin, + bool use_hw_secure_codecs, RendererCdmManager* manager, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb) { + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb) { DCHECK(manager); + scoped_ptr<ProxyMediaKeys> proxy_media_keys(new ProxyMediaKeys( + manager, session_message_cb, session_closed_cb, legacy_session_error_cb, + session_keys_change_cb, session_expiration_update_cb)); - // TODO(jrummell): Add support for SessionKeysChangeCB and - // SessionExpirationUpdateCB. - scoped_ptr<ProxyMediaKeys> proxy_media_keys( - new ProxyMediaKeys(manager, - session_message_cb, - session_ready_cb, - session_closed_cb, - session_error_cb)); - proxy_media_keys->InitializeCdm(key_system, security_origin); - return proxy_media_keys.Pass(); + // ProxyMediaKeys ownership passed to the promise, but keep a copy in order + // to call InitializeCdm(). + ProxyMediaKeys* proxy_media_keys_copy = proxy_media_keys.get(); + scoped_ptr<CdmInitializedPromise> promise( + new CdmInitializedPromise(cdm_created_cb, proxy_media_keys.Pass())); + proxy_media_keys_copy->InitializeCdm(key_system, security_origin, + use_hw_secure_codecs, promise.Pass()); } ProxyMediaKeys::~ProxyMediaKeys() { manager_->DestroyCdm(cdm_id_); manager_->UnregisterMediaKeys(cdm_id_); - - // Reject any outstanding promises. - for (PromiseMap::iterator it = session_id_to_promise_map_.begin(); - it != session_id_to_promise_map_.end(); - ++it) { - it->second->reject( - media::MediaKeys::NOT_SUPPORTED_ERROR, 0, "The operation was aborted."); - } - session_id_to_promise_map_.clear(); + cdm_promise_adapter_.Clear(); } void ProxyMediaKeys::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { - promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented."); + uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); + manager_->SetServerCertificate(cdm_id_, promise_id, certificate); } -void ProxyMediaKeys::CreateSession( - const std::string& init_data_type, - const uint8* init_data, - int init_data_length, +void ProxyMediaKeys::CreateSessionAndGenerateRequest( SessionType session_type, + media::EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) { + if (session_type != media::MediaKeys::TEMPORARY_SESSION) { + promise->reject(NOT_SUPPORTED_ERROR, 0, + "Only the temporary session type is supported."); + return; + } + // TODO(xhwang): Move these checks up to blink and DCHECK here. // See http://crbug.com/342510 - CdmHostMsg_CreateSession_ContentType create_session_content_type; - if (init_data_type == "cenc") { - create_session_content_type = CREATE_SESSION_TYPE_MP4; - } else if (init_data_type == "webm") { - create_session_content_type = CREATE_SESSION_TYPE_WEBM; - } else { - DLOG(ERROR) << "Unsupported EME CreateSession content type of " - << init_data_type; - promise->reject( - NOT_SUPPORTED_ERROR, - 0, - "Unsupported EME CreateSession init data type of " + init_data_type); - return; + CdmHostMsg_CreateSession_InitDataType create_session_init_data_type = + INIT_DATA_TYPE_WEBM; + switch (init_data_type) { + case media::EmeInitDataType::CENC: + create_session_init_data_type = INIT_DATA_TYPE_CENC; + break; + case media::EmeInitDataType::WEBM: + create_session_init_data_type = INIT_DATA_TYPE_WEBM; + break; + case media::EmeInitDataType::KEYIDS: + case media::EmeInitDataType::UNKNOWN: + DLOG(ERROR) << "Unsupported EME CreateSession init data type"; + promise->reject(NOT_SUPPORTED_ERROR, 0, + "Unsupported EME CreateSession init data type"); + return; } - uint32 session_id = CreateSessionId(); - SavePromise(session_id, promise.Pass()); - manager_->CreateSession( - cdm_id_, - session_id, - create_session_content_type, - std::vector<uint8>(init_data, init_data + init_data_length)); + uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); + manager_->CreateSessionAndGenerateRequest( + cdm_id_, promise_id, create_session_init_data_type, init_data); } void ProxyMediaKeys::LoadSession( - const std::string& web_session_id, + SessionType session_type, + const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) { // TODO(xhwang): Check key system and platform support for LoadSession in - // blink and add NOTREACHED() here. + // blink and add NOTREACHED() here. See http://crbug.com/384152 DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading."; promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); } void ProxyMediaKeys::UpdateSession( - const std::string& web_session_id, - const uint8* response, - int response_length, + const std::string& session_id, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) { - uint32 session_id = LookupSessionId(web_session_id); - if (!session_id) { - promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); - return; - } - - SavePromise(session_id, promise.Pass()); - manager_->UpdateSession( - cdm_id_, - session_id, - std::vector<uint8>(response, response + response_length)); + uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); + manager_->UpdateSession(cdm_id_, promise_id, session_id, response); } -void ProxyMediaKeys::CloseSession(const std::string& web_session_id, +void ProxyMediaKeys::CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) { - uint32 session_id = LookupSessionId(web_session_id); - if (!session_id) { - promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); - return; - } - - SavePromise(session_id, promise.Pass()); - manager_->ReleaseSession(cdm_id_, session_id); + uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); + manager_->CloseSession(cdm_id_, promise_id, session_id); } void ProxyMediaKeys::RemoveSession( - const std::string& web_session_id, + const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) { - promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented."); + // TODO(xhwang): Check key system and platform support for LoadSession in + // blink and add NOTREACHED() here. See http://crbug.com/384152 + promise->reject(NOT_SUPPORTED_ERROR, 0, "RemoveSession() not supported."); } -void ProxyMediaKeys::GetUsableKeyIds(const std::string& web_session_id, - scoped_ptr<media::KeyIdsPromise> promise) { - promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented."); +media::CdmContext* ProxyMediaKeys::GetCdmContext() { + return this; +} + +media::Decryptor* ProxyMediaKeys::GetDecryptor() { + return nullptr; } int ProxyMediaKeys::GetCdmId() const { return cdm_id_; } -void ProxyMediaKeys::OnSessionCreated(uint32 session_id, - const std::string& web_session_id) { - AssignWebSessionId(session_id, web_session_id); - scoped_ptr<media::CdmPromise> promise = TakePromise(session_id); - if (promise) { - media::NewSessionCdmPromise* session_promise( - static_cast<media::NewSessionCdmPromise*>(promise.get())); - session_promise->resolve(web_session_id); - } +void ProxyMediaKeys::OnSessionMessage( + const std::string& session_id, + media::MediaKeys::MessageType message_type, + const std::vector<uint8_t>& message, + const GURL& legacy_destination_url) { + session_message_cb_.Run(session_id, message_type, message, + legacy_destination_url); } -void ProxyMediaKeys::OnSessionMessage(uint32 session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { - session_message_cb_.Run( - LookupWebSessionId(session_id), message, destination_url); +void ProxyMediaKeys::OnSessionClosed(const std::string& session_id) { + session_closed_cb_.Run(session_id); } -void ProxyMediaKeys::OnSessionReady(uint32 session_id) { - scoped_ptr<media::CdmPromise> promise = TakePromise(session_id); - if (promise) { - media::SimpleCdmPromise* simple_promise( - static_cast<media::SimpleCdmPromise*>(promise.get())); - simple_promise->resolve(); - } else { - // Still needed for keyadded. - const std::string web_session_id = LookupWebSessionId(session_id); - session_ready_cb_.Run(web_session_id); - } +void ProxyMediaKeys::OnLegacySessionError(const std::string& session_id, + media::MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message) { + legacy_session_error_cb_.Run(session_id, exception, system_code, + error_message); } -void ProxyMediaKeys::OnSessionClosed(uint32 session_id) { - const std::string web_session_id = LookupWebSessionId(session_id); - DropWebSessionId(web_session_id); - scoped_ptr<media::CdmPromise> promise = TakePromise(session_id); - if (promise) { - media::SimpleCdmPromise* simple_promise( - static_cast<media::SimpleCdmPromise*>(promise.get())); - simple_promise->resolve(); - } else { - // It is possible for the CDM to close a session independent of a - // Release() request. - session_closed_cb_.Run(web_session_id); - } +void ProxyMediaKeys::OnSessionKeysChange(const std::string& session_id, + bool has_additional_usable_key, + media::CdmKeysInfo keys_info) { + session_keys_change_cb_.Run(session_id, has_additional_usable_key, + keys_info.Pass()); } -void ProxyMediaKeys::OnSessionError(uint32 session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code) { - const std::string web_session_id = LookupWebSessionId(session_id); - media::MediaKeys::Exception exception_code; - switch (error_code) { - case media::MediaKeys::kClientError: - exception_code = media::MediaKeys::CLIENT_ERROR; - break; - case media::MediaKeys::kOutputError: - exception_code = media::MediaKeys::OUTPUT_ERROR; - break; - case media::MediaKeys::kUnknownError: - default: - exception_code = media::MediaKeys::UNKNOWN_ERROR; - break; - } +void ProxyMediaKeys::OnSessionExpirationUpdate( + const std::string& session_id, + const base::Time& new_expiry_time) { + session_expiration_update_cb_.Run(session_id, new_expiry_time); +} - scoped_ptr<media::CdmPromise> promise = TakePromise(session_id); - if (promise) { - promise->reject(exception_code, system_code, std::string()); - return; - } +void ProxyMediaKeys::OnPromiseResolved(uint32_t promise_id) { + cdm_promise_adapter_.ResolvePromise(promise_id); +} - // Errors generally happen in response to a request, but it is possible - // for something bad to happen in the CDM and it needs to tell the client. - session_error_cb_.Run( - web_session_id, exception_code, system_code, std::string()); +void ProxyMediaKeys::OnPromiseResolvedWithSession( + uint32_t promise_id, + const std::string& session_id) { + cdm_promise_adapter_.ResolvePromise(promise_id, session_id); +} + +void ProxyMediaKeys::OnPromiseRejected(uint32_t promise_id, + media::MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message) { + cdm_promise_adapter_.RejectPromise(promise_id, exception, system_code, + error_message); } ProxyMediaKeys::ProxyMediaKeys( RendererCdmManager* manager, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb) + const media::LegacySessionErrorCB& legacy_session_error_cb, + const media::SessionKeysChangeCB& session_keys_change_cb, + const media::SessionExpirationUpdateCB& session_expiration_update_cb) : manager_(manager), session_message_cb_(session_message_cb), - session_ready_cb_(session_ready_cb), session_closed_cb_(session_closed_cb), - session_error_cb_(session_error_cb), - next_session_id_(1) { + legacy_session_error_cb_(legacy_session_error_cb), + session_keys_change_cb_(session_keys_change_cb), + session_expiration_update_cb_(session_expiration_update_cb) { cdm_id_ = manager->RegisterMediaKeys(this); } -void ProxyMediaKeys::InitializeCdm(const std::string& key_system, - const GURL& security_origin) { - manager_->InitializeCdm(cdm_id_, this, key_system, security_origin); -} - -uint32_t ProxyMediaKeys::CreateSessionId() { - return next_session_id_++; -} - -void ProxyMediaKeys::AssignWebSessionId(uint32_t session_id, - const std::string& web_session_id) { - DCHECK(!ContainsKey(web_session_to_session_id_map_, web_session_id)); - DCHECK(session_id); - web_session_to_session_id_map_.insert( - std::make_pair(web_session_id, session_id)); -} - -uint32_t ProxyMediaKeys::LookupSessionId( - const std::string& web_session_id) const { - SessionIdMap::const_iterator it = - web_session_to_session_id_map_.find(web_session_id); - return (it != web_session_to_session_id_map_.end()) ? it->second : 0; -} - -std::string ProxyMediaKeys::LookupWebSessionId(uint32_t session_id) const { - for (SessionIdMap::const_iterator it = web_session_to_session_id_map_.begin(); - it != web_session_to_session_id_map_.end(); - ++it) { - if (it->second == session_id) - return it->first; - } - // Possible to get an error creating a session, so no |web_session_id| - // available. - return std::string(); -} - -void ProxyMediaKeys::DropWebSessionId(const std::string& web_session_id) { - web_session_to_session_id_map_.erase(web_session_id); -} - -void ProxyMediaKeys::SavePromise(uint32_t session_id, - scoped_ptr<media::CdmPromise> promise) { - // Should only be one promise outstanding for any |session_id|. - DCHECK(!ContainsKey(session_id_to_promise_map_, session_id)); - session_id_to_promise_map_.add(session_id, promise.Pass()); -} - -scoped_ptr<media::CdmPromise> ProxyMediaKeys::TakePromise(uint32_t session_id) { - PromiseMap::iterator it = session_id_to_promise_map_.find(session_id); - // May not be a promise associated with this session for asynchronous events. - if (it == session_id_to_promise_map_.end()) - return scoped_ptr<media::CdmPromise>(); - return session_id_to_promise_map_.take_and_erase(it); +void ProxyMediaKeys::InitializeCdm( + const std::string& key_system, + const GURL& security_origin, + bool use_hw_secure_codecs, + scoped_ptr<media::SimpleCdmPromise> promise) { + uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); + manager_->InitializeCdm(cdm_id_, promise_id, this, key_system, + security_origin, use_hw_secure_codecs); } } // namespace content diff --git a/chromium/content/renderer/media/crypto/proxy_media_keys.h b/chromium/content/renderer/media/crypto/proxy_media_keys.h index 6b4df648276..b256dfa5e29 100644 --- a/chromium/content/renderer/media/crypto/proxy_media_keys.h +++ b/chromium/content/renderer/media/crypto/proxy_media_keys.h @@ -7,11 +7,15 @@ #include <map> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/containers/scoped_ptr_hash_map.h" +#include "media/base/cdm_context.h" +#include "media/base/cdm_factory.h" #include "media/base/cdm_promise.h" +#include "media/base/cdm_promise_adapter.h" #include "media/base/media_keys.h" class GURL; @@ -21,114 +25,95 @@ namespace content { class RendererCdmManager; // A MediaKeys proxy that wraps the EME part of RendererCdmManager. -class ProxyMediaKeys : public media::MediaKeys { +class ProxyMediaKeys : public media::MediaKeys, public media::CdmContext { public: - static scoped_ptr<ProxyMediaKeys> Create( + static void Create( const std::string& key_system, const GURL& security_origin, + bool use_hw_secure_codecs, RendererCdmManager* manager, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb); + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb); - virtual ~ProxyMediaKeys(); + ~ProxyMediaKeys() override; // MediaKeys implementation. - virtual void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + void SetServerCertificate( + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) override; - virtual void CreateSession( - const std::string& init_data_type, - const uint8* init_data, - int init_data_length, + void CreateSessionAndGenerateRequest( SessionType session_type, + media::EmeInitDataType init_data_type, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) override; - virtual void LoadSession( - const std::string& web_session_id, - scoped_ptr<media::NewSessionCdmPromise> promise) override; - virtual void UpdateSession( - const std::string& web_session_id, - const uint8* response, - int response_length, - scoped_ptr<media::SimpleCdmPromise> promise) override; - virtual void CloseSession( - const std::string& web_session_id, - scoped_ptr<media::SimpleCdmPromise> promise) override; - virtual void RemoveSession( - const std::string& web_session_id, - scoped_ptr<media::SimpleCdmPromise> promise) override; - virtual void GetUsableKeyIds( - const std::string& web_session_id, - scoped_ptr<media::KeyIdsPromise> promise) override; - virtual int GetCdmId() const override; + void LoadSession(SessionType session_type, + const std::string& session_id, + scoped_ptr<media::NewSessionCdmPromise> promise) override; + void UpdateSession(const std::string& session_id, + const std::vector<uint8_t>& response, + scoped_ptr<media::SimpleCdmPromise> promise) override; + void CloseSession(const std::string& session_id, + scoped_ptr<media::SimpleCdmPromise> promise) override; + void RemoveSession(const std::string& session_id, + scoped_ptr<media::SimpleCdmPromise> promise) override; + media::CdmContext* GetCdmContext() override; + + // media::CdmContext implementation. + media::Decryptor* GetDecryptor() override; + int GetCdmId() const override; // Callbacks. - void OnSessionCreated(uint32 session_id, const std::string& web_session_id); - void OnSessionMessage(uint32 session_id, - const std::vector<uint8>& message, - const GURL& destination_url); - void OnSessionReady(uint32 session_id); - void OnSessionClosed(uint32 session_id); - void OnSessionError(uint32 session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code); + void OnSessionMessage(const std::string& session_id, + media::MediaKeys::MessageType message_type, + const std::vector<uint8_t>& message, + const GURL& legacy_destination_url); + void OnSessionClosed(const std::string& session_id); + void OnLegacySessionError(const std::string& session_id, + media::MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message); + void OnSessionKeysChange(const std::string& session_id, + bool has_additional_usable_key, + media::CdmKeysInfo keys_info); + void OnSessionExpirationUpdate(const std::string& session_id, + const base::Time& new_expiry_time); + + void OnPromiseResolved(uint32_t promise_id); + void OnPromiseResolvedWithSession(uint32_t promise_id, + const std::string& session_id); + void OnPromiseRejected(uint32_t promise_id, + media::MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message); private: - // The Android-specific code that handles sessions uses integer session ids - // (basically a reference id), but media::MediaKeys bases everything on - // web_session_id (a string representing the actual session id as generated - // by the CDM). SessionIdMap is used to map between the web_session_id and - // the session_id used by the Android-specific code. - typedef base::hash_map<std::string, uint32_t> SessionIdMap; - - // The following types keep track of Promises. The index is the - // Android-specific session_id, so that returning results can be matched to - // the corresponding promise. - typedef base::ScopedPtrHashMap<uint32_t, media::CdmPromise> PromiseMap; - - ProxyMediaKeys(RendererCdmManager* manager, - const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, - const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb); + ProxyMediaKeys( + RendererCdmManager* manager, + const media::SessionMessageCB& session_message_cb, + const media::SessionClosedCB& session_closed_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, + const media::SessionKeysChangeCB& session_keys_change_cb, + const media::SessionExpirationUpdateCB& session_expiration_update_cb); void InitializeCdm(const std::string& key_system, - const GURL& security_origin); - - // These functions keep track of Android-specific session_ids <-> - // web_session_ids mappings. - // TODO(jrummell): Remove this once the Android-specific code changes to - // support string web session ids. - uint32_t CreateSessionId(); - void AssignWebSessionId(uint32_t session_id, - const std::string& web_session_id); - uint32_t LookupSessionId(const std::string& web_session_id) const; - std::string LookupWebSessionId(uint32_t session_id) const; - void DropWebSessionId(const std::string& web_session_id); - - // Helper function to keep track of promises. Adding takes ownership of the - // promise, transferred back to caller on take. - void SavePromise(uint32_t session_id, scoped_ptr<media::CdmPromise> promise); - scoped_ptr<media::CdmPromise> TakePromise(uint32_t session_id); + const GURL& security_origin, + bool use_hw_secure_codecs, + scoped_ptr<media::SimpleCdmPromise> promise); RendererCdmManager* manager_; int cdm_id_; media::SessionMessageCB session_message_cb_; - media::SessionReadyCB session_ready_cb_; media::SessionClosedCB session_closed_cb_; - media::SessionErrorCB session_error_cb_; - - // Android-specific. See comment above CreateSessionId(). - uint32_t next_session_id_; - SessionIdMap web_session_to_session_id_map_; + media::LegacySessionErrorCB legacy_session_error_cb_; + media::SessionKeysChangeCB session_keys_change_cb_; + media::SessionExpirationUpdateCB session_expiration_update_cb_; - // Keep track of outstanding promises. This map owns the promise object. - PromiseMap session_id_to_promise_map_; + media::CdmPromiseAdapter cdm_promise_adapter_; DISALLOW_COPY_AND_ASSIGN(ProxyMediaKeys); }; diff --git a/chromium/content/renderer/media/crypto/render_cdm_factory.cc b/chromium/content/renderer/media/crypto/render_cdm_factory.cc index 63fec99ed31..fe1a5dae2e9 100644 --- a/chromium/content/renderer/media/crypto/render_cdm_factory.cc +++ b/chromium/content/renderer/media/crypto/render_cdm_factory.cc @@ -4,11 +4,17 @@ #include "content/renderer/media/crypto/render_cdm_factory.h" +#include "base/bind.h" +#include "base/location.h" #include "base/logging.h" -#include "content/renderer/media/crypto/key_systems.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop_proxy.h" +#include "media/base/cdm_config.h" +#include "media/base/cdm_promise.h" +#include "media/base/key_systems.h" +#include "media/base/media_keys.h" #include "media/cdm/aes_decryptor.h" #include "url/gurl.h" - #if defined(ENABLE_PEPPER_CDMS) #include "content/renderer/media/crypto/ppapi_decryptor.h" #elif defined(ENABLE_BROWSER_CDMS) @@ -17,66 +23,76 @@ namespace content { -#if defined(ENABLE_PEPPER_CDMS) RenderCdmFactory::RenderCdmFactory( - const CreatePepperCdmCB& create_pepper_cdm_cb) - : create_pepper_cdm_cb_(create_pepper_cdm_cb) { -} +#if defined(ENABLE_PEPPER_CDMS) + const CreatePepperCdmCB& create_pepper_cdm_cb, #elif defined(ENABLE_BROWSER_CDMS) -RenderCdmFactory::RenderCdmFactory(RendererCdmManager* manager) - : manager_(manager) { -} -#else -RenderCdmFactory::RenderCdmFactory() { -} + RendererCdmManager* manager, #endif // defined(ENABLE_PEPPER_CDMS) + RenderFrame* render_frame) + : RenderFrameObserver(render_frame) +#if defined(ENABLE_PEPPER_CDMS) + , create_pepper_cdm_cb_(create_pepper_cdm_cb) +#elif defined(ENABLE_BROWSER_CDMS) + , manager_(manager) +#endif // defined(ENABLE_PEPPER_CDMS) +{ +} RenderCdmFactory::~RenderCdmFactory() { + DCHECK(thread_checker_.CalledOnValidThread()); } -scoped_ptr<media::MediaKeys> RenderCdmFactory::Create( +void RenderCdmFactory::Create( const std::string& key_system, const GURL& security_origin, + const media::CdmConfig& cdm_config, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb) { - // TODO(jrummell): Pass |security_origin| to all constructors. - // TODO(jrummell): Enable the following line once blink code updated to - // check the security origin before calling. - // DCHECK(security_origin.is_valid()); + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!security_origin.is_valid()) { + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(cdm_created_cb, nullptr, "Invalid origin.")); + return; + } - if (CanUseAesDecryptor(key_system)) { - return scoped_ptr<media::MediaKeys>(new media::AesDecryptor( - session_message_cb, session_closed_cb, session_keys_change_cb)); + if (media::CanUseAesDecryptor(key_system)) { + // TODO(sandersd): Currently the prefixed API always allows distinctive + // identifiers and persistent state. Once that changes we can sanity check + // here that neither is allowed for AesDecryptor, since it does not support + // them and should never be configured that way. http://crbug.com/455271 + scoped_ptr<media::MediaKeys> cdm( + new media::AesDecryptor(security_origin, session_message_cb, + session_closed_cb, session_keys_change_cb)); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, base::Bind(cdm_created_cb, base::Passed(&cdm), "")); + return; } #if defined(ENABLE_PEPPER_CDMS) - return scoped_ptr<media::MediaKeys>( - PpapiDecryptor::Create(key_system, - security_origin, - create_pepper_cdm_cb_, - session_message_cb, - session_ready_cb, - session_closed_cb, - session_error_cb, - session_keys_change_cb, - session_expiration_update_cb)); + DCHECK(!cdm_config.use_hw_secure_codecs); + PpapiDecryptor::Create( + key_system, security_origin, cdm_config.allow_distinctive_identifier, + cdm_config.allow_persistent_state, create_pepper_cdm_cb_, + session_message_cb, session_closed_cb, legacy_session_error_cb, + session_keys_change_cb, session_expiration_update_cb, cdm_created_cb); #elif defined(ENABLE_BROWSER_CDMS) - return scoped_ptr<media::MediaKeys>( - ProxyMediaKeys::Create(key_system, - security_origin, - manager_, - session_message_cb, - session_ready_cb, - session_closed_cb, - session_error_cb, - session_keys_change_cb, - session_expiration_update_cb)); + DCHECK(cdm_config.allow_distinctive_identifier); + DCHECK(cdm_config.allow_persistent_state); + ProxyMediaKeys::Create( + key_system, security_origin, cdm_config.use_hw_secure_codecs, manager_, + session_message_cb, session_closed_cb, legacy_session_error_cb, + session_keys_change_cb, session_expiration_update_cb, cdm_created_cb); #else - return nullptr; + // No possible CDM to create, so fail the request. + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, + base::Bind(cdm_created_cb, nullptr, "Key system not supported.")); #endif // defined(ENABLE_PEPPER_CDMS) } diff --git a/chromium/content/renderer/media/crypto/render_cdm_factory.h b/chromium/content/renderer/media/crypto/render_cdm_factory.h index f09f01bf433..80502db9332 100644 --- a/chromium/content/renderer/media/crypto/render_cdm_factory.h +++ b/chromium/content/renderer/media/crypto/render_cdm_factory.h @@ -8,6 +8,8 @@ #include <string> #include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" +#include "content/public/renderer/render_frame_observer.h" #include "media/base/cdm_factory.h" #include "media/base/media_keys.h" @@ -17,34 +19,41 @@ class GURL; +namespace media { +struct CdmConfig; +} // namespace media + namespace content { #if defined(ENABLE_BROWSER_CDMS) class RendererCdmManager; #endif -class RenderCdmFactory : public media::CdmFactory { +// CdmFactory implementation in content/renderer. This class is not thread safe +// and should only be used on one thread. +class RenderCdmFactory : public media::CdmFactory, public RenderFrameObserver { public: + RenderCdmFactory( #if defined(ENABLE_PEPPER_CDMS) - explicit RenderCdmFactory(const CreatePepperCdmCB& create_pepper_cdm_cb); + const CreatePepperCdmCB& create_pepper_cdm_cb, #elif defined(ENABLE_BROWSER_CDMS) - explicit RenderCdmFactory(RendererCdmManager* manager); -#else - RenderCdmFactory(); + RendererCdmManager* manager, #endif // defined(ENABLE_PEPPER_CDMS) + RenderFrame* render_frame); ~RenderCdmFactory() override; - scoped_ptr<media::MediaKeys> Create( + // CdmFactory implementation. + void Create( const std::string& key_system, const GURL& security_origin, + const media::CdmConfig& cdm_config, const media::SessionMessageCB& session_message_cb, - const media::SessionReadyCB& session_ready_cb, const media::SessionClosedCB& session_closed_cb, - const media::SessionErrorCB& session_error_cb, + const media::LegacySessionErrorCB& legacy_session_error_cb, const media::SessionKeysChangeCB& session_keys_change_cb, - const media::SessionExpirationUpdateCB& session_expiration_update_cb) - override; + const media::SessionExpirationUpdateCB& session_expiration_update_cb, + const media::CdmCreatedCB& cdm_created_cb) override; private: #if defined(ENABLE_PEPPER_CDMS) @@ -54,6 +63,8 @@ class RenderCdmFactory : public media::CdmFactory { RendererCdmManager* manager_; #endif + base::ThreadChecker thread_checker_; + DISALLOW_COPY_AND_ASSIGN(RenderCdmFactory); }; diff --git a/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc b/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc index 3bfdc6e0709..be9c5eaade7 100644 --- a/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc +++ b/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc @@ -7,18 +7,21 @@ #include "base/stl_util.h" #include "content/common/media/cdm_messages.h" #include "content/renderer/media/crypto/proxy_media_keys.h" +#include "media/base/cdm_context.h" +#include "media/base/limits.h" namespace content { +using media::MediaKeys; + // Maximum sizes for various EME API parameters. These are checks to prevent // unnecessarily large messages from being passed around, and the sizes // are somewhat arbitrary as the EME spec doesn't specify any limits. -const size_t kMaxWebSessionIdLength = 512; const size_t kMaxSessionMessageLength = 10240; // 10 KB RendererCdmManager::RendererCdmManager(RenderFrame* render_frame) : RenderFrameObserver(render_frame), - next_cdm_id_(media::MediaKeys::kInvalidCdmId + 1) { + next_cdm_id_(media::CdmContext::kInvalidCdmId + 1) { } RendererCdmManager::~RendererCdmManager() { @@ -30,46 +33,69 @@ RendererCdmManager::~RendererCdmManager() { bool RendererCdmManager::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RendererCdmManager, msg) - IPC_MESSAGE_HANDLER(CdmMsg_SessionCreated, OnSessionCreated) IPC_MESSAGE_HANDLER(CdmMsg_SessionMessage, OnSessionMessage) - IPC_MESSAGE_HANDLER(CdmMsg_SessionReady, OnSessionReady) IPC_MESSAGE_HANDLER(CdmMsg_SessionClosed, OnSessionClosed) - IPC_MESSAGE_HANDLER(CdmMsg_SessionError, OnSessionError) + IPC_MESSAGE_HANDLER(CdmMsg_LegacySessionError, OnLegacySessionError) + IPC_MESSAGE_HANDLER(CdmMsg_SessionKeysChange, OnSessionKeysChange) + IPC_MESSAGE_HANDLER(CdmMsg_SessionExpirationUpdate, + OnSessionExpirationUpdate) + IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromise, OnPromiseResolved) + IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromiseWithSession, + OnPromiseResolvedWithSession) + IPC_MESSAGE_HANDLER(CdmMsg_RejectPromise, OnPromiseRejected) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void RendererCdmManager::InitializeCdm(int cdm_id, + uint32_t promise_id, ProxyMediaKeys* media_keys, const std::string& key_system, - const GURL& security_origin) { + const GURL& security_origin, + bool use_hw_secure_codecs) { + DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; + CdmHostMsg_InitializeCdm_Params params; + params.key_system = key_system; + params.security_origin = security_origin; + params.use_hw_secure_codecs = use_hw_secure_codecs; + Send(new CdmHostMsg_InitializeCdm(routing_id(), cdm_id, promise_id, params)); +} + +void RendererCdmManager::SetServerCertificate( + int cdm_id, + uint32_t promise_id, + const std::vector<uint8_t>& certificate) { DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; - Send(new CdmHostMsg_InitializeCdm( - routing_id(), cdm_id, key_system, security_origin)); + Send(new CdmHostMsg_SetServerCertificate(routing_id(), cdm_id, promise_id, + certificate)); } -void RendererCdmManager::CreateSession( +void RendererCdmManager::CreateSessionAndGenerateRequest( int cdm_id, - uint32 session_id, - CdmHostMsg_CreateSession_ContentType content_type, - const std::vector<uint8>& init_data) { + uint32_t promise_id, + CdmHostMsg_CreateSession_InitDataType init_data_type, + const std::vector<uint8_t>& init_data) { DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; - Send(new CdmHostMsg_CreateSession( - routing_id(), cdm_id, session_id, content_type, init_data)); + Send(new CdmHostMsg_CreateSessionAndGenerateRequest( + routing_id(), cdm_id, promise_id, init_data_type, init_data)); } void RendererCdmManager::UpdateSession(int cdm_id, - uint32 session_id, - const std::vector<uint8>& response) { + uint32_t promise_id, + const std::string& session_id, + const std::vector<uint8_t>& response) { DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; - Send( - new CdmHostMsg_UpdateSession(routing_id(), cdm_id, session_id, response)); + Send(new CdmHostMsg_UpdateSession(routing_id(), cdm_id, promise_id, + session_id, response)); } -void RendererCdmManager::ReleaseSession(int cdm_id, uint32 session_id) { +void RendererCdmManager::CloseSession(int cdm_id, + uint32_t promise_id, + const std::string& session_id) { DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; - Send(new CdmHostMsg_ReleaseSession(routing_id(), cdm_id, session_id)); + Send(new CdmHostMsg_CloseSession(routing_id(), cdm_id, promise_id, + session_id)); } void RendererCdmManager::DestroyCdm(int cdm_id) { @@ -77,57 +103,106 @@ void RendererCdmManager::DestroyCdm(int cdm_id) { Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id)); } -void RendererCdmManager::OnSessionCreated(int cdm_id, - uint32 session_id, - const std::string& web_session_id) { - if (web_session_id.length() > kMaxWebSessionIdLength) { - OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); +void RendererCdmManager::OnSessionMessage( + int cdm_id, + const std::string& session_id, + media::MediaKeys::MessageType message_type, + const std::vector<uint8>& message, + const GURL& legacy_destination_url) { + if (message.size() > kMaxSessionMessageLength) { + NOTREACHED(); + LOG(ERROR) << "Message is too long and dropped."; return; } ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); if (media_keys) - media_keys->OnSessionCreated(session_id, web_session_id); + media_keys->OnSessionMessage(session_id, message_type, message, + legacy_destination_url); } -void RendererCdmManager::OnSessionMessage(int cdm_id, - uint32 session_id, - const std::vector<uint8>& message, - const GURL& destination_url) { - if (message.size() > kMaxSessionMessageLength) { - OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); +void RendererCdmManager::OnSessionClosed(int cdm_id, + const std::string& session_id) { + ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); + if (media_keys) + media_keys->OnSessionClosed(session_id); +} + +void RendererCdmManager::OnLegacySessionError( + int cdm_id, + const std::string& session_id, + MediaKeys::Exception exception, + uint32 system_code, + const std::string& error_message) { + ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); + if (media_keys) + media_keys->OnLegacySessionError(session_id, exception, system_code, + error_message); +} + +void RendererCdmManager::OnSessionKeysChange( + int cdm_id, + const std::string& session_id, + bool has_additional_usable_key, + const std::vector<media::CdmKeyInformation>& key_info_vector) { + ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); + if (!media_keys) return; - } + media::CdmKeysInfo keys_info; + keys_info.reserve(key_info_vector.size()); + for (const auto& key_info : key_info_vector) + keys_info.push_back(new media::CdmKeyInformation(key_info)); + + media_keys->OnSessionKeysChange(session_id, has_additional_usable_key, + keys_info.Pass()); +} + +void RendererCdmManager::OnSessionExpirationUpdate( + int cdm_id, + const std::string& session_id, + const base::Time& new_expiry_time) { ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); if (media_keys) - media_keys->OnSessionMessage(session_id, message, destination_url); + media_keys->OnSessionExpirationUpdate(session_id, new_expiry_time); } -void RendererCdmManager::OnSessionReady(int cdm_id, uint32 session_id) { +void RendererCdmManager::OnPromiseResolved(int cdm_id, uint32_t promise_id) { ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); if (media_keys) - media_keys->OnSessionReady(session_id); + media_keys->OnPromiseResolved(promise_id); } -void RendererCdmManager::OnSessionClosed(int cdm_id, uint32 session_id) { +void RendererCdmManager::OnPromiseResolvedWithSession( + int cdm_id, + uint32_t promise_id, + const std::string& session_id) { + if (session_id.length() > media::limits::kMaxSessionIdLength) { + NOTREACHED(); + OnPromiseRejected(cdm_id, promise_id, MediaKeys::INVALID_ACCESS_ERROR, 0, + "Session ID is too long"); + return; + } + ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); if (media_keys) - media_keys->OnSessionClosed(session_id); + media_keys->OnPromiseResolvedWithSession(promise_id, session_id); } -void RendererCdmManager::OnSessionError(int cdm_id, - uint32 session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code) { +void RendererCdmManager::OnPromiseRejected(int cdm_id, + uint32_t promise_id, + MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message) { ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); if (media_keys) - media_keys->OnSessionError(session_id, error_code, system_code); + media_keys->OnPromiseRejected(promise_id, exception, system_code, + error_message); } int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys* media_keys) { int cdm_id = next_cdm_id_++; - DCHECK_NE(cdm_id, media::MediaKeys::kInvalidCdmId); + DCHECK_NE(cdm_id, media::CdmContext::kInvalidCdmId); DCHECK(!ContainsKey(proxy_media_keys_map_, cdm_id)); proxy_media_keys_map_[cdm_id] = media_keys; return cdm_id; diff --git a/chromium/content/renderer/media/crypto/renderer_cdm_manager.h b/chromium/content/renderer/media/crypto/renderer_cdm_manager.h index 4944144685d..1ab051324e6 100644 --- a/chromium/content/renderer/media/crypto/renderer_cdm_manager.h +++ b/chromium/content/renderer/media/crypto/renderer_cdm_manager.h @@ -28,24 +28,33 @@ class RendererCdmManager : public RenderFrameObserver { public: // Constructs a RendererCdmManager object for the |render_frame|. explicit RendererCdmManager(RenderFrame* render_frame); - virtual ~RendererCdmManager(); + ~RendererCdmManager() override; // RenderFrameObserver overrides. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; // Encrypted media related methods. void InitializeCdm(int cdm_id, + uint32_t promise_id, ProxyMediaKeys* media_keys, const std::string& key_system, - const GURL& security_origin); - void CreateSession(int cdm_id, - uint32 session_id, - CdmHostMsg_CreateSession_ContentType conent_type, - const std::vector<uint8>& init_data); + const GURL& security_origin, + bool use_hw_secure_codecs); + void SetServerCertificate(int cdm_id, + uint32_t promise_id, + const std::vector<uint8>& certificate); + void CreateSessionAndGenerateRequest( + int cdm_id, + uint32_t promise_id, + CdmHostMsg_CreateSession_InitDataType init_data_type, + const std::vector<uint8>& init_data); void UpdateSession(int cdm_id, - uint32 session_id, + uint32_t promise_id, + const std::string& session_id, const std::vector<uint8>& response); - void ReleaseSession(int cdm_id, uint32 session_id); + void CloseSession(int cdm_id, + uint32_t promise_id, + const std::string& session_id); void DestroyCdm(int cdm_id); // Registers a ProxyMediaKeys object. Returns allocated CDM ID. @@ -59,19 +68,35 @@ class RendererCdmManager : public RenderFrameObserver { ProxyMediaKeys* GetMediaKeys(int cdm_id); // Message handlers. - void OnSessionCreated(int cdm_id, - uint32 session_id, - const std::string& web_session_id); void OnSessionMessage(int cdm_id, - uint32 session_id, + const std::string& session_id, + media::MediaKeys::MessageType message_type, const std::vector<uint8>& message, - const GURL& destination_url); - void OnSessionReady(int cdm_id, uint32 session_id); - void OnSessionClosed(int cdm_id, uint32 session_id); - void OnSessionError(int cdm_id, - uint32 session_id, - media::MediaKeys::KeyError error_code, - uint32 system_code); + const GURL& legacy_destination_url); + void OnSessionClosed(int cdm_id, const std::string& session_id); + void OnLegacySessionError(int cdm_id, + const std::string& session_id, + media::MediaKeys::Exception exception, + uint32 system_code, + const std::string& error_message); + void OnSessionKeysChange( + int cdm_id, + const std::string& session_id, + bool has_additional_usable_key, + const std::vector<media::CdmKeyInformation>& key_info_vector); + void OnSessionExpirationUpdate(int cdm_id, + const std::string& session_id, + const base::Time& new_expiry_time); + + void OnPromiseResolved(int cdm_id, uint32_t promise_id); + void OnPromiseResolvedWithSession(int cdm_id, + uint32_t promise_id, + const std::string& session_id); + void OnPromiseRejected(int cdm_id, + uint32_t promise_id, + media::MediaKeys::Exception exception, + uint32_t system_code, + const std::string& error_message); // CDM ID should be unique per renderer frame. // TODO(xhwang): Use uint32 to prevent undefined overflow behavior. |