Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: media/mojo/clients/mojo_cdm.cc

Issue 2426813002: EME: Close existing sessions on CDM failure (Closed)
Patch Set: add test Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/mojo/clients/mojo_cdm.h" 5 #include "media/mojo/clients/mojo_cdm.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 18 matching lines...) Expand all
29 static void RejectPromise(std::unique_ptr<PromiseType> promise, 29 static void RejectPromise(std::unique_ptr<PromiseType> promise,
30 mojom::CdmPromiseResultPtr result) { 30 mojom::CdmPromiseResultPtr result) {
31 promise->reject(static_cast<MediaKeys::Exception>(result->exception), 31 promise->reject(static_cast<MediaKeys::Exception>(result->exception),
32 result->system_code, result->error_message); 32 result->system_code, result->error_message);
33 } 33 }
34 34
35 // static 35 // static
36 void MojoCdm::Create( 36 void MojoCdm::Create(
37 const std::string& key_system, 37 const std::string& key_system,
38 const GURL& security_origin, 38 const GURL& security_origin,
39 const media::CdmConfig& cdm_config, 39 const CdmConfig& cdm_config,
40 mojom::ContentDecryptionModulePtr remote_cdm, 40 mojom::ContentDecryptionModulePtr remote_cdm,
41 const media::SessionMessageCB& session_message_cb, 41 const SessionMessageCB& session_message_cb,
42 const media::SessionClosedCB& session_closed_cb, 42 const SessionClosedCB& session_closed_cb,
43 const media::SessionKeysChangeCB& session_keys_change_cb, 43 const SessionKeysChangeCB& session_keys_change_cb,
44 const media::SessionExpirationUpdateCB& session_expiration_update_cb, 44 const SessionExpirationUpdateCB& session_expiration_update_cb,
45 const media::CdmCreatedCB& cdm_created_cb) { 45 const CdmCreatedCB& cdm_created_cb) {
46 scoped_refptr<MojoCdm> mojo_cdm( 46 scoped_refptr<MojoCdm> mojo_cdm(
47 new MojoCdm(std::move(remote_cdm), session_message_cb, session_closed_cb, 47 new MojoCdm(std::move(remote_cdm), session_message_cb, session_closed_cb,
48 session_keys_change_cb, session_expiration_update_cb)); 48 session_keys_change_cb, session_expiration_update_cb));
49 49
50 // |mojo_cdm| ownership is passed to the promise. 50 // |mojo_cdm| ownership is passed to the promise.
51 std::unique_ptr<CdmInitializedPromise> promise( 51 std::unique_ptr<CdmInitializedPromise> promise(
52 new CdmInitializedPromise(cdm_created_cb, mojo_cdm)); 52 new CdmInitializedPromise(cdm_created_cb, mojo_cdm));
53 53
54 mojo_cdm->InitializeCdm(key_system, security_origin, cdm_config, 54 mojo_cdm->InitializeCdm(key_system, security_origin, cdm_config,
55 std::move(promise)); 55 std::move(promise));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 decryptor_task_runner_->DeleteSoon(FROM_HERE, decryptor_.release()); 91 decryptor_task_runner_->DeleteSoon(FROM_HERE, decryptor_.release());
92 } 92 }
93 } 93 }
94 94
95 // Using base::Unretained(this) below is safe because |this| owns |remote_cdm_|, 95 // Using base::Unretained(this) below is safe because |this| owns |remote_cdm_|,
96 // and if |this| is destroyed, |remote_cdm_| will be destroyed as well. Then the 96 // and if |this| is destroyed, |remote_cdm_| will be destroyed as well. Then the
97 // error handler can't be invoked and callbacks won't be dispatched. 97 // error handler can't be invoked and callbacks won't be dispatched.
98 98
99 void MojoCdm::InitializeCdm(const std::string& key_system, 99 void MojoCdm::InitializeCdm(const std::string& key_system,
100 const GURL& security_origin, 100 const GURL& security_origin,
101 const media::CdmConfig& cdm_config, 101 const CdmConfig& cdm_config,
102 std::unique_ptr<CdmInitializedPromise> promise) { 102 std::unique_ptr<CdmInitializedPromise> promise) {
103 DVLOG(1) << __FUNCTION__ << ": " << key_system; 103 DVLOG(1) << __FUNCTION__ << ": " << key_system;
104 DCHECK(thread_checker_.CalledOnValidThread()); 104 DCHECK(thread_checker_.CalledOnValidThread());
105 105
106 // If connection error has happened, fail immediately. 106 // If connection error has happened, fail immediately.
107 if (remote_cdm_.encountered_error()) { 107 if (remote_cdm_.encountered_error()) {
108 LOG(ERROR) << "Remote CDM encountered error."; 108 LOG(ERROR) << "Remote CDM encountered error.";
109 promise->reject(NOT_SUPPORTED_ERROR, 0, "Mojo CDM creation failed."); 109 promise->reject(NOT_SUPPORTED_ERROR, 0, "Mojo CDM creation failed.");
110 return; 110 return;
111 } 111 }
112 112
113 // Otherwise, set an error handler to catch the connection error. 113 // Otherwise, set an error handler to catch the connection error.
114 remote_cdm_.set_connection_error_handler( 114 remote_cdm_.set_connection_error_handler(
115 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this))); 115 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this)));
116 116
117 pending_init_promise_ = std::move(promise); 117 pending_init_promise_ = std::move(promise);
118 118
119 remote_cdm_->Initialize( 119 remote_cdm_->Initialize(
120 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config), 120 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config),
121 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this))); 121 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this)));
122 } 122 }
123 123
124 void MojoCdm::OnConnectionError() { 124 void MojoCdm::OnConnectionError() {
125 LOG(ERROR) << "Remote CDM connection error."; 125 LOG(ERROR) << "Remote CDM connection error.";
126 DCHECK(thread_checker_.CalledOnValidThread()); 126 DCHECK(thread_checker_.CalledOnValidThread());
127 127
128 // We only handle initial connection error. 128 // Handle initial connection error.
129 if (!pending_init_promise_) 129 if (pending_init_promise_) {
130 return; 130 pending_init_promise_->reject(NOT_SUPPORTED_ERROR, 0,
131 "Mojo CDM creation failed.");
132 pending_init_promise_.reset();
133 }
131 134
132 pending_init_promise_->reject(NOT_SUPPORTED_ERROR, 0, 135 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_);
133 "Mojo CDM creation failed.");
134 pending_init_promise_.reset();
135 } 136 }
136 137
137 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, 138 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate,
138 std::unique_ptr<SimpleCdmPromise> promise) { 139 std::unique_ptr<SimpleCdmPromise> promise) {
139 DVLOG(2) << __FUNCTION__; 140 DVLOG(2) << __FUNCTION__;
140 DCHECK(thread_checker_.CalledOnValidThread()); 141 DCHECK(thread_checker_.CalledOnValidThread());
141 142
142 remote_cdm_->SetServerCertificate( 143 remote_cdm_->SetServerCertificate(
143 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 144 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
144 base::Unretained(this), base::Passed(&promise))); 145 base::Unretained(this), base::Passed(&promise)));
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 remote_cdm_->RemoveSession( 202 remote_cdm_->RemoveSession(
202 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 203 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
203 base::Unretained(this), base::Passed(&promise))); 204 base::Unretained(this), base::Passed(&promise)));
204 } 205 }
205 206
206 CdmContext* MojoCdm::GetCdmContext() { 207 CdmContext* MojoCdm::GetCdmContext() {
207 DVLOG(2) << __FUNCTION__; 208 DVLOG(2) << __FUNCTION__;
208 return this; 209 return this;
209 } 210 }
210 211
211 media::Decryptor* MojoCdm::GetDecryptor() { 212 Decryptor* MojoCdm::GetDecryptor() {
212 base::AutoLock auto_lock(lock_); 213 base::AutoLock auto_lock(lock_);
213 214
214 if (!decryptor_task_runner_) 215 if (!decryptor_task_runner_)
215 decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 216 decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get();
216 217
217 DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); 218 DCHECK(decryptor_task_runner_->BelongsToCurrentThread());
218 219
219 // Can be called on a different thread. 220 // Can be called on a different thread.
220 if (decryptor_ptr_info_.is_valid()) { 221 if (decryptor_ptr_info_.is_valid()) {
221 DCHECK(!decryptor_); 222 DCHECK(!decryptor_);
(...skipping 19 matching lines...) Expand all
241 DCHECK(thread_checker_.CalledOnValidThread()); 242 DCHECK(thread_checker_.CalledOnValidThread());
242 243
243 session_message_cb_.Run( 244 session_message_cb_.Run(
244 session_id, static_cast<MediaKeys::MessageType>(message_type), message); 245 session_id, static_cast<MediaKeys::MessageType>(message_type), message);
245 } 246 }
246 247
247 void MojoCdm::OnSessionClosed(const std::string& session_id) { 248 void MojoCdm::OnSessionClosed(const std::string& session_id) {
248 DVLOG(2) << __FUNCTION__; 249 DVLOG(2) << __FUNCTION__;
249 DCHECK(thread_checker_.CalledOnValidThread()); 250 DCHECK(thread_checker_.CalledOnValidThread());
250 251
252 cdm_session_tracker_.RemoveSession(session_id);
251 session_closed_cb_.Run(session_id); 253 session_closed_cb_.Run(session_id);
252 } 254 }
253 255
254 void MojoCdm::OnSessionKeysChange( 256 void MojoCdm::OnSessionKeysChange(
255 const std::string& session_id, 257 const std::string& session_id,
256 bool has_additional_usable_key, 258 bool has_additional_usable_key,
257 std::vector<mojom::CdmKeyInformationPtr> keys_info) { 259 std::vector<mojom::CdmKeyInformationPtr> keys_info) {
258 DVLOG(2) << __FUNCTION__; 260 DVLOG(2) << __FUNCTION__;
259 DCHECK(thread_checker_.CalledOnValidThread()); 261 DCHECK(thread_checker_.CalledOnValidThread());
260 262
261 // TODO(jrummell): Handling resume playback should be done in the media 263 // TODO(jrummell): Handling resume playback should be done in the media
262 // player, not in the Decryptors. http://crbug.com/413413. 264 // player, not in the Decryptors. http://crbug.com/413413.
263 if (has_additional_usable_key) { 265 if (has_additional_usable_key) {
264 base::AutoLock auto_lock(lock_); 266 base::AutoLock auto_lock(lock_);
265 if (decryptor_) { 267 if (decryptor_) {
266 DCHECK(decryptor_task_runner_); 268 DCHECK(decryptor_task_runner_);
267 decryptor_task_runner_->PostTask( 269 decryptor_task_runner_->PostTask(
268 FROM_HERE, 270 FROM_HERE,
269 base::Bind(&MojoCdm::OnKeyAdded, weak_factory_.GetWeakPtr())); 271 base::Bind(&MojoCdm::OnKeyAdded, weak_factory_.GetWeakPtr()));
270 } 272 }
271 } 273 }
272 274
273 media::CdmKeysInfo key_data; 275 CdmKeysInfo key_data;
274 key_data.reserve(keys_info.size()); 276 key_data.reserve(keys_info.size());
275 for (size_t i = 0; i < keys_info.size(); ++i) { 277 for (size_t i = 0; i < keys_info.size(); ++i) {
276 key_data.push_back( 278 key_data.push_back(
277 keys_info[i].To<std::unique_ptr<media::CdmKeyInformation>>().release()); 279 keys_info[i].To<std::unique_ptr<CdmKeyInformation>>().release());
278 } 280 }
279 session_keys_change_cb_.Run(session_id, has_additional_usable_key, 281 session_keys_change_cb_.Run(session_id, has_additional_usable_key,
280 std::move(key_data)); 282 std::move(key_data));
281 } 283 }
282 284
283 void MojoCdm::OnSessionExpirationUpdate(const std::string& session_id, 285 void MojoCdm::OnSessionExpirationUpdate(const std::string& session_id,
284 double new_expiry_time_sec) { 286 double new_expiry_time_sec) {
285 DVLOG(2) << __FUNCTION__; 287 DVLOG(2) << __FUNCTION__;
286 DCHECK(thread_checker_.CalledOnValidThread()); 288 DCHECK(thread_checker_.CalledOnValidThread());
287 289
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 if (result->success) 330 if (result->success)
329 promise->resolve(); 331 promise->resolve();
330 else 332 else
331 RejectPromise(std::move(promise), std::move(result)); 333 RejectPromise(std::move(promise), std::move(result));
332 } 334 }
333 335
334 void MojoCdm::OnNewSessionCdmPromiseResult( 336 void MojoCdm::OnNewSessionCdmPromiseResult(
335 std::unique_ptr<NewSessionCdmPromise> promise, 337 std::unique_ptr<NewSessionCdmPromise> promise,
336 mojom::CdmPromiseResultPtr result, 338 mojom::CdmPromiseResultPtr result,
337 const std::string& session_id) { 339 const std::string& session_id) {
338 if (result->success) 340 if (result->success) {
341 cdm_session_tracker_.AddSession(session_id);
339 promise->resolve(session_id); 342 promise->resolve(session_id);
340 else 343 } else
341 RejectPromise(std::move(promise), std::move(result)); 344 RejectPromise(std::move(promise), std::move(result));
342 } 345 }
343 346
344 } // namespace media 347 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698