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

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

Issue 2426813002: EME: Close existing sessions on CDM failure (Closed)
Patch Set: Created 4 years, 2 months 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 12 matching lines...) Expand all
68 session_keys_change_cb_(session_keys_change_cb), 68 session_keys_change_cb_(session_keys_change_cb),
69 session_expiration_update_cb_(session_expiration_update_cb), 69 session_expiration_update_cb_(session_expiration_update_cb),
70 weak_factory_(this) { 70 weak_factory_(this) {
71 DVLOG(1) << __FUNCTION__; 71 DVLOG(1) << __FUNCTION__;
72 DCHECK(!session_message_cb_.is_null()); 72 DCHECK(!session_message_cb_.is_null());
73 DCHECK(!session_closed_cb_.is_null()); 73 DCHECK(!session_closed_cb_.is_null());
74 DCHECK(!session_keys_change_cb_.is_null()); 74 DCHECK(!session_keys_change_cb_.is_null());
75 DCHECK(!session_expiration_update_cb_.is_null()); 75 DCHECK(!session_expiration_update_cb_.is_null());
76 76
77 remote_cdm_->SetClient(binding_.CreateInterfacePtrAndBind()); 77 remote_cdm_->SetClient(binding_.CreateInterfacePtrAndBind());
78 binding_.set_connection_error_handler(
79 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this)));
xhwang 2016/10/18 18:07:28 This is registered on line 117. Will that work as
jrummell 2016/10/20 22:11:25 There won't be any sessions created until Initiali
78 } 80 }
79 81
80 MojoCdm::~MojoCdm() { 82 MojoCdm::~MojoCdm() {
81 DVLOG(1) << __FUNCTION__; 83 DVLOG(1) << __FUNCTION__;
82 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
83 85
84 base::AutoLock auto_lock(lock_); 86 base::AutoLock auto_lock(lock_);
85 87
86 // Release |decryptor_| on the correct thread. If GetDecryptor() is never 88 // Release |decryptor_| on the correct thread. If GetDecryptor() is never
87 // called but |decryptor_ptr_info_| is not null, it is not bound to any thread 89 // called but |decryptor_ptr_info_| is not null, it is not bound to any thread
88 // and is safe to be released on the current thread. 90 // and is safe to be released on the current thread.
89 if (decryptor_task_runner_ && 91 if (decryptor_task_runner_ &&
90 !decryptor_task_runner_->BelongsToCurrentThread() && decryptor_) { 92 !decryptor_task_runner_->BelongsToCurrentThread() && decryptor_) {
91 decryptor_task_runner_->DeleteSoon(FROM_HERE, decryptor_.release()); 93 decryptor_task_runner_->DeleteSoon(FROM_HERE, decryptor_.release());
92 } 94 }
93 } 95 }
94 96
95 // Using base::Unretained(this) below is safe because |this| owns |remote_cdm_|, 97 // 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 98 // 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. 99 // error handler can't be invoked and callbacks won't be dispatched.
98 100
99 void MojoCdm::InitializeCdm(const std::string& key_system, 101 void MojoCdm::InitializeCdm(const std::string& key_system,
100 const GURL& security_origin, 102 const GURL& security_origin,
101 const media::CdmConfig& cdm_config, 103 const CdmConfig& cdm_config,
102 std::unique_ptr<CdmInitializedPromise> promise) { 104 std::unique_ptr<CdmInitializedPromise> promise) {
103 DVLOG(1) << __FUNCTION__ << ": " << key_system; 105 DVLOG(1) << __FUNCTION__ << ": " << key_system;
104 DCHECK(thread_checker_.CalledOnValidThread()); 106 DCHECK(thread_checker_.CalledOnValidThread());
105 107
106 // If connection error has happened, fail immediately. 108 // If connection error has happened, fail immediately.
107 if (remote_cdm_.encountered_error()) { 109 if (remote_cdm_.encountered_error()) {
108 LOG(ERROR) << "Remote CDM encountered error."; 110 LOG(ERROR) << "Remote CDM encountered error.";
109 promise->reject(NOT_SUPPORTED_ERROR, 0, "Mojo CDM creation failed."); 111 promise->reject(NOT_SUPPORTED_ERROR, 0, "Mojo CDM creation failed.");
110 return; 112 return;
111 } 113 }
112 114
113 // Otherwise, set an error handler to catch the connection error. 115 // Otherwise, set an error handler to catch the connection error.
114 remote_cdm_.set_connection_error_handler( 116 remote_cdm_.set_connection_error_handler(
115 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this))); 117 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this)));
116 118
117 pending_init_promise_ = std::move(promise); 119 pending_init_promise_ = std::move(promise);
118 120
119 remote_cdm_->Initialize( 121 remote_cdm_->Initialize(
120 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config), 122 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config),
121 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this))); 123 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this)));
122 } 124 }
123 125
124 void MojoCdm::OnConnectionError() { 126 void MojoCdm::OnConnectionError() {
125 LOG(ERROR) << "Remote CDM connection error."; 127 LOG(ERROR) << "Remote CDM connection error.";
126 DCHECK(thread_checker_.CalledOnValidThread()); 128 DCHECK(thread_checker_.CalledOnValidThread());
127 129
128 // We only handle initial connection error. 130 // Handle initial connection error.
129 if (!pending_init_promise_) 131 if (pending_init_promise_) {
130 return; 132 pending_init_promise_->reject(NOT_SUPPORTED_ERROR, 0,
133 "Mojo CDM creation failed.");
134 pending_init_promise_.reset();
135 }
131 136
132 pending_init_promise_->reject(NOT_SUPPORTED_ERROR, 0, 137 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_);
133 "Mojo CDM creation failed.");
134 pending_init_promise_.reset();
135 } 138 }
136 139
137 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, 140 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate,
138 std::unique_ptr<SimpleCdmPromise> promise) { 141 std::unique_ptr<SimpleCdmPromise> promise) {
139 DVLOG(2) << __FUNCTION__; 142 DVLOG(2) << __FUNCTION__;
140 DCHECK(thread_checker_.CalledOnValidThread()); 143 DCHECK(thread_checker_.CalledOnValidThread());
141 144
142 remote_cdm_->SetServerCertificate( 145 remote_cdm_->SetServerCertificate(
143 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 146 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
144 base::Unretained(this), base::Passed(&promise))); 147 base::Unretained(this), base::Passed(&promise)));
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 remote_cdm_->RemoveSession( 204 remote_cdm_->RemoveSession(
202 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 205 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
203 base::Unretained(this), base::Passed(&promise))); 206 base::Unretained(this), base::Passed(&promise)));
204 } 207 }
205 208
206 CdmContext* MojoCdm::GetCdmContext() { 209 CdmContext* MojoCdm::GetCdmContext() {
207 DVLOG(2) << __FUNCTION__; 210 DVLOG(2) << __FUNCTION__;
208 return this; 211 return this;
209 } 212 }
210 213
211 media::Decryptor* MojoCdm::GetDecryptor() { 214 Decryptor* MojoCdm::GetDecryptor() {
212 base::AutoLock auto_lock(lock_); 215 base::AutoLock auto_lock(lock_);
213 216
214 if (!decryptor_task_runner_) 217 if (!decryptor_task_runner_)
215 decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 218 decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get();
216 219
217 DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); 220 DCHECK(decryptor_task_runner_->BelongsToCurrentThread());
218 221
219 // Can be called on a different thread. 222 // Can be called on a different thread.
220 if (decryptor_ptr_info_.is_valid()) { 223 if (decryptor_ptr_info_.is_valid()) {
221 DCHECK(!decryptor_); 224 DCHECK(!decryptor_);
(...skipping 19 matching lines...) Expand all
241 DCHECK(thread_checker_.CalledOnValidThread()); 244 DCHECK(thread_checker_.CalledOnValidThread());
242 245
243 session_message_cb_.Run( 246 session_message_cb_.Run(
244 session_id, static_cast<MediaKeys::MessageType>(message_type), message); 247 session_id, static_cast<MediaKeys::MessageType>(message_type), message);
245 } 248 }
246 249
247 void MojoCdm::OnSessionClosed(const std::string& session_id) { 250 void MojoCdm::OnSessionClosed(const std::string& session_id) {
248 DVLOG(2) << __FUNCTION__; 251 DVLOG(2) << __FUNCTION__;
249 DCHECK(thread_checker_.CalledOnValidThread()); 252 DCHECK(thread_checker_.CalledOnValidThread());
250 253
254 cdm_session_tracker_.RemoveSession(session_id);
251 session_closed_cb_.Run(session_id); 255 session_closed_cb_.Run(session_id);
252 } 256 }
253 257
254 void MojoCdm::OnSessionKeysChange( 258 void MojoCdm::OnSessionKeysChange(
255 const std::string& session_id, 259 const std::string& session_id,
256 bool has_additional_usable_key, 260 bool has_additional_usable_key,
257 std::vector<mojom::CdmKeyInformationPtr> keys_info) { 261 std::vector<mojom::CdmKeyInformationPtr> keys_info) {
258 DVLOG(2) << __FUNCTION__; 262 DVLOG(2) << __FUNCTION__;
259 DCHECK(thread_checker_.CalledOnValidThread()); 263 DCHECK(thread_checker_.CalledOnValidThread());
260 264
261 // TODO(jrummell): Handling resume playback should be done in the media 265 // TODO(jrummell): Handling resume playback should be done in the media
262 // player, not in the Decryptors. http://crbug.com/413413. 266 // player, not in the Decryptors. http://crbug.com/413413.
263 if (has_additional_usable_key) { 267 if (has_additional_usable_key) {
264 base::AutoLock auto_lock(lock_); 268 base::AutoLock auto_lock(lock_);
265 if (decryptor_) { 269 if (decryptor_) {
266 DCHECK(decryptor_task_runner_); 270 DCHECK(decryptor_task_runner_);
267 decryptor_task_runner_->PostTask( 271 decryptor_task_runner_->PostTask(
268 FROM_HERE, 272 FROM_HERE,
269 base::Bind(&MojoCdm::OnKeyAdded, weak_factory_.GetWeakPtr())); 273 base::Bind(&MojoCdm::OnKeyAdded, weak_factory_.GetWeakPtr()));
270 } 274 }
271 } 275 }
272 276
273 media::CdmKeysInfo key_data; 277 CdmKeysInfo key_data;
274 key_data.reserve(keys_info.size()); 278 key_data.reserve(keys_info.size());
275 for (size_t i = 0; i < keys_info.size(); ++i) { 279 for (size_t i = 0; i < keys_info.size(); ++i) {
276 key_data.push_back( 280 key_data.push_back(
277 keys_info[i].To<std::unique_ptr<media::CdmKeyInformation>>().release()); 281 keys_info[i].To<std::unique_ptr<CdmKeyInformation>>().release());
278 } 282 }
279 session_keys_change_cb_.Run(session_id, has_additional_usable_key, 283 session_keys_change_cb_.Run(session_id, has_additional_usable_key,
280 std::move(key_data)); 284 std::move(key_data));
281 } 285 }
282 286
283 void MojoCdm::OnSessionExpirationUpdate(const std::string& session_id, 287 void MojoCdm::OnSessionExpirationUpdate(const std::string& session_id,
284 double new_expiry_time_sec) { 288 double new_expiry_time_sec) {
285 DVLOG(2) << __FUNCTION__; 289 DVLOG(2) << __FUNCTION__;
286 DCHECK(thread_checker_.CalledOnValidThread()); 290 DCHECK(thread_checker_.CalledOnValidThread());
287 291
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 if (result->success) 332 if (result->success)
329 promise->resolve(); 333 promise->resolve();
330 else 334 else
331 RejectPromise(std::move(promise), std::move(result)); 335 RejectPromise(std::move(promise), std::move(result));
332 } 336 }
333 337
334 void MojoCdm::OnNewSessionCdmPromiseResult( 338 void MojoCdm::OnNewSessionCdmPromiseResult(
335 std::unique_ptr<NewSessionCdmPromise> promise, 339 std::unique_ptr<NewSessionCdmPromise> promise,
336 mojom::CdmPromiseResultPtr result, 340 mojom::CdmPromiseResultPtr result,
337 const std::string& session_id) { 341 const std::string& session_id) {
338 if (result->success) 342 if (result->success) {
343 cdm_session_tracker_.AddSession(session_id);
339 promise->resolve(session_id); 344 promise->resolve(session_id);
340 else 345 } else
341 RejectPromise(std::move(promise), std::move(result)); 346 RejectPromise(std::move(promise), std::move(result));
342 } 347 }
343 348
344 } // namespace media 349 } // namespace media
OLDNEW
« media/base/cdm_session_tracker.h ('K') | « media/mojo/clients/mojo_cdm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698