| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/crypto/proxy_decryptor.h" | 5 #include "content/renderer/media/crypto/proxy_decryptor.h" |
| 6 | 6 |
| 7 #include <cstring> |
| 8 |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" |
| 10 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 11 #include "content/renderer/media/crypto/content_decryption_module_factory.h" | 13 #include "content/renderer/media/crypto/content_decryption_module_factory.h" |
| 12 #if defined(OS_ANDROID) | 14 #if defined(OS_ANDROID) |
| 13 #include "content/renderer/media/android/renderer_media_player_manager.h" | 15 #include "content/renderer/media/android/renderer_media_player_manager.h" |
| 14 #endif // defined(OS_ANDROID) | 16 #endif // defined(OS_ANDROID) |
| 15 #include "media/cdm/json_web_key.h" | 17 #include "media/cdm/json_web_key.h" |
| 16 #include "media/cdm/key_system_names.h" | 18 #include "media/cdm/key_system_names.h" |
| 17 | 19 |
| 18 namespace content { | 20 namespace content { |
| 19 | 21 |
| 20 // Since these reference IDs may conflict with the ones generated in | 22 // Since these reference IDs may conflict with the ones generated in |
| 21 // WebContentDecryptionModuleSessionImpl for the short time both paths are | 23 // WebContentDecryptionModuleSessionImpl for the short time both paths are |
| 22 // active, start with 100000 and generate the IDs from there. | 24 // active, start with 100000 and generate the IDs from there. |
| 23 // TODO(jrummell): Only allow one path http://crbug.com/306680. | 25 // TODO(jrummell): Only allow one path http://crbug.com/306680. |
| 24 uint32 ProxyDecryptor::next_session_id_ = 100000; | 26 uint32 ProxyDecryptor::next_session_id_ = 100000; |
| 25 | 27 |
| 26 const uint32 kInvalidSessionId = 0; | 28 const uint32 kInvalidSessionId = 0; |
| 27 | 29 |
| 30 // Special system code to signal a closed persistent session in a SessionError() |
| 31 // call. This is needed because there is no SessionClosed() call in the prefixed |
| 32 // EME API. |
| 33 const int kSessionClosedSystemCode = 7 * 1024 * 1024 + 7; |
| 34 |
| 28 #if defined(ENABLE_PEPPER_CDMS) | 35 #if defined(ENABLE_PEPPER_CDMS) |
| 29 void ProxyDecryptor::DestroyHelperPlugin() { | 36 void ProxyDecryptor::DestroyHelperPlugin() { |
| 30 ContentDecryptionModuleFactory::DestroyHelperPlugin( | 37 ContentDecryptionModuleFactory::DestroyHelperPlugin( |
| 31 web_media_player_client_, web_frame_); | 38 web_media_player_client_, web_frame_); |
| 32 } | 39 } |
| 33 #endif // defined(ENABLE_PEPPER_CDMS) | 40 #endif // defined(ENABLE_PEPPER_CDMS) |
| 34 | 41 |
| 35 ProxyDecryptor::ProxyDecryptor( | 42 ProxyDecryptor::ProxyDecryptor( |
| 36 #if defined(ENABLE_PEPPER_CDMS) | 43 #if defined(ENABLE_PEPPER_CDMS) |
| 37 blink::WebMediaPlayerClient* web_media_player_client, | 44 blink::WebMediaPlayerClient* web_media_player_client, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 DCHECK(!media_keys_); | 83 DCHECK(!media_keys_); |
| 77 media_keys_ = CreateMediaKeys(key_system, frame_url); | 84 media_keys_ = CreateMediaKeys(key_system, frame_url); |
| 78 if (!media_keys_) | 85 if (!media_keys_) |
| 79 return false; | 86 return false; |
| 80 | 87 |
| 81 is_clear_key_ = | 88 is_clear_key_ = |
| 82 media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); | 89 media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); |
| 83 return true; | 90 return true; |
| 84 } | 91 } |
| 85 | 92 |
| 93 // Returns true if |data| is prefixed with |header| and has data after the |
| 94 // |header|. |
| 95 bool HasHeader(const uint8* data, int data_length, const std::string& header) { |
| 96 return static_cast<size_t>(data_length) > header.size() && |
| 97 std::equal(data, data + header.size(), header.begin()); |
| 98 } |
| 99 |
| 86 bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type, | 100 bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type, |
| 87 const uint8* init_data, | 101 const uint8* init_data, |
| 88 int init_data_length) { | 102 int init_data_length) { |
| 89 // Use a unique reference id for this request. | 103 // Use a unique reference id for this request. |
| 90 uint32 session_id = next_session_id_++; | 104 uint32 session_id = next_session_id_++; |
| 91 | 105 |
| 92 const uint8 kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|"; | 106 const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|"; |
| 93 const int kPrefixedApiLoadSessionHeaderLength = | 107 const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|"; |
| 94 sizeof(kPrefixedApiLoadSessionHeader) - 1; | |
| 95 | 108 |
| 96 if (init_data_length > kPrefixedApiLoadSessionHeaderLength && | 109 if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) { |
| 97 std::equal(init_data, | 110 persistent_sessions_.insert(session_id); |
| 98 init_data + kPrefixedApiLoadSessionHeaderLength, | |
| 99 kPrefixedApiLoadSessionHeader)) { | |
| 100 // TODO(xhwang): Track loadable session to handle OnSessionClosed(). | |
| 101 // See: http://crbug.com/340859. | |
| 102 media_keys_->LoadSession( | 111 media_keys_->LoadSession( |
| 103 session_id, | 112 session_id, |
| 104 std::string(reinterpret_cast<const char*>( | 113 std::string(reinterpret_cast<const char*>( |
| 105 init_data + kPrefixedApiLoadSessionHeaderLength), | 114 init_data + strlen(kPrefixedApiLoadSessionHeader)), |
| 106 init_data_length - kPrefixedApiLoadSessionHeaderLength)); | 115 init_data_length - strlen(kPrefixedApiLoadSessionHeader))); |
| 107 return true; | 116 return true; |
| 108 } | 117 } |
| 109 | 118 |
| 119 if (HasHeader( |
| 120 init_data, init_data_length, kPrefixedApiPersistentSessionHeader)) |
| 121 persistent_sessions_.insert(session_id); |
| 122 |
| 110 return media_keys_->CreateSession( | 123 return media_keys_->CreateSession( |
| 111 session_id, content_type, init_data, init_data_length); | 124 session_id, content_type, init_data, init_data_length); |
| 112 } | 125 } |
| 113 | 126 |
| 114 void ProxyDecryptor::AddKey(const uint8* key, | 127 void ProxyDecryptor::AddKey(const uint8* key, |
| 115 int key_length, | 128 int key_length, |
| 116 const uint8* init_data, | 129 const uint8* init_data, |
| 117 int init_data_length, | 130 int init_data_length, |
| 118 const std::string& web_session_id) { | 131 const std::string& web_session_id) { |
| 119 DVLOG(1) << "AddKey()"; | 132 DVLOG(1) << "AddKey()"; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 // Assumes that OnSessionCreated() has been called before this. | 225 // Assumes that OnSessionCreated() has been called before this. |
| 213 key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url); | 226 key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url); |
| 214 } | 227 } |
| 215 | 228 |
| 216 void ProxyDecryptor::OnSessionReady(uint32 session_id) { | 229 void ProxyDecryptor::OnSessionReady(uint32 session_id) { |
| 217 // Assumes that OnSessionCreated() has been called before this. | 230 // Assumes that OnSessionCreated() has been called before this. |
| 218 key_added_cb_.Run(LookupWebSessionId(session_id)); | 231 key_added_cb_.Run(LookupWebSessionId(session_id)); |
| 219 } | 232 } |
| 220 | 233 |
| 221 void ProxyDecryptor::OnSessionClosed(uint32 session_id) { | 234 void ProxyDecryptor::OnSessionClosed(uint32 session_id) { |
| 222 // No closed event in EME v0.1b. | 235 std::set<uint32>::iterator it = persistent_sessions_.find(session_id); |
| 236 if (it != persistent_sessions_.end()) { |
| 237 persistent_sessions_.erase(it); |
| 238 OnSessionError( |
| 239 session_id, media::MediaKeys::kUnknownError, kSessionClosedSystemCode); |
| 240 } |
| 241 |
| 242 sessions_.erase(session_id); |
| 223 } | 243 } |
| 224 | 244 |
| 225 void ProxyDecryptor::OnSessionError(uint32 session_id, | 245 void ProxyDecryptor::OnSessionError(uint32 session_id, |
| 226 media::MediaKeys::KeyError error_code, | 246 media::MediaKeys::KeyError error_code, |
| 227 int system_code) { | 247 int system_code) { |
| 228 // Assumes that OnSessionCreated() has been called before this. | 248 // Assumes that OnSessionCreated() has been called before this. |
| 229 key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code); | 249 key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code); |
| 230 } | 250 } |
| 231 | 251 |
| 232 uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) const { | 252 uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) const { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 246 | 266 |
| 247 const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) const { | 267 const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) const { |
| 248 DCHECK_NE(session_id, kInvalidSessionId); | 268 DCHECK_NE(session_id, kInvalidSessionId); |
| 249 | 269 |
| 250 // Session may not exist if error happens during GenerateKeyRequest(). | 270 // Session may not exist if error happens during GenerateKeyRequest(). |
| 251 SessionIdMap::const_iterator it = sessions_.find(session_id); | 271 SessionIdMap::const_iterator it = sessions_.find(session_id); |
| 252 return (it != sessions_.end()) ? it->second : base::EmptyString(); | 272 return (it != sessions_.end()) ? it->second : base::EmptyString(); |
| 253 } | 273 } |
| 254 | 274 |
| 255 } // namespace content | 275 } // namespace content |
| OLD | NEW |