Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/renderer/media/crypto/ppapi_decryptor.h" | 5 #include "content/renderer/media/crypto/ppapi_decryptor.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | |
| 10 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 11 #include "base/location.h" | 12 #include "base/location.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 14 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
| 15 #include "content/renderer/media/crypto/key_systems.h" | 16 #include "content/renderer/media/crypto/key_systems.h" |
| 16 #include "content/renderer/pepper/content_decryptor_delegate.h" | 17 #include "content/renderer/pepper/content_decryptor_delegate.h" |
| 17 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" | 18 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" |
| 18 #include "media/base/audio_decoder_config.h" | 19 #include "media/base/audio_decoder_config.h" |
| 20 #include "media/base/cdm_promise.h" | |
| 19 #include "media/base/data_buffer.h" | 21 #include "media/base/data_buffer.h" |
| 20 #include "media/base/decoder_buffer.h" | 22 #include "media/base/decoder_buffer.h" |
| 21 #include "media/base/video_decoder_config.h" | 23 #include "media/base/video_decoder_config.h" |
| 22 #include "media/base/video_frame.h" | 24 #include "media/base/video_frame.h" |
| 23 | 25 |
| 24 namespace content { | 26 namespace content { |
| 25 | 27 |
| 28 // When overriding SimpleCdmPromise, need some callbacks that will never get | |
| 29 // used. | |
| 30 static void DoNothingOnResolve() { | |
| 31 NOTIMPLEMENTED(); | |
| 32 } | |
| 33 | |
| 34 static void DoNothingOnError(media::MediaKeys::Exception exception_code, | |
|
xhwang
2014/05/29 23:44:38
s/Error/Reject to be consistent?
jrummell
2014/05/30 18:04:25
Done.
| |
| 35 uint32 system_code, | |
| 36 const std::string& error_message) { | |
| 37 NOTIMPLEMENTED(); | |
| 38 } | |
| 39 | |
| 40 // This class is needed so that resolving an Update() promise triggers playback | |
| 41 // of the stream. It intercepts the resolve() call to invoke an additional | |
| 42 // callback. | |
| 43 class SessionUpdatedPromise : public media::SimpleCdmPromise { | |
| 44 public: | |
| 45 SessionUpdatedPromise(scoped_ptr<media::SimpleCdmPromise> caller_promise, | |
| 46 base::Closure additional_resolve_cb) | |
| 47 : media::SimpleCdmPromise(base::Bind(&DoNothingOnResolve), | |
| 48 base::Bind(&DoNothingOnError)), | |
|
xhwang
2014/05/29 23:44:38
hmm, this is still hacky.
How about drop DISALLO
jrummell
2014/05/30 18:04:25
Added default constructor on SimpleCdmPromise, so
xhwang
2014/06/02 21:59:21
I like this much better :)
| |
| 49 caller_promise_(caller_promise.Pass()), | |
| 50 additional_resolve_cb_(additional_resolve_cb) {} | |
| 51 | |
| 52 virtual void resolve() OVERRIDE { | |
| 53 additional_resolve_cb_.Run(); | |
| 54 caller_promise_->resolve(); | |
| 55 } | |
| 56 | |
| 57 virtual void reject(media::MediaKeys::Exception exception_code, | |
| 58 uint32 system_code, | |
| 59 const std::string& error_message) OVERRIDE { | |
| 60 caller_promise_->reject(exception_code, system_code, error_message); | |
| 61 } | |
| 62 | |
| 63 protected: | |
| 64 scoped_ptr<media::SimpleCdmPromise> caller_promise_; | |
| 65 base::Closure additional_resolve_cb_; | |
| 66 }; | |
| 67 | |
| 26 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( | 68 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( |
| 27 const std::string& key_system, | 69 const std::string& key_system, |
| 28 const GURL& security_origin, | 70 const GURL& security_origin, |
| 29 const CreatePepperCdmCB& create_pepper_cdm_cb, | 71 const CreatePepperCdmCB& create_pepper_cdm_cb, |
| 30 const media::SessionCreatedCB& session_created_cb, | |
| 31 const media::SessionMessageCB& session_message_cb, | 72 const media::SessionMessageCB& session_message_cb, |
| 32 const media::SessionReadyCB& session_ready_cb, | 73 const media::SessionReadyCB& session_ready_cb, |
| 33 const media::SessionClosedCB& session_closed_cb, | 74 const media::SessionClosedCB& session_closed_cb, |
| 34 const media::SessionErrorCB& session_error_cb) { | 75 const media::SessionErrorCB& session_error_cb) { |
| 35 std::string plugin_type = GetPepperType(key_system); | 76 std::string plugin_type = GetPepperType(key_system); |
| 36 DCHECK(!plugin_type.empty()); | 77 DCHECK(!plugin_type.empty()); |
| 37 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper = | 78 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper = |
| 38 create_pepper_cdm_cb.Run(plugin_type, security_origin); | 79 create_pepper_cdm_cb.Run(plugin_type, security_origin); |
| 39 if (!pepper_cdm_wrapper) { | 80 if (!pepper_cdm_wrapper) { |
| 40 DLOG(ERROR) << "Plugin instance creation failed."; | 81 DLOG(ERROR) << "Plugin instance creation failed."; |
| 41 return scoped_ptr<PpapiDecryptor>(); | 82 return scoped_ptr<PpapiDecryptor>(); |
| 42 } | 83 } |
| 43 | 84 |
| 44 return scoped_ptr<PpapiDecryptor>( | 85 return scoped_ptr<PpapiDecryptor>( |
| 45 new PpapiDecryptor(key_system, | 86 new PpapiDecryptor(key_system, |
| 46 pepper_cdm_wrapper.Pass(), | 87 pepper_cdm_wrapper.Pass(), |
| 47 session_created_cb, | |
| 48 session_message_cb, | 88 session_message_cb, |
| 49 session_ready_cb, | 89 session_ready_cb, |
| 50 session_closed_cb, | 90 session_closed_cb, |
| 51 session_error_cb)); | 91 session_error_cb)); |
| 52 } | 92 } |
| 53 | 93 |
| 54 PpapiDecryptor::PpapiDecryptor( | 94 PpapiDecryptor::PpapiDecryptor( |
| 55 const std::string& key_system, | 95 const std::string& key_system, |
| 56 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, | 96 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, |
| 57 const media::SessionCreatedCB& session_created_cb, | |
| 58 const media::SessionMessageCB& session_message_cb, | 97 const media::SessionMessageCB& session_message_cb, |
| 59 const media::SessionReadyCB& session_ready_cb, | 98 const media::SessionReadyCB& session_ready_cb, |
| 60 const media::SessionClosedCB& session_closed_cb, | 99 const media::SessionClosedCB& session_closed_cb, |
| 61 const media::SessionErrorCB& session_error_cb) | 100 const media::SessionErrorCB& session_error_cb) |
| 62 : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()), | 101 : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()), |
| 63 session_created_cb_(session_created_cb), | |
| 64 session_message_cb_(session_message_cb), | 102 session_message_cb_(session_message_cb), |
| 65 session_ready_cb_(session_ready_cb), | 103 session_ready_cb_(session_ready_cb), |
| 66 session_closed_cb_(session_closed_cb), | 104 session_closed_cb_(session_closed_cb), |
| 67 session_error_cb_(session_error_cb), | 105 session_error_cb_(session_error_cb), |
| 68 render_loop_proxy_(base::MessageLoopProxy::current()), | 106 render_loop_proxy_(base::MessageLoopProxy::current()), |
| 69 weak_ptr_factory_(this) { | 107 weak_ptr_factory_(this) { |
| 70 DCHECK(pepper_cdm_wrapper_.get()); | 108 DCHECK(pepper_cdm_wrapper_.get()); |
| 71 DCHECK(!session_created_cb_.is_null()); | |
| 72 DCHECK(!session_message_cb_.is_null()); | 109 DCHECK(!session_message_cb_.is_null()); |
| 73 DCHECK(!session_ready_cb_.is_null()); | 110 DCHECK(!session_ready_cb_.is_null()); |
| 74 DCHECK(!session_closed_cb_.is_null()); | 111 DCHECK(!session_closed_cb_.is_null()); |
| 75 DCHECK(!session_error_cb_.is_null()); | 112 DCHECK(!session_error_cb_.is_null()); |
| 76 | 113 |
| 77 base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); | 114 base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); |
| 78 CdmDelegate()->Initialize( | 115 CdmDelegate()->Initialize( |
| 79 key_system, | 116 key_system, |
| 80 base::Bind(&PpapiDecryptor::OnSessionCreated, weak_this), | |
| 81 base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this), | 117 base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this), |
| 82 base::Bind(&PpapiDecryptor::OnSessionReady, weak_this), | 118 base::Bind(&PpapiDecryptor::OnSessionReady, weak_this), |
| 83 base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this), | 119 base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this), |
| 84 base::Bind(&PpapiDecryptor::OnSessionError, weak_this), | 120 base::Bind(&PpapiDecryptor::OnSessionError, weak_this), |
| 85 base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this)); | 121 base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this)); |
| 86 } | 122 } |
| 87 | 123 |
| 88 PpapiDecryptor::~PpapiDecryptor() { | 124 PpapiDecryptor::~PpapiDecryptor() { |
| 89 pepper_cdm_wrapper_.reset(); | 125 pepper_cdm_wrapper_.reset(); |
| 90 } | 126 } |
| 91 | 127 |
| 92 bool PpapiDecryptor::CreateSession(uint32 session_id, | 128 void PpapiDecryptor::CreateSession( |
| 93 const std::string& content_type, | 129 const std::string& init_data_type, |
| 94 const uint8* init_data, | 130 const uint8* init_data, |
| 95 int init_data_length) { | 131 int init_data_length, |
| 96 DVLOG(2) << __FUNCTION__; | 132 SessionType session_type, |
| 97 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 133 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 98 | |
| 99 if (!CdmDelegate() || | |
| 100 !CdmDelegate()->CreateSession( | |
| 101 session_id, content_type, init_data, init_data_length)) { | |
| 102 ReportFailureToCallPlugin(session_id); | |
| 103 return false; | |
| 104 } | |
| 105 | |
| 106 return true; | |
| 107 } | |
| 108 | |
| 109 void PpapiDecryptor::LoadSession(uint32 session_id, | |
| 110 const std::string& web_session_id) { | |
| 111 DVLOG(2) << __FUNCTION__; | 134 DVLOG(2) << __FUNCTION__; |
| 112 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 135 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 113 | 136 |
| 114 if (!CdmDelegate()) { | 137 if (!CdmDelegate()) { |
| 115 ReportFailureToCallPlugin(session_id); | 138 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 116 return; | 139 return; |
| 117 } | 140 } |
| 118 | 141 |
| 119 CdmDelegate()->LoadSession(session_id, web_session_id); | 142 CdmDelegate()->CreateSession(init_data_type, |
| 143 init_data, | |
| 144 init_data_length, | |
| 145 session_type, | |
| 146 promise.Pass()); | |
| 120 } | 147 } |
| 121 | 148 |
| 122 void PpapiDecryptor::UpdateSession(uint32 session_id, | 149 void PpapiDecryptor::LoadSession( |
| 123 const uint8* response, | 150 const std::string& web_session_id, |
| 124 int response_length) { | 151 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 125 DVLOG(2) << __FUNCTION__; | 152 DVLOG(2) << __FUNCTION__; |
| 126 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 153 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 127 | 154 |
| 128 if (!CdmDelegate() || | 155 if (!CdmDelegate()) { |
| 129 !CdmDelegate()->UpdateSession(session_id, response, response_length)) { | 156 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 130 ReportFailureToCallPlugin(session_id); | |
| 131 return; | 157 return; |
| 132 } | 158 } |
| 159 | |
| 160 CdmDelegate()->LoadSession(web_session_id, promise.Pass()); | |
| 133 } | 161 } |
| 134 | 162 |
| 135 void PpapiDecryptor::ReleaseSession(uint32 session_id) { | 163 void PpapiDecryptor::UpdateSession( |
| 136 DVLOG(2) << __FUNCTION__; | 164 const std::string& web_session_id, |
| 165 const uint8* response, | |
| 166 int response_length, | |
| 167 scoped_ptr<media::SimpleCdmPromise> promise) { | |
| 137 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 168 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 138 | 169 |
| 139 if (!CdmDelegate() || !CdmDelegate()->ReleaseSession(session_id)) { | 170 if (!CdmDelegate()) { |
| 140 ReportFailureToCallPlugin(session_id); | 171 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 141 return; | 172 return; |
| 142 } | 173 } |
| 174 | |
| 175 scoped_ptr<SessionUpdatedPromise> update_promise( | |
|
xhwang
2014/05/29 23:44:38
s/update_promise/session_updated_promise?
jrummell
2014/05/30 18:04:25
Done.
| |
| 176 new SessionUpdatedPromise(promise.Pass(), | |
| 177 base::Bind(&PpapiDecryptor::ResumePlayback, | |
| 178 weak_ptr_factory_.GetWeakPtr()))); | |
| 179 CdmDelegate()->UpdateSession( | |
| 180 web_session_id, | |
| 181 response, | |
| 182 response_length, | |
| 183 update_promise.PassAs<media::SimpleCdmPromise>()); | |
| 184 } | |
| 185 | |
| 186 void PpapiDecryptor::ReleaseSession( | |
| 187 const std::string& web_session_id, | |
| 188 scoped_ptr<media::SimpleCdmPromise> promise) { | |
| 189 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 190 | |
| 191 if (!CdmDelegate()) { | |
| 192 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); | |
| 193 return; | |
| 194 } | |
| 195 | |
| 196 CdmDelegate()->ReleaseSession(web_session_id, promise.Pass()); | |
| 143 } | 197 } |
| 144 | 198 |
| 145 media::Decryptor* PpapiDecryptor::GetDecryptor() { | 199 media::Decryptor* PpapiDecryptor::GetDecryptor() { |
| 146 return this; | 200 return this; |
| 147 } | 201 } |
| 148 | 202 |
| 149 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, | 203 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, |
| 150 const NewKeyCB& new_key_cb) { | 204 const NewKeyCB& new_key_cb) { |
| 151 if (!render_loop_proxy_->BelongsToCurrentThread()) { | 205 if (!render_loop_proxy_->BelongsToCurrentThread()) { |
| 152 render_loop_proxy_->PostTask(FROM_HERE, | 206 render_loop_proxy_->PostTask(FROM_HERE, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 weak_ptr_factory_.GetWeakPtr(), | 377 weak_ptr_factory_.GetWeakPtr(), |
| 324 stream_type)); | 378 stream_type)); |
| 325 return; | 379 return; |
| 326 } | 380 } |
| 327 | 381 |
| 328 DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type; | 382 DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type; |
| 329 if (CdmDelegate()) | 383 if (CdmDelegate()) |
| 330 CdmDelegate()->DeinitializeDecoder(stream_type); | 384 CdmDelegate()->DeinitializeDecoder(stream_type); |
| 331 } | 385 } |
| 332 | 386 |
| 333 void PpapiDecryptor::ReportFailureToCallPlugin(uint32 session_id) { | |
| 334 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 335 DVLOG(1) << "Failed to call plugin."; | |
| 336 session_error_cb_.Run(session_id, kUnknownError, 0); | |
| 337 } | |
| 338 | |
| 339 void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type, | 387 void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type, |
| 340 bool success) { | 388 bool success) { |
| 341 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 389 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 342 switch (stream_type) { | 390 switch (stream_type) { |
| 343 case kAudio: | 391 case kAudio: |
| 344 DCHECK(!audio_decoder_init_cb_.is_null()); | 392 DCHECK(!audio_decoder_init_cb_.is_null()); |
| 345 base::ResetAndReturn(&audio_decoder_init_cb_).Run(success); | 393 base::ResetAndReturn(&audio_decoder_init_cb_).Run(success); |
| 346 break; | 394 break; |
| 347 case kVideo: | 395 case kVideo: |
| 348 DCHECK(!video_decoder_init_cb_.is_null()); | 396 DCHECK(!video_decoder_init_cb_.is_null()); |
| 349 base::ResetAndReturn(&video_decoder_init_cb_).Run(success); | 397 base::ResetAndReturn(&video_decoder_init_cb_).Run(success); |
| 350 break; | 398 break; |
| 351 default: | 399 default: |
| 352 NOTREACHED(); | 400 NOTREACHED(); |
| 353 } | 401 } |
| 354 } | 402 } |
| 355 | 403 |
| 356 void PpapiDecryptor::OnSessionCreated(uint32 session_id, | 404 void PpapiDecryptor::OnSessionMessage(const std::string& web_session_id, |
| 357 const std::string& web_session_id) { | |
| 358 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 359 session_created_cb_.Run(session_id, web_session_id); | |
| 360 } | |
| 361 | |
| 362 void PpapiDecryptor::OnSessionMessage(uint32 session_id, | |
| 363 const std::vector<uint8>& message, | 405 const std::vector<uint8>& message, |
| 364 const GURL& destination_url) { | 406 const GURL& destination_url) { |
| 365 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 407 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 366 session_message_cb_.Run(session_id, message, destination_url); | 408 session_message_cb_.Run(web_session_id, message, destination_url); |
| 367 } | 409 } |
| 368 | 410 |
| 369 void PpapiDecryptor::OnSessionReady(uint32 session_id) { | 411 void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) { |
| 370 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 412 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 371 | 413 |
| 414 ResumePlayback(); | |
| 415 session_ready_cb_.Run(web_session_id); | |
| 416 } | |
| 417 | |
| 418 void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) { | |
| 419 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 420 session_closed_cb_.Run(web_session_id); | |
| 421 } | |
| 422 | |
| 423 void PpapiDecryptor::OnSessionError(const std::string& web_session_id, | |
| 424 MediaKeys::Exception exception_code, | |
| 425 uint32 system_code, | |
| 426 const std::string& error_description) { | |
| 427 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 428 session_error_cb_.Run( | |
| 429 web_session_id, exception_code, system_code, error_description); | |
| 430 } | |
| 431 | |
| 432 void PpapiDecryptor::ResumePlayback() { | |
| 372 // Based on the spec, we need to resume playback when update() completes | 433 // Based on the spec, we need to resume playback when update() completes |
| 373 // successfully, or when a session is successfully loaded. In both cases, | 434 // successfully, or when a session is successfully loaded (triggered by |
| 374 // the CDM fires OnSessionReady() event. So we choose to call the NewKeyCBs | 435 // OnSessionReady()). So we choose to call the NewKeyCBs here. |
| 375 // here. | |
| 376 // TODO(xhwang): Rename OnSessionReady to indicate that the playback may | |
| 377 // resume successfully (e.g. a new key is available or available again). | |
| 378 if (!new_audio_key_cb_.is_null()) | 436 if (!new_audio_key_cb_.is_null()) |
| 379 new_audio_key_cb_.Run(); | 437 new_audio_key_cb_.Run(); |
| 380 | 438 |
| 381 if (!new_video_key_cb_.is_null()) | 439 if (!new_video_key_cb_.is_null()) |
| 382 new_video_key_cb_.Run(); | 440 new_video_key_cb_.Run(); |
| 383 | |
| 384 session_ready_cb_.Run(session_id); | |
| 385 } | |
| 386 | |
| 387 void PpapiDecryptor::OnSessionClosed(uint32 session_id) { | |
| 388 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 389 session_closed_cb_.Run(session_id); | |
| 390 } | |
| 391 | |
| 392 void PpapiDecryptor::OnSessionError(uint32 session_id, | |
| 393 media::MediaKeys::KeyError error_code, | |
| 394 uint32 system_code) { | |
| 395 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | |
| 396 session_error_cb_.Run(session_id, error_code, system_code); | |
| 397 } | 441 } |
| 398 | 442 |
| 399 void PpapiDecryptor::OnFatalPluginError() { | 443 void PpapiDecryptor::OnFatalPluginError() { |
| 400 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 444 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 401 pepper_cdm_wrapper_.reset(); | 445 pepper_cdm_wrapper_.reset(); |
| 402 } | 446 } |
| 403 | 447 |
| 404 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() { | 448 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() { |
| 405 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 449 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 406 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL; | 450 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL; |
| 407 } | 451 } |
| 408 | 452 |
| 409 } // namespace content | 453 } // namespace content |
| OLD | NEW |