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 "webcontentdecryptionmodulesession_impl.h" | 5 #include "webcontentdecryptionmodulesession_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | |
| 10 #include "base/numerics/safe_conversions.h" | 11 #include "base/numerics/safe_conversions.h" |
| 11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 13 #include "media/base/cdm_key_information.h" | 14 #include "media/base/cdm_key_information.h" |
| 14 #include "media/base/cdm_promise.h" | 15 #include "media/base/cdm_promise.h" |
| 15 #include "media/base/key_system_names.h" | 16 #include "media/base/key_system_names.h" |
| 16 #include "media/base/key_systems.h" | 17 #include "media/base/key_systems.h" |
| 17 #include "media/base/limits.h" | 18 #include "media/base/limits.h" |
| 18 #include "media/base/media_keys.h" | 19 #include "media/base/media_keys.h" |
| 19 #include "media/blink/cdm_result_promise.h" | 20 #include "media/blink/cdm_result_promise.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 std::string sanitized_data = GenerateJWKSet(keys, session_type); | 218 std::string sanitized_data = GenerateJWKSet(keys, session_type); |
| 218 sanitized_response->assign(sanitized_data.begin(), sanitized_data.end()); | 219 sanitized_response->assign(sanitized_data.begin(), sanitized_data.end()); |
| 219 return true; | 220 return true; |
| 220 } | 221 } |
| 221 | 222 |
| 222 // TODO(jrummell): Verify responses for Widevine. | 223 // TODO(jrummell): Verify responses for Widevine. |
| 223 sanitized_response->assign(response, response + response_length); | 224 sanitized_response->assign(response, response + response_length); |
| 224 return true; | 225 return true; |
| 225 } | 226 } |
| 226 | 227 |
| 228 // If we need to close the session while destroying this object, we need a | |
| 229 // dummy promise that won't call back into this object (or try to pass | |
| 230 // something back to blink). | |
| 231 class IgnoreResponsePromise : public SimpleCdmPromise { | |
|
xhwang
2016/11/11 18:52:46
move this to an anonymous namespace, maybe togethe
jrummell
2016/11/11 21:14:23
Done.
| |
| 232 public: | |
| 233 IgnoreResponsePromise() {} | |
| 234 ~IgnoreResponsePromise() override {} | |
| 235 | |
| 236 // SimpleCdmPromise implementation. | |
| 237 void resolve() final { MarkPromiseSettled(); } | |
| 238 void reject(CdmPromise::Exception exception_code, | |
| 239 uint32_t system_code, | |
| 240 const std::string& error_message) final { | |
| 241 MarkPromiseSettled(); | |
| 242 } | |
| 243 }; | |
| 244 | |
| 227 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( | 245 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( |
| 228 const scoped_refptr<CdmSessionAdapter>& adapter) | 246 const scoped_refptr<CdmSessionAdapter>& adapter) |
| 229 : adapter_(adapter), is_closed_(false), weak_ptr_factory_(this) { | 247 : adapter_(adapter), |
| 230 } | 248 is_closed_(false), |
| 249 has_close_been_called_(false), | |
| 250 weak_ptr_factory_(this) {} | |
| 231 | 251 |
| 232 WebContentDecryptionModuleSessionImpl:: | 252 WebContentDecryptionModuleSessionImpl:: |
| 233 ~WebContentDecryptionModuleSessionImpl() { | 253 ~WebContentDecryptionModuleSessionImpl() { |
| 234 DCHECK(thread_checker_.CalledOnValidThread()); | 254 DCHECK(thread_checker_.CalledOnValidThread()); |
| 235 if (!session_id_.empty()) | 255 |
| 256 if (!session_id_.empty()) { | |
| 236 adapter_->UnregisterSession(session_id_); | 257 adapter_->UnregisterSession(session_id_); |
| 258 | |
| 259 // From http://w3c.github.io/encrypted-media/#mediakeysession-interface | |
| 260 // "If a MediaKeySession object is not closed when it becomes inaccessible | |
| 261 // to the page, the CDM shall close the key session associated with the | |
| 262 // object." | |
| 263 // | |
| 264 // This object is destroyed when the corresponding blink object is no | |
| 265 // longer needed (which may be due to it becoming inaccessible to the | |
| 266 // page), so if the session is not closed and CloseSession() has not yet | |
| 267 // been called, call CloseSession() now. Since this object is being | |
| 268 // destroyed, there is no need for the promise to do anything as this | |
| 269 // session will be gone. | |
| 270 if (!is_closed_ && !has_close_been_called_) { | |
|
xhwang
2016/11/11 18:52:46
There's a corner case where the CDM may self-close
jrummell
2016/11/11 21:14:23
Acknowledged.
| |
| 271 adapter_->CloseSession(session_id_, | |
| 272 base::MakeUnique<IgnoreResponsePromise>()); | |
| 273 } | |
| 274 } | |
| 237 } | 275 } |
| 238 | 276 |
| 239 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { | 277 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { |
| 240 client_ = client; | 278 client_ = client; |
| 241 } | 279 } |
| 242 | 280 |
| 243 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { | 281 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { |
| 244 return blink::WebString::fromUTF8(session_id_); | 282 return blink::WebString::fromUTF8(session_id_); |
| 245 } | 283 } |
| 246 | 284 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 | 424 |
| 387 adapter_->UpdateSession( | 425 adapter_->UpdateSession( |
| 388 session_id_, sanitized_response, | 426 session_id_, sanitized_response, |
| 389 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( | 427 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( |
| 390 result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName))); | 428 result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName))); |
| 391 } | 429 } |
| 392 | 430 |
| 393 void WebContentDecryptionModuleSessionImpl::close( | 431 void WebContentDecryptionModuleSessionImpl::close( |
| 394 blink::WebContentDecryptionModuleResult result) { | 432 blink::WebContentDecryptionModuleResult result) { |
| 395 DCHECK(!session_id_.empty()); | 433 DCHECK(!session_id_.empty()); |
| 396 DCHECK(thread_checker_.CalledOnValidThread()); | 434 DCHECK(thread_checker_.CalledOnValidThread()); |
|
xhwang
2016/11/11 18:52:46
DCHECK(!has_close_been_called_) since we can't clo
jrummell
2016/11/11 21:14:23
Done. We shouldn't call close() if |is_closed_| is
| |
| 435 | |
| 436 has_close_been_called_ = true; | |
| 397 adapter_->CloseSession( | 437 adapter_->CloseSession( |
| 398 session_id_, | 438 session_id_, |
| 399 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( | 439 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( |
| 400 result, adapter_->GetKeySystemUMAPrefix() + kCloseSessionUMAName))); | 440 result, adapter_->GetKeySystemUMAPrefix() + kCloseSessionUMAName))); |
| 401 } | 441 } |
| 402 | 442 |
| 403 void WebContentDecryptionModuleSessionImpl::remove( | 443 void WebContentDecryptionModuleSessionImpl::remove( |
| 404 blink::WebContentDecryptionModuleResult result) { | 444 blink::WebContentDecryptionModuleResult result) { |
| 405 DCHECK(!session_id_.empty()); | 445 DCHECK(!session_id_.empty()); |
| 406 DCHECK(thread_checker_.CalledOnValidThread()); | 446 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 504 |
| 465 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; | 505 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; |
| 466 session_id_ = session_id; | 506 session_id_ = session_id; |
| 467 *status = | 507 *status = |
| 468 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) | 508 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) |
| 469 ? SessionInitStatus::NEW_SESSION | 509 ? SessionInitStatus::NEW_SESSION |
| 470 : SessionInitStatus::SESSION_ALREADY_EXISTS; | 510 : SessionInitStatus::SESSION_ALREADY_EXISTS; |
| 471 } | 511 } |
| 472 | 512 |
| 473 } // namespace media | 513 } // namespace media |
| OLD | NEW |