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::OnSessionClosed() {
195 blink::WebContentDecryptionModuleResult::SessionStatus
196 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
197 const std::string& web_session_id) {
198 // CDM will return NULL if the session to be loaded can't be found.
199 if (web_session_id.empty())
200 return blink::WebContentDecryptionModuleResult::SessionNotFound;
202 DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
203 web_session_id_ = web_session_id;
204 return adapter_->RegisterSession(web_session_id_,
205 weak_ptr_factory_.GetWeakPtr())
206 ? blink::WebContentDecryptionModuleResult::NewSession
207 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
210 } // namespace content