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.
5 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.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_session_adapter.h"
13 #include "media/base/cdm_promise.h"
14 #include "media/base/media_keys.h"
15 #include "media/blink/cdm_result_promise.h"
16 #include "media/blink/new_session_cdm_result_promise.h"
17 #include "third_party/WebKit/public/platform/WebURL.h"
21 const char kCreateSessionUMAName
[] = "CreateSession";
22 const char kLoadSessionUMAName
[] = "LoadSession";
24 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
25 const scoped_refptr
<CdmSessionAdapter
>& adapter
)
28 weak_ptr_factory_(this) {
31 WebContentDecryptionModuleSessionImpl::
32 ~WebContentDecryptionModuleSessionImpl() {
33 if (!web_session_id_
.empty())
34 adapter_
->UnregisterSession(web_session_id_
);
37 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client
* client
) {
41 blink::WebString
WebContentDecryptionModuleSessionImpl::sessionId() const {
42 return blink::WebString::fromUTF8(web_session_id_
);
45 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
46 const blink::WebString
& init_data_type
,
47 const uint8
* init_data
,
48 size_t init_data_length
) {
49 // TODO(jrummell): Remove once blink updated.
53 void WebContentDecryptionModuleSessionImpl::update(const uint8
* response
,
54 size_t response_length
) {
55 // TODO(jrummell): Remove once blink updated.
59 void WebContentDecryptionModuleSessionImpl::release() {
60 // TODO(jrummell): Remove once blink updated.
64 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
65 const blink::WebString
& init_data_type
,
66 const uint8
* init_data
,
67 size_t init_data_length
,
68 const blink::WebString
& session_type
,
69 blink::WebContentDecryptionModuleResult result
) {
70 DCHECK(web_session_id_
.empty());
72 // TODO(ddorwin): Guard against this in supported types check and remove this.
73 // Chromium only supports ASCII MIME types.
74 if (!base::IsStringASCII(init_data_type
)) {
76 std::string message
= "The initialization data type " +
77 init_data_type
.utf8() +
78 " is not supported by the key system.";
79 result
.completeWithError(
80 blink::WebContentDecryptionModuleExceptionNotSupportedError
,
82 blink::WebString::fromUTF8(message
));
86 std::string init_data_type_as_ascii
= base::UTF16ToASCII(init_data_type
);
87 DLOG_IF(WARNING
, init_data_type_as_ascii
.find('/') != std::string::npos
)
88 << "init_data_type '" << init_data_type_as_ascii
89 << "' may be a MIME type";
91 adapter_
->InitializeNewSession(
92 init_data_type_as_ascii
,
95 media::MediaKeys::TEMPORARY_SESSION
,
96 scoped_ptr
<media::NewSessionCdmPromise
>(
97 new media::NewSessionCdmResultPromise(
99 adapter_
->GetKeySystemUMAPrefix() + kCreateSessionUMAName
,
101 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized
,
102 base::Unretained(this)))));
105 void WebContentDecryptionModuleSessionImpl::load(
106 const blink::WebString
& session_id
,
107 blink::WebContentDecryptionModuleResult result
) {
108 DCHECK(!session_id
.isEmpty());
109 DCHECK(web_session_id_
.empty());
111 adapter_
->LoadSession(
112 base::UTF16ToASCII(session_id
),
113 scoped_ptr
<media::NewSessionCdmPromise
>(
114 new media::NewSessionCdmResultPromise(
116 adapter_
->GetKeySystemUMAPrefix() + kLoadSessionUMAName
,
118 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized
,
119 base::Unretained(this)))));
122 void WebContentDecryptionModuleSessionImpl::update(
123 const uint8
* response
,
124 size_t response_length
,
125 blink::WebContentDecryptionModuleResult result
) {
127 DCHECK(!web_session_id_
.empty());
128 adapter_
->UpdateSession(
132 scoped_ptr
<media::SimpleCdmPromise
>(
133 new media::CdmResultPromise
<>(result
, std::string())));
136 void WebContentDecryptionModuleSessionImpl::close(
137 blink::WebContentDecryptionModuleResult result
) {
138 DCHECK(!web_session_id_
.empty());
139 adapter_
->CloseSession(
141 scoped_ptr
<media::SimpleCdmPromise
>(
142 new media::CdmResultPromise
<>(result
, std::string())));
145 void WebContentDecryptionModuleSessionImpl::remove(
146 blink::WebContentDecryptionModuleResult result
) {
147 DCHECK(!web_session_id_
.empty());
148 adapter_
->RemoveSession(
150 scoped_ptr
<media::SimpleCdmPromise
>(
151 new media::CdmResultPromise
<>(result
, std::string())));
154 void WebContentDecryptionModuleSessionImpl::getUsableKeyIds(
155 blink::WebContentDecryptionModuleResult result
) {
156 DCHECK(!web_session_id_
.empty());
157 adapter_
->GetUsableKeyIds(
159 scoped_ptr
<media::KeyIdsPromise
>(
160 new media::CdmResultPromise
<media::KeyIdsVector
>(result
,
164 void WebContentDecryptionModuleSessionImpl::release(
165 blink::WebContentDecryptionModuleResult result
) {
169 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
170 const std::vector
<uint8
>& message
,
171 const GURL
& destination_url
) {
172 DCHECK(client_
) << "Client not set before message event";
174 message
.empty() ? NULL
: &message
[0], message
.size(), destination_url
);
177 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
178 bool has_additional_usable_key
) {
179 // TODO(jrummell): Update this once Blink client supports this.
182 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
183 const base::Time
& new_expiry_time
) {
184 client_
->expirationChanged(new_expiry_time
.ToJsTime());
187 void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
191 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
199 void WebContentDecryptionModuleSessionImpl::OnSessionError(
200 media::MediaKeys::Exception exception_code
,
202 const std::string
& error_message
) {
203 // Convert |exception_code| back to MediaKeyErrorCode if possible.
204 // TODO(jrummell): Update this conversion when promises flow
205 // back into blink:: (as blink:: will have its own error definition).
206 switch (exception_code
) {
207 case media::MediaKeys::CLIENT_ERROR
:
208 client_
->error(Client::MediaKeyErrorCodeClient
, system_code
);
211 // This will include all other CDM4 errors and any error generated
213 client_
->error(Client::MediaKeyErrorCodeUnknown
, system_code
);
218 blink::WebContentDecryptionModuleResult::SessionStatus
219 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
220 const std::string
& web_session_id
) {
221 // CDM will return NULL if the session to be loaded can't be found.
222 if (web_session_id
.empty())
223 return blink::WebContentDecryptionModuleResult::SessionNotFound
;
225 DCHECK(web_session_id_
.empty()) << "Session ID may not be changed once set.";
226 web_session_id_
= web_session_id
;
227 return adapter_
->RegisterSession(web_session_id_
,
228 weak_ptr_factory_
.GetWeakPtr())
229 ? blink::WebContentDecryptionModuleResult::NewSession
230 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists
;
233 } // namespace content