• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "url/gurl.h"
20 
21 namespace content {
22 
23 // Forwards the session ID-based callbacks of the MediaKeys interface to the
24 // appropriate session object.
25 class SessionIdAdapter {
26  public:
27   SessionIdAdapter();
28   ~SessionIdAdapter();
29 
30   // On success, creates a MediaKeys, returns it in |media_keys|, returns true.
31   bool Initialize(const std::string& key_system,
32                   scoped_ptr<media::MediaKeys>* media_keys);
33 
34   // Generates a unique internal session id.
35   uint32 GenerateSessionId();
36 
37   // Adds a session to the internal map. Does not take ownership of the session.
38   void AddSession(uint32 session_id,
39                   WebContentDecryptionModuleSessionImpl* session);
40 
41   // Removes a session from the internal map.
42   void RemoveSession(uint32 session_id);
43 
44  private:
45   typedef std::map<uint32, WebContentDecryptionModuleSessionImpl*> SessionMap;
46 
47   // Callbacks for firing session events.
48   void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
49   void OnSessionMessage(uint32 session_id,
50                         const std::vector<uint8>& message,
51                         const std::string& destination_url);
52   void OnSessionReady(uint32 session_id);
53   void OnSessionClosed(uint32 session_id);
54   void OnSessionError(uint32 session_id,
55                       media::MediaKeys::KeyError error_code,
56                       int system_code);
57 
58   // Helper function of the callbacks.
59   WebContentDecryptionModuleSessionImpl* GetSession(uint32 session_id);
60 
61   base::WeakPtrFactory<SessionIdAdapter> weak_ptr_factory_;
62 
63   SessionMap sessions_;
64 
65   // Session ID should be unique per renderer process for debugging purposes.
66   static uint32 next_session_id_;
67 
68   DISALLOW_COPY_AND_ASSIGN(SessionIdAdapter);
69 };
70 
71 const uint32 kStartingSessionId = 1;
72 uint32 SessionIdAdapter::next_session_id_ = kStartingSessionId;
73 COMPILE_ASSERT(kStartingSessionId > media::MediaKeys::kInvalidSessionId,
74                invalid_starting_value);
75 
SessionIdAdapter()76 SessionIdAdapter::SessionIdAdapter()
77     : weak_ptr_factory_(this) {
78 }
79 
~SessionIdAdapter()80 SessionIdAdapter::~SessionIdAdapter() {
81 }
82 
Initialize(const std::string & key_system,scoped_ptr<media::MediaKeys> * media_keys)83 bool SessionIdAdapter::Initialize(const std::string& key_system,
84                                   scoped_ptr<media::MediaKeys>* media_keys) {
85   DCHECK(media_keys);
86   DCHECK(!*media_keys);
87 
88   base::WeakPtr<SessionIdAdapter> weak_this = weak_ptr_factory_.GetWeakPtr();
89   scoped_ptr<media::MediaKeys> created_media_keys =
90       ContentDecryptionModuleFactory::Create(
91           // TODO(ddorwin): Address lower in the stack: http://crbug.com/252065
92           "webkit-" + key_system,
93 #if defined(ENABLE_PEPPER_CDMS)
94           // TODO(ddorwin): Support Pepper-based CDMs: http://crbug.com/250049
95           NULL,
96           NULL,
97           base::Closure(),
98 #elif defined(OS_ANDROID)
99           // TODO(xhwang): Support Android.
100           NULL,
101           0,
102           // TODO(ddorwin): Get the URL for the frame containing the MediaKeys.
103           GURL(),
104 #endif  // defined(ENABLE_PEPPER_CDMS)
105           base::Bind(&SessionIdAdapter::OnSessionCreated, weak_this),
106           base::Bind(&SessionIdAdapter::OnSessionMessage, weak_this),
107           base::Bind(&SessionIdAdapter::OnSessionReady, weak_this),
108           base::Bind(&SessionIdAdapter::OnSessionClosed, weak_this),
109           base::Bind(&SessionIdAdapter::OnSessionError, weak_this));
110   if (!created_media_keys)
111     return false;
112 
113   *media_keys = created_media_keys.Pass();
114   return true;
115 }
116 
GenerateSessionId()117 uint32 SessionIdAdapter::GenerateSessionId() {
118   return next_session_id_++;
119 }
120 
AddSession(uint32 session_id,WebContentDecryptionModuleSessionImpl * session)121 void SessionIdAdapter::AddSession(
122     uint32 session_id,
123     WebContentDecryptionModuleSessionImpl* session) {
124   DCHECK(sessions_.find(session_id) == sessions_.end());
125   sessions_[session_id] = session;
126 }
127 
RemoveSession(uint32 session_id)128 void SessionIdAdapter::RemoveSession(uint32 session_id) {
129   DCHECK(sessions_.find(session_id) != sessions_.end());
130   sessions_.erase(session_id);
131 }
132 
OnSessionCreated(uint32 session_id,const std::string & web_session_id)133 void SessionIdAdapter::OnSessionCreated(uint32 session_id,
134                                         const std::string& web_session_id) {
135   GetSession(session_id)->OnSessionCreated(web_session_id);
136 }
137 
OnSessionMessage(uint32 session_id,const std::vector<uint8> & message,const std::string & destination_url)138 void SessionIdAdapter::OnSessionMessage(uint32 session_id,
139                                         const std::vector<uint8>& message,
140                                         const std::string& destination_url) {
141   GetSession(session_id)->OnSessionMessage(message, destination_url);
142 }
143 
OnSessionReady(uint32 session_id)144 void SessionIdAdapter::OnSessionReady(uint32 session_id) {
145   GetSession(session_id)->OnSessionReady();
146 }
147 
OnSessionClosed(uint32 session_id)148 void SessionIdAdapter::OnSessionClosed(uint32 session_id) {
149   GetSession(session_id)->OnSessionClosed();
150 }
151 
OnSessionError(uint32 session_id,media::MediaKeys::KeyError error_code,int system_code)152 void SessionIdAdapter::OnSessionError(uint32 session_id,
153                                       media::MediaKeys::KeyError error_code,
154                                       int system_code) {
155   GetSession(session_id)->OnSessionError(error_code, system_code);
156 }
157 
GetSession(uint32 session_id)158 WebContentDecryptionModuleSessionImpl* SessionIdAdapter::GetSession(
159     uint32 session_id) {
160   DCHECK(sessions_.find(session_id) != sessions_.end());
161   return sessions_[session_id];
162 }
163 
164 //------------------------------------------------------------------------------
165 
166 WebContentDecryptionModuleImpl*
Create(const base::string16 & key_system)167 WebContentDecryptionModuleImpl::Create(const base::string16& key_system) {
168   // TODO(ddorwin): Guard against this in supported types check and remove this.
169   // Chromium only supports ASCII key systems.
170   if (!IsStringASCII(key_system)) {
171     NOTREACHED();
172     return NULL;
173   }
174 
175   // SessionIdAdapter creates the MediaKeys so it can provide its callbacks to
176   // during creation of the MediaKeys.
177   scoped_ptr<media::MediaKeys> media_keys;
178   scoped_ptr<SessionIdAdapter> adapter(new SessionIdAdapter());
179   if (!adapter->Initialize(UTF16ToASCII(key_system), &media_keys))
180     return NULL;
181 
182   return new WebContentDecryptionModuleImpl(media_keys.Pass(), adapter.Pass());
183 }
184 
WebContentDecryptionModuleImpl(scoped_ptr<media::MediaKeys> media_keys,scoped_ptr<SessionIdAdapter> adapter)185 WebContentDecryptionModuleImpl::WebContentDecryptionModuleImpl(
186     scoped_ptr<media::MediaKeys> media_keys,
187     scoped_ptr<SessionIdAdapter> adapter)
188     : media_keys_(media_keys.Pass()),
189       adapter_(adapter.Pass()) {
190 }
191 
~WebContentDecryptionModuleImpl()192 WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() {
193 }
194 
195 // The caller owns the created session.
196 blink::WebContentDecryptionModuleSession*
createSession(blink::WebContentDecryptionModuleSession::Client * client)197 WebContentDecryptionModuleImpl::createSession(
198     blink::WebContentDecryptionModuleSession::Client* client) {
199   DCHECK(media_keys_);
200   uint32 session_id = adapter_->GenerateSessionId();
201   WebContentDecryptionModuleSessionImpl* session =
202       new WebContentDecryptionModuleSessionImpl(
203           session_id,
204           media_keys_.get(),
205           client,
206           base::Bind(&WebContentDecryptionModuleImpl::OnSessionClosed,
207                      base::Unretained(this)));
208 
209   adapter_->AddSession(session_id, session);
210   return session;
211 }
212 
OnSessionClosed(uint32 session_id)213 void WebContentDecryptionModuleImpl::OnSessionClosed(uint32 session_id) {
214   adapter_->RemoveSession(session_id);
215 }
216 
217 }  // namespace content
218