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 20namespace content { 21 22// Forwards the session ID-based callbacks of the MediaKeys interface to the 23// appropriate session object. 24class 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 64SessionIdAdapter::SessionIdAdapter() 65 : weak_ptr_factory_(this) { 66} 67 68SessionIdAdapter::~SessionIdAdapter() { 69} 70 71bool 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 101void 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 108void SessionIdAdapter::RemoveSession(const std::string& session_id) { 109 DCHECK(sessions_.find(session_id) != sessions_.end()); 110 sessions_.erase(session_id); 111} 112 113void SessionIdAdapter::KeyAdded(const std::string& session_id) { 114 GetSession(session_id)->KeyAdded(); 115} 116 117void 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 123void 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 129WebContentDecryptionModuleSessionImpl* 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 140WebContentDecryptionModuleImpl* 141WebContentDecryptionModuleImpl::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 159WebContentDecryptionModuleImpl::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 166WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() { 167} 168 169// The caller owns the created session. 170WebKit::WebContentDecryptionModuleSession* 171WebContentDecryptionModuleImpl::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 186void WebContentDecryptionModuleImpl::OnSessionClosed( 187 const std::string& session_id) { 188 adapter_->RemoveSession(session_id); 189} 190 191} // namespace content 192