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

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

Issue 2561263002: [eme] Reject CDM calls after connection error (Closed)
Patch Set: changes Created 4 years 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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
16 #include "media/base/cdm_context.h" 16 #include "media/base/cdm_context.h"
17 #include "media/base/cdm_key_information.h" 17 #include "media/base/cdm_key_information.h"
18 #include "media/base/cdm_promise.h" 18 #include "media/base/cdm_promise.h"
19 #include "media/mojo/clients/mojo_decryptor.h" 19 #include "media/mojo/clients/mojo_decryptor.h"
20 #include "media/mojo/common/media_type_converters.h" 20 #include "media/mojo/common/media_type_converters.h"
21 #include "media/mojo/interfaces/decryptor.mojom.h" 21 #include "media/mojo/interfaces/decryptor.mojom.h"
22 #include "services/service_manager/public/cpp/connect.h" 22 #include "services/service_manager/public/cpp/connect.h"
23 #include "services/service_manager/public/interfaces/interface_provider.mojom.h" 23 #include "services/service_manager/public/interfaces/interface_provider.mojom.h"
24 #include "url/gurl.h" 24 #include "url/gurl.h"
25 25
26 namespace media { 26 namespace media {
27 27
28 template <typename PromiseType>
29 static void RejectPromise(std::unique_ptr<PromiseType> promise,
30 mojom::CdmPromiseResultPtr result) {
31 promise->reject(result->exception, result->system_code,
32 result->error_message);
33 }
34
35 // static 28 // static
36 void MojoCdm::Create( 29 void MojoCdm::Create(
37 const std::string& key_system, 30 const std::string& key_system,
38 const GURL& security_origin, 31 const GURL& security_origin,
39 const CdmConfig& cdm_config, 32 const CdmConfig& cdm_config,
40 mojom::ContentDecryptionModulePtr remote_cdm, 33 mojom::ContentDecryptionModulePtr remote_cdm,
41 const SessionMessageCB& session_message_cb, 34 const SessionMessageCB& session_message_cb,
42 const SessionClosedCB& session_closed_cb, 35 const SessionClosedCB& session_closed_cb,
43 const SessionKeysChangeCB& session_keys_change_cb, 36 const SessionKeysChangeCB& session_keys_change_cb,
44 const SessionExpirationUpdateCB& session_expiration_update_cb, 37 const SessionExpirationUpdateCB& session_expiration_update_cb,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 remote_cdm_.set_connection_error_with_reason_handler( 108 remote_cdm_.set_connection_error_with_reason_handler(
116 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this))); 109 base::Bind(&MojoCdm::OnConnectionError, base::Unretained(this)));
117 110
118 pending_init_promise_ = std::move(promise); 111 pending_init_promise_ = std::move(promise);
119 112
120 remote_cdm_->Initialize( 113 remote_cdm_->Initialize(
121 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config), 114 key_system, security_origin.spec(), mojom::CdmConfig::From(cdm_config),
122 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this))); 115 base::Bind(&MojoCdm::OnCdmInitialized, base::Unretained(this)));
123 } 116 }
124 117
125 // TODO(xhwang): Properly handle CDM calls after connection error.
126 // See http://crbug.com/671362
127 void MojoCdm::OnConnectionError(uint32_t custom_reason, 118 void MojoCdm::OnConnectionError(uint32_t custom_reason,
128 const std::string& description) { 119 const std::string& description) {
129 LOG(ERROR) << "Remote CDM connection error: custom_reason=" << custom_reason 120 LOG(ERROR) << "Remote CDM connection error: custom_reason=" << custom_reason
130 << ", description=\"" << description << "\""; 121 << ", description=\"" << description << "\"";
131 DCHECK(thread_checker_.CalledOnValidThread()); 122 DCHECK(thread_checker_.CalledOnValidThread());
132 123
124 remote_cdm_.reset();
125
133 // Handle initial connection error. 126 // Handle initial connection error.
134 if (pending_init_promise_) { 127 if (pending_init_promise_) {
135 DCHECK(!cdm_session_tracker_.HasRemainingSessions()); 128 DCHECK(!cdm_session_tracker_.HasRemainingSessions());
136 pending_init_promise_->reject(CdmPromise::NOT_SUPPORTED_ERROR, 0, 129 pending_init_promise_->reject(CdmPromise::NOT_SUPPORTED_ERROR, 0,
137 "Mojo CDM creation failed."); 130 "Mojo CDM creation failed.");
138 // Dropping the promise could cause |this| to be destructed. 131 // Dropping the promise could cause |this| to be destructed.
139 pending_init_promise_.reset(); 132 pending_init_promise_.reset();
140 return; 133 return;
141 } 134 }
142 135
136 // As communication with the remote CDM is broken, reject any outstanding
137 // promises and close all the existing sessions.
138 cdm_promise_adapter_.Clear();
xhwang 2016/12/14 18:43:54 Thanks, I think you already fixed the second probl
jrummell 2016/12/15 21:53:56 Done.
143 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_); 139 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_);
144 } 140 }
145 141
146 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, 142 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate,
147 std::unique_ptr<SimpleCdmPromise> promise) { 143 std::unique_ptr<SimpleCdmPromise> promise) {
148 DVLOG(2) << __func__; 144 DVLOG(2) << __func__;
149 DCHECK(thread_checker_.CalledOnValidThread()); 145 DCHECK(thread_checker_.CalledOnValidThread());
150 146
147 if (!remote_cdm_) {
148 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
149 "CDM connection lost.");
150 return;
151 }
152
153 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
151 remote_cdm_->SetServerCertificate( 154 remote_cdm_->SetServerCertificate(
152 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 155 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
153 base::Unretained(this), base::Passed(&promise))); 156 base::Unretained(this), promise_id));
154 } 157 }
155 158
156 void MojoCdm::CreateSessionAndGenerateRequest( 159 void MojoCdm::CreateSessionAndGenerateRequest(
157 SessionType session_type, 160 SessionType session_type,
158 EmeInitDataType init_data_type, 161 EmeInitDataType init_data_type,
159 const std::vector<uint8_t>& init_data, 162 const std::vector<uint8_t>& init_data,
160 std::unique_ptr<NewSessionCdmPromise> promise) { 163 std::unique_ptr<NewSessionCdmPromise> promise) {
161 DVLOG(2) << __func__; 164 DVLOG(2) << __func__;
162 DCHECK(thread_checker_.CalledOnValidThread()); 165 DCHECK(thread_checker_.CalledOnValidThread());
163 166
167 if (!remote_cdm_) {
168 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
169 "CDM connection lost.");
170 return;
171 }
172
173 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
164 remote_cdm_->CreateSessionAndGenerateRequest( 174 remote_cdm_->CreateSessionAndGenerateRequest(
165 session_type, init_data_type, init_data, 175 session_type, init_data_type, init_data,
166 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this), 176 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this),
167 base::Passed(&promise))); 177 promise_id));
168 } 178 }
169 179
170 void MojoCdm::LoadSession(SessionType session_type, 180 void MojoCdm::LoadSession(SessionType session_type,
171 const std::string& session_id, 181 const std::string& session_id,
172 std::unique_ptr<NewSessionCdmPromise> promise) { 182 std::unique_ptr<NewSessionCdmPromise> promise) {
173 DVLOG(2) << __func__; 183 DVLOG(2) << __func__;
174 DCHECK(thread_checker_.CalledOnValidThread()); 184 DCHECK(thread_checker_.CalledOnValidThread());
175 185
176 remote_cdm_->LoadSession( 186 if (!remote_cdm_) {
177 session_type, session_id, 187 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
178 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this), 188 "CDM connection lost.");
179 base::Passed(&promise))); 189 return;
190 }
191
192 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
193 remote_cdm_->LoadSession(session_type, session_id,
194 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult,
195 base::Unretained(this), promise_id));
180 } 196 }
181 197
182 void MojoCdm::UpdateSession(const std::string& session_id, 198 void MojoCdm::UpdateSession(const std::string& session_id,
183 const std::vector<uint8_t>& response, 199 const std::vector<uint8_t>& response,
184 std::unique_ptr<SimpleCdmPromise> promise) { 200 std::unique_ptr<SimpleCdmPromise> promise) {
185 DVLOG(2) << __func__; 201 DVLOG(2) << __func__;
186 DCHECK(thread_checker_.CalledOnValidThread()); 202 DCHECK(thread_checker_.CalledOnValidThread());
187 203
188 remote_cdm_->UpdateSession( 204 if (!remote_cdm_) {
189 session_id, response, 205 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
190 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, base::Unretained(this), 206 "CDM connection lost.");
191 base::Passed(&promise))); 207 return;
208 }
209
210 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
211 remote_cdm_->UpdateSession(session_id, response,
212 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
213 base::Unretained(this), promise_id));
192 } 214 }
193 215
194 void MojoCdm::CloseSession(const std::string& session_id, 216 void MojoCdm::CloseSession(const std::string& session_id,
195 std::unique_ptr<SimpleCdmPromise> promise) { 217 std::unique_ptr<SimpleCdmPromise> promise) {
196 DVLOG(2) << __func__; 218 DVLOG(2) << __func__;
197 DCHECK(thread_checker_.CalledOnValidThread()); 219 DCHECK(thread_checker_.CalledOnValidThread());
198 220
199 remote_cdm_->CloseSession( 221 if (!remote_cdm_) {
200 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 222 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
201 base::Unretained(this), base::Passed(&promise))); 223 "CDM connection lost.");
224 return;
225 }
226
227 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
228 remote_cdm_->CloseSession(session_id,
229 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
230 base::Unretained(this), promise_id));
202 } 231 }
203 232
204 void MojoCdm::RemoveSession(const std::string& session_id, 233 void MojoCdm::RemoveSession(const std::string& session_id,
205 std::unique_ptr<SimpleCdmPromise> promise) { 234 std::unique_ptr<SimpleCdmPromise> promise) {
206 DVLOG(2) << __func__; 235 DVLOG(2) << __func__;
207 DCHECK(thread_checker_.CalledOnValidThread()); 236 DCHECK(thread_checker_.CalledOnValidThread());
208 237
209 remote_cdm_->RemoveSession( 238 if (!remote_cdm_) {
210 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, 239 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0,
211 base::Unretained(this), base::Passed(&promise))); 240 "CDM connection lost.");
241 return;
242 }
243
244 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
245 remote_cdm_->RemoveSession(session_id,
246 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult,
247 base::Unretained(this), promise_id));
212 } 248 }
213 249
214 CdmContext* MojoCdm::GetCdmContext() { 250 CdmContext* MojoCdm::GetCdmContext() {
215 DVLOG(2) << __func__; 251 DVLOG(2) << __func__;
216 return this; 252 return this;
217 } 253 }
218 254
219 Decryptor* MojoCdm::GetDecryptor() { 255 Decryptor* MojoCdm::GetDecryptor() {
220 base::AutoLock auto_lock(lock_); 256 base::AutoLock auto_lock(lock_);
221 257
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 } 334 }
299 335
300 void MojoCdm::OnCdmInitialized(mojom::CdmPromiseResultPtr result, 336 void MojoCdm::OnCdmInitialized(mojom::CdmPromiseResultPtr result,
301 int cdm_id, 337 int cdm_id,
302 mojom::DecryptorPtr decryptor) { 338 mojom::DecryptorPtr decryptor) {
303 DVLOG(2) << __func__ << " cdm_id: " << cdm_id; 339 DVLOG(2) << __func__ << " cdm_id: " << cdm_id;
304 DCHECK(thread_checker_.CalledOnValidThread()); 340 DCHECK(thread_checker_.CalledOnValidThread());
305 DCHECK(pending_init_promise_); 341 DCHECK(pending_init_promise_);
306 342
307 if (!result->success) { 343 if (!result->success) {
308 RejectPromise(std::move(pending_init_promise_), std::move(result)); 344 pending_init_promise_->reject(result->exception, result->system_code,
345 result->error_message);
309 return; 346 return;
310 } 347 }
311 348
312 { 349 {
313 base::AutoLock auto_lock(lock_); 350 base::AutoLock auto_lock(lock_);
314 DCHECK_NE(CdmContext::kInvalidCdmId, cdm_id); 351 DCHECK_NE(CdmContext::kInvalidCdmId, cdm_id);
315 cdm_id_ = cdm_id; 352 cdm_id_ = cdm_id;
316 decryptor_ptr_info_ = decryptor.PassInterface(); 353 decryptor_ptr_info_ = decryptor.PassInterface();
317 } 354 }
318 355
319 pending_init_promise_->resolve(); 356 pending_init_promise_->resolve();
320 pending_init_promise_.reset(); 357 pending_init_promise_.reset();
321 } 358 }
322 359
323 void MojoCdm::OnKeyAdded() { 360 void MojoCdm::OnKeyAdded() {
324 base::AutoLock auto_lock(lock_); 361 base::AutoLock auto_lock(lock_);
325 362
326 DCHECK(decryptor_task_runner_); 363 DCHECK(decryptor_task_runner_);
327 DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); 364 DCHECK(decryptor_task_runner_->BelongsToCurrentThread());
328 DCHECK(decryptor_); 365 DCHECK(decryptor_);
329 366
330 decryptor_->OnKeyAdded(); 367 decryptor_->OnKeyAdded();
331 } 368 }
332 369
333 void MojoCdm::OnSimpleCdmPromiseResult( 370 void MojoCdm::OnSimpleCdmPromiseResult(uint32_t promise_id,
334 std::unique_ptr<SimpleCdmPromise> promise, 371 mojom::CdmPromiseResultPtr result) {
335 mojom::CdmPromiseResultPtr result) { 372 if (result->success) {
336 if (result->success) 373 cdm_promise_adapter_.ResolvePromise(promise_id);
337 promise->resolve(); 374 } else {
338 else 375 cdm_promise_adapter_.RejectPromise(promise_id, result->exception,
339 RejectPromise(std::move(promise), std::move(result)); 376 result->system_code,
377 result->error_message);
378 }
340 } 379 }
341 380
342 void MojoCdm::OnNewSessionCdmPromiseResult( 381 void MojoCdm::OnNewSessionCdmPromiseResult(uint32_t promise_id,
343 std::unique_ptr<NewSessionCdmPromise> promise, 382 mojom::CdmPromiseResultPtr result,
344 mojom::CdmPromiseResultPtr result, 383 const std::string& session_id) {
345 const std::string& session_id) {
346 if (result->success) { 384 if (result->success) {
347 cdm_session_tracker_.AddSession(session_id); 385 cdm_session_tracker_.AddSession(session_id);
348 promise->resolve(session_id); 386 cdm_promise_adapter_.ResolvePromise(promise_id, session_id);
349 } else 387 } else {
350 RejectPromise(std::move(promise), std::move(result)); 388 cdm_promise_adapter_.RejectPromise(promise_id, result->exception,
389 result->system_code,
390 result->error_message);
391 }
351 } 392 }
352 393
353 } // namespace media 394 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698