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 |