Chromium Code Reviews| Index: content/renderer/media/crypto/proxy_decryptor.cc |
| diff --git a/content/renderer/media/crypto/proxy_decryptor.cc b/content/renderer/media/crypto/proxy_decryptor.cc |
| index 95fe49ffc7ee4f3bac4a105568943868ed3cd8a7..9cb8dacc8c9234a3f00832f15468b626e32a7689 100644 |
| --- a/content/renderer/media/crypto/proxy_decryptor.cc |
| +++ b/content/renderer/media/crypto/proxy_decryptor.cc |
| @@ -11,6 +11,7 @@ |
| #include "base/logging.h" |
| #include "base/strings/string_util.h" |
| #include "content/renderer/media/crypto/content_decryption_module_factory.h" |
| +#include "media/base/media_keys_session_promise.h" |
| #include "media/cdm/json_web_key.h" |
| #include "media/cdm/key_system_names.h" |
| @@ -24,14 +25,6 @@ |
| namespace content { |
| -// Since these reference IDs may conflict with the ones generated in |
| -// WebContentDecryptionModuleSessionImpl for the short time both paths are |
| -// active, start with 100000 and generate the IDs from there. |
| -// TODO(jrummell): Only allow one path http://crbug.com/306680. |
| -uint32 ProxyDecryptor::next_session_id_ = 100000; |
| - |
| -const uint32 kInvalidSessionId = 0; |
| - |
| // 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. |
| @@ -105,28 +98,46 @@ bool HasHeader(const uint8* data, int data_length, const std::string& header) { |
| bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type, |
| const uint8* init_data, |
| int init_data_length) { |
| - // Use a unique reference id for this request. |
| - uint32 session_id = next_session_id_++; |
| - |
| const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|"; |
| const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|"; |
| + DVLOG(1) << "GenerateKeyRequest()"; |
| if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) { |
| - persistent_sessions_.insert(session_id); |
| + scoped_ptr<media::MediaKeysSessionPromise> promise( |
| + new media::MediaKeysSessionPromise( |
| + media::PromiseResolvedCB(), |
| + base::Bind(&ProxyDecryptor::SetSessionId, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + true), // Persistent session. |
| + base::Bind(&ProxyDecryptor::OnSessionError, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + std::string()))); // No session id until created. |
| media_keys_->LoadSession( |
| - session_id, |
| std::string(reinterpret_cast<const char*>( |
| init_data + strlen(kPrefixedApiLoadSessionHeader)), |
| - init_data_length - strlen(kPrefixedApiLoadSessionHeader))); |
| + init_data_length - strlen(kPrefixedApiLoadSessionHeader)), |
| + promise.Pass()); |
| return true; |
| } |
| - if (HasHeader( |
| - init_data, init_data_length, kPrefixedApiPersistentSessionHeader)) |
| - persistent_sessions_.insert(session_id); |
| - |
| - return media_keys_->CreateSession( |
| - session_id, content_type, init_data, init_data_length); |
| + bool persistent = HasHeader( |
| + init_data, init_data_length, kPrefixedApiPersistentSessionHeader); |
| + media::MediaKeys::SessionType session_type = |
| + persistent ? media::MediaKeys::SessionType::kPersistent |
|
xhwang
2014/05/05 20:46:42
The "SessionType::" part isn't needed.
jrummell
2014/05/08 23:37:45
Done.
|
| + : media::MediaKeys::SessionType::kTemporary; |
| + |
| + scoped_ptr<media::MediaKeysSessionPromise> promise( |
| + new media::MediaKeysSessionPromise( |
| + media::PromiseResolvedCB(), |
| + base::Bind(&ProxyDecryptor::SetSessionId, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + persistent), |
| + base::Bind(&ProxyDecryptor::OnSessionError, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + std::string()))); |
| + media_keys_->CreateSession( |
| + content_type, init_data, init_data_length, session_type, promise.Pass()); |
| + return true; |
| } |
| void ProxyDecryptor::AddKey(const uint8* key, |
| @@ -136,18 +147,29 @@ void ProxyDecryptor::AddKey(const uint8* key, |
| const std::string& web_session_id) { |
| DVLOG(1) << "AddKey()"; |
| - // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. |
| - uint32 session_id = LookupSessionId(web_session_id); |
| - if (session_id == kInvalidSessionId) { |
| - // Session hasn't been referenced before, so it is an error. |
| - // Note that the specification says "If sessionId is not null and is |
| - // unrecognized, throw an INVALID_ACCESS_ERR." However, for backwards |
| - // compatibility the error is not thrown, but rather reported as a |
| - // KeyError. |
| - key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); |
| - return; |
| + // If |web_session_id| is null, then use the single reference id. |
| + std::string session_id(web_session_id); |
| + if (session_id.empty()) { |
| + if (active_sessions_.size() == 1) { |
| + std::set<std::string>::iterator it = active_sessions_.begin(); |
| + session_id = *it; |
| + } else { |
| + OnSessionError( |
| + std::string(), "NotSupportedError", 0, "SessionId not specified."); |
| + return; |
| + } |
| } |
| + scoped_ptr<media::MediaKeysSessionPromise> promise( |
| + new media::MediaKeysSessionPromise( |
| + base::Bind(&ProxyDecryptor::OnSessionReady, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + web_session_id), |
| + media::PromiseResolvedWithSessionCB(), |
| + 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, |
| @@ -164,27 +186,29 @@ void ProxyDecryptor::AddKey(const uint8* key, |
| 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()); |
| + media_keys_->UpdateSession(session_id, |
| + reinterpret_cast<const uint8*>(jwk.data()), |
| + jwk.size(), |
| + promise.Pass()); |
| return; |
| } |
| - media_keys_->UpdateSession(session_id, key, key_length); |
| + media_keys_->UpdateSession(session_id, key, key_length, promise.Pass()); |
| } |
| -void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) { |
| +void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { |
| DVLOG(1) << "CancelKeyRequest()"; |
| - // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. |
| - uint32 session_reference_id = LookupSessionId(session_id); |
| - if (session_reference_id == kInvalidSessionId) { |
| - // Session hasn't been created, so it is an error. |
| - key_error_cb_.Run( |
| - std::string(), media::MediaKeys::kUnknownError, 0); |
| - } |
| - else { |
| - media_keys_->ReleaseSession(session_reference_id); |
| - } |
| + scoped_ptr<media::MediaKeysSessionPromise> promise( |
| + new media::MediaKeysSessionPromise( |
| + base::Bind(&ProxyDecryptor::OnSessionClosed, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + web_session_id), |
| + media::PromiseResolvedWithSessionCB(), |
| + base::Bind(&ProxyDecryptor::OnSessionError, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + web_session_id))); |
| + media_keys_->ReleaseSession(web_session_id, promise.Pass()); |
| } |
| scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( |
| @@ -199,8 +223,6 @@ scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( |
| manager_, |
| &cdm_id_, |
| #endif // defined(ENABLE_PEPPER_CDMS) |
| - base::Bind(&ProxyDecryptor::OnSessionCreated, |
| - weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&ProxyDecryptor::OnSessionMessage, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&ProxyDecryptor::OnSessionReady, |
| @@ -211,67 +233,56 @@ scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| -void ProxyDecryptor::OnSessionCreated(uint32 session_id, |
| - const std::string& web_session_id) { |
| - // Due to heartbeat messages, OnSessionCreated() can get called multiple |
| - // times. |
| - SessionIdMap::iterator it = sessions_.find(session_id); |
| - DCHECK(it == sessions_.end() || it->second == web_session_id); |
| - if (it == sessions_.end()) |
| - sessions_[session_id] = web_session_id; |
| -} |
| - |
| -void ProxyDecryptor::OnSessionMessage(uint32 session_id, |
| +void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id, |
| const std::vector<uint8>& message, |
| const std::string& destination_url) { |
| - // Assumes that OnSessionCreated() has been called before this. |
| - key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url); |
| + key_message_cb_.Run(web_session_id, message, destination_url); |
| } |
| -void ProxyDecryptor::OnSessionReady(uint32 session_id) { |
| - // Assumes that OnSessionCreated() has been called before this. |
| - key_added_cb_.Run(LookupWebSessionId(session_id)); |
| +void ProxyDecryptor::OnSessionReady(const std::string& web_session_id) { |
| + key_added_cb_.Run(web_session_id); |
| } |
| -void ProxyDecryptor::OnSessionClosed(uint32 session_id) { |
| - std::set<uint32>::iterator it = persistent_sessions_.find(session_id); |
| +void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { |
| + std::set<std::string>::iterator it = |
| + persistent_sessions_.find(web_session_id); |
| + active_sessions_.erase(web_session_id); |
| if (it != persistent_sessions_.end()) { |
| persistent_sessions_.erase(it); |
| - OnSessionError( |
| - session_id, media::MediaKeys::kUnknownError, kSessionClosedSystemCode); |
| + OnSessionError(web_session_id, |
| + "NotSupportedError", |
| + kSessionClosedSystemCode, |
| + "Do not close persistent sessions."); |
| } |
| - |
| - sessions_.erase(session_id); |
| } |
| -void ProxyDecryptor::OnSessionError(uint32 session_id, |
| - media::MediaKeys::KeyError error_code, |
| - uint32 system_code) { |
| - // Assumes that OnSessionCreated() has been called before this. |
| - key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code); |
| -} |
| - |
| -uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) const { |
| - for (SessionIdMap::const_iterator it = sessions_.begin(); |
| - it != sessions_.end(); |
| - ++it) { |
| - if (it->second == session_id) |
| - return it->first; |
| +void ProxyDecryptor::OnSessionError(const std::string& web_session_id, |
| + const std::string& error_name, |
| + 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. |
| + if (error_name == "CDM4ClientError") { |
| + key_error_cb_.Run( |
| + web_session_id, media::MediaKeys::KeyError::kClientError, system_code); |
| + } else if (error_name == "CDM4OutputError") { |
| + key_error_cb_.Run( |
| + web_session_id, media::MediaKeys::KeyError::kOutputError, system_code); |
| + } else { |
| + // This will include all other CDM4 errors and any error generated |
| + // by CDM5 or later. |
| + key_error_cb_.Run( |
| + web_session_id, media::MediaKeys::KeyError::kUnknownError, system_code); |
| } |
| - |
| - // If |session_id| is null, then use the single reference id. |
| - if (session_id.empty() && sessions_.size() == 1) |
| - return sessions_.begin()->first; |
| - |
| - return kInvalidSessionId; |
| } |
| -const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) const { |
| - DCHECK_NE(session_id, kInvalidSessionId); |
| - |
| - // Session may not exist if error happens during GenerateKeyRequest(). |
| - SessionIdMap::const_iterator it = sessions_.find(session_id); |
| - return (it != sessions_.end()) ? it->second : base::EmptyString(); |
| +void ProxyDecryptor::SetSessionId(bool persistent, |
| + const std::string& web_session_id) { |
| + active_sessions_.insert(web_session_id); |
| + if (persistent) { |
| + persistent_sessions_.insert(web_session_id); |
| + } |
| } |
| } // namespace content |