| 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/numerics/safe_conversions.h" | 10 #include "base/numerics/safe_conversions.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 break; | 95 break; |
| 96 } | 96 } |
| 97 | 97 |
| 98 NOTREACHED(); | 98 NOTREACHED(); |
| 99 return MediaKeys::TEMPORARY_SESSION; | 99 return MediaKeys::TEMPORARY_SESSION; |
| 100 } | 100 } |
| 101 | 101 |
| 102 static bool SanitizeInitData(EmeInitDataType init_data_type, | 102 static bool SanitizeInitData(EmeInitDataType init_data_type, |
| 103 const unsigned char* init_data, | 103 const unsigned char* init_data, |
| 104 size_t init_data_length, | 104 size_t init_data_length, |
| 105 std::vector<uint8>* sanitized_init_data, | 105 std::vector<uint8_t>* sanitized_init_data, |
| 106 std::string* error_message) { | 106 std::string* error_message) { |
| 107 if (init_data_length > limits::kMaxInitDataLength) { | 107 if (init_data_length > limits::kMaxInitDataLength) { |
| 108 error_message->assign("Initialization data too long."); | 108 error_message->assign("Initialization data too long."); |
| 109 return false; | 109 return false; |
| 110 } | 110 } |
| 111 | 111 |
| 112 switch (init_data_type) { | 112 switch (init_data_type) { |
| 113 case EmeInitDataType::WEBM: | 113 case EmeInitDataType::WEBM: |
| 114 sanitized_init_data->assign(init_data, init_data + init_data_length); | 114 sanitized_init_data->assign(init_data, init_data + init_data_length); |
| 115 return true; | 115 return true; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 172 |
| 173 for (const char c : *sanitized_session_id) { | 173 for (const char c : *sanitized_session_id) { |
| 174 if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c)) | 174 if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c)) |
| 175 return false; | 175 return false; |
| 176 } | 176 } |
| 177 | 177 |
| 178 return true; | 178 return true; |
| 179 } | 179 } |
| 180 | 180 |
| 181 static bool SanitizeResponse(const std::string& key_system, | 181 static bool SanitizeResponse(const std::string& key_system, |
| 182 const uint8* response, | 182 const uint8_t* response, |
| 183 size_t response_length, | 183 size_t response_length, |
| 184 std::vector<uint8>* sanitized_response) { | 184 std::vector<uint8_t>* sanitized_response) { |
| 185 // The user agent should thoroughly validate the response before passing it | 185 // The user agent should thoroughly validate the response before passing it |
| 186 // to the CDM. This may include verifying values are within reasonable limits, | 186 // to the CDM. This may include verifying values are within reasonable limits, |
| 187 // stripping irrelevant data or fields, pre-parsing it, sanitizing it, | 187 // stripping irrelevant data or fields, pre-parsing it, sanitizing it, |
| 188 // and/or generating a fully sanitized version. The user agent should check | 188 // and/or generating a fully sanitized version. The user agent should check |
| 189 // that the length and values of fields are reasonable. Unknown fields should | 189 // that the length and values of fields are reasonable. Unknown fields should |
| 190 // be rejected or removed. | 190 // be rejected or removed. |
| 191 if (response_length > limits::kMaxSessionResponseLength) | 191 if (response_length > limits::kMaxSessionResponseLength) |
| 192 return false; | 192 return false; |
| 193 | 193 |
| 194 if (IsClearKey(key_system) || IsExternalClearKey(key_system)) { | 194 if (IsClearKey(key_system) || IsExternalClearKey(key_system)) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 // before passing it to the CDM. This includes verifying that the length | 272 // before passing it to the CDM. This includes verifying that the length |
| 273 // and values of fields are reasonable, verifying that values are within | 273 // and values of fields are reasonable, verifying that values are within |
| 274 // reasonable limits, and stripping irrelevant, unsupported, or unknown | 274 // reasonable limits, and stripping irrelevant, unsupported, or unknown |
| 275 // data or fields. It is recommended that user agents pre-parse, sanitize, | 275 // data or fields. It is recommended that user agents pre-parse, sanitize, |
| 276 // and/or generate a fully sanitized version of the Initialization Data. | 276 // and/or generate a fully sanitized version of the Initialization Data. |
| 277 // If the Initialization Data format specified by initDataType support | 277 // If the Initialization Data format specified by initDataType support |
| 278 // multiple entries, the user agent should remove entries that are not | 278 // multiple entries, the user agent should remove entries that are not |
| 279 // needed by the CDM. | 279 // needed by the CDM. |
| 280 // 9.3 If the previous step failed, reject promise with a new DOMException | 280 // 9.3 If the previous step failed, reject promise with a new DOMException |
| 281 // whose name is InvalidAccessError. | 281 // whose name is InvalidAccessError. |
| 282 std::vector<uint8> sanitized_init_data; | 282 std::vector<uint8_t> sanitized_init_data; |
| 283 std::string message; | 283 std::string message; |
| 284 if (!SanitizeInitData(eme_init_data_type, init_data, init_data_length, | 284 if (!SanitizeInitData(eme_init_data_type, init_data, init_data_length, |
| 285 &sanitized_init_data, &message)) { | 285 &sanitized_init_data, &message)) { |
| 286 result.completeWithError( | 286 result.completeWithError( |
| 287 blink::WebContentDecryptionModuleExceptionInvalidAccessError, 0, | 287 blink::WebContentDecryptionModuleExceptionInvalidAccessError, 0, |
| 288 blink::WebString::fromUTF8(message)); | 288 blink::WebString::fromUTF8(message)); |
| 289 return; | 289 return; |
| 290 } | 290 } |
| 291 | 291 |
| 292 // 9.4 Let session id be the empty string. | 292 // 9.4 Let session id be the empty string. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 adapter_->LoadSession( | 328 adapter_->LoadSession( |
| 329 MediaKeys::PERSISTENT_LICENSE_SESSION, sanitized_session_id, | 329 MediaKeys::PERSISTENT_LICENSE_SESSION, sanitized_session_id, |
| 330 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise( | 330 scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise( |
| 331 result, adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName, | 331 result, adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName, |
| 332 base::Bind( | 332 base::Bind( |
| 333 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized, | 333 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized, |
| 334 weak_ptr_factory_.GetWeakPtr())))); | 334 weak_ptr_factory_.GetWeakPtr())))); |
| 335 } | 335 } |
| 336 | 336 |
| 337 void WebContentDecryptionModuleSessionImpl::update( | 337 void WebContentDecryptionModuleSessionImpl::update( |
| 338 const uint8* response, | 338 const uint8_t* response, |
| 339 size_t response_length, | 339 size_t response_length, |
| 340 blink::WebContentDecryptionModuleResult result) { | 340 blink::WebContentDecryptionModuleResult result) { |
| 341 DCHECK(response); | 341 DCHECK(response); |
| 342 DCHECK(!session_id_.empty()); | 342 DCHECK(!session_id_.empty()); |
| 343 DCHECK(thread_checker_.CalledOnValidThread()); | 343 DCHECK(thread_checker_.CalledOnValidThread()); |
| 344 | 344 |
| 345 std::vector<uint8> sanitized_response; | 345 std::vector<uint8_t> sanitized_response; |
| 346 if (!SanitizeResponse(adapter_->GetKeySystem(), response, response_length, | 346 if (!SanitizeResponse(adapter_->GetKeySystem(), response, response_length, |
| 347 &sanitized_response)) { | 347 &sanitized_response)) { |
| 348 result.completeWithError( | 348 result.completeWithError( |
| 349 blink::WebContentDecryptionModuleExceptionInvalidAccessError, 0, | 349 blink::WebContentDecryptionModuleExceptionInvalidAccessError, 0, |
| 350 "Invalid response."); | 350 "Invalid response."); |
| 351 return; | 351 return; |
| 352 } | 352 } |
| 353 | 353 |
| 354 adapter_->UpdateSession( | 354 adapter_->UpdateSession( |
| 355 session_id_, sanitized_response, | 355 session_id_, sanitized_response, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 372 DCHECK(!session_id_.empty()); | 372 DCHECK(!session_id_.empty()); |
| 373 DCHECK(thread_checker_.CalledOnValidThread()); | 373 DCHECK(thread_checker_.CalledOnValidThread()); |
| 374 adapter_->RemoveSession( | 374 adapter_->RemoveSession( |
| 375 session_id_, | 375 session_id_, |
| 376 scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>( | 376 scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>( |
| 377 result, adapter_->GetKeySystemUMAPrefix() + kRemoveSessionUMAName))); | 377 result, adapter_->GetKeySystemUMAPrefix() + kRemoveSessionUMAName))); |
| 378 } | 378 } |
| 379 | 379 |
| 380 void WebContentDecryptionModuleSessionImpl::OnSessionMessage( | 380 void WebContentDecryptionModuleSessionImpl::OnSessionMessage( |
| 381 MediaKeys::MessageType message_type, | 381 MediaKeys::MessageType message_type, |
| 382 const std::vector<uint8>& message) { | 382 const std::vector<uint8_t>& message) { |
| 383 DCHECK(client_) << "Client not set before message event"; | 383 DCHECK(client_) << "Client not set before message event"; |
| 384 DCHECK(thread_checker_.CalledOnValidThread()); | 384 DCHECK(thread_checker_.CalledOnValidThread()); |
| 385 client_->message(convertMessageType(message_type), message.data(), | 385 client_->message(convertMessageType(message_type), message.data(), |
| 386 message.size()); | 386 message.size()); |
| 387 } | 387 } |
| 388 | 388 |
| 389 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange( | 389 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange( |
| 390 bool has_additional_usable_key, | 390 bool has_additional_usable_key, |
| 391 CdmKeysInfo keys_info) { | 391 CdmKeysInfo keys_info) { |
| 392 DCHECK(thread_checker_.CalledOnValidThread()); | 392 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 | 431 |
| 432 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; | 432 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; |
| 433 session_id_ = session_id; | 433 session_id_ = session_id; |
| 434 *status = | 434 *status = |
| 435 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) | 435 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) |
| 436 ? SessionInitStatus::NEW_SESSION | 436 ? SessionInitStatus::NEW_SESSION |
| 437 : SessionInitStatus::SESSION_ALREADY_EXISTS; | 437 : SessionInitStatus::SESSION_ALREADY_EXISTS; |
| 438 } | 438 } |
| 439 | 439 |
| 440 } // namespace media | 440 } // namespace media |
| OLD | NEW |