Home | History | Annotate | Download | only in media
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/media/cdm_session_adapter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/memory/weak_ptr.h"
     10 #include "base/stl_util.h"
     11 #include "content/renderer/media/crypto/content_decryption_module_factory.h"
     12 #include "content/renderer/media/crypto/key_systems.h"
     13 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"
     14 #include "media/base/cdm_promise.h"
     15 #include "media/base/media_keys.h"
     16 #include "url/gurl.h"
     17 
     18 namespace content {
     19 
     20 const char kMediaEME[] = "Media.EME.";
     21 const char kDot[] = ".";
     22 
     23 CdmSessionAdapter::CdmSessionAdapter() :
     24 #if defined(ENABLE_BROWSER_CDMS)
     25     cdm_id_(0),
     26 #endif
     27     weak_ptr_factory_(this) {}
     28 
     29 CdmSessionAdapter::~CdmSessionAdapter() {}
     30 
     31 bool CdmSessionAdapter::Initialize(
     32 #if defined(ENABLE_PEPPER_CDMS)
     33     const CreatePepperCdmCB& create_pepper_cdm_cb,
     34 #elif defined(ENABLE_BROWSER_CDMS)
     35     RendererCdmManager* manager,
     36 #endif  // defined(ENABLE_PEPPER_CDMS)
     37     const std::string& key_system,
     38     const GURL& security_origin) {
     39   key_system_uma_prefix_ = kMediaEME + KeySystemNameForUMA(key_system) + kDot;
     40   base::WeakPtr<CdmSessionAdapter> weak_this = weak_ptr_factory_.GetWeakPtr();
     41   media_keys_ = ContentDecryptionModuleFactory::Create(
     42       key_system,
     43       security_origin,
     44 #if defined(ENABLE_PEPPER_CDMS)
     45       create_pepper_cdm_cb,
     46 #elif defined(ENABLE_BROWSER_CDMS)
     47       manager,
     48       &cdm_id_,
     49 #endif  // defined(ENABLE_PEPPER_CDMS)
     50       base::Bind(&CdmSessionAdapter::OnSessionMessage, weak_this),
     51       base::Bind(&CdmSessionAdapter::OnSessionReady, weak_this),
     52       base::Bind(&CdmSessionAdapter::OnSessionClosed, weak_this),
     53       base::Bind(&CdmSessionAdapter::OnSessionError, weak_this),
     54       base::Bind(&CdmSessionAdapter::OnSessionKeysChange, weak_this),
     55       base::Bind(&CdmSessionAdapter::OnSessionExpirationUpdate, weak_this));
     56 
     57   // Success if |media_keys_| created.
     58   return media_keys_;
     59 }
     60 
     61 void CdmSessionAdapter::SetServerCertificate(
     62     const uint8* server_certificate,
     63     int server_certificate_length,
     64     scoped_ptr<media::SimpleCdmPromise> promise) {
     65   media_keys_->SetServerCertificate(
     66       server_certificate, server_certificate_length, promise.Pass());
     67 }
     68 
     69 WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::CreateSession() {
     70   return new WebContentDecryptionModuleSessionImpl(this);
     71 }
     72 
     73 bool CdmSessionAdapter::RegisterSession(
     74     const std::string& web_session_id,
     75     base::WeakPtr<WebContentDecryptionModuleSessionImpl> session) {
     76   // If this session ID is already registered, don't register it again.
     77   if (ContainsKey(sessions_, web_session_id))
     78     return false;
     79 
     80   sessions_[web_session_id] = session;
     81   return true;
     82 }
     83 
     84 void CdmSessionAdapter::UnregisterSession(const std::string& web_session_id) {
     85   DCHECK(ContainsKey(sessions_, web_session_id));
     86   sessions_.erase(web_session_id);
     87 }
     88 
     89 void CdmSessionAdapter::InitializeNewSession(
     90     const std::string& init_data_type,
     91     const uint8* init_data,
     92     int init_data_length,
     93     media::MediaKeys::SessionType session_type,
     94     scoped_ptr<media::NewSessionCdmPromise> promise) {
     95   media_keys_->CreateSession(init_data_type,
     96                              init_data,
     97                              init_data_length,
     98                              session_type,
     99                              promise.Pass());
    100 }
    101 
    102 void CdmSessionAdapter::UpdateSession(
    103     const std::string& web_session_id,
    104     const uint8* response,
    105     int response_length,
    106     scoped_ptr<media::SimpleCdmPromise> promise) {
    107   media_keys_->UpdateSession(
    108       web_session_id, response, response_length, promise.Pass());
    109 }
    110 
    111 void CdmSessionAdapter::CloseSession(
    112     const std::string& web_session_id,
    113     scoped_ptr<media::SimpleCdmPromise> promise) {
    114   media_keys_->CloseSession(web_session_id, promise.Pass());
    115 }
    116 
    117 void CdmSessionAdapter::RemoveSession(
    118     const std::string& web_session_id,
    119     scoped_ptr<media::SimpleCdmPromise> promise) {
    120   media_keys_->RemoveSession(web_session_id, promise.Pass());
    121 }
    122 
    123 void CdmSessionAdapter::GetUsableKeyIds(
    124     const std::string& web_session_id,
    125     scoped_ptr<media::KeyIdsPromise> promise) {
    126   media_keys_->GetUsableKeyIds(web_session_id, promise.Pass());
    127 }
    128 
    129 media::Decryptor* CdmSessionAdapter::GetDecryptor() {
    130   return media_keys_->GetDecryptor();
    131 }
    132 
    133 const std::string& CdmSessionAdapter::GetKeySystemUMAPrefix() const {
    134   return key_system_uma_prefix_;
    135 }
    136 
    137 #if defined(ENABLE_BROWSER_CDMS)
    138 int CdmSessionAdapter::GetCdmId() const {
    139   return cdm_id_;
    140 }
    141 #endif  // defined(ENABLE_BROWSER_CDMS)
    142 
    143 void CdmSessionAdapter::OnSessionMessage(const std::string& web_session_id,
    144                                          const std::vector<uint8>& message,
    145                                          const GURL& destination_url) {
    146   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    147   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    148                              << web_session_id;
    149   if (session)
    150     session->OnSessionMessage(message, destination_url);
    151 }
    152 
    153 void CdmSessionAdapter::OnSessionKeysChange(const std::string& web_session_id,
    154                                             bool has_additional_usable_key) {
    155   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    156   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    157                              << web_session_id;
    158   if (session)
    159     session->OnSessionKeysChange(has_additional_usable_key);
    160 }
    161 
    162 void CdmSessionAdapter::OnSessionExpirationUpdate(
    163     const std::string& web_session_id,
    164     const base::Time& new_expiry_time) {
    165   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    166   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    167                              << web_session_id;
    168   if (session)
    169     session->OnSessionExpirationUpdate(new_expiry_time);
    170 }
    171 
    172 void CdmSessionAdapter::OnSessionReady(const std::string& web_session_id) {
    173   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    174   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    175                              << web_session_id;
    176   if (session)
    177     session->OnSessionReady();
    178 }
    179 
    180 void CdmSessionAdapter::OnSessionClosed(const std::string& web_session_id) {
    181   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    182   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    183                              << web_session_id;
    184   if (session)
    185     session->OnSessionClosed();
    186 }
    187 
    188 void CdmSessionAdapter::OnSessionError(
    189     const std::string& web_session_id,
    190     media::MediaKeys::Exception exception_code,
    191     uint32 system_code,
    192     const std::string& error_message) {
    193   WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
    194   DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
    195                              << web_session_id;
    196   if (session)
    197     session->OnSessionError(exception_code, system_code, error_message);
    198 }
    199 
    200 WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::GetSession(
    201     const std::string& web_session_id) {
    202   // Since session objects may get garbage collected, it is possible that there
    203   // are events coming back from the CDM and the session has been unregistered.
    204   // We can not tell if the CDM is firing events at sessions that never existed.
    205   SessionMap::iterator session = sessions_.find(web_session_id);
    206   return (session != sessions_.end()) ? session->second.get() : NULL;
    207 }
    208 
    209 }  // namespace content
    210