Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: media/cdm/aes_decryptor.cc

Issue 2831963003: EME: Allow temporary sessions to be removed for ClearKey only. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cdm/aes_decryptor.h ('k') | media/cdm/aes_decryptor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "media/cdm/aes_decryptor.h" 5 #include "media/cdm/aes_decryptor.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <list> 8 #include <list>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "crypto/encryptor.h" 15 #include "crypto/encryptor.h"
16 #include "crypto/symmetric_key.h" 16 #include "crypto/symmetric_key.h"
17 #include "media/base/audio_decoder_config.h" 17 #include "media/base/audio_decoder_config.h"
18 #include "media/base/cdm_key_information.h"
19 #include "media/base/cdm_promise.h" 18 #include "media/base/cdm_promise.h"
20 #include "media/base/decoder_buffer.h" 19 #include "media/base/decoder_buffer.h"
21 #include "media/base/decrypt_config.h" 20 #include "media/base/decrypt_config.h"
22 #include "media/base/limits.h" 21 #include "media/base/limits.h"
23 #include "media/base/video_decoder_config.h" 22 #include "media/base/video_decoder_config.h"
24 #include "media/base/video_frame.h" 23 #include "media/base/video_frame.h"
25 #include "media/cdm/json_web_key.h" 24 #include "media/cdm/json_web_key.h"
26 #include "media/media_features.h" 25 #include "media/media_features.h"
27 26
28 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 27 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 DCHECK_EQ(decrypted_text.size(), encrypted_text.size()); 223 DCHECK_EQ(decrypted_text.size(), encrypted_text.size());
225 224
226 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( 225 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom(
227 reinterpret_cast<const uint8_t*>(sample), sample_size); 226 reinterpret_cast<const uint8_t*>(sample), sample_size);
228 CopySubsamples(subsamples, kDstContainsClearBytes, 227 CopySubsamples(subsamples, kDstContainsClearBytes,
229 reinterpret_cast<const uint8_t*>(decrypted_text.data()), 228 reinterpret_cast<const uint8_t*>(decrypted_text.data()),
230 output->writable_data()); 229 output->writable_data());
231 return output; 230 return output;
232 } 231 }
233 232
234 AesDecryptor::AesDecryptor(const GURL& /* security_origin */, 233 AesDecryptor::AesDecryptor(
235 const SessionMessageCB& session_message_cb, 234 const GURL& /* security_origin */,
236 const SessionClosedCB& session_closed_cb, 235 const SessionMessageCB& session_message_cb,
237 const SessionKeysChangeCB& session_keys_change_cb) 236 const SessionClosedCB& session_closed_cb,
237 const SessionKeysChangeCB& session_keys_change_cb,
238 const SessionExpirationUpdateCB& session_expiration_update_cb)
238 : session_message_cb_(session_message_cb), 239 : session_message_cb_(session_message_cb),
239 session_closed_cb_(session_closed_cb), 240 session_closed_cb_(session_closed_cb),
240 session_keys_change_cb_(session_keys_change_cb) { 241 session_keys_change_cb_(session_keys_change_cb),
242 session_expiration_update_cb_(session_expiration_update_cb) {
241 // AesDecryptor doesn't keep any persistent data, so no need to do anything 243 // AesDecryptor doesn't keep any persistent data, so no need to do anything
242 // with |security_origin|. 244 // with |security_origin|.
243 DCHECK(!session_message_cb_.is_null()); 245 DCHECK(!session_message_cb_.is_null());
244 DCHECK(!session_closed_cb_.is_null()); 246 DCHECK(!session_closed_cb_.is_null());
245 DCHECK(!session_keys_change_cb_.is_null()); 247 DCHECK(!session_keys_change_cb_.is_null());
246 } 248 }
247 249
248 AesDecryptor::~AesDecryptor() { 250 AesDecryptor::~AesDecryptor() {
249 key_map_.clear(); 251 key_map_.clear();
250 } 252 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 386
385 if (!new_audio_key_cb_.is_null()) 387 if (!new_audio_key_cb_.is_null())
386 new_audio_key_cb_.Run(); 388 new_audio_key_cb_.Run();
387 389
388 if (!new_video_key_cb_.is_null()) 390 if (!new_video_key_cb_.is_null())
389 new_video_key_cb_.Run(); 391 new_video_key_cb_.Run();
390 } 392 }
391 393
392 promise->resolve(); 394 promise->resolve();
393 395
394 // Create the list of all available keys for this session. 396 session_keys_change_cb_.Run(
395 CdmKeysInfo keys_info; 397 session_id, key_added,
396 { 398 GenerateKeysInfoList(session_id, CdmKeyInformation::USABLE));
397 base::AutoLock auto_lock(key_map_lock_);
398 for (const auto& item : key_map_) {
399 if (item.second->Contains(session_id)) {
400 keys_info.push_back(
401 new CdmKeyInformation(item.first, CdmKeyInformation::USABLE, 0));
402 }
403 }
404 }
405
406 session_keys_change_cb_.Run(session_id, key_added, std::move(keys_info));
407 } 399 }
408 400
409 // Runs the parallel steps from https://w3c.github.io/encrypted-media/#close. 401 // Runs the parallel steps from https://w3c.github.io/encrypted-media/#close.
410 void AesDecryptor::CloseSession(const std::string& session_id, 402 void AesDecryptor::CloseSession(const std::string& session_id,
411 std::unique_ptr<SimpleCdmPromise> promise) { 403 std::unique_ptr<SimpleCdmPromise> promise) {
412 // Validate that this is a reference to an open session. close() shouldn't 404 // Validate that this is a reference to an open session. close() shouldn't
413 // be called if the session is already closed. However, the operation is 405 // be called if the session is already closed. However, the operation is
414 // asynchronous, so there is a window where close() was called a second time 406 // asynchronous, so there is a window where close() was called a second time
415 // just before the closed event arrives. As a result it is possible that the 407 // just before the closed event arrives. As a result it is possible that the
416 // session is already closed, so assume that the session is closed if it 408 // session is already closed, so assume that the session is closed if it
(...skipping 13 matching lines...) Expand all
430 open_sessions_.erase(it); 422 open_sessions_.erase(it);
431 DeleteKeysForSession(session_id); 423 DeleteKeysForSession(session_id);
432 424
433 // 5.3. Queue a task to run the following steps: 425 // 5.3. Queue a task to run the following steps:
434 // 5.3.1. Run the Session Closed algorithm on the session. 426 // 5.3.1. Run the Session Closed algorithm on the session.
435 session_closed_cb_.Run(session_id); 427 session_closed_cb_.Run(session_id);
436 // 5.3.2. Resolve promise. 428 // 5.3.2. Resolve promise.
437 promise->resolve(); 429 promise->resolve();
438 } 430 }
439 431
432 // Runs the parallel steps from https://w3c.github.io/encrypted-media/#remove.
440 void AesDecryptor::RemoveSession(const std::string& session_id, 433 void AesDecryptor::RemoveSession(const std::string& session_id,
441 std::unique_ptr<SimpleCdmPromise> promise) { 434 std::unique_ptr<SimpleCdmPromise> promise) {
442 NOTIMPLEMENTED() << "Need to address https://crbug.com/616166."; 435 std::set<std::string>::iterator it = open_sessions_.find(session_id);
443 promise->reject(CdmPromise::INVALID_ACCESS_ERROR, 0, 436 if (it == open_sessions_.end()) {
444 "Session does not exist."); 437 // Session doesn't exist. Since this should only be called if the session
438 // existed at one time, this must mean the session has been closed.
439 promise->reject(CdmPromise::INVALID_STATE_ERROR, 0,
440 "The session is already closed.");
441 return;
442 }
443
444 // Create the list of all existing keys for this session. They will be
445 // removed, so set the status to "released".
446 CdmKeysInfo keys_info =
447 GenerateKeysInfoList(session_id, CdmKeyInformation::RELEASED);
448
449 // 4.1. Let cdm be the CDM instance represented by session's cdm instance
450 // value.
451 // 4.2 Let message be null.
452 // 4.3 Let message type be null.
453 // 4.4 Use the cdm to execute the following steps:
454 // 4.4.1.1 Destroy the license(s) and/or key(s) associated with the session.
455 DeleteKeysForSession(session_id);
456
457 // 4.4.1.2 Follow the steps for the value of this object's session type
458 // from the following list:
459 // "temporary"
460 // Continue with the following steps.
461 // "persistent-license"
462 // (Not supported, so no need to do anything.)
463
464 // 4.5. Queue a task to run the following steps:
465 // 4.5.1 Run the Update Key Statuses algorithm on the session, providing
466 // all key ID(s) in the session along with the "released"
467 // MediaKeyStatus value for each.
468 session_keys_change_cb_.Run(session_id, false, std::move(keys_info));
469
470 // 4.5.2 Run the Update Expiration algorithm on the session, providing NaN.
471 session_expiration_update_cb_.Run(session_id, base::Time());
472
473 // 4.5.3 If any of the preceding steps failed, reject promise with a new
474 // DOMException whose name is the appropriate error name.
475 // 4.5.4 Let message type be "license-release".
476 // 4.5.5 If message is not null, run the Queue a "message" Event algorithm
477 // on the session, providing message type and message.
478 // (Not needed as message is only set for persistent licenses, and they're
479 // not supported here.)
480
481 // 4.5.6. Resolve promise.
482 promise->resolve();
445 } 483 }
446 484
447 CdmContext* AesDecryptor::GetCdmContext() { 485 CdmContext* AesDecryptor::GetCdmContext() {
448 return this; 486 return this;
449 } 487 }
450 488
451 Decryptor* AesDecryptor::GetDecryptor() { 489 Decryptor* AesDecryptor::GetDecryptor() {
452 return this; 490 return this;
453 } 491 }
454 492
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 // iterator, so we need to increment it first. 639 // iterator, so we need to increment it first.
602 KeyIdToSessionKeysMap::iterator current = it; 640 KeyIdToSessionKeysMap::iterator current = it;
603 ++it; 641 ++it;
604 key_map_.erase(current); 642 key_map_.erase(current);
605 } else { 643 } else {
606 ++it; 644 ++it;
607 } 645 }
608 } 646 }
609 } 647 }
610 648
649 CdmKeysInfo AesDecryptor::GenerateKeysInfoList(
650 const std::string& session_id,
651 CdmKeyInformation::KeyStatus status) {
652 // Create the list of all available keys for this session.
653 CdmKeysInfo keys_info;
654 {
655 base::AutoLock auto_lock(key_map_lock_);
656 for (const auto& item : key_map_) {
657 if (item.second->Contains(session_id)) {
658 keys_info.push_back(new CdmKeyInformation(item.first, status, 0));
659 }
660 }
661 }
662 return keys_info;
663 }
664
611 AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret) 665 AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret)
612 : secret_(secret) { 666 : secret_(secret) {
613 } 667 }
614 668
615 AesDecryptor::DecryptionKey::~DecryptionKey() {} 669 AesDecryptor::DecryptionKey::~DecryptionKey() {}
616 670
617 bool AesDecryptor::DecryptionKey::Init() { 671 bool AesDecryptor::DecryptionKey::Init() {
618 CHECK(!secret_.empty()); 672 CHECK(!secret_.empty());
619 decryption_key_ = 673 decryption_key_ =
620 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_); 674 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_);
621 if (!decryption_key_) 675 if (!decryption_key_)
622 return false; 676 return false;
623 return true; 677 return true;
624 } 678 }
625 679
626 } // namespace media 680 } // namespace media
OLDNEW
« no previous file with comments | « media/cdm/aes_decryptor.h ('k') | media/cdm/aes_decryptor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698