Home | History | Annotate | Download | only in media
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/media/webcontentdecryptionmodule_impl.h"
      6 
      7 #include <map>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/bind.h"
     12 #include "base/callback_helpers.h"
     13 #include "base/logging.h"
     14 #include "base/memory/weak_ptr.h"
     15 #include "base/strings/string_util.h"
     16 #include "content/renderer/media/crypto/content_decryption_module_factory.h"
     17 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"
     18 #include "media/base/media_keys.h"
     19 
     20 namespace content {
     21 
     22 // Forwards the session ID-based callbacks of the MediaKeys interface to the
     23 // appropriate session object.
     24 class SessionIdAdapter {
     25  public:
     26   SessionIdAdapter();
     27   ~SessionIdAdapter();
     28 
     29   // On success, creates a MediaKeys, returns it in |media_keys|, returns true.
     30   bool Initialize(const std::string& key_system,
     31                   scoped_ptr<media::MediaKeys>* media_keys);
     32 
     33   // Adds a session to the internal map. Does not take ownership of the session.
     34   void AddSession(const std::string& session_id,
     35                   WebContentDecryptionModuleSessionImpl* session);
     36 
     37   // Removes a session from the internal map.
     38   void RemoveSession(const std::string& session_id);
     39 
     40  private:
     41   typedef std::map<std::string, WebContentDecryptionModuleSessionImpl*>
     42       SessionMap;
     43 
     44   // Callbacks for firing key events.
     45   void KeyAdded(const std::string& session_id);
     46   void KeyError(const std::string& session_id,
     47                 media::MediaKeys::KeyError error_code,
     48                 int system_code);
     49   void KeyMessage(const std::string& session_id,
     50                   const std::vector<uint8>& message,
     51                   const std::string& destination_url);
     52 
     53   // Helper function of the callbacks.
     54   WebContentDecryptionModuleSessionImpl* GetSession(
     55       const std::string& session_id);
     56 
     57   base::WeakPtrFactory<SessionIdAdapter> weak_ptr_factory_;
     58 
     59   SessionMap sessions_;
     60 
     61   DISALLOW_COPY_AND_ASSIGN(SessionIdAdapter);
     62 };
     63 
     64 SessionIdAdapter::SessionIdAdapter()
     65     : weak_ptr_factory_(this) {
     66 }
     67 
     68 SessionIdAdapter::~SessionIdAdapter() {
     69 }
     70 
     71 bool SessionIdAdapter::Initialize(const std::string& key_system,
     72                                   scoped_ptr<media::MediaKeys>* media_keys) {
     73   DCHECK(media_keys);
     74   DCHECK(!*media_keys);
     75 
     76   base::WeakPtr<SessionIdAdapter> weak_this = weak_ptr_factory_.GetWeakPtr();
     77   scoped_ptr<media::MediaKeys> created_media_keys =
     78       ContentDecryptionModuleFactory::Create(
     79           // TODO(ddorwin): Address lower in the stack: http://crbug.com/252065
     80           "webkit-" + key_system,
     81 #if defined(ENABLE_PEPPER_CDMS)
     82           // TODO(ddorwin): Support Pepper-based CDMs: http://crbug.com/250049
     83           NULL,
     84           NULL,
     85           base::Closure(),
     86 #elif defined(OS_ANDROID)
     87           // TODO(xhwang): Support Android.
     88           NULL,
     89           0,
     90 #endif  // defined(ENABLE_PEPPER_CDMS)
     91           base::Bind(&SessionIdAdapter::KeyAdded, weak_this),
     92           base::Bind(&SessionIdAdapter::KeyError, weak_this),
     93           base::Bind(&SessionIdAdapter::KeyMessage, weak_this));
     94   if (!created_media_keys)
     95     return false;
     96 
     97   *media_keys = created_media_keys.Pass();
     98   return true;
     99 }
    100 
    101 void SessionIdAdapter::AddSession(
    102     const std::string& session_id,
    103     WebContentDecryptionModuleSessionImpl* session) {
    104   DCHECK(sessions_.find(session_id) == sessions_.end());
    105   sessions_[session_id] = session;
    106 }
    107 
    108 void SessionIdAdapter::RemoveSession(const std::string& session_id) {
    109   DCHECK(sessions_.find(session_id) != sessions_.end());
    110   sessions_.erase(session_id);
    111 }
    112 
    113 void SessionIdAdapter::KeyAdded(const std::string& session_id) {
    114   GetSession(session_id)->KeyAdded();
    115 }
    116 
    117 void SessionIdAdapter::KeyError(const std::string& session_id,
    118                                 media::MediaKeys::KeyError error_code,
    119                                 int system_code) {
    120   GetSession(session_id)->KeyError(error_code, system_code);
    121 }
    122 
    123 void SessionIdAdapter::KeyMessage(const std::string& session_id,
    124                                   const std::vector<uint8>& message,
    125                                   const std::string& destination_url) {
    126   GetSession(session_id)->KeyMessage(message, destination_url);
    127 }
    128 
    129 WebContentDecryptionModuleSessionImpl* SessionIdAdapter::GetSession(
    130     const std::string& session_id) {
    131   // TODO(ddorwin): Map session IDs correctly. For now, we only support one.
    132   std::string session_object_id = "";
    133   WebContentDecryptionModuleSessionImpl* session = sessions_[session_object_id];
    134   DCHECK(session); // It must have been present.
    135   return session;
    136 }
    137 
    138 //------------------------------------------------------------------------------
    139 
    140 WebContentDecryptionModuleImpl*
    141 WebContentDecryptionModuleImpl::Create(const string16& key_system) {
    142   // TODO(ddorwin): Guard against this in supported types check and remove this.
    143   // Chromium only supports ASCII key systems.
    144   if (!IsStringASCII(key_system)) {
    145     NOTREACHED();
    146     return NULL;
    147   }
    148 
    149   // SessionIdAdapter creates the MediaKeys so it can provide its callbacks to
    150   // during creation of the MediaKeys.
    151   scoped_ptr<media::MediaKeys> media_keys;
    152   scoped_ptr<SessionIdAdapter> adapter(new SessionIdAdapter());
    153   if (!adapter->Initialize(UTF16ToASCII(key_system), &media_keys))
    154     return NULL;
    155 
    156   return new WebContentDecryptionModuleImpl(media_keys.Pass(), adapter.Pass());
    157 }
    158 
    159 WebContentDecryptionModuleImpl::WebContentDecryptionModuleImpl(
    160     scoped_ptr<media::MediaKeys> media_keys,
    161     scoped_ptr<SessionIdAdapter> adapter)
    162     : media_keys_(media_keys.Pass()),
    163       adapter_(adapter.Pass()) {
    164 }
    165 
    166 WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() {
    167 }
    168 
    169 // The caller owns the created session.
    170 WebKit::WebContentDecryptionModuleSession*
    171 WebContentDecryptionModuleImpl::createSession(
    172     WebKit::WebContentDecryptionModuleSession::Client* client) {
    173   DCHECK(media_keys_);
    174   WebContentDecryptionModuleSessionImpl* session =
    175       new WebContentDecryptionModuleSessionImpl(
    176           media_keys_.get(),
    177           client,
    178           base::Bind(&WebContentDecryptionModuleImpl::OnSessionClosed,
    179                      base::Unretained(this)));
    180 
    181   // TODO(ddorwin): session_id is not populated yet!
    182   adapter_->AddSession(session->session_id(), session);
    183   return session;
    184 }
    185 
    186 void WebContentDecryptionModuleImpl::OnSessionClosed(
    187     const std::string& session_id) {
    188   adapter_->RemoveSession(session_id);
    189 }
    190 
    191 }  // namespace content
    192