| 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 "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/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "crypto/encryptor.h" | 16 #include "crypto/encryptor.h" |
| 17 #include "crypto/symmetric_key.h" | 17 #include "crypto/symmetric_key.h" |
| 18 #include "media/base/audio_decoder_config.h" | 18 #include "media/base/audio_decoder_config.h" |
| 19 #include "media/base/cdm_key_information.h" | 19 #include "media/base/cdm_key_information.h" |
| 20 #include "media/base/cdm_promise.h" | 20 #include "media/base/cdm_promise.h" |
| 21 #include "media/base/decoder_buffer.h" | 21 #include "media/base/decoder_buffer.h" |
| 22 #include "media/base/decrypt_config.h" | 22 #include "media/base/decrypt_config.h" |
| 23 #include "media/base/limits.h" |
| 23 #include "media/base/video_decoder_config.h" | 24 #include "media/base/video_decoder_config.h" |
| 24 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
| 25 #include "media/cdm/json_web_key.h" | 26 #include "media/cdm/json_web_key.h" |
| 26 | 27 |
| 27 #if defined(USE_PROPRIETARY_CODECS) | 28 #if defined(USE_PROPRIETARY_CODECS) |
| 28 #include "media/cdm/cenc_utils.h" | 29 #include "media/cdm/cenc_utils.h" |
| 29 #endif | 30 #endif |
| 30 | 31 |
| 31 namespace media { | 32 namespace media { |
| 32 | 33 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 EmeInitDataType init_data_type, | 262 EmeInitDataType init_data_type, |
| 262 const std::vector<uint8_t>& init_data, | 263 const std::vector<uint8_t>& init_data, |
| 263 std::unique_ptr<NewSessionCdmPromise> promise) { | 264 std::unique_ptr<NewSessionCdmPromise> promise) { |
| 264 std::string session_id(base::UintToString(next_session_id_++)); | 265 std::string session_id(base::UintToString(next_session_id_++)); |
| 265 valid_sessions_.insert(session_id); | 266 valid_sessions_.insert(session_id); |
| 266 | 267 |
| 267 // For now, the AesDecryptor does not care about |session_type|. | 268 // For now, the AesDecryptor does not care about |session_type|. |
| 268 // TODO(jrummell): Validate |session_type|. | 269 // TODO(jrummell): Validate |session_type|. |
| 269 | 270 |
| 270 std::vector<uint8_t> message; | 271 std::vector<uint8_t> message; |
| 271 // TODO(jrummell): Since unprefixed will never send NULL, remove this check | 272 std::vector<std::vector<uint8_t>> keys; |
| 272 // when prefixed EME is removed (http://crbug.com/249976). | 273 switch (init_data_type) { |
| 273 if (!init_data.empty()) { | 274 case EmeInitDataType::WEBM: |
| 274 std::vector<std::vector<uint8_t>> keys; | 275 // |init_data| is simply the key needed. |
| 275 switch (init_data_type) { | 276 if (init_data.size() < limits::kMinKeyIdLength || |
| 276 case EmeInitDataType::WEBM: | 277 init_data.size() > limits::kMaxKeyIdLength) { |
| 277 // |init_data| is simply the key needed. | 278 promise->reject(NOT_SUPPORTED_ERROR, 0, "Incorrect length"); |
| 278 keys.push_back(init_data); | 279 return; |
| 279 break; | 280 } |
| 280 case EmeInitDataType::CENC: | 281 keys.push_back(init_data); |
| 282 break; |
| 283 case EmeInitDataType::CENC: |
| 281 #if defined(USE_PROPRIETARY_CODECS) | 284 #if defined(USE_PROPRIETARY_CODECS) |
| 282 // |init_data| is a set of 0 or more concatenated 'pssh' boxes. | 285 // |init_data| is a set of 0 or more concatenated 'pssh' boxes. |
| 283 if (!GetKeyIdsForCommonSystemId(init_data, &keys)) { | 286 if (!GetKeyIdsForCommonSystemId(init_data, &keys)) { |
| 284 promise->reject(NOT_SUPPORTED_ERROR, 0, | 287 promise->reject(NOT_SUPPORTED_ERROR, 0, "No supported PSSH box found."); |
| 285 "No supported PSSH box found."); | 288 return; |
| 286 return; | 289 } |
| 287 } | 290 break; |
| 288 break; | |
| 289 #else | 291 #else |
| 290 promise->reject(NOT_SUPPORTED_ERROR, 0, | 292 promise->reject(NOT_SUPPORTED_ERROR, 0, |
| 291 "Initialization data type CENC is not supported."); | 293 "Initialization data type CENC is not supported."); |
| 294 return; |
| 295 #endif |
| 296 case EmeInitDataType::KEYIDS: { |
| 297 std::string init_data_string(init_data.begin(), init_data.end()); |
| 298 std::string error_message; |
| 299 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, |
| 300 &error_message)) { |
| 301 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message); |
| 292 return; | 302 return; |
| 293 #endif | |
| 294 case EmeInitDataType::KEYIDS: { | |
| 295 std::string init_data_string(init_data.begin(), init_data.end()); | |
| 296 std::string error_message; | |
| 297 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, | |
| 298 &error_message)) { | |
| 299 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message); | |
| 300 return; | |
| 301 } | |
| 302 break; | |
| 303 } | 303 } |
| 304 default: | 304 break; |
| 305 NOTREACHED(); | |
| 306 promise->reject(NOT_SUPPORTED_ERROR, 0, | |
| 307 "init_data_type not supported."); | |
| 308 return; | |
| 309 } | 305 } |
| 310 CreateLicenseRequest(keys, session_type, &message); | 306 default: |
| 307 NOTREACHED(); |
| 308 promise->reject(NOT_SUPPORTED_ERROR, 0, "init_data_type not supported."); |
| 309 return; |
| 311 } | 310 } |
| 311 CreateLicenseRequest(keys, session_type, &message); |
| 312 | 312 |
| 313 promise->resolve(session_id); | 313 promise->resolve(session_id); |
| 314 | 314 |
| 315 // No URL needed for license requests. | 315 // No URL needed for license requests. |
| 316 GURL empty_gurl; | 316 GURL empty_gurl; |
| 317 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); | 317 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); |
| 318 } | 318 } |
| 319 | 319 |
| 320 void AesDecryptor::LoadSession(SessionType session_type, | 320 void AesDecryptor::LoadSession(SessionType session_type, |
| 321 const std::string& session_id, | 321 const std::string& session_id, |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 valid_sessions_.erase(it); | 409 valid_sessions_.erase(it); |
| 410 | 410 |
| 411 // Close the session. | 411 // Close the session. |
| 412 DeleteKeysForSession(session_id); | 412 DeleteKeysForSession(session_id); |
| 413 promise->resolve(); | 413 promise->resolve(); |
| 414 session_closed_cb_.Run(session_id); | 414 session_closed_cb_.Run(session_id); |
| 415 } | 415 } |
| 416 | 416 |
| 417 void AesDecryptor::RemoveSession(const std::string& session_id, | 417 void AesDecryptor::RemoveSession(const std::string& session_id, |
| 418 std::unique_ptr<SimpleCdmPromise> promise) { | 418 std::unique_ptr<SimpleCdmPromise> promise) { |
| 419 // AesDecryptor doesn't keep any persistent data, so this should be | 419 // See https://crbug.com/416194. |
| 420 // NOT_REACHED(). | 420 NOTREACHED() << "AesDecryptor doesn't support persistent sessions."; |
| 421 // TODO(jrummell): Make sure persistent session types are rejected. | |
| 422 // http://crbug.com/384152. | |
| 423 // | |
| 424 // However, v0.1b calls to CancelKeyRequest() will call this, so close the | |
| 425 // session, if it exists. | |
| 426 // TODO(jrummell): Remove the close() call when prefixed EME is removed. | |
| 427 // http://crbug.com/249976. | |
| 428 if (valid_sessions_.find(session_id) != valid_sessions_.end()) { | |
| 429 CloseSession(session_id, std::move(promise)); | |
| 430 return; | |
| 431 } | |
| 432 | |
| 433 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); | 421 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); |
| 434 } | 422 } |
| 435 | 423 |
| 436 CdmContext* AesDecryptor::GetCdmContext() { | 424 CdmContext* AesDecryptor::GetCdmContext() { |
| 437 return this; | 425 return this; |
| 438 } | 426 } |
| 439 | 427 |
| 440 Decryptor* AesDecryptor::GetDecryptor() { | 428 Decryptor* AesDecryptor::GetDecryptor() { |
| 441 return this; | 429 return this; |
| 442 } | 430 } |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 bool AesDecryptor::DecryptionKey::Init() { | 596 bool AesDecryptor::DecryptionKey::Init() { |
| 609 CHECK(!secret_.empty()); | 597 CHECK(!secret_.empty()); |
| 610 decryption_key_.reset(crypto::SymmetricKey::Import( | 598 decryption_key_.reset(crypto::SymmetricKey::Import( |
| 611 crypto::SymmetricKey::AES, secret_)); | 599 crypto::SymmetricKey::AES, secret_)); |
| 612 if (!decryption_key_) | 600 if (!decryption_key_) |
| 613 return false; | 601 return false; |
| 614 return true; | 602 return true; |
| 615 } | 603 } |
| 616 | 604 |
| 617 } // namespace media | 605 } // namespace media |
| OLD | NEW |