• 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/webcontentdecryptionmodulesession_impl.h"
6 
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/renderer/media/cdm_result_promise.h"
13 #include "content/renderer/media/cdm_session_adapter.h"
14 #include "media/base/cdm_promise.h"
15 #include "third_party/WebKit/public/platform/WebURL.h"
16 
17 namespace content {
18 
19 const char kCreateSessionUMAName[] = "CreateSession";
20 
21 typedef base::Callback<blink::WebContentDecryptionModuleResult::SessionStatus(
22     const std::string& web_session_id)> SessionInitializedCB;
23 
24 class NewSessionCdmResultPromise : public CdmResultPromise<std::string> {
25  public:
NewSessionCdmResultPromise(blink::WebContentDecryptionModuleResult result,std::string uma_name,const SessionInitializedCB & new_session_created_cb)26   NewSessionCdmResultPromise(blink::WebContentDecryptionModuleResult result,
27                              std::string uma_name,
28                              const SessionInitializedCB& new_session_created_cb)
29       : CdmResultPromise<std::string>(result, uma_name),
30         new_session_created_cb_(new_session_created_cb) {}
31 
32  protected:
OnResolve(const std::string & web_session_id)33   virtual void OnResolve(const std::string& web_session_id) OVERRIDE {
34     blink::WebContentDecryptionModuleResult::SessionStatus status =
35         new_session_created_cb_.Run(web_session_id);
36     web_cdm_result_.completeWithSession(status);
37   }
38 
39  private:
40   SessionInitializedCB new_session_created_cb_;
41 };
42 
WebContentDecryptionModuleSessionImpl(const scoped_refptr<CdmSessionAdapter> & adapter)43 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
44     const scoped_refptr<CdmSessionAdapter>& adapter)
45     : adapter_(adapter),
46       is_closed_(false),
47       weak_ptr_factory_(this) {
48 }
49 
50 WebContentDecryptionModuleSessionImpl::
~WebContentDecryptionModuleSessionImpl()51     ~WebContentDecryptionModuleSessionImpl() {
52   if (!web_session_id_.empty())
53     adapter_->UnregisterSession(web_session_id_);
54 }
55 
setClientInterface(Client * client)56 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
57   client_ = client;
58 }
59 
sessionId() const60 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
61   return blink::WebString::fromUTF8(web_session_id_);
62 }
63 
initializeNewSession(const blink::WebString & init_data_type,const uint8 * init_data,size_t init_data_length)64 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
65     const blink::WebString& init_data_type,
66     const uint8* init_data,
67     size_t init_data_length) {
68   // TODO(jrummell): Remove once blink updated.
69   NOTREACHED();
70 }
71 
update(const uint8 * response,size_t response_length)72 void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
73                                                    size_t response_length) {
74   // TODO(jrummell): Remove once blink updated.
75   NOTREACHED();
76 }
77 
release()78 void WebContentDecryptionModuleSessionImpl::release() {
79   // TODO(jrummell): Remove once blink updated.
80   NOTREACHED();
81 }
82 
initializeNewSession(const blink::WebString & init_data_type,const uint8 * init_data,size_t init_data_length,const blink::WebString & session_type,blink::WebContentDecryptionModuleResult result)83 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
84     const blink::WebString& init_data_type,
85     const uint8* init_data,
86     size_t init_data_length,
87     const blink::WebString& session_type,
88     blink::WebContentDecryptionModuleResult result) {
89 
90   // TODO(ddorwin): Guard against this in supported types check and remove this.
91   // Chromium only supports ASCII MIME types.
92   if (!base::IsStringASCII(init_data_type)) {
93     NOTREACHED();
94     std::string message = "The initialization data type " +
95                           init_data_type.utf8() +
96                           " is not supported by the key system.";
97     result.completeWithError(
98         blink::WebContentDecryptionModuleExceptionNotSupportedError,
99         0,
100         blink::WebString::fromUTF8(message));
101     return;
102   }
103 
104   std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
105   DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
106       << "init_data_type '" << init_data_type_as_ascii
107       << "' may be a MIME type";
108 
109   adapter_->InitializeNewSession(
110       init_data_type_as_ascii,
111       init_data,
112       init_data_length,
113       media::MediaKeys::TEMPORARY_SESSION,
114       scoped_ptr<media::NewSessionCdmPromise>(new NewSessionCdmResultPromise(
115           result,
116           adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName,
117           base::Bind(
118               &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
119               base::Unretained(this)))));
120 }
121 
update(const uint8 * response,size_t response_length,blink::WebContentDecryptionModuleResult result)122 void WebContentDecryptionModuleSessionImpl::update(
123     const uint8* response,
124     size_t response_length,
125     blink::WebContentDecryptionModuleResult result) {
126   DCHECK(response);
127   DCHECK(!web_session_id_.empty());
128   adapter_->UpdateSession(
129       web_session_id_,
130       response,
131       response_length,
132       scoped_ptr<media::SimpleCdmPromise>(new SimpleCdmResultPromise(result)));
133 }
134 
close(blink::WebContentDecryptionModuleResult result)135 void WebContentDecryptionModuleSessionImpl::close(
136     blink::WebContentDecryptionModuleResult result) {
137   DCHECK(!web_session_id_.empty());
138   adapter_->CloseSession(
139       web_session_id_,
140       scoped_ptr<media::SimpleCdmPromise>(new SimpleCdmResultPromise(result)));
141 }
142 
remove(blink::WebContentDecryptionModuleResult result)143 void WebContentDecryptionModuleSessionImpl::remove(
144     blink::WebContentDecryptionModuleResult result) {
145   DCHECK(!web_session_id_.empty());
146   adapter_->RemoveSession(
147       web_session_id_,
148       scoped_ptr<media::SimpleCdmPromise>(new SimpleCdmResultPromise(result)));
149 }
150 
getUsableKeyIds(blink::WebContentDecryptionModuleResult result)151 void WebContentDecryptionModuleSessionImpl::getUsableKeyIds(
152     blink::WebContentDecryptionModuleResult result) {
153   DCHECK(!web_session_id_.empty());
154   adapter_->GetUsableKeyIds(
155       web_session_id_,
156       scoped_ptr<media::KeyIdsPromise>(
157           new CdmResultPromise<media::KeyIdsVector>(result)));
158 }
159 
release(blink::WebContentDecryptionModuleResult result)160 void WebContentDecryptionModuleSessionImpl::release(
161     blink::WebContentDecryptionModuleResult result) {
162   close(result);
163 }
164 
OnSessionMessage(const std::vector<uint8> & message,const GURL & destination_url)165 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
166     const std::vector<uint8>& message,
167     const GURL& destination_url) {
168   DCHECK(client_) << "Client not set before message event";
169   client_->message(
170       message.empty() ? NULL : &message[0], message.size(), destination_url);
171 }
172 
OnSessionKeysChange(bool has_additional_usable_key)173 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
174     bool has_additional_usable_key) {
175   // TODO(jrummell): Update this once Blink client supports this.
176 }
177 
OnSessionExpirationUpdate(const base::Time & new_expiry_time)178 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
179     const base::Time& new_expiry_time) {
180   // TODO(jrummell): Update this once Blink client supports this.
181   // The EME spec has expiration attribute as the time in milliseconds, so use
182   // InMillisecondsF() to convert.
183 }
184 
OnSessionReady()185 void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
186   client_->ready();
187 }
188 
OnSessionClosed()189 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
190   if (!is_closed_) {
191     is_closed_ = true;
192     client_->close();
193   }
194 }
195 
OnSessionError(media::MediaKeys::Exception exception_code,uint32 system_code,const std::string & error_message)196 void WebContentDecryptionModuleSessionImpl::OnSessionError(
197     media::MediaKeys::Exception exception_code,
198     uint32 system_code,
199     const std::string& error_message) {
200   // Convert |exception_code| back to MediaKeyErrorCode if possible.
201   // TODO(jrummell): Update this conversion when promises flow
202   // back into blink:: (as blink:: will have its own error definition).
203   switch (exception_code) {
204     case media::MediaKeys::CLIENT_ERROR:
205       client_->error(Client::MediaKeyErrorCodeClient, system_code);
206       break;
207     default:
208       // This will include all other CDM4 errors and any error generated
209       // by CDM5 or later.
210       client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
211       break;
212   }
213 }
214 
215 blink::WebContentDecryptionModuleResult::SessionStatus
OnSessionInitialized(const std::string & web_session_id)216 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
217     const std::string& web_session_id) {
218   // CDM will return NULL if the session to be loaded can't be found.
219   if (web_session_id.empty())
220     return blink::WebContentDecryptionModuleResult::SessionNotFound;
221 
222   DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
223   web_session_id_ = web_session_id;
224   return adapter_->RegisterSession(web_session_id_,
225                                    weak_ptr_factory_.GetWeakPtr())
226              ? blink::WebContentDecryptionModuleResult::NewSession
227              : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
228 }
229 
230 }  // namespace content
231