| 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" |
| 20 #include "media/blink/cdm_session_adapter.h" | 21 #include "media/blink/cdm_session_adapter.h" |
| 21 #include "media/blink/webmediaplayer_util.h" | 22 #include "media/blink/webmediaplayer_util.h" |
| 22 #include "media/cdm/json_web_key.h" | 23 #include "media/cdm/json_web_key.h" |
| 23 #include "third_party/WebKit/public/platform/WebData.h" | 24 #include "third_party/WebKit/public/platform/WebData.h" |
| 24 #include "third_party/WebKit/public/platform/WebEncryptedMediaKeyInformation.h" | 25 #include "third_party/WebKit/public/platform/WebEncryptedMediaKeyInformation.h" |
| 25 #include "third_party/WebKit/public/platform/WebString.h" | 26 #include "third_party/WebKit/public/platform/WebString.h" |
| 26 #include "third_party/WebKit/public/platform/WebURL.h" | 27 #include "third_party/WebKit/public/platform/WebURL.h" |
| 27 #include "third_party/WebKit/public/platform/WebVector.h" | 28 #include "third_party/WebKit/public/platform/WebVector.h" |
| 28 | 29 |
| 29 #if defined(USE_PROPRIETARY_CODECS) | 30 #if defined(USE_PROPRIETARY_CODECS) |
| 30 #include "media/cdm/cenc_utils.h" | 31 #include "media/cdm/cenc_utils.h" |
| 31 #endif | 32 #endif |
| 32 | 33 |
| 33 namespace media { | 34 namespace media { |
| 34 | 35 |
| 36 namespace { |
| 37 |
| 35 const char kCloseSessionUMAName[] = "CloseSession"; | 38 const char kCloseSessionUMAName[] = "CloseSession"; |
| 36 const char kGenerateRequestUMAName[] = "GenerateRequest"; | 39 const char kGenerateRequestUMAName[] = "GenerateRequest"; |
| 37 const char kLoadSessionUMAName[] = "LoadSession"; | 40 const char kLoadSessionUMAName[] = "LoadSession"; |
| 38 const char kRemoveSessionUMAName[] = "RemoveSession"; | 41 const char kRemoveSessionUMAName[] = "RemoveSession"; |
| 39 const char kUpdateSessionUMAName[] = "UpdateSession"; | 42 const char kUpdateSessionUMAName[] = "UpdateSession"; |
| 40 | 43 |
| 41 static blink::WebContentDecryptionModuleSession::Client::MessageType | 44 blink::WebContentDecryptionModuleSession::Client::MessageType |
| 42 convertMessageType(MediaKeys::MessageType message_type) { | 45 convertMessageType(MediaKeys::MessageType message_type) { |
| 43 switch (message_type) { | 46 switch (message_type) { |
| 44 case media::MediaKeys::LICENSE_REQUEST: | 47 case media::MediaKeys::LICENSE_REQUEST: |
| 45 return blink::WebContentDecryptionModuleSession::Client::MessageType:: | 48 return blink::WebContentDecryptionModuleSession::Client::MessageType:: |
| 46 LicenseRequest; | 49 LicenseRequest; |
| 47 case media::MediaKeys::LICENSE_RENEWAL: | 50 case media::MediaKeys::LICENSE_RENEWAL: |
| 48 return blink::WebContentDecryptionModuleSession::Client::MessageType:: | 51 return blink::WebContentDecryptionModuleSession::Client::MessageType:: |
| 49 LicenseRenewal; | 52 LicenseRenewal; |
| 50 case media::MediaKeys::LICENSE_RELEASE: | 53 case media::MediaKeys::LICENSE_RELEASE: |
| 51 return blink::WebContentDecryptionModuleSession::Client::MessageType:: | 54 return blink::WebContentDecryptionModuleSession::Client::MessageType:: |
| 52 LicenseRelease; | 55 LicenseRelease; |
| 53 } | 56 } |
| 54 | 57 |
| 55 NOTREACHED(); | 58 NOTREACHED(); |
| 56 return blink::WebContentDecryptionModuleSession::Client::MessageType:: | 59 return blink::WebContentDecryptionModuleSession::Client::MessageType:: |
| 57 LicenseRequest; | 60 LicenseRequest; |
| 58 } | 61 } |
| 59 | 62 |
| 60 static blink::WebEncryptedMediaKeyInformation::KeyStatus convertStatus( | 63 blink::WebEncryptedMediaKeyInformation::KeyStatus convertStatus( |
| 61 media::CdmKeyInformation::KeyStatus status) { | 64 media::CdmKeyInformation::KeyStatus status) { |
| 62 switch (status) { | 65 switch (status) { |
| 63 case media::CdmKeyInformation::USABLE: | 66 case media::CdmKeyInformation::USABLE: |
| 64 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Usable; | 67 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Usable; |
| 65 case media::CdmKeyInformation::INTERNAL_ERROR: | 68 case media::CdmKeyInformation::INTERNAL_ERROR: |
| 66 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError; | 69 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError; |
| 67 case media::CdmKeyInformation::EXPIRED: | 70 case media::CdmKeyInformation::EXPIRED: |
| 68 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Expired; | 71 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Expired; |
| 69 case media::CdmKeyInformation::OUTPUT_RESTRICTED: | 72 case media::CdmKeyInformation::OUTPUT_RESTRICTED: |
| 70 return blink::WebEncryptedMediaKeyInformation::KeyStatus:: | 73 return blink::WebEncryptedMediaKeyInformation::KeyStatus:: |
| 71 OutputRestricted; | 74 OutputRestricted; |
| 72 case media::CdmKeyInformation::OUTPUT_DOWNSCALED: | 75 case media::CdmKeyInformation::OUTPUT_DOWNSCALED: |
| 73 return blink::WebEncryptedMediaKeyInformation::KeyStatus:: | 76 return blink::WebEncryptedMediaKeyInformation::KeyStatus:: |
| 74 OutputDownscaled; | 77 OutputDownscaled; |
| 75 case media::CdmKeyInformation::KEY_STATUS_PENDING: | 78 case media::CdmKeyInformation::KEY_STATUS_PENDING: |
| 76 return blink::WebEncryptedMediaKeyInformation::KeyStatus::StatusPending; | 79 return blink::WebEncryptedMediaKeyInformation::KeyStatus::StatusPending; |
| 77 case media::CdmKeyInformation::RELEASED: | 80 case media::CdmKeyInformation::RELEASED: |
| 78 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Released; | 81 return blink::WebEncryptedMediaKeyInformation::KeyStatus::Released; |
| 79 } | 82 } |
| 80 | 83 |
| 81 NOTREACHED(); | 84 NOTREACHED(); |
| 82 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError; | 85 return blink::WebEncryptedMediaKeyInformation::KeyStatus::InternalError; |
| 83 } | 86 } |
| 84 | 87 |
| 85 static MediaKeys::SessionType convertSessionType( | 88 MediaKeys::SessionType convertSessionType( |
| 86 blink::WebEncryptedMediaSessionType session_type) { | 89 blink::WebEncryptedMediaSessionType session_type) { |
| 87 switch (session_type) { | 90 switch (session_type) { |
| 88 case blink::WebEncryptedMediaSessionType::Temporary: | 91 case blink::WebEncryptedMediaSessionType::Temporary: |
| 89 return MediaKeys::TEMPORARY_SESSION; | 92 return MediaKeys::TEMPORARY_SESSION; |
| 90 case blink::WebEncryptedMediaSessionType::PersistentLicense: | 93 case blink::WebEncryptedMediaSessionType::PersistentLicense: |
| 91 return MediaKeys::PERSISTENT_LICENSE_SESSION; | 94 return MediaKeys::PERSISTENT_LICENSE_SESSION; |
| 92 case blink::WebEncryptedMediaSessionType::PersistentReleaseMessage: | 95 case blink::WebEncryptedMediaSessionType::PersistentReleaseMessage: |
| 93 return MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION; | 96 return MediaKeys::PERSISTENT_RELEASE_MESSAGE_SESSION; |
| 94 case blink::WebEncryptedMediaSessionType::Unknown: | 97 case blink::WebEncryptedMediaSessionType::Unknown: |
| 95 break; | 98 break; |
| 96 } | 99 } |
| 97 | 100 |
| 98 NOTREACHED(); | 101 NOTREACHED(); |
| 99 return MediaKeys::TEMPORARY_SESSION; | 102 return MediaKeys::TEMPORARY_SESSION; |
| 100 } | 103 } |
| 101 | 104 |
| 102 static bool SanitizeInitData(EmeInitDataType init_data_type, | 105 bool SanitizeInitData(EmeInitDataType init_data_type, |
| 103 const unsigned char* init_data, | 106 const unsigned char* init_data, |
| 104 size_t init_data_length, | 107 size_t init_data_length, |
| 105 std::vector<uint8_t>* sanitized_init_data, | 108 std::vector<uint8_t>* sanitized_init_data, |
| 106 std::string* error_message) { | 109 std::string* error_message) { |
| 107 DCHECK_GT(init_data_length, 0u); | 110 DCHECK_GT(init_data_length, 0u); |
| 108 if (init_data_length > limits::kMaxInitDataLength) { | 111 if (init_data_length > limits::kMaxInitDataLength) { |
| 109 error_message->assign("Initialization data too long."); | 112 error_message->assign("Initialization data too long."); |
| 110 return false; | 113 return false; |
| 111 } | 114 } |
| 112 | 115 |
| 113 switch (init_data_type) { | 116 switch (init_data_type) { |
| 114 case EmeInitDataType::WEBM: | 117 case EmeInitDataType::WEBM: |
| 115 // |init_data| for WebM is a single key. | 118 // |init_data| for WebM is a single key. |
| 116 if (init_data_length > limits::kMaxKeyIdLength) { | 119 if (init_data_length > limits::kMaxKeyIdLength) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 159 |
| 157 case EmeInitDataType::UNKNOWN: | 160 case EmeInitDataType::UNKNOWN: |
| 158 break; | 161 break; |
| 159 } | 162 } |
| 160 | 163 |
| 161 NOTREACHED(); | 164 NOTREACHED(); |
| 162 error_message->assign("Initialization data type is not supported."); | 165 error_message->assign("Initialization data type is not supported."); |
| 163 return false; | 166 return false; |
| 164 } | 167 } |
| 165 | 168 |
| 166 static bool SanitizeSessionId(const blink::WebString& session_id, | 169 bool SanitizeSessionId(const blink::WebString& session_id, |
| 167 std::string* sanitized_session_id) { | 170 std::string* sanitized_session_id) { |
| 168 // The user agent should thoroughly validate the sessionId value before | 171 // The user agent should thoroughly validate the sessionId value before |
| 169 // passing it to the CDM. At a minimum, this should include checking that | 172 // passing it to the CDM. At a minimum, this should include checking that |
| 170 // the length and value (e.g. alphanumeric) are reasonable. | 173 // the length and value (e.g. alphanumeric) are reasonable. |
| 171 if (!session_id.containsOnlyASCII()) | 174 if (!session_id.containsOnlyASCII()) |
| 172 return false; | 175 return false; |
| 173 | 176 |
| 174 sanitized_session_id->assign(session_id.ascii()); | 177 sanitized_session_id->assign(session_id.ascii()); |
| 175 if (sanitized_session_id->length() > limits::kMaxSessionIdLength) | 178 if (sanitized_session_id->length() > limits::kMaxSessionIdLength) |
| 176 return false; | 179 return false; |
| 177 | 180 |
| 178 for (const char c : *sanitized_session_id) { | 181 for (const char c : *sanitized_session_id) { |
| 179 if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c)) | 182 if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c)) |
| 180 return false; | 183 return false; |
| 181 } | 184 } |
| 182 | 185 |
| 183 return true; | 186 return true; |
| 184 } | 187 } |
| 185 | 188 |
| 186 static bool SanitizeResponse(const std::string& key_system, | 189 bool SanitizeResponse(const std::string& key_system, |
| 187 const uint8_t* response, | 190 const uint8_t* response, |
| 188 size_t response_length, | 191 size_t response_length, |
| 189 std::vector<uint8_t>* sanitized_response) { | 192 std::vector<uint8_t>* sanitized_response) { |
| 190 // The user agent should thoroughly validate the response before passing it | 193 // The user agent should thoroughly validate the response before passing it |
| 191 // to the CDM. This may include verifying values are within reasonable limits, | 194 // to the CDM. This may include verifying values are within reasonable limits, |
| 192 // stripping irrelevant data or fields, pre-parsing it, sanitizing it, | 195 // stripping irrelevant data or fields, pre-parsing it, sanitizing it, |
| 193 // and/or generating a fully sanitized version. The user agent should check | 196 // and/or generating a fully sanitized version. The user agent should check |
| 194 // that the length and values of fields are reasonable. Unknown fields should | 197 // that the length and values of fields are reasonable. Unknown fields should |
| 195 // be rejected or removed. | 198 // be rejected or removed. |
| 196 if (response_length > limits::kMaxSessionResponseLength) | 199 if (response_length > limits::kMaxSessionResponseLength) |
| 197 return false; | 200 return false; |
| 198 | 201 |
| 199 if (IsClearKey(key_system) || IsExternalClearKey(key_system)) { | 202 if (IsClearKey(key_system) || IsExternalClearKey(key_system)) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 217 std::string sanitized_data = GenerateJWKSet(keys, session_type); | 220 std::string sanitized_data = GenerateJWKSet(keys, session_type); |
| 218 sanitized_response->assign(sanitized_data.begin(), sanitized_data.end()); | 221 sanitized_response->assign(sanitized_data.begin(), sanitized_data.end()); |
| 219 return true; | 222 return true; |
| 220 } | 223 } |
| 221 | 224 |
| 222 // TODO(jrummell): Verify responses for Widevine. | 225 // TODO(jrummell): Verify responses for Widevine. |
| 223 sanitized_response->assign(response, response + response_length); | 226 sanitized_response->assign(response, response + response_length); |
| 224 return true; | 227 return true; |
| 225 } | 228 } |
| 226 | 229 |
| 230 // If we need to close the session while destroying this object, we need a |
| 231 // dummy promise that won't call back into this object (or try to pass |
| 232 // something back to blink). |
| 233 class IgnoreResponsePromise : public SimpleCdmPromise { |
| 234 public: |
| 235 IgnoreResponsePromise() {} |
| 236 ~IgnoreResponsePromise() override {} |
| 237 |
| 238 // SimpleCdmPromise implementation. |
| 239 void resolve() final { MarkPromiseSettled(); } |
| 240 void reject(CdmPromise::Exception exception_code, |
| 241 uint32_t system_code, |
| 242 const std::string& error_message) final { |
| 243 MarkPromiseSettled(); |
| 244 } |
| 245 }; |
| 246 |
| 247 } // namespace |
| 248 |
| 227 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( | 249 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( |
| 228 const scoped_refptr<CdmSessionAdapter>& adapter) | 250 const scoped_refptr<CdmSessionAdapter>& adapter) |
| 229 : adapter_(adapter), is_closed_(false), weak_ptr_factory_(this) { | 251 : adapter_(adapter), |
| 230 } | 252 has_close_been_called_(false), |
| 253 is_closed_(false), |
| 254 weak_ptr_factory_(this) {} |
| 231 | 255 |
| 232 WebContentDecryptionModuleSessionImpl:: | 256 WebContentDecryptionModuleSessionImpl:: |
| 233 ~WebContentDecryptionModuleSessionImpl() { | 257 ~WebContentDecryptionModuleSessionImpl() { |
| 234 DCHECK(thread_checker_.CalledOnValidThread()); | 258 DCHECK(thread_checker_.CalledOnValidThread()); |
| 235 if (!session_id_.empty()) | 259 |
| 260 if (!session_id_.empty()) { |
| 236 adapter_->UnregisterSession(session_id_); | 261 adapter_->UnregisterSession(session_id_); |
| 262 |
| 263 // From http://w3c.github.io/encrypted-media/#mediakeysession-interface |
| 264 // "If a MediaKeySession object is not closed when it becomes inaccessible |
| 265 // to the page, the CDM shall close the key session associated with the |
| 266 // object." |
| 267 // |
| 268 // This object is destroyed when the corresponding blink object is no |
| 269 // longer needed (which may be due to it becoming inaccessible to the |
| 270 // page), so if the session is not closed and CloseSession() has not yet |
| 271 // been called, call CloseSession() now. Since this object is being |
| 272 // destroyed, there is no need for the promise to do anything as this |
| 273 // session will be gone. |
| 274 if (!is_closed_ && !has_close_been_called_) { |
| 275 adapter_->CloseSession(session_id_, |
| 276 base::MakeUnique<IgnoreResponsePromise>()); |
| 277 } |
| 278 } |
| 237 } | 279 } |
| 238 | 280 |
| 239 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { | 281 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { |
| 240 client_ = client; | 282 client_ = client; |
| 241 } | 283 } |
| 242 | 284 |
| 243 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { | 285 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { |
| 244 return blink::WebString::fromUTF8(session_id_); | 286 return blink::WebString::fromUTF8(session_id_); |
| 245 } | 287 } |
| 246 | 288 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 } | 427 } |
| 386 | 428 |
| 387 adapter_->UpdateSession( | 429 adapter_->UpdateSession( |
| 388 session_id_, sanitized_response, | 430 session_id_, sanitized_response, |
| 389 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( | 431 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( |
| 390 result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName))); | 432 result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName))); |
| 391 } | 433 } |
| 392 | 434 |
| 393 void WebContentDecryptionModuleSessionImpl::close( | 435 void WebContentDecryptionModuleSessionImpl::close( |
| 394 blink::WebContentDecryptionModuleResult result) { | 436 blink::WebContentDecryptionModuleResult result) { |
| 437 // close() shouldn't be called if the session is already closed. blink |
| 438 // prevents a second call to close(), but since the operation is |
| 439 // asynchronous, there is a window where close() was called just before |
| 440 // the closed event arrives. The CDM should handle the case where |
| 441 // close() is called after it has already closed the session. |
| 395 DCHECK(!session_id_.empty()); | 442 DCHECK(!session_id_.empty()); |
| 443 DCHECK(!has_close_been_called_); |
| 396 DCHECK(thread_checker_.CalledOnValidThread()); | 444 DCHECK(thread_checker_.CalledOnValidThread()); |
| 445 |
| 446 has_close_been_called_ = true; |
| 397 adapter_->CloseSession( | 447 adapter_->CloseSession( |
| 398 session_id_, | 448 session_id_, |
| 399 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( | 449 std::unique_ptr<SimpleCdmPromise>(new CdmResultPromise<>( |
| 400 result, adapter_->GetKeySystemUMAPrefix() + kCloseSessionUMAName))); | 450 result, adapter_->GetKeySystemUMAPrefix() + kCloseSessionUMAName))); |
| 401 } | 451 } |
| 402 | 452 |
| 403 void WebContentDecryptionModuleSessionImpl::remove( | 453 void WebContentDecryptionModuleSessionImpl::remove( |
| 404 blink::WebContentDecryptionModuleResult result) { | 454 blink::WebContentDecryptionModuleResult result) { |
| 405 DCHECK(!session_id_.empty()); | 455 DCHECK(!session_id_.empty()); |
| 406 DCHECK(thread_checker_.CalledOnValidThread()); | 456 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } | 488 } |
| 439 | 489 |
| 440 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate( | 490 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate( |
| 441 const base::Time& new_expiry_time) { | 491 const base::Time& new_expiry_time) { |
| 442 DCHECK(thread_checker_.CalledOnValidThread()); | 492 DCHECK(thread_checker_.CalledOnValidThread()); |
| 443 client_->expirationChanged(new_expiry_time.ToJsTime()); | 493 client_->expirationChanged(new_expiry_time.ToJsTime()); |
| 444 } | 494 } |
| 445 | 495 |
| 446 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { | 496 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { |
| 447 DCHECK(thread_checker_.CalledOnValidThread()); | 497 DCHECK(thread_checker_.CalledOnValidThread()); |
| 498 |
| 499 // Only send one closed event to blink. |
| 448 if (is_closed_) | 500 if (is_closed_) |
| 449 return; | 501 return; |
| 450 | 502 |
| 451 is_closed_ = true; | 503 is_closed_ = true; |
| 452 client_->close(); | 504 client_->close(); |
| 453 } | 505 } |
| 454 | 506 |
| 455 void WebContentDecryptionModuleSessionImpl::OnSessionInitialized( | 507 void WebContentDecryptionModuleSessionImpl::OnSessionInitialized( |
| 456 const std::string& session_id, | 508 const std::string& session_id, |
| 457 SessionInitStatus* status) { | 509 SessionInitStatus* status) { |
| 458 DCHECK(thread_checker_.CalledOnValidThread()); | 510 DCHECK(thread_checker_.CalledOnValidThread()); |
| 459 // CDM will return NULL if the session to be loaded can't be found. | 511 // CDM will return NULL if the session to be loaded can't be found. |
| 460 if (session_id.empty()) { | 512 if (session_id.empty()) { |
| 461 *status = SessionInitStatus::SESSION_NOT_FOUND; | 513 *status = SessionInitStatus::SESSION_NOT_FOUND; |
| 462 return; | 514 return; |
| 463 } | 515 } |
| 464 | 516 |
| 465 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; | 517 DCHECK(session_id_.empty()) << "Session ID may not be changed once set."; |
| 466 session_id_ = session_id; | 518 session_id_ = session_id; |
| 467 *status = | 519 *status = |
| 468 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) | 520 adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr()) |
| 469 ? SessionInitStatus::NEW_SESSION | 521 ? SessionInitStatus::NEW_SESSION |
| 470 : SessionInitStatus::SESSION_ALREADY_EXISTS; | 522 : SessionInitStatus::SESSION_ALREADY_EXISTS; |
| 471 } | 523 } |
| 472 | 524 |
| 473 } // namespace media | 525 } // namespace media |
| OLD | NEW |