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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "content/renderer/media/crypto/content_decryption_module_factory.h" | 11 #include "content/renderer/media/crypto/content_decryption_module_factory.h" |
12 #if defined(OS_ANDROID) | 12 #if defined(OS_ANDROID) |
13 #include "content/renderer/media/android/renderer_media_player_manager.h" | 13 #include "content/renderer/media/android/renderer_media_player_manager.h" |
14 #endif // defined(OS_ANDROID) | 14 #endif // defined(OS_ANDROID) |
15 #include "media/cdm/json_web_key.h" | 15 #include "media/cdm/json_web_key.h" |
16 #include "media/cdm/key_system_names.h" | 16 #include "media/cdm/key_system_names.h" |
17 | 17 |
18 namespace content { | 18 namespace content { |
19 | 19 |
20 // Since these reference IDs may conflict with the ones generated in | 20 // Since these reference IDs may conflict with the ones generated in |
21 // WebContentDecryptionModuleSessionImpl for the short time both paths are | 21 // WebContentDecryptionModuleSessionImpl for the short time both paths are |
22 // active, start with 100000 and generate the IDs from there. | 22 // active, start with 100000 and generate the IDs from there. |
23 // TODO(jrummell): Only allow one path http://crbug.com/306680. | 23 // TODO(jrummell): Only allow one path http://crbug.com/306680. |
24 uint32 ProxyDecryptor::next_reference_id_ = 100000; | 24 uint32 ProxyDecryptor::next_session_id_ = 100000; |
25 | 25 |
26 const uint32 INVALID_REFERENCE_ID = 0; | 26 const uint32 kInvalidSessionId = 0; |
27 | 27 |
28 #if defined(ENABLE_PEPPER_CDMS) | 28 #if defined(ENABLE_PEPPER_CDMS) |
29 void ProxyDecryptor::DestroyHelperPlugin() { | 29 void ProxyDecryptor::DestroyHelperPlugin() { |
30 ContentDecryptionModuleFactory::DestroyHelperPlugin( | 30 ContentDecryptionModuleFactory::DestroyHelperPlugin( |
31 web_media_player_client_, web_frame_); | 31 web_media_player_client_, web_frame_); |
32 } | 32 } |
33 #endif // defined(ENABLE_PEPPER_CDMS) | 33 #endif // defined(ENABLE_PEPPER_CDMS) |
34 | 34 |
35 ProxyDecryptor::ProxyDecryptor( | 35 ProxyDecryptor::ProxyDecryptor( |
36 #if defined(ENABLE_PEPPER_CDMS) | 36 #if defined(ENABLE_PEPPER_CDMS) |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 is_clear_key_ = | 110 is_clear_key_ = |
111 media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); | 111 media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); |
112 return true; | 112 return true; |
113 } | 113 } |
114 | 114 |
115 bool ProxyDecryptor::GenerateKeyRequest(const std::string& type, | 115 bool ProxyDecryptor::GenerateKeyRequest(const std::string& type, |
116 const uint8* init_data, | 116 const uint8* init_data, |
117 int init_data_length) { | 117 int init_data_length) { |
118 // Use a unique reference id for this request. | 118 // Use a unique reference id for this request. |
119 uint32 reference_id = next_reference_id_++; | 119 uint32 session_id = next_session_id_++; |
120 if (!media_keys_->CreateSession( | 120 if (!media_keys_->CreateSession( |
121 reference_id, type, init_data, init_data_length)) { | 121 session_id, type, init_data, init_data_length)) { |
122 media_keys_.reset(); | 122 media_keys_.reset(); |
123 return false; | 123 return false; |
124 } | 124 } |
125 | 125 |
126 return true; | 126 return true; |
127 } | 127 } |
128 | 128 |
129 void ProxyDecryptor::AddKey(const uint8* key, | 129 void ProxyDecryptor::AddKey(const uint8* key, |
130 int key_length, | 130 int key_length, |
131 const uint8* init_data, | 131 const uint8* init_data, |
132 int init_data_length, | 132 int init_data_length, |
133 const std::string& session_id) { | 133 const std::string& web_session_id) { |
134 DVLOG(1) << "AddKey()"; | 134 DVLOG(1) << "AddKey()"; |
135 | 135 |
136 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. | 136 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. |
137 uint32 reference_id = LookupReferenceId(session_id); | 137 uint32 session_id = LookupSessionId(web_session_id); |
138 if (reference_id == INVALID_REFERENCE_ID) { | 138 if (session_id == kInvalidSessionId) { |
139 // Session hasn't been referenced before, so it is an error. | 139 // Session hasn't been referenced before, so it is an error. |
140 // Note that the specification says "If sessionId is not null and is | 140 // Note that the specification says "If sessionId is not null and is |
141 // unrecognized, throw an INVALID_ACCESS_ERR." However, for backwards | 141 // unrecognized, throw an INVALID_ACCESS_ERR." However, for backwards |
142 // compatibility the error is not thrown, but rather reported as a | 142 // compatibility the error is not thrown, but rather reported as a |
143 // KeyError. | 143 // KeyError. |
144 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); | 144 key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); |
145 return; | 145 return; |
146 } | 146 } |
147 | 147 |
148 // EME WD spec only supports a single array passed to the CDM. For | 148 // EME WD spec only supports a single array passed to the CDM. For |
149 // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). | 149 // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). |
150 // Since the EME WD spec supports the key as a JSON Web Key, | 150 // Since the EME WD spec supports the key as a JSON Web Key, |
151 // convert the 2 arrays to a JWK and pass it as the single array. | 151 // convert the 2 arrays to a JWK and pass it as the single array. |
152 if (is_clear_key_) { | 152 if (is_clear_key_) { |
153 // Decryptor doesn't support empty key ID (see http://crbug.com/123265). | 153 // Decryptor doesn't support empty key ID (see http://crbug.com/123265). |
154 // So ensure a non-empty value is passed. | 154 // So ensure a non-empty value is passed. |
155 if (!init_data) { | 155 if (!init_data) { |
156 static const uint8 kDummyInitData[1] = {0}; | 156 static const uint8 kDummyInitData[1] = {0}; |
157 init_data = kDummyInitData; | 157 init_data = kDummyInitData; |
158 init_data_length = arraysize(kDummyInitData); | 158 init_data_length = arraysize(kDummyInitData); |
159 } | 159 } |
160 | 160 |
161 std::string jwk = | 161 std::string jwk = |
162 media::GenerateJWKSet(key, key_length, init_data, init_data_length); | 162 media::GenerateJWKSet(key, key_length, init_data, init_data_length); |
163 DCHECK(!jwk.empty()); | 163 DCHECK(!jwk.empty()); |
164 media_keys_->UpdateSession( | 164 media_keys_->UpdateSession( |
165 reference_id, reinterpret_cast<const uint8*>(jwk.data()), jwk.size()); | 165 session_id, reinterpret_cast<const uint8*>(jwk.data()), jwk.size()); |
166 return; | 166 return; |
167 } | 167 } |
168 | 168 |
169 media_keys_->UpdateSession(reference_id, key, key_length); | 169 media_keys_->UpdateSession(session_id, key, key_length); |
170 } | 170 } |
171 | 171 |
172 void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) { | 172 void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) { |
173 DVLOG(1) << "CancelKeyRequest()"; | 173 DVLOG(1) << "CancelKeyRequest()"; |
174 | 174 |
175 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. | 175 // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. |
176 uint32 reference_id = LookupReferenceId(session_id); | 176 uint32 session_reference_id = LookupSessionId(session_id); |
177 if (reference_id == INVALID_REFERENCE_ID) { | 177 if (session_reference_id == kInvalidSessionId) { |
178 // Session hasn't been created, so it is an error. | 178 // Session hasn't been created, so it is an error. |
179 key_error_cb_.Run( | 179 key_error_cb_.Run( |
180 std::string(), media::MediaKeys::kUnknownError, 0); | 180 std::string(), media::MediaKeys::kUnknownError, 0); |
181 } | 181 } |
182 else { | 182 else { |
183 media_keys_->ReleaseSession(reference_id); | 183 media_keys_->ReleaseSession(session_reference_id); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( | 187 scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( |
188 const std::string& key_system, | 188 const std::string& key_system, |
189 const GURL& frame_url) { | 189 const GURL& frame_url) { |
190 return ContentDecryptionModuleFactory::Create( | 190 return ContentDecryptionModuleFactory::Create( |
191 key_system, | 191 key_system, |
192 #if defined(ENABLE_PEPPER_CDMS) | 192 #if defined(ENABLE_PEPPER_CDMS) |
193 web_media_player_client_, | 193 web_media_player_client_, |
(...skipping 10 matching lines...) Expand all Loading... |
204 base::Bind(&ProxyDecryptor::OnSessionMessage, | 204 base::Bind(&ProxyDecryptor::OnSessionMessage, |
205 weak_ptr_factory_.GetWeakPtr()), | 205 weak_ptr_factory_.GetWeakPtr()), |
206 base::Bind(&ProxyDecryptor::OnSessionReady, | 206 base::Bind(&ProxyDecryptor::OnSessionReady, |
207 weak_ptr_factory_.GetWeakPtr()), | 207 weak_ptr_factory_.GetWeakPtr()), |
208 base::Bind(&ProxyDecryptor::OnSessionClosed, | 208 base::Bind(&ProxyDecryptor::OnSessionClosed, |
209 weak_ptr_factory_.GetWeakPtr()), | 209 weak_ptr_factory_.GetWeakPtr()), |
210 base::Bind(&ProxyDecryptor::OnSessionError, | 210 base::Bind(&ProxyDecryptor::OnSessionError, |
211 weak_ptr_factory_.GetWeakPtr())); | 211 weak_ptr_factory_.GetWeakPtr())); |
212 } | 212 } |
213 | 213 |
214 void ProxyDecryptor::OnSessionCreated(uint32 reference_id, | 214 void ProxyDecryptor::OnSessionCreated(uint32 session_id, |
215 const std::string& session_id) { | 215 const std::string& web_session_id) { |
216 // Due to heartbeat messages, OnSessionCreated() can get called multiple | 216 // Due to heartbeat messages, OnSessionCreated() can get called multiple |
217 // times. | 217 // times. |
218 SessionIdMap::iterator it = sessions_.find(reference_id); | 218 SessionIdMap::iterator it = sessions_.find(session_id); |
219 DCHECK(it == sessions_.end() || it->second == session_id); | 219 DCHECK(it == sessions_.end() || it->second == web_session_id); |
220 if (it == sessions_.end()) | 220 if (it == sessions_.end()) |
221 sessions_[reference_id] = session_id; | 221 sessions_[session_id] = web_session_id; |
222 } | 222 } |
223 | 223 |
224 void ProxyDecryptor::OnSessionMessage(uint32 reference_id, | 224 void ProxyDecryptor::OnSessionMessage(uint32 session_id, |
225 const std::vector<uint8>& message, | 225 const std::vector<uint8>& message, |
226 const std::string& destination_url) { | 226 const std::string& destination_url) { |
227 // Assumes that OnSessionCreated() has been called before this. | 227 // Assumes that OnSessionCreated() has been called before this. |
228 key_message_cb_.Run(LookupSessionId(reference_id), message, destination_url); | 228 key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url); |
229 } | 229 } |
230 | 230 |
231 void ProxyDecryptor::OnSessionReady(uint32 reference_id) { | 231 void ProxyDecryptor::OnSessionReady(uint32 session_id) { |
232 // Assumes that OnSessionCreated() has been called before this. | 232 // Assumes that OnSessionCreated() has been called before this. |
233 key_added_cb_.Run(LookupSessionId(reference_id)); | 233 key_added_cb_.Run(LookupWebSessionId(session_id)); |
234 } | 234 } |
235 | 235 |
236 void ProxyDecryptor::OnSessionClosed(uint32 reference_id) { | 236 void ProxyDecryptor::OnSessionClosed(uint32 session_id) { |
237 // No closed event in EME v0.1b. | 237 // No closed event in EME v0.1b. |
238 } | 238 } |
239 | 239 |
240 void ProxyDecryptor::OnSessionError(uint32 reference_id, | 240 void ProxyDecryptor::OnSessionError(uint32 session_id, |
241 media::MediaKeys::KeyError error_code, | 241 media::MediaKeys::KeyError error_code, |
242 int system_code) { | 242 int system_code) { |
243 // Assumes that OnSessionCreated() has been called before this. | 243 // Assumes that OnSessionCreated() has been called before this. |
244 key_error_cb_.Run(LookupSessionId(reference_id), error_code, system_code); | 244 key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code); |
245 } | 245 } |
246 | 246 |
247 uint32 ProxyDecryptor::LookupReferenceId(const std::string& session_id) { | 247 uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) { |
248 for (SessionIdMap::iterator it = sessions_.begin(); | 248 for (SessionIdMap::iterator it = sessions_.begin(); |
249 it != sessions_.end(); | 249 it != sessions_.end(); |
250 ++it) { | 250 ++it) { |
251 if (it->second == session_id) | 251 if (it->second == session_id) |
252 return it->first; | 252 return it->first; |
253 } | 253 } |
254 | 254 |
255 // If |session_id| is null, then use the single reference id. | 255 // If |session_id| is null, then use the single reference id. |
256 if (session_id.empty() && sessions_.size() == 1) | 256 if (session_id.empty() && sessions_.size() == 1) |
257 return sessions_.begin()->first; | 257 return sessions_.begin()->first; |
258 | 258 |
259 return INVALID_REFERENCE_ID; | 259 return kInvalidSessionId; |
260 } | 260 } |
261 | 261 |
262 const std::string& ProxyDecryptor::LookupSessionId(uint32 reference_id) { | 262 const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) { |
263 DCHECK_NE(reference_id, INVALID_REFERENCE_ID); | 263 DCHECK_NE(session_id, kInvalidSessionId); |
264 | 264 |
265 // Session may not exist if error happens during GenerateKeyRequest(). | 265 // Session may not exist if error happens during GenerateKeyRequest(). |
266 SessionIdMap::iterator it = sessions_.find(reference_id); | 266 SessionIdMap::iterator it = sessions_.find(session_id); |
267 return (it != sessions_.end()) ? it->second : base::EmptyString(); | 267 return (it != sessions_.end()) ? it->second : base::EmptyString(); |
268 } | 268 } |
269 | 269 |
270 } // namespace content | 270 } // namespace content |
OLD | NEW |