Chromium Code Reviews| 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 INVALID_SESSION_ID = 0; |
|
xhwang
2013/12/05 18:51:37
We use kCamelCase for consts.
jrummell
2013/12/06 23:42:35
Done.
| |
| 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 = LookupReferenceId(web_session_id); |
| 138 if (reference_id == INVALID_REFERENCE_ID) { | 138 if (session_id == INVALID_SESSION_ID) { |
| 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 = LookupReferenceId(session_id); |
| 177 if (reference_id == INVALID_REFERENCE_ID) { | 177 if (session_reference_id == INVALID_SESSION_ID) { |
| 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(LookupSessionId(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(LookupSessionId(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(LookupSessionId(session_id), error_code, system_code); |
| 245 } | 245 } |
| 246 | 246 |
| 247 uint32 ProxyDecryptor::LookupReferenceId(const std::string& session_id) { | 247 uint32 ProxyDecryptor::LookupReferenceId(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 INVALID_SESSION_ID; |
| 260 } | 260 } |
| 261 | 261 |
| 262 const std::string& ProxyDecryptor::LookupSessionId(uint32 reference_id) { | 262 const std::string& ProxyDecryptor::LookupSessionId(uint32 session_id) { |
| 263 DCHECK_NE(reference_id, INVALID_REFERENCE_ID); | 263 DCHECK_NE(session_id, INVALID_SESSION_ID); |
| 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 |