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.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 base::Closure additional_resolve_cb_; | 86 base::Closure additional_resolve_cb_; |
87 }; | 87 }; |
88 | 88 |
89 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( | 89 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( |
90 const std::string& key_system, | 90 const std::string& key_system, |
91 const GURL& security_origin, | 91 const GURL& security_origin, |
92 const CreatePepperCdmCB& create_pepper_cdm_cb, | 92 const CreatePepperCdmCB& create_pepper_cdm_cb, |
93 const media::SessionMessageCB& session_message_cb, | 93 const media::SessionMessageCB& session_message_cb, |
94 const media::SessionReadyCB& session_ready_cb, | 94 const media::SessionReadyCB& session_ready_cb, |
95 const media::SessionClosedCB& session_closed_cb, | 95 const media::SessionClosedCB& session_closed_cb, |
96 const media::SessionErrorCB& session_error_cb) { | 96 const media::SessionErrorCB& session_error_cb, |
| 97 const media::SessionKeysChangeCB& session_keys_change_cb, |
| 98 const media::SessionExpirationUpdateCB& session_expiration_update_cb) { |
97 std::string plugin_type = GetPepperType(key_system); | 99 std::string plugin_type = GetPepperType(key_system); |
98 DCHECK(!plugin_type.empty()); | 100 DCHECK(!plugin_type.empty()); |
99 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper = | 101 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper = |
100 create_pepper_cdm_cb.Run(plugin_type, security_origin); | 102 create_pepper_cdm_cb.Run(plugin_type, security_origin); |
101 if (!pepper_cdm_wrapper) { | 103 if (!pepper_cdm_wrapper) { |
102 DLOG(ERROR) << "Plugin instance creation failed."; | 104 DLOG(ERROR) << "Plugin instance creation failed."; |
103 return scoped_ptr<PpapiDecryptor>(); | 105 return scoped_ptr<PpapiDecryptor>(); |
104 } | 106 } |
105 | 107 |
106 return scoped_ptr<PpapiDecryptor>( | 108 return scoped_ptr<PpapiDecryptor>( |
107 new PpapiDecryptor(key_system, | 109 new PpapiDecryptor(key_system, |
108 pepper_cdm_wrapper.Pass(), | 110 pepper_cdm_wrapper.Pass(), |
109 session_message_cb, | 111 session_message_cb, |
110 session_ready_cb, | 112 session_ready_cb, |
111 session_closed_cb, | 113 session_closed_cb, |
112 session_error_cb)); | 114 session_error_cb, |
| 115 session_keys_change_cb, |
| 116 session_expiration_update_cb)); |
113 } | 117 } |
114 | 118 |
115 PpapiDecryptor::PpapiDecryptor( | 119 PpapiDecryptor::PpapiDecryptor( |
116 const std::string& key_system, | 120 const std::string& key_system, |
117 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, | 121 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper, |
118 const media::SessionMessageCB& session_message_cb, | 122 const media::SessionMessageCB& session_message_cb, |
119 const media::SessionReadyCB& session_ready_cb, | 123 const media::SessionReadyCB& session_ready_cb, |
120 const media::SessionClosedCB& session_closed_cb, | 124 const media::SessionClosedCB& session_closed_cb, |
121 const media::SessionErrorCB& session_error_cb) | 125 const media::SessionErrorCB& session_error_cb, |
| 126 const media::SessionKeysChangeCB& session_keys_change_cb, |
| 127 const media::SessionExpirationUpdateCB& session_expiration_update_cb) |
122 : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()), | 128 : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()), |
123 session_message_cb_(session_message_cb), | 129 session_message_cb_(session_message_cb), |
124 session_ready_cb_(session_ready_cb), | 130 session_ready_cb_(session_ready_cb), |
125 session_closed_cb_(session_closed_cb), | 131 session_closed_cb_(session_closed_cb), |
126 session_error_cb_(session_error_cb), | 132 session_error_cb_(session_error_cb), |
| 133 session_keys_change_cb_(session_keys_change_cb), |
| 134 session_expiration_update_cb_(session_expiration_update_cb), |
127 render_loop_proxy_(base::MessageLoopProxy::current()), | 135 render_loop_proxy_(base::MessageLoopProxy::current()), |
128 weak_ptr_factory_(this) { | 136 weak_ptr_factory_(this) { |
129 DCHECK(pepper_cdm_wrapper_.get()); | 137 DCHECK(pepper_cdm_wrapper_.get()); |
130 DCHECK(!session_message_cb_.is_null()); | 138 DCHECK(!session_message_cb_.is_null()); |
131 DCHECK(!session_ready_cb_.is_null()); | 139 DCHECK(!session_ready_cb_.is_null()); |
132 DCHECK(!session_closed_cb_.is_null()); | 140 DCHECK(!session_closed_cb_.is_null()); |
133 DCHECK(!session_error_cb_.is_null()); | 141 DCHECK(!session_error_cb_.is_null()); |
| 142 DCHECK(!session_keys_change_cb.is_null()); |
| 143 DCHECK(!session_expiration_update_cb.is_null()); |
134 | 144 |
135 base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); | 145 base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr(); |
136 CdmDelegate()->Initialize( | 146 CdmDelegate()->Initialize( |
137 key_system, | 147 key_system, |
138 base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this), | 148 base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this), |
139 base::Bind(&PpapiDecryptor::OnSessionReady, weak_this), | 149 base::Bind(&PpapiDecryptor::OnSessionReady, weak_this), |
140 base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this), | 150 base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this), |
141 base::Bind(&PpapiDecryptor::OnSessionError, weak_this), | 151 base::Bind(&PpapiDecryptor::OnSessionError, weak_this), |
| 152 base::Bind(&PpapiDecryptor::OnSessionKeysChange, weak_this), |
| 153 base::Bind(&PpapiDecryptor::OnSessionExpirationUpdate, weak_this), |
142 base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this)); | 154 base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this)); |
143 } | 155 } |
144 | 156 |
145 PpapiDecryptor::~PpapiDecryptor() { | 157 PpapiDecryptor::~PpapiDecryptor() { |
146 pepper_cdm_wrapper_.reset(); | 158 pepper_cdm_wrapper_.reset(); |
147 } | 159 } |
148 | 160 |
| 161 void PpapiDecryptor::SetServerCertificate( |
| 162 const uint8* certificate_data, |
| 163 int certificate_data_length, |
| 164 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 165 DVLOG(2) << __FUNCTION__; |
| 166 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 167 |
| 168 if (!CdmDelegate()) { |
| 169 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 170 return; |
| 171 } |
| 172 |
| 173 CdmDelegate()->SetServerCertificate( |
| 174 certificate_data, certificate_data_length, promise.Pass()); |
| 175 } |
| 176 |
149 void PpapiDecryptor::CreateSession( | 177 void PpapiDecryptor::CreateSession( |
150 const std::string& init_data_type, | 178 const std::string& init_data_type, |
151 const uint8* init_data, | 179 const uint8* init_data, |
152 int init_data_length, | 180 int init_data_length, |
153 SessionType session_type, | 181 SessionType session_type, |
154 scoped_ptr<media::NewSessionCdmPromise> promise) { | 182 scoped_ptr<media::NewSessionCdmPromise> promise) { |
155 DVLOG(2) << __FUNCTION__; | 183 DVLOG(2) << __FUNCTION__; |
156 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 184 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
157 | 185 |
158 if (!CdmDelegate()) { | 186 if (!CdmDelegate()) { |
(...skipping 12 matching lines...) Expand all Loading... |
171 const std::string& web_session_id, | 199 const std::string& web_session_id, |
172 scoped_ptr<media::NewSessionCdmPromise> promise) { | 200 scoped_ptr<media::NewSessionCdmPromise> promise) { |
173 DVLOG(2) << __FUNCTION__; | 201 DVLOG(2) << __FUNCTION__; |
174 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 202 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
175 | 203 |
176 if (!CdmDelegate()) { | 204 if (!CdmDelegate()) { |
177 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); | 205 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
178 return; | 206 return; |
179 } | 207 } |
180 | 208 |
| 209 // TODO(jrummell): Intercepting the promise should not be necessary once |
| 210 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413. |
181 scoped_ptr<SessionLoadedPromise> session_loaded_promise( | 211 scoped_ptr<SessionLoadedPromise> session_loaded_promise( |
182 new SessionLoadedPromise(promise.Pass(), | 212 new SessionLoadedPromise(promise.Pass(), |
183 base::Bind(&PpapiDecryptor::ResumePlayback, | 213 base::Bind(&PpapiDecryptor::ResumePlayback, |
184 weak_ptr_factory_.GetWeakPtr()))); | 214 weak_ptr_factory_.GetWeakPtr()))); |
185 | 215 |
186 CdmDelegate()->LoadSession( | 216 CdmDelegate()->LoadSession( |
187 web_session_id, | 217 web_session_id, |
188 session_loaded_promise.PassAs<media::NewSessionCdmPromise>()); | 218 session_loaded_promise.PassAs<media::NewSessionCdmPromise>()); |
189 } | 219 } |
190 | 220 |
191 void PpapiDecryptor::UpdateSession( | 221 void PpapiDecryptor::UpdateSession( |
192 const std::string& web_session_id, | 222 const std::string& web_session_id, |
193 const uint8* response, | 223 const uint8* response, |
194 int response_length, | 224 int response_length, |
195 scoped_ptr<media::SimpleCdmPromise> promise) { | 225 scoped_ptr<media::SimpleCdmPromise> promise) { |
196 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 226 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
197 | 227 |
198 if (!CdmDelegate()) { | 228 if (!CdmDelegate()) { |
199 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); | 229 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
200 return; | 230 return; |
201 } | 231 } |
202 | 232 |
| 233 // TODO(jrummell): Intercepting the promise should not be necessary once |
| 234 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413. |
203 scoped_ptr<SessionUpdatedPromise> session_updated_promise( | 235 scoped_ptr<SessionUpdatedPromise> session_updated_promise( |
204 new SessionUpdatedPromise(promise.Pass(), | 236 new SessionUpdatedPromise(promise.Pass(), |
205 base::Bind(&PpapiDecryptor::ResumePlayback, | 237 base::Bind(&PpapiDecryptor::ResumePlayback, |
206 weak_ptr_factory_.GetWeakPtr()))); | 238 weak_ptr_factory_.GetWeakPtr()))); |
207 CdmDelegate()->UpdateSession( | 239 CdmDelegate()->UpdateSession( |
208 web_session_id, | 240 web_session_id, |
209 response, | 241 response, |
210 response_length, | 242 response_length, |
211 session_updated_promise.PassAs<media::SimpleCdmPromise>()); | 243 session_updated_promise.PassAs<media::SimpleCdmPromise>()); |
212 } | 244 } |
213 | 245 |
214 void PpapiDecryptor::ReleaseSession( | 246 void PpapiDecryptor::CloseSession(const std::string& web_session_id, |
| 247 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 248 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 249 |
| 250 if (!CdmDelegate()) { |
| 251 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 252 return; |
| 253 } |
| 254 |
| 255 CdmDelegate()->CloseSession(web_session_id, promise.Pass()); |
| 256 } |
| 257 |
| 258 void PpapiDecryptor::RemoveSession( |
215 const std::string& web_session_id, | 259 const std::string& web_session_id, |
216 scoped_ptr<media::SimpleCdmPromise> promise) { | 260 scoped_ptr<media::SimpleCdmPromise> promise) { |
217 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 261 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
218 | 262 |
219 if (!CdmDelegate()) { | 263 if (!CdmDelegate()) { |
220 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); | 264 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
221 return; | 265 return; |
222 } | 266 } |
223 | 267 |
224 CdmDelegate()->CloseSession(web_session_id, promise.Pass()); | 268 CdmDelegate()->RemoveSession(web_session_id, promise.Pass()); |
| 269 } |
| 270 |
| 271 void PpapiDecryptor::GetUsableKeyIds(const std::string& web_session_id, |
| 272 scoped_ptr<media::KeyIdsPromise> promise) { |
| 273 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 274 |
| 275 if (!CdmDelegate()) { |
| 276 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); |
| 277 return; |
| 278 } |
| 279 |
| 280 CdmDelegate()->GetUsableKeyIds(web_session_id, promise.Pass()); |
225 } | 281 } |
226 | 282 |
227 media::Decryptor* PpapiDecryptor::GetDecryptor() { | 283 media::Decryptor* PpapiDecryptor::GetDecryptor() { |
228 return this; | 284 return this; |
229 } | 285 } |
230 | 286 |
231 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, | 287 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, |
232 const NewKeyCB& new_key_cb) { | 288 const NewKeyCB& new_key_cb) { |
233 if (!render_loop_proxy_->BelongsToCurrentThread()) { | 289 if (!render_loop_proxy_->BelongsToCurrentThread()) { |
234 render_loop_proxy_->PostTask(FROM_HERE, | 290 render_loop_proxy_->PostTask(FROM_HERE, |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 } | 485 } |
430 } | 486 } |
431 | 487 |
432 void PpapiDecryptor::OnSessionMessage(const std::string& web_session_id, | 488 void PpapiDecryptor::OnSessionMessage(const std::string& web_session_id, |
433 const std::vector<uint8>& message, | 489 const std::vector<uint8>& message, |
434 const GURL& destination_url) { | 490 const GURL& destination_url) { |
435 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 491 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
436 session_message_cb_.Run(web_session_id, message, destination_url); | 492 session_message_cb_.Run(web_session_id, message, destination_url); |
437 } | 493 } |
438 | 494 |
| 495 void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id, |
| 496 bool has_additional_usable_key) { |
| 497 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 498 |
| 499 // TODO(jrummell): Handling resume playback should be done in the media |
| 500 // player, not in the Decryptors. http://crbug.com/413413. |
| 501 if (has_additional_usable_key) |
| 502 ResumePlayback(); |
| 503 |
| 504 session_keys_change_cb_.Run(web_session_id, has_additional_usable_key); |
| 505 } |
| 506 |
| 507 void PpapiDecryptor::OnSessionExpirationUpdate( |
| 508 const std::string& web_session_id, |
| 509 const base::Time& new_expiry_time) { |
| 510 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
| 511 session_expiration_update_cb_.Run(web_session_id, new_expiry_time); |
| 512 } |
| 513 |
439 void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) { | 514 void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) { |
440 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 515 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
441 | 516 |
| 517 // TODO(jrummell): Calling ResumePlayback() here should not be necessary once |
| 518 // OnSessionKeysChange() is called in all cases. http://crbug.com/413413. |
442 ResumePlayback(); | 519 ResumePlayback(); |
443 session_ready_cb_.Run(web_session_id); | 520 session_ready_cb_.Run(web_session_id); |
444 } | 521 } |
445 | 522 |
446 void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) { | 523 void PpapiDecryptor::OnSessionClosed(const std::string& web_session_id) { |
447 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 524 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
448 session_closed_cb_.Run(web_session_id); | 525 session_closed_cb_.Run(web_session_id); |
449 } | 526 } |
450 | 527 |
451 void PpapiDecryptor::OnSessionError(const std::string& web_session_id, | 528 void PpapiDecryptor::OnSessionError(const std::string& web_session_id, |
(...skipping 20 matching lines...) Expand all Loading... |
472 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 549 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
473 pepper_cdm_wrapper_.reset(); | 550 pepper_cdm_wrapper_.reset(); |
474 } | 551 } |
475 | 552 |
476 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() { | 553 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() { |
477 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); | 554 DCHECK(render_loop_proxy_->BelongsToCurrentThread()); |
478 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL; | 555 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL; |
479 } | 556 } |
480 | 557 |
481 } // namespace content | 558 } // namespace content |
OLD | NEW |