| Index: media/cdm/proxy_decryptor.cc
|
| diff --git a/media/cdm/proxy_decryptor.cc b/media/cdm/proxy_decryptor.cc
|
| index 944b61405c415927b8bda4e8d1e30ebc0e5fb844..6a1c9f8d5467ddbc3c2af5203f24be973431760e 100644
|
| --- a/media/cdm/proxy_decryptor.cc
|
| +++ b/media/cdm/proxy_decryptor.cc
|
| @@ -25,11 +25,22 @@ namespace media {
|
| // EME API.
|
| const int kSessionClosedSystemCode = 29127;
|
|
|
| +ProxyDecryptor::PendingGenerateKeyRequestData::PendingGenerateKeyRequestData(
|
| + EmeInitDataType init_data_type,
|
| + const std::vector<uint8>& init_data)
|
| + : init_data_type(init_data_type), init_data(init_data) {
|
| +}
|
| +
|
| +ProxyDecryptor::PendingGenerateKeyRequestData::
|
| + ~PendingGenerateKeyRequestData() {
|
| +}
|
| +
|
| ProxyDecryptor::ProxyDecryptor(MediaPermission* media_permission,
|
| const KeyAddedCB& key_added_cb,
|
| const KeyErrorCB& key_error_cb,
|
| const KeyMessageCB& key_message_cb)
|
| - : media_permission_(media_permission),
|
| + : is_creating_cdm_(false),
|
| + media_permission_(media_permission),
|
| key_added_cb_(key_added_cb),
|
| key_error_cb_(key_error_cb),
|
| key_message_cb_(key_message_cb),
|
| @@ -46,33 +57,77 @@ ProxyDecryptor::~ProxyDecryptor() {
|
| media_keys_.reset();
|
| }
|
|
|
| -CdmContext* ProxyDecryptor::GetCdmContext() {
|
| - return media_keys_ ? media_keys_->GetCdmContext() : nullptr;
|
| +void ProxyDecryptor::CreateCdm(CdmFactory* cdm_factory,
|
| + const std::string& key_system,
|
| + const GURL& security_origin,
|
| + const SetCdmContextCB& set_cdm_context_cb) {
|
| + DVLOG(1) << __FUNCTION__ << ": key_system = " << key_system;
|
| + DCHECK(!is_creating_cdm_);
|
| + DCHECK(!media_keys_);
|
| +
|
| + // TODO(sandersd): Trigger permissions check here and use it to determine
|
| + // distinctive identifier support, instead of always requiring the
|
| + // permission. http://crbug.com/455271
|
| + bool allow_distinctive_identifier = true;
|
| + bool allow_persistent_state = true;
|
| +
|
| + is_creating_cdm_ = true;
|
| +
|
| + base::WeakPtr<ProxyDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
|
| + cdm_factory->Create(
|
| + key_system, allow_distinctive_identifier, allow_persistent_state,
|
| + security_origin, base::Bind(&ProxyDecryptor::OnSessionMessage, weak_this),
|
| + base::Bind(&ProxyDecryptor::OnSessionClosed, weak_this),
|
| + base::Bind(&ProxyDecryptor::OnLegacySessionError, weak_this),
|
| + base::Bind(&ProxyDecryptor::OnSessionKeysChange, weak_this),
|
| + base::Bind(&ProxyDecryptor::OnSessionExpirationUpdate, weak_this),
|
| + base::Bind(&ProxyDecryptor::OnCdmCreated, weak_this, key_system,
|
| + security_origin, set_cdm_context_cb));
|
| }
|
|
|
| -bool ProxyDecryptor::InitializeCDM(CdmFactory* cdm_factory,
|
| - const std::string& key_system,
|
| - const GURL& security_origin) {
|
| - DVLOG(1) << "InitializeCDM: key_system = " << key_system;
|
| +void ProxyDecryptor::OnCdmCreated(const std::string& key_system,
|
| + const GURL& security_origin,
|
| + const SetCdmContextCB& set_cdm_context_cb,
|
| + scoped_ptr<MediaKeys> cdm) {
|
| + is_creating_cdm_ = false;
|
|
|
| - DCHECK(!media_keys_);
|
| - media_keys_ = CreateMediaKeys(cdm_factory, key_system, security_origin);
|
| - if (!media_keys_)
|
| - return false;
|
| + if (!cdm) {
|
| + set_cdm_context_cb.Run(nullptr, base::Bind(&IgnoreCdmAttached));
|
| + return;
|
| + }
|
|
|
| key_system_ = key_system;
|
| security_origin_ = security_origin;
|
| + is_clear_key_ = IsClearKey(key_system) || IsExternalClearKey(key_system);
|
| + media_keys_ = cdm.Pass();
|
| +
|
| + set_cdm_context_cb.Run(media_keys_->GetCdmContext(),
|
| + base::Bind(&IgnoreCdmAttached));
|
|
|
| - is_clear_key_ =
|
| - IsClearKey(key_system) || IsExternalClearKey(key_system);
|
| - return true;
|
| + for (const auto& request : pending_requests_)
|
| + GenerateKeyRequestInternal(request.init_data_type, request.init_data);
|
| + pending_requests_.clear();
|
| +}
|
| +
|
| +void ProxyDecryptor::GenerateKeyRequest(EmeInitDataType init_data_type,
|
| + const uint8* init_data,
|
| + int init_data_length) {
|
| + std::vector<uint8> init_data_vector(init_data, init_data + init_data_length);
|
| +
|
| + if (is_creating_cdm_) {
|
| + pending_requests_.push_back(
|
| + PendingGenerateKeyRequestData(init_data_type, init_data_vector));
|
| + return;
|
| + }
|
| +
|
| + GenerateKeyRequestInternal(init_data_type, init_data_vector);
|
| }
|
|
|
| // 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());
|
| +bool HasHeader(const std::vector<uint8>& data, const std::string& header) {
|
| + return data.size() > header.size() &&
|
| + std::equal(header.begin(), header.end(), data.begin());
|
| }
|
|
|
| // Removes the first |length| items from |data|.
|
| @@ -80,23 +135,30 @@ void StripHeader(std::vector<uint8>& data, size_t length) {
|
| data.erase(data.begin(), data.begin() + length);
|
| }
|
|
|
| -bool ProxyDecryptor::GenerateKeyRequest(EmeInitDataType init_data_type,
|
| - const uint8* init_data,
|
| - int init_data_length) {
|
| - DVLOG(1) << "GenerateKeyRequest()";
|
| +void ProxyDecryptor::GenerateKeyRequestInternal(
|
| + EmeInitDataType init_data_type,
|
| + const std::vector<uint8>& init_data) {
|
| + DVLOG(1) << __FUNCTION__;
|
| + DCHECK(!is_creating_cdm_);
|
| +
|
| + if (!media_keys_) {
|
| + OnLegacySessionError(std::string(), MediaKeys::NOT_SUPPORTED_ERROR, 0,
|
| + "CDM creation failed.");
|
| + return;
|
| + }
|
| +
|
| 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)) {
|
| + std::vector<uint8> stripped_init_data = init_data;
|
| + if (HasHeader(init_data, kPrefixedApiLoadSessionHeader)) {
|
| session_creation_type = LoadSession;
|
| - StripHeader(init_data_vector, strlen(kPrefixedApiLoadSessionHeader));
|
| - } else if (HasHeader(init_data,
|
| - init_data_length,
|
| - kPrefixedApiPersistentSessionHeader)) {
|
| + StripHeader(stripped_init_data, strlen(kPrefixedApiLoadSessionHeader));
|
| + } else if (HasHeader(init_data, kPrefixedApiPersistentSessionHeader)) {
|
| session_creation_type = PersistentSession;
|
| - StripHeader(init_data_vector, strlen(kPrefixedApiPersistentSessionHeader));
|
| + StripHeader(stripped_init_data,
|
| + strlen(kPrefixedApiPersistentSessionHeader));
|
| }
|
|
|
| scoped_ptr<NewSessionCdmPromise> promise(new CdmCallbackPromise<std::string>(
|
| @@ -110,10 +172,10 @@ bool ProxyDecryptor::GenerateKeyRequest(EmeInitDataType init_data_type,
|
| media_keys_->LoadSession(
|
| MediaKeys::PERSISTENT_LICENSE_SESSION,
|
| std::string(
|
| - reinterpret_cast<const char*>(vector_as_array(&init_data_vector)),
|
| - init_data_vector.size()),
|
| + reinterpret_cast<const char*>(vector_as_array(&stripped_init_data)),
|
| + stripped_init_data.size()),
|
| promise.Pass());
|
| - return true;
|
| + return;
|
| }
|
|
|
| MediaKeys::SessionType session_type =
|
| @@ -125,9 +187,9 @@ bool ProxyDecryptor::GenerateKeyRequest(EmeInitDataType init_data_type,
|
| // external clear key.
|
| DCHECK(!key_system_.empty());
|
| if (CanUseAesDecryptor(key_system_) || IsExternalClearKey(key_system_)) {
|
| - OnPermissionStatus(session_type, init_data_type, init_data_vector,
|
| + OnPermissionStatus(session_type, init_data_type, stripped_init_data,
|
| promise.Pass(), true /* granted */);
|
| - return true;
|
| + return;
|
| }
|
|
|
| #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
| @@ -135,13 +197,11 @@ bool ProxyDecryptor::GenerateKeyRequest(EmeInitDataType init_data_type,
|
| MediaPermission::PROTECTED_MEDIA_IDENTIFIER, security_origin_,
|
| base::Bind(&ProxyDecryptor::OnPermissionStatus,
|
| weak_ptr_factory_.GetWeakPtr(), session_type, init_data_type,
|
| - init_data_vector, base::Passed(&promise)));
|
| + stripped_init_data, base::Passed(&promise)));
|
| #else
|
| - OnPermissionStatus(session_type, init_data_type, init_data_vector,
|
| + OnPermissionStatus(session_type, init_data_type, stripped_init_data,
|
| promise.Pass(), true /* granted */);
|
| #endif
|
| -
|
| - return true;
|
| }
|
|
|
| void ProxyDecryptor::OnPermissionStatus(
|
| @@ -168,6 +228,12 @@ void ProxyDecryptor::AddKey(const uint8* key,
|
| const std::string& session_id) {
|
| DVLOG(1) << "AddKey()";
|
|
|
| + if (!media_keys_) {
|
| + OnLegacySessionError(std::string(), MediaKeys::INVALID_STATE_ERROR, 0,
|
| + "CDM creation failed.");
|
| + return;
|
| + }
|
| +
|
| // In the prefixed API, the session parameter provided to addKey() is
|
| // optional, so use the single existing session if it exists.
|
| std::string new_session_id(session_id);
|
| @@ -216,6 +282,12 @@ void ProxyDecryptor::AddKey(const uint8* key,
|
| void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
|
| DVLOG(1) << "CancelKeyRequest()";
|
|
|
| + if (!media_keys_) {
|
| + OnLegacySessionError(std::string(), MediaKeys::INVALID_STATE_ERROR, 0,
|
| + "CDM creation failed.");
|
| + return;
|
| + }
|
| +
|
| scoped_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>(
|
| base::Bind(&ProxyDecryptor::OnSessionClosed,
|
| weak_ptr_factory_.GetWeakPtr(), session_id),
|
| @@ -224,25 +296,6 @@ void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
|
| media_keys_->RemoveSession(session_id, promise.Pass());
|
| }
|
|
|
| -scoped_ptr<MediaKeys> ProxyDecryptor::CreateMediaKeys(
|
| - CdmFactory* cdm_factory,
|
| - const std::string& key_system,
|
| - const GURL& security_origin) {
|
| - // TODO(sandersd): Trigger permissions check here and use it to determine
|
| - // distinctive identifier support, instead of always requiring the
|
| - // permission. http://crbug.com/455271
|
| - bool allow_distinctive_identifier = true;
|
| - bool allow_persistent_state = true;
|
| - base::WeakPtr<ProxyDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
|
| - return cdm_factory->Create(
|
| - key_system, allow_distinctive_identifier, allow_persistent_state,
|
| - security_origin, base::Bind(&ProxyDecryptor::OnSessionMessage, weak_this),
|
| - base::Bind(&ProxyDecryptor::OnSessionClosed, weak_this),
|
| - base::Bind(&ProxyDecryptor::OnLegacySessionError, weak_this),
|
| - base::Bind(&ProxyDecryptor::OnSessionKeysChange, weak_this),
|
| - base::Bind(&ProxyDecryptor::OnSessionExpirationUpdate, weak_this));
|
| -}
|
| -
|
| void ProxyDecryptor::OnSessionMessage(const std::string& session_id,
|
| MediaKeys::MessageType message_type,
|
| const std::vector<uint8>& message,
|
|
|