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) 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool loadSession = 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader); 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool persistent = HasHeader( 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) init_data, init_data_length, kPrefixedApiPersistentSessionHeader); 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::NewSessionCdmPromise> promise( 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::NewSessionCdmPromise( 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::SetSessionId, 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) persistent || loadSession), 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string()))); // No session id until created. 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (loadSession) { 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media_keys_->LoadSession( 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string(reinterpret_cast<const char*>( 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) init_data + strlen(kPrefixedApiLoadSessionHeader)), 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) init_data_length - strlen(kPrefixedApiLoadSessionHeader)), 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) promise.Pass()); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::SessionType session_type = 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) persistent ? media::MediaKeys::PERSISTENT_SESSION 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : media::MediaKeys::TEMPORARY_SESSION; 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->CreateSession( 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content_type, init_data, init_data_length, session_type, promise.Pass()); 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ProxyDecryptor::AddKey(const uint8* key, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int key_length, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* init_data, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int init_data_length, 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& web_session_id) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "AddKey()"; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // In the prefixed API, the session parameter provided to addKey() is 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // optional, so use the single existing session if it exists. 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(jrummell): remove when the prefixed API is removed. 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string session_id(web_session_id); 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (session_id.empty()) { 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (active_sessions_.size() == 1) { 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::hash_map<std::string, bool>::iterator it = active_sessions_.begin(); 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) session_id = it->first; 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSessionError(std::string(), 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::NOT_SUPPORTED_ERROR, 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 0, 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "SessionId not specified."); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::SimpleCdmPromise> promise( 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionReady, 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id), 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id))); 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // EME WD spec only supports a single array passed to the CDM. For 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Since the EME WD spec supports the key as a JSON Web Key, 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // convert the 2 arrays to a JWK and pass it as the single array. 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_clear_key_) { 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Decryptor doesn't support empty key ID (see http://crbug.com/123265). 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // So ensure a non-empty value is passed. 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!init_data) { 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const uint8 kDummyInitData[1] = {0}; 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) init_data = kDummyInitData; 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) init_data_length = arraysize(kDummyInitData); 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string jwk = 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::GenerateJWKSet(key, key_length, init_data, init_data_length); 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!jwk.empty()); 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->UpdateSession(session_id, 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<const uint8*>(jwk.data()), 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) jwk.size(), 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) promise.Pass()); 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->UpdateSession(session_id, key, key_length, promise.Pass()); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "CancelKeyRequest()"; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<media::SimpleCdmPromise> promise( 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionClosed, 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id), 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) web_session_id))); 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media_keys_->ReleaseSession(web_session_id, promise.Pass()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( 20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& key_system, 209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const GURL& security_origin) { 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return ContentDecryptionModuleFactory::Create( 2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) key_system, 212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch security_origin, 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(ENABLE_PEPPER_CDMS) 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) create_pepper_cdm_cb_, 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#elif defined(ENABLE_BROWSER_CDMS) 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) manager_, 217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch &cdm_id_, 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif // defined(ENABLE_PEPPER_CDMS) 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionMessage, 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionReady, 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionClosed, 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ProxyDecryptor::OnSessionError, 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id, 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<uint8>& message, 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const GURL& destination_url) { 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Assumes that OnSessionCreated() has been called before this. 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_message_cb_.Run(web_session_id, message, destination_url); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionReady(const std::string& web_session_id) { 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_added_cb_.Run(web_session_id); 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionClosed(const std::string& web_session_id) { 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::hash_map<std::string, bool>::iterator it = 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) active_sessions_.find(web_session_id); 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Latest EME spec separates closing a session ("allows an application to 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // indicate that it no longer needs the session") and actually closing the 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // session (done by the CDM at any point "such as in response to a close() 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // call, when the session is no longer needed, or when system resources are 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // lost.") Thus the CDM may cause 2 close() events -- one to resolve the 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // close() promise, and a second to actually close the session. Prefixed EME 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // only expects 1 close event, so drop the second (and subsequent) events. 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // However, this means we can't tell if the CDM is generating spurious close() 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // events. 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it == active_sessions_.end()) 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it->second) { 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnSessionError(web_session_id, 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::NOT_SUPPORTED_ERROR, 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kSessionClosedSystemCode, 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "Do not close persistent sessions."); 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) active_sessions_.erase(it); 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::OnSessionError(const std::string& web_session_id, 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::Exception exception_code, 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 system_code, 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& error_message) { 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Convert |error_name| back to MediaKeys::KeyError if possible. Prefixed 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // EME has different error message, so all the specific error events will 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // get lost. 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::MediaKeys::KeyError error_code; 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (exception_code) { 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case media::MediaKeys::CLIENT_ERROR: 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kClientError; 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case media::MediaKeys::OUTPUT_ERROR: 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kOutputError; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This will include all other CDM4 errors and any error generated 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // by CDM5 or later. 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error_code = media::MediaKeys::kUnknownError; 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key_error_cb_.Run(web_session_id, error_code, system_code); 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ProxyDecryptor::SetSessionId(bool persistent, 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& web_session_id) { 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) active_sessions_.insert(std::make_pair(web_session_id, persistent)); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace content 295