Prevent UAF of RenderFrames from GuestViewContainer
[chromium-blink-merge.git] / media / blink / webcontentdecryptionmodulesession_impl.cc
blob348ae44f0ea4452aaffda1df448283b5ff2d4a94
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_promise.h"
14 #include "media/base/media_keys.h"
15 #include "media/blink/cdm_result_promise.h"
16 #include "media/blink/cdm_session_adapter.h"
17 #include "media/blink/new_session_cdm_result_promise.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebURL.h"
21 namespace media {
23 const char kCreateSessionUMAName[] = "CreateSession";
24 const char kLoadSessionUMAName[] = "LoadSession";
26 // TODO(jrummell): Pass an enum from blink. http://crbug.com/418239.
27 const char kTemporarySessionType[] = "temporary";
28 const char kPersistentLicenseSessionType[] = "persistent-license";
29 const char kPersistentReleaseMessageSessionType[] =
30 "persistent-release-message";
32 static blink::WebContentDecryptionModuleSession::Client::MessageType
33 convertMessageType(MediaKeys::MessageType message_type) {
34 switch (message_type) {
35 case media::MediaKeys::LICENSE_REQUEST:
36 return blink::WebContentDecryptionModuleSession::Client::MessageType::
37 LicenseRequest;
38 case media::MediaKeys::LICENSE_RENEWAL:
39 return blink::WebContentDecryptionModuleSession::Client::MessageType::
40 LicenseRenewal;
41 case media::MediaKeys::LICENSE_RELEASE:
42 return blink::WebContentDecryptionModuleSession::Client::MessageType::
43 LicenseRelease;
46 NOTREACHED();
47 return blink::WebContentDecryptionModuleSession::Client::MessageType::
48 LicenseRequest;
51 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
52 const scoped_refptr<CdmSessionAdapter>& adapter)
53 : adapter_(adapter), is_closed_(false), weak_ptr_factory_(this) {
56 WebContentDecryptionModuleSessionImpl::
57 ~WebContentDecryptionModuleSessionImpl() {
58 if (!web_session_id_.empty())
59 adapter_->UnregisterSession(web_session_id_);
62 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
63 client_ = client;
66 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
67 return blink::WebString::fromUTF8(web_session_id_);
70 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
71 const blink::WebString& init_data_type,
72 const uint8* init_data,
73 size_t init_data_length) {
74 // TODO(jrummell): Remove once blink updated.
75 NOTREACHED();
78 void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
79 size_t response_length) {
80 // TODO(jrummell): Remove once blink updated.
81 NOTREACHED();
84 void WebContentDecryptionModuleSessionImpl::release() {
85 // TODO(jrummell): Remove once blink updated.
86 NOTREACHED();
89 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
90 const blink::WebString& init_data_type,
91 const uint8* init_data,
92 size_t init_data_length,
93 const blink::WebString& session_type,
94 blink::WebContentDecryptionModuleResult result) {
95 DCHECK(web_session_id_.empty());
97 // TODO(ddorwin): Guard against this in supported types check and remove this.
98 // Chromium only supports ASCII MIME types.
99 if (!base::IsStringASCII(init_data_type)) {
100 NOTREACHED();
101 std::string message = "The initialization data type " +
102 init_data_type.utf8() +
103 " is not supported by the key system.";
104 result.completeWithError(
105 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
106 blink::WebString::fromUTF8(message));
107 return;
110 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
111 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
112 << "init_data_type '" << init_data_type_as_ascii
113 << "' may be a MIME type";
115 MediaKeys::SessionType session_type_enum;
116 if (session_type == kPersistentLicenseSessionType) {
117 session_type_enum = MediaKeys::PERSISTENT_LICENSE_SESSION;
118 } else if (session_type == kPersistentReleaseMessageSessionType) {
119 session_type_enum = MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION;
120 } else {
121 DCHECK(session_type == kTemporarySessionType);
122 session_type_enum = MediaKeys::TEMPORARY_SESSION;
125 adapter_->InitializeNewSession(
126 init_data_type_as_ascii, init_data,
127 base::saturated_cast<int>(init_data_length), session_type_enum,
128 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise(
129 result, adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName,
130 base::Bind(
131 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
132 base::Unretained(this)))));
135 void WebContentDecryptionModuleSessionImpl::load(
136 const blink::WebString& session_id,
137 blink::WebContentDecryptionModuleResult result) {
138 DCHECK(!session_id.isEmpty());
139 DCHECK(web_session_id_.empty());
141 // TODO(jrummell): Now that there are 2 types of persistent sessions, the
142 // session type should be passed from blink. Type should also be passed in the
143 // constructor (and removed from initializeNewSession()).
144 adapter_->LoadSession(
145 MediaKeys::PERSISTENT_LICENSE_SESSION, base::UTF16ToASCII(session_id),
146 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise(
147 result, adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName,
148 base::Bind(
149 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
150 base::Unretained(this)))));
153 void WebContentDecryptionModuleSessionImpl::update(
154 const uint8* response,
155 size_t response_length,
156 blink::WebContentDecryptionModuleResult result) {
157 DCHECK(response);
158 DCHECK(!web_session_id_.empty());
159 adapter_->UpdateSession(web_session_id_, response,
160 base::saturated_cast<int>(response_length),
161 scoped_ptr<SimpleCdmPromise>(
162 new CdmResultPromise<>(result, std::string())));
165 void WebContentDecryptionModuleSessionImpl::close(
166 blink::WebContentDecryptionModuleResult result) {
167 DCHECK(!web_session_id_.empty());
168 adapter_->CloseSession(web_session_id_,
169 scoped_ptr<SimpleCdmPromise>(
170 new CdmResultPromise<>(result, std::string())));
173 void WebContentDecryptionModuleSessionImpl::remove(
174 blink::WebContentDecryptionModuleResult result) {
175 DCHECK(!web_session_id_.empty());
176 adapter_->RemoveSession(web_session_id_,
177 scoped_ptr<SimpleCdmPromise>(
178 new CdmResultPromise<>(result, std::string())));
181 void WebContentDecryptionModuleSessionImpl::release(
182 blink::WebContentDecryptionModuleResult result) {
183 close(result);
186 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
187 MediaKeys::MessageType message_type,
188 const std::vector<uint8>& message) {
189 DCHECK(client_) << "Client not set before message event";
190 client_->message(convertMessageType(message_type),
191 message.empty() ? NULL : &message[0], message.size());
194 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
195 bool has_additional_usable_key) {
196 // TODO(jrummell): Update this once Blink client supports this.
199 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
200 const base::Time& new_expiry_time) {
201 client_->expirationChanged(new_expiry_time.ToJsTime());
204 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
205 if (is_closed_)
206 return;
208 is_closed_ = true;
209 client_->close();
212 blink::WebContentDecryptionModuleResult::SessionStatus
213 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
214 const std::string& web_session_id) {
215 // CDM will return NULL if the session to be loaded can't be found.
216 if (web_session_id.empty())
217 return blink::WebContentDecryptionModuleResult::SessionNotFound;
219 DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
220 web_session_id_ = web_session_id;
221 return adapter_->RegisterSession(web_session_id_,
222 weak_ptr_factory_.GetWeakPtr())
223 ? blink::WebContentDecryptionModuleResult::NewSession
224 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
227 } // namespace media