Revert of Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320) (patchset...
[chromium-blink-merge.git] / media / blink / webcontentdecryptionmodulesession_impl.cc
blob643aa948d34179cb5b88594da1673318004cb67c
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 "webcontentdecryptionmodulesession_impl.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "media/base/cdm_key_information.h"
14 #include "media/base/cdm_promise.h"
15 #include "media/base/key_systems.h"
16 #include "media/base/media_keys.h"
17 #include "media/blink/cdm_result_promise.h"
18 #include "media/blink/cdm_session_adapter.h"
19 #include "media/blink/new_session_cdm_result_promise.h"
20 #include "media/blink/webmediaplayer_util.h"
21 #include "third_party/WebKit/public/platform/WebData.h"
22 #include "third_party/WebKit/public/platform/WebEncryptedMediaKeyInformation.h"
23 #include "third_party/WebKit/public/platform/WebString.h"
24 #include "third_party/WebKit/public/platform/WebURL.h"
25 #include "third_party/WebKit/public/platform/WebVector.h"
27 namespace media {
29 const char kCloseSessionUMAName[] = "CloseSession";
30 const char kGenerateRequestUMAName[] = "GenerateRequest";
31 const char kLoadSessionUMAName[] = "LoadSession";
32 const char kRemoveSessionUMAName[] = "RemoveSession";
33 const char kUpdateSessionUMAName[] = "UpdateSession";
35 static blink::WebContentDecryptionModuleSession::Client::MessageType
36 convertMessageType(MediaKeys::MessageType message_type) {
37 switch (message_type) {
38 case media::MediaKeys::LICENSE_REQUEST:
39 return blink::WebContentDecryptionModuleSession::Client::MessageType::
40 LicenseRequest;
41 case media::MediaKeys::LICENSE_RENEWAL:
42 return blink::WebContentDecryptionModuleSession::Client::MessageType::
43 LicenseRenewal;
44 case media::MediaKeys::LICENSE_RELEASE:
45 return blink::WebContentDecryptionModuleSession::Client::MessageType::
46 LicenseRelease;
49 NOTREACHED();
50 return blink::WebContentDecryptionModuleSession::Client::MessageType::
51 LicenseRequest;
54 static blink::WebEncryptedMediaKeyInformation::KeyStatus convertStatus(
55 media::CdmKeyInformation::KeyStatus status) {
56 switch (status) {
57 case media::CdmKeyInformation::USABLE:
58 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Usable;
59 case media::CdmKeyInformation::INTERNAL_ERROR:
60 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError;
61 case media::CdmKeyInformation::EXPIRED:
62 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Expired;
63 case media::CdmKeyInformation::OUTPUT_NOT_ALLOWED:
64 return blink::WebEncryptedMediaKeyInformation::KeyStatus::
65 OutputNotAllowed;
66 case media::CdmKeyInformation::OUTPUT_DOWNSCALED:
67 return blink::WebEncryptedMediaKeyInformation::KeyStatus::
68 OutputDownscaled;
69 case media::CdmKeyInformation::KEY_STATUS_PENDING:
70 return blink::WebEncryptedMediaKeyInformation::KeyStatus::StatusPending;
73 NOTREACHED();
74 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError;
77 static MediaKeys::SessionType convertSessionType(
78 blink::WebEncryptedMediaSessionType session_type) {
79 switch (session_type) {
80 case blink::WebEncryptedMediaSessionType::Temporary:
81 return MediaKeys::TEMPORARY_SESSION;
82 case blink::WebEncryptedMediaSessionType::PersistentLicense:
83 return MediaKeys::PERSISTENT_LICENSE_SESSION;
84 case blink::WebEncryptedMediaSessionType::PersistentReleaseMessage:
85 return MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION;
86 case blink::WebEncryptedMediaSessionType::Unknown:
87 break;
90 NOTREACHED();
91 return MediaKeys::TEMPORARY_SESSION;
94 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
95 const scoped_refptr<CdmSessionAdapter>& adapter)
96 : adapter_(adapter), is_closed_(false), weak_ptr_factory_(this) {
99 WebContentDecryptionModuleSessionImpl::
100 ~WebContentDecryptionModuleSessionImpl() {
101 if (!session_id_.empty())
102 adapter_->UnregisterSession(session_id_);
105 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
106 client_ = client;
109 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
110 return blink::WebString::fromUTF8(session_id_);
113 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
114 blink::WebEncryptedMediaInitDataType init_data_type,
115 const unsigned char* init_data,
116 size_t init_data_length,
117 blink::WebEncryptedMediaSessionType session_type,
118 blink::WebContentDecryptionModuleResult result) {
119 DCHECK(session_id_.empty());
121 // Step 5 from https://w3c.github.io/encrypted-media/#generateRequest.
122 // 5. If the Key System implementation represented by this object's cdm
123 // implementation value does not support initDataType as an Initialization
124 // Data Type, return a promise rejected with a new DOMException whose name
125 // is NotSupportedError. String comparison is case-sensitive.
126 EmeInitDataType eme_init_data_type = ConvertToEmeInitDataType(init_data_type);
127 if (!IsSupportedKeySystemWithInitDataType(adapter_->GetKeySystem(),
128 eme_init_data_type)) {
129 std::string message =
130 "The initialization data type is not supported by the key system.";
131 result.completeWithError(
132 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
133 blink::WebString::fromUTF8(message));
134 return;
137 adapter_->InitializeNewSession(
138 eme_init_data_type, init_data,
139 base::saturated_cast<int>(init_data_length),
140 convertSessionType(session_type),
141 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise(
142 result, adapter_->GetKeySystemUMAPrefix() + kGenerateRequestUMAName,
143 base::Bind(
144 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
145 base::Unretained(this)))));
148 // TODO(jrummell): Remove this. http://crbug.com/418239.
149 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
150 const blink::WebString& init_data_type,
151 const uint8* init_data,
152 size_t init_data_length,
153 const blink::WebString& session_type,
154 blink::WebContentDecryptionModuleResult result) {
155 NOTREACHED();
158 void WebContentDecryptionModuleSessionImpl::load(
159 const blink::WebString& session_id,
160 blink::WebContentDecryptionModuleResult result) {
161 DCHECK(!session_id.isEmpty());
162 DCHECK(session_id_.empty());
164 // TODO(jrummell): Now that there are 2 types of persistent sessions, the
165 // session type should be passed from blink. Type should also be passed in the
166 // constructor (and removed from initializeNewSession()).
167 adapter_->LoadSession(
168 MediaKeys::PERSISTENT_LICENSE_SESSION, base::UTF16ToASCII(session_id),
169 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise(
170 result, adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName,
171 base::Bind(
172 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
173 base::Unretained(this)))));
176 void WebContentDecryptionModuleSessionImpl::update(
177 const uint8* response,
178 size_t response_length,
179 blink::WebContentDecryptionModuleResult result) {
180 DCHECK(response);
181 DCHECK(!session_id_.empty());
182 adapter_->UpdateSession(
183 session_id_, response, base::saturated_cast<int>(response_length),
184 scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>(
185 result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName)));
188 void WebContentDecryptionModuleSessionImpl::close(
189 blink::WebContentDecryptionModuleResult result) {
190 DCHECK(!session_id_.empty());
191 adapter_->CloseSession(
192 session_id_,
193 scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>(
194 result, adapter_->GetKeySystemUMAPrefix() + kCloseSessionUMAName)));
197 void WebContentDecryptionModuleSessionImpl::remove(
198 blink::WebContentDecryptionModuleResult result) {
199 DCHECK(!session_id_.empty());
200 adapter_->RemoveSession(
201 session_id_,
202 scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>(
203 result, adapter_->GetKeySystemUMAPrefix() + kRemoveSessionUMAName)));
206 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
207 MediaKeys::MessageType message_type,
208 const std::vector<uint8>& message) {
209 DCHECK(client_) << "Client not set before message event";
210 client_->message(convertMessageType(message_type),
211 message.empty() ? NULL : &message[0], message.size());
214 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
215 bool has_additional_usable_key,
216 CdmKeysInfo keys_info) {
217 blink::WebVector<blink::WebEncryptedMediaKeyInformation> keys(
218 keys_info.size());
219 for (size_t i = 0; i < keys_info.size(); ++i) {
220 const auto& key_info = keys_info[i];
221 keys[i].setId(blink::WebData(reinterpret_cast<char*>(&key_info->key_id[0]),
222 key_info->key_id.size()));
223 keys[i].setStatus(convertStatus(key_info->status));
224 keys[i].setSystemCode(key_info->system_code);
227 // Now send the event to blink.
228 client_->keysStatusesChange(keys, has_additional_usable_key);
231 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
232 const base::Time& new_expiry_time) {
233 client_->expirationChanged(new_expiry_time.ToJsTime());
236 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
237 if (is_closed_)
238 return;
240 is_closed_ = true;
241 client_->close();
244 blink::WebContentDecryptionModuleResult::SessionStatus
245 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
246 const std::string& session_id) {
247 // CDM will return NULL if the session to be loaded can't be found.
248 if (session_id.empty())
249 return blink::WebContentDecryptionModuleResult::SessionNotFound;
251 DCHECK(session_id_.empty()) << "Session ID may not be changed once set.";
252 session_id_ = session_id;
253 return adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr())
254 ? blink::WebContentDecryptionModuleResult::NewSession
255 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
258 } // namespace media