1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/crypto/proxy_decryptor.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cstring> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_util.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/crypto/content_decryption_module_factory.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/cdm_promise.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "media/cdm/json_web_key.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "media/cdm/key_system_names.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS) 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/renderer/media/crypto/pepper_cdm_wrapper.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif // defined(ENABLE_PEPPER_CDMS) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(ENABLE_BROWSER_CDMS) 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/crypto/renderer_cdm_manager.h" 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // defined(ENABLE_BROWSER_CDMS) 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace content { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Special system code to signal a closed persistent session in a SessionError() 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// call. This is needed because there is no SessionClosed() call in the prefixed 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// EME API. 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kSessionClosedSystemCode = 29127; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyDecryptor::ProxyDecryptor( 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(ENABLE_PEPPER_CDMS) 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CreatePepperCdmCB& create_pepper_cdm_cb, 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#elif defined(ENABLE_BROWSER_CDMS) 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RendererCdmManager* manager, 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif // defined(ENABLE_PEPPER_CDMS) 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const KeyAddedCB& key_added_cb, 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const KeyErrorCB& key_error_cb, 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const KeyMessageCB& key_message_cb) 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) : 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(ENABLE_PEPPER_CDMS) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) create_pepper_cdm_cb_(create_pepper_cdm_cb), 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#elif defined(ENABLE_BROWSER_CDMS) 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) manager_(manager), 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cdm_id_(RendererCdmManager::kInvalidCdmId), 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif // defined(ENABLE_PEPPER_CDMS) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key_added_cb_(key_added_cb), 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key_error_cb_(key_error_cb), 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_message_cb_(key_message_cb), 5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) is_clear_key_(false), 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) weak_ptr_factory_(this) { 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS) 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!create_pepper_cdm_cb_.is_null()); 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif // defined(ENABLE_PEPPER_CDMS) 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!key_added_cb_.is_null()); 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!key_error_cb_.is_null()); 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!key_message_cb_.is_null()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyDecryptor::~ProxyDecryptor() { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Destroy the decryptor explicitly before destroying the plugin. 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media_keys_.reset(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)media::Decryptor* ProxyDecryptor::GetDecryptor() { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return media_keys_ ? media_keys_->GetDecryptor() : NULL; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(ENABLE_BROWSER_CDMS) 72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochint ProxyDecryptor::GetCdmId() { 73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return cdm_id_; 74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif 76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool ProxyDecryptor::InitializeCDM(const std::string& key_system, 78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const GURL& security_origin) { 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DVLOG(1) << "InitializeCDM: key_system = " << key_system; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!media_keys_); 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch media_keys_ = CreateMediaKeys(key_system, security_origin); 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!media_keys_) 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_clear_key_ = 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true if |data| is prefixed with |header| and has data after the 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |header|. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HasHeader(const uint8* data, int data_length, const std::string& header) { 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<size_t>(data_length) > header.size() && 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::equal(data, data + header.size(), header.begin()); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type, 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const uint8* init_data, 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int init_data_length) { 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DVLOG(1) << "GenerateKeyRequest()"; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|"; 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|"; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SessionCreationType session_creation_type = TemporarySession; 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) { 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_creation_type = LoadSession; 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (HasHeader(init_data, 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) init_data_length, 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kPrefixedApiPersistentSessionHeader)) { 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_creation_type = PersistentSession; 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::NewSessionCdmPromise> promise( 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::NewSessionCdmPromise( 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::SetSessionId, 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_creation_type), 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string()))); // No session id until created. 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (session_creation_type == LoadSession) { 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media_keys_->LoadSession( 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string(reinterpret_cast<const char*>( 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) init_data + strlen(kPrefixedApiLoadSessionHeader)), 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) init_data_length - strlen(kPrefixedApiLoadSessionHeader)), 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) promise.Pass()); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::SessionType session_type = 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_creation_type == PersistentSession 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ? media::MediaKeys::PERSISTENT_SESSION 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : media::MediaKeys::TEMPORARY_SESSION; 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Convert MIME types used in the prefixed implementation. 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string init_data_type; 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (content_type == "audio/mp4" || content_type == "video/mp4") { 1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) init_data_type = "cenc"; 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (content_type == "audio/webm" || content_type == "video/webm") { 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) init_data_type = "webm"; 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) init_data_type = content_type; 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) media_keys_->CreateSession(init_data_type, init_data, init_data_length, 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_type, promise.Pass()); 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::AddKey(const uint8* key, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_length, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* init_data, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int init_data_length, 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& web_session_id) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "AddKey()"; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // In the prefixed API, the session parameter provided to addKey() is 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // optional, so use the single existing session if it exists. 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(jrummell): remove when the prefixed API is removed. 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string session_id(web_session_id); 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (session_id.empty()) { 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (active_sessions_.size() == 1) { 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::hash_map<std::string, bool>::iterator it = active_sessions_.begin(); 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_id = it->first; 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSessionError(std::string(), 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::NOT_SUPPORTED_ERROR, 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 0, 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "SessionId not specified."); 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::SimpleCdmPromise> promise( 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionReady, 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id), 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id))); 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // EME WD spec only supports a single array passed to the CDM. For 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Since the EME WD spec supports the key as a JSON Web Key, 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // convert the 2 arrays to a JWK and pass it as the single array. 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_clear_key_) { 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Decryptor doesn't support empty key ID (see http://crbug.com/123265). 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // So ensure a non-empty value is passed. 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!init_data) { 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const uint8 kDummyInitData[1] = {0}; 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) init_data = kDummyInitData; 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) init_data_length = arraysize(kDummyInitData); 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string jwk = 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::GenerateJWKSet(key, key_length, init_data, init_data_length); 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!jwk.empty()); 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->UpdateSession(session_id, 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<const uint8*>(jwk.data()), 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jwk.size(), 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) promise.Pass()); 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->UpdateSession(session_id, key, key_length, promise.Pass()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "CancelKeyRequest()"; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::SimpleCdmPromise> promise( 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionClosed, 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id), 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id))); 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_keys_->RemoveSession(web_session_id, promise.Pass()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( 22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& key_system, 226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const GURL& security_origin) { 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return ContentDecryptionModuleFactory::Create( 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) key_system, 229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch security_origin, 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS) 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) create_pepper_cdm_cb_, 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#elif defined(ENABLE_BROWSER_CDMS) 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) manager_, 234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch &cdm_id_, 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif // defined(ENABLE_PEPPER_CDMS) 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionMessage, 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionReady, 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionClosed, 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr()), 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ProxyDecryptor::OnSessionKeysChange, 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr()), 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&ProxyDecryptor::OnSessionExpirationUpdate, 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id, 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<uint8>& message, 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const GURL& destination_url) { 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Assumes that OnSessionCreated() has been called before this. 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // For ClearKey, convert the message from JSON into just passing the key 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // as the message. If unable to extract the key, return the message unchanged. 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (is_clear_key_) { 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::vector<uint8> key; 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (media::ExtractFirstKeyIdFromLicenseRequest(message, &key)) { 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) key_message_cb_.Run(web_session_id, key, destination_url); 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_message_cb_.Run(web_session_id, message, destination_url); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyDecryptor::OnSessionKeysChange(const std::string& web_session_id, 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool has_additional_usable_key) { 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // EME v0.1b doesn't support this event. 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProxyDecryptor::OnSessionExpirationUpdate( 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& web_session_id, 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::Time& new_expiry_time) { 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // EME v0.1b doesn't support this event. 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionReady(const std::string& web_session_id) { 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_added_cb_.Run(web_session_id); 281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::hash_map<std::string, bool>::iterator it = 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) active_sessions_.find(web_session_id); 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Latest EME spec separates closing a session ("allows an application to 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // indicate that it no longer needs the session") and actually closing the 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // session (done by the CDM at any point "such as in response to a close() 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // call, when the session is no longer needed, or when system resources are 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // lost.") Thus the CDM may cause 2 close() events -- one to resolve the 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // close() promise, and a second to actually close the session. Prefixed EME 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // only expects 1 close event, so drop the second (and subsequent) events. 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // However, this means we can't tell if the CDM is generating spurious close() 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // events. 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it == active_sessions_.end()) 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it->second) { 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSessionError(web_session_id, 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::NOT_SUPPORTED_ERROR, 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kSessionClosedSystemCode, 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "Do not close persistent sessions."); 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) active_sessions_.erase(it); 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionError(const std::string& web_session_id, 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::Exception exception_code, 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 system_code, 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& error_message) { 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Convert |error_name| back to MediaKeys::KeyError if possible. Prefixed 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // EME has different error message, so all the specific error events will 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // get lost. 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::KeyError error_code; 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (exception_code) { 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case media::MediaKeys::CLIENT_ERROR: 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kClientError; 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case media::MediaKeys::OUTPUT_ERROR: 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kOutputError; 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This will include all other CDM4 errors and any error generated 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // by CDM5 or later. 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kUnknownError; 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_error_cb_.Run(web_session_id, error_code, system_code); 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ProxyDecryptor::SetSessionId(SessionCreationType session_type, 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& web_session_id) { 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Loaded sessions are considered persistent. 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool is_persistent = 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) session_type == PersistentSession || session_type == LoadSession; 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) active_sessions_.insert(std::make_pair(web_session_id, is_persistent)); 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // For LoadSession(), generate the SessionReady event. 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (session_type == LoadSession) 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnSessionReady(web_session_id); 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace content 345