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 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |