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_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"
19 const char kCreateSessionUMAName[] = "CreateSession";
21 typedef base::Callback<blink::WebContentDecryptionModuleResult::SessionStatus(
22 const std::string& web_session_id)> SessionInitializedCB;
24 class NewSessionCdmResultPromise : public CdmResultPromise<std::string> {
26 NewSessionCdmResultPromise(blink::WebContentDecryptionModuleResult result,
28 const SessionInitializedCB& new_session_created_cb)
29 : CdmResultPromise<std::string>(result, uma_name),
30 new_session_created_cb_(new_session_created_cb) {}
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);
40 SessionInitializedCB new_session_created_cb_;
43 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
44 const scoped_refptr<CdmSessionAdapter>& adapter)
47 weak_ptr_factory_(this) {
50 WebContentDecryptionModuleSessionImpl::
51 ~WebContentDecryptionModuleSessionImpl() {
52 if (!web_session_id_.empty())
53 adapter_->UnregisterSession(web_session_id_);
56 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
60 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
61 return blink::WebString::fromUTF8(web_session_id_);
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.
72 void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
73 size_t response_length) {
74 // TODO(jrummell): Remove once blink updated.
78 void WebContentDecryptionModuleSessionImpl::release() {
79 // TODO(jrummell): Remove once blink updated.
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) {
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)) {
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,
100 blink::WebString::fromUTF8(message));
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";
109 adapter_->InitializeNewSession(
110 init_data_type_as_ascii,
113 media::MediaKeys::TEMPORARY_SESSION,
114 scoped_ptr<media::NewSessionCdmPromise>(new NewSessionCdmResultPromise(
116 adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName,
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>(new SimpleCdmResultPromise(result)));
135 void WebContentDecryptionModuleSessionImpl::close(
136 blink::WebContentDecryptionModuleResult result) {
137 DCHECK(!web_session_id_.empty());
138 adapter_->CloseSession(
140 scoped_ptr<media::SimpleCdmPromise>(new SimpleCdmResultPromise(result)));
143 void WebContentDecryptionModuleSessionImpl::remove(
144 blink::WebContentDecryptionModuleResult result) {
145 DCHECK(!web_session_id_.empty());
146 adapter_->RemoveSession(
148 scoped_ptr<media::SimpleCdmPromise>(new SimpleCdmResultPromise(result)));
151 void WebContentDecryptionModuleSessionImpl::getUsableKeyIds(
152 blink::WebContentDecryptionModuleResult result) {
153 DCHECK(!web_session_id_.empty());
154 adapter_->GetUsableKeyIds(
156 scoped_ptr<media::KeyIdsPromise>(
157 new CdmResultPromise<media::KeyIdsVector>(result)));
160 void WebContentDecryptionModuleSessionImpl::release(
161 blink::WebContentDecryptionModuleResult result) {
165 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
166 const std::vector<uint8>& message,
167 const GURL& destination_url) {
168 DCHECK(client_) << "Client not set before message event";
170 message.empty() ? NULL : &message[0], message.size(), destination_url);
173 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
174 bool has_additional_usable_key) {
175 // TODO(jrummell): Update this once Blink client supports this.
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.
185 void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
189 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
196 void WebContentDecryptionModuleSessionImpl::OnSessionError(
197 media::MediaKeys::Exception exception_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);
208 // This will include all other CDM4 errors and any error generated
210 client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
215 blink::WebContentDecryptionModuleResult::SessionStatus
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;
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;
230 } // namespace content