Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |