Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/base/android/media_drm_bridge.h" | 5 #include "media/base/android/media_drm_bridge.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/android/jni_array.h" | 10 #include "base/android/jni_array.h" |
| 11 #include "base/android/jni_string.h" | 11 #include "base/android/jni_string.h" |
| 12 #include "base/bind.h" | |
| 12 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 13 #include "base/containers/hash_tables.h" | 14 #include "base/containers/hash_tables.h" |
| 14 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 15 #include "base/location.h" | 16 #include "base/location.h" |
| 16 #include "base/logging.h" | 17 #include "base/logging.h" |
| 17 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
| 18 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 19 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 21 #include "base/sys_byteorder.h" | 22 #include "base/sys_byteorder.h" |
| 22 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
| 23 #include "base/thread_task_runner_handle.h" | 24 #include "base/thread_task_runner_handle.h" |
| 24 #include "jni/MediaDrmBridge_jni.h" | 25 #include "jni/MediaDrmBridge_jni.h" |
| 25 #include "media/base/android/media_client_android.h" | 26 #include "media/base/android/media_client_android.h" |
| 27 #include "media/base/android/media_codec_player.h" // for GetMediaTaskRunner() | |
| 26 #include "media/base/android/media_drm_bridge_delegate.h" | 28 #include "media/base/android/media_drm_bridge_delegate.h" |
| 27 #include "media/base/cdm_key_information.h" | 29 #include "media/base/cdm_key_information.h" |
| 28 | 30 |
| 29 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 31 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 30 | 32 |
| 33 #define RUN_CB_ON_MEDIA_THREAD(cb, ...) \ | |
| 34 do { \ | |
| 35 if (run_on_media_thread_ && \ | |
| 36 !GetMediaTaskRunner()->BelongsToCurrentThread()) { \ | |
| 37 GetMediaTaskRunner()->PostTask(FROM_HERE, \ | |
| 38 base::Bind(cb, ##__VA_ARGS__)); \ | |
| 39 } else { \ | |
| 40 cb.Run(__VA_ARGS__); \ | |
| 41 } \ | |
| 42 } while (0) | |
| 43 | |
| 31 using base::android::AttachCurrentThread; | 44 using base::android::AttachCurrentThread; |
| 32 using base::android::ConvertUTF8ToJavaString; | 45 using base::android::ConvertUTF8ToJavaString; |
| 33 using base::android::ConvertJavaStringToUTF8; | 46 using base::android::ConvertJavaStringToUTF8; |
| 34 using base::android::JavaByteArrayToByteVector; | 47 using base::android::JavaByteArrayToByteVector; |
| 35 using base::android::ScopedJavaLocalRef; | 48 using base::android::ScopedJavaLocalRef; |
| 36 | 49 |
| 37 namespace media { | 50 namespace media { |
| 38 | 51 |
| 39 namespace { | 52 namespace { |
| 40 | 53 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 int32 os_bugfix_version = 0; | 234 int32 os_bugfix_version = 0; |
| 222 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, | 235 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, |
| 223 &os_minor_version, | 236 &os_minor_version, |
| 224 &os_bugfix_version); | 237 &os_bugfix_version); |
| 225 if (os_major_version == 4 && os_minor_version == 4 && os_bugfix_version == 0) | 238 if (os_major_version == 4 && os_minor_version == 4 && os_bugfix_version == 0) |
| 226 return false; | 239 return false; |
| 227 | 240 |
| 228 return true; | 241 return true; |
| 229 } | 242 } |
| 230 | 243 |
| 244 // static | |
| 245 bool MediaDrmBridge::CanCreate(const std::string& key_system, | |
| 246 SecurityLevel widevine_security_level) { | |
| 247 if (!IsAvailable()) { | |
| 248 DVLOG(1) << __FUNCTION__ << ": DRM is not available"; | |
| 249 return false; | |
| 250 } | |
| 251 | |
| 252 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); | |
| 253 if (scheme_uuid.empty()) { | |
| 254 DVLOG(1) << __FUNCTION__ << ": key system " << key_system | |
| 255 << " not supported"; | |
| 256 return false; | |
| 257 } | |
| 258 | |
| 259 if (key_system == kWidevineKeySystem && | |
| 260 widevine_security_level != SECURITY_LEVEL_NONE && | |
| 261 !std::equal(scheme_uuid.begin(), scheme_uuid.end(), kWidevineUuid)) { | |
| 262 NOTREACHED() << "Widevine security level " << widevine_security_level | |
| 263 << "used with another key system"; | |
| 264 return false; | |
| 265 } | |
| 266 return true; | |
| 267 } | |
| 268 | |
| 231 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 | 269 // TODO(ddorwin): This is specific to Widevine. http://crbug.com/459400 |
| 232 // static | 270 // static |
| 233 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { | 271 bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) { |
| 234 DCHECK(IsAvailable()); | 272 DCHECK(IsAvailable()); |
| 235 return SECURITY_LEVEL_1 == security_level; | 273 return SECURITY_LEVEL_1 == security_level; |
| 236 } | 274 } |
| 237 | 275 |
| 238 // static | 276 // static |
| 239 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { | 277 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { |
| 240 return g_key_system_manager.Get().GetPlatformKeySystemNames(); | 278 return g_key_system_manager.Get().GetPlatformKeySystemNames(); |
| 241 } | 279 } |
| 242 | 280 |
| 243 // static | 281 // static |
| 244 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { | 282 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { |
| 245 DCHECK(!key_system.empty()); | 283 DCHECK(!key_system.empty()); |
| 246 return IsKeySystemSupportedWithTypeImpl(key_system, ""); | 284 return IsKeySystemSupportedWithTypeImpl(key_system, ""); |
| 247 } | 285 } |
| 248 | 286 |
| 249 // static | 287 // static |
| 250 bool MediaDrmBridge::IsKeySystemSupportedWithType( | 288 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
| 251 const std::string& key_system, | 289 const std::string& key_system, |
| 252 const std::string& container_mime_type) { | 290 const std::string& container_mime_type) { |
| 253 DCHECK(!key_system.empty() && !container_mime_type.empty()); | 291 DCHECK(!key_system.empty() && !container_mime_type.empty()); |
| 254 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); | 292 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); |
| 255 } | 293 } |
| 256 | 294 |
| 295 // static | |
| 257 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { | 296 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
| 258 return RegisterNativesImpl(env); | 297 return RegisterNativesImpl(env); |
| 259 } | 298 } |
| 260 | 299 |
| 261 MediaDrmBridge::MediaDrmBridge( | 300 MediaDrmBridge::MediaDrmBridge( |
| 262 const std::vector<uint8>& scheme_uuid, | 301 const std::vector<uint8>& scheme_uuid, |
| 263 const SessionMessageCB& session_message_cb, | 302 const SessionMessageCB& session_message_cb, |
| 264 const SessionClosedCB& session_closed_cb, | 303 const SessionClosedCB& session_closed_cb, |
| 265 const LegacySessionErrorCB& legacy_session_error_cb, | 304 const LegacySessionErrorCB& legacy_session_error_cb, |
| 266 const SessionKeysChangeCB& session_keys_change_cb, | 305 const SessionKeysChangeCB& session_keys_change_cb, |
| 267 const SessionExpirationUpdateCB& session_expiration_update_cb) | 306 const SessionExpirationUpdateCB& session_expiration_update_cb) |
| 268 : scheme_uuid_(scheme_uuid), | 307 : scheme_uuid_(scheme_uuid), |
| 269 session_message_cb_(session_message_cb), | 308 session_message_cb_(session_message_cb), |
| 270 session_closed_cb_(session_closed_cb), | 309 session_closed_cb_(session_closed_cb), |
| 271 legacy_session_error_cb_(legacy_session_error_cb), | 310 legacy_session_error_cb_(legacy_session_error_cb), |
| 272 session_keys_change_cb_(session_keys_change_cb), | 311 session_keys_change_cb_(session_keys_change_cb), |
| 273 session_expiration_update_cb_(session_expiration_update_cb) { | 312 session_expiration_update_cb_(session_expiration_update_cb), |
| 313 run_on_media_thread_(false), | |
| 314 weak_factory_(this) { | |
| 315 DVLOG(1) << "MediaDrmBridge::MediaDrmBridge"; | |
| 316 | |
| 317 // When this flag is set we need to repost the notifications about | |
| 318 // crypto became ready and a key had been added to the Media thread. | |
| 319 run_on_media_thread_ = GetMediaTaskRunner()->BelongsToCurrentThread(); | |
| 320 | |
| 321 // Create internal callbacks to repost Java new key notification and | |
| 322 // promise related notifications to the media thread. | |
| 323 | |
| 324 base::WeakPtr<MediaDrmBridge> weak_this = weak_factory_.GetWeakPtr(); | |
| 325 | |
| 326 internal_keys_added_cb_ = | |
| 327 base::Bind(&MediaDrmBridge::InternalKeysAdded, weak_this); | |
| 328 internal_promise_resolved_cb_ = | |
| 329 base::Bind(&MediaDrmBridge::InternalPromiseResolved, weak_this); | |
| 330 internal_promise_resolved_with_session_cb_ = base::Bind( | |
| 331 &MediaDrmBridge::InternalPromiseResolvedWithSession, weak_this); | |
| 332 internal_promise_rejected_cb_ = | |
| 333 base::Bind(&MediaDrmBridge::InternalPromiseRejected, weak_this); | |
| 334 | |
| 274 JNIEnv* env = AttachCurrentThread(); | 335 JNIEnv* env = AttachCurrentThread(); |
| 275 CHECK(env); | 336 CHECK(env); |
| 276 | 337 |
| 277 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 338 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 278 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 339 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 279 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 340 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
| 280 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 341 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
| 281 } | 342 } |
| 282 | 343 |
| 283 MediaDrmBridge::~MediaDrmBridge() { | 344 MediaDrmBridge::~MediaDrmBridge() { |
| 284 JNIEnv* env = AttachCurrentThread(); | 345 JNIEnv* env = AttachCurrentThread(); |
| 285 player_tracker_.NotifyCdmUnset(); | 346 player_tracker_.NotifyCdmUnset(); |
| 286 if (!j_media_drm_.is_null()) | 347 if (!j_media_drm_.is_null()) |
| 287 Java_MediaDrmBridge_destroy(env, j_media_drm_.obj()); | 348 Java_MediaDrmBridge_destroy(env, j_media_drm_.obj()); |
| 288 } | 349 } |
| 289 | 350 |
| 290 // static | 351 // static |
| 291 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( | 352 scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> MediaDrmBridge::Create( |
| 292 const std::string& key_system, | 353 const std::string& key_system, |
| 354 SecurityLevel widevine_security_level, | |
| 293 const SessionMessageCB& session_message_cb, | 355 const SessionMessageCB& session_message_cb, |
| 294 const SessionClosedCB& session_closed_cb, | 356 const SessionClosedCB& session_closed_cb, |
| 295 const LegacySessionErrorCB& legacy_session_error_cb, | 357 const LegacySessionErrorCB& legacy_session_error_cb, |
| 296 const SessionKeysChangeCB& session_keys_change_cb, | 358 const SessionKeysChangeCB& session_keys_change_cb, |
| 297 const SessionExpirationUpdateCB& session_expiration_update_cb) { | 359 const SessionExpirationUpdateCB& session_expiration_update_cb) { |
| 298 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 360 scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> media_drm_bridge; |
| 299 if (!IsAvailable()) | 361 if (!IsAvailable()) |
| 300 return media_drm_bridge.Pass(); | 362 return media_drm_bridge.Pass(); |
| 301 | 363 |
| 302 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); | 364 UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system); |
| 303 if (scheme_uuid.empty()) | 365 if (scheme_uuid.empty()) |
| 304 return media_drm_bridge.Pass(); | 366 return media_drm_bridge.Pass(); |
| 305 | 367 |
| 306 media_drm_bridge.reset( | 368 media_drm_bridge.reset( |
| 307 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, | 369 new MediaDrmBridge(scheme_uuid, session_message_cb, session_closed_cb, |
| 308 legacy_session_error_cb, session_keys_change_cb, | 370 legacy_session_error_cb, session_keys_change_cb, |
| 309 session_expiration_update_cb)); | 371 session_expiration_update_cb)); |
| 310 | 372 |
| 311 if (media_drm_bridge->j_media_drm_.is_null()) | 373 if (media_drm_bridge->j_media_drm_.is_null()) |
| 312 media_drm_bridge.reset(); | 374 media_drm_bridge.reset(); |
| 313 | 375 |
| 376 if (key_system == kWidevineKeySystem && | |
|
ddorwin
2015/09/16 20:42:21
We shouldn't need the WV check here again.
| |
| 377 widevine_security_level != SECURITY_LEVEL_NONE && | |
| 378 !media_drm_bridge->SetSecurityLevel(widevine_security_level)) { | |
| 379 DVLOG(1) << __FUNCTION__ << ": failed to set security level " | |
| 380 << widevine_security_level; | |
| 381 media_drm_bridge.reset(); | |
| 382 } | |
| 383 | |
| 314 return media_drm_bridge.Pass(); | 384 return media_drm_bridge.Pass(); |
| 315 } | 385 } |
| 316 | 386 |
| 317 // static | 387 // static |
| 318 scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport( | 388 scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> |
| 319 const std::string& key_system) { | 389 MediaDrmBridge::CreateWithoutSessionSupport(const std::string& key_system) { |
| 320 return MediaDrmBridge::Create( | 390 return MediaDrmBridge::Create(key_system, SECURITY_LEVEL_NONE, |
| 321 key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(), | 391 SessionMessageCB(), SessionClosedCB(), |
| 322 SessionKeysChangeCB(), SessionExpirationUpdateCB()); | 392 LegacySessionErrorCB(), SessionKeysChangeCB(), |
| 393 SessionExpirationUpdateCB()); | |
| 323 } | 394 } |
| 324 | 395 |
| 325 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 396 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
| 326 if (security_level != SECURITY_LEVEL_NONE && | 397 if (security_level != SECURITY_LEVEL_NONE && |
| 327 !std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid)) { | 398 !std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid)) { |
| 328 NOTREACHED() << "Widevine security level " << security_level | 399 NOTREACHED() << "Widevine security level " << security_level |
| 329 << "used with another key system"; | 400 << "used with another key system"; |
| 330 return false; | 401 return false; |
| 331 } | 402 } |
| 332 | 403 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 const std::string& session_id, | 489 const std::string& session_id, |
| 419 scoped_ptr<media::NewSessionCdmPromise> promise) { | 490 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 420 NOTIMPLEMENTED() << "EME persistent sessions not yet supported on Android."; | 491 NOTIMPLEMENTED() << "EME persistent sessions not yet supported on Android."; |
| 421 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); | 492 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); |
| 422 } | 493 } |
| 423 | 494 |
| 424 void MediaDrmBridge::UpdateSession( | 495 void MediaDrmBridge::UpdateSession( |
| 425 const std::string& session_id, | 496 const std::string& session_id, |
| 426 const std::vector<uint8_t>& response, | 497 const std::vector<uint8_t>& response, |
| 427 scoped_ptr<media::SimpleCdmPromise> promise) { | 498 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 428 DVLOG(1) << __FUNCTION__; | 499 DVLOG(1) << __FUNCTION__ << " session_id:" << session_id; |
| 429 | 500 |
| 430 JNIEnv* env = AttachCurrentThread(); | 501 JNIEnv* env = AttachCurrentThread(); |
| 431 ScopedJavaLocalRef<jbyteArray> j_response = base::android::ToJavaByteArray( | 502 ScopedJavaLocalRef<jbyteArray> j_response = base::android::ToJavaByteArray( |
| 432 env, vector_as_array(&response), response.size()); | 503 env, vector_as_array(&response), response.size()); |
| 433 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( | 504 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( |
| 434 env, reinterpret_cast<const uint8_t*>(session_id.data()), | 505 env, reinterpret_cast<const uint8_t*>(session_id.data()), |
| 435 session_id.size()); | 506 session_id.size()); |
| 436 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); | 507 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); |
| 437 Java_MediaDrmBridge_updateSession(env, j_media_drm_.obj(), j_session_id.obj(), | 508 Java_MediaDrmBridge_updateSession(env, j_media_drm_.obj(), j_session_id.obj(), |
| 438 j_response.obj(), promise_id); | 509 j_response.obj(), promise_id); |
| 439 } | 510 } |
| 440 | 511 |
| 441 void MediaDrmBridge::CloseSession(const std::string& session_id, | 512 void MediaDrmBridge::CloseSession(const std::string& session_id, |
| 442 scoped_ptr<media::SimpleCdmPromise> promise) { | 513 scoped_ptr<media::SimpleCdmPromise> promise) { |
| 443 DVLOG(1) << __FUNCTION__; | 514 DVLOG(1) << __FUNCTION__; |
| 515 | |
| 444 JNIEnv* env = AttachCurrentThread(); | 516 JNIEnv* env = AttachCurrentThread(); |
| 445 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( | 517 ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( |
| 446 env, reinterpret_cast<const uint8_t*>(session_id.data()), | 518 env, reinterpret_cast<const uint8_t*>(session_id.data()), |
| 447 session_id.size()); | 519 session_id.size()); |
| 448 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); | 520 uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); |
| 449 Java_MediaDrmBridge_closeSession(env, j_media_drm_.obj(), j_session_id.obj(), | 521 Java_MediaDrmBridge_closeSession(env, j_media_drm_.obj(), j_session_id.obj(), |
| 450 promise_id); | 522 promise_id); |
| 451 } | 523 } |
| 452 | 524 |
| 453 void MediaDrmBridge::RemoveSession( | 525 void MediaDrmBridge::RemoveSession( |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 465 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb, | 537 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb, |
| 466 const base::Closure& cdm_unset_cb) { | 538 const base::Closure& cdm_unset_cb) { |
| 467 return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); | 539 return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); |
| 468 } | 540 } |
| 469 | 541 |
| 470 void MediaDrmBridge::UnregisterPlayer(int registration_id) { | 542 void MediaDrmBridge::UnregisterPlayer(int registration_id) { |
| 471 player_tracker_.UnregisterPlayer(registration_id); | 543 player_tracker_.UnregisterPlayer(registration_id); |
| 472 } | 544 } |
| 473 | 545 |
| 474 void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) { | 546 void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) { |
| 547 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; | |
| 548 | |
| 475 if (closure.is_null()) { | 549 if (closure.is_null()) { |
| 476 media_crypto_ready_cb_.Reset(); | 550 media_crypto_ready_cb_.Reset(); |
| 477 return; | 551 return; |
| 478 } | 552 } |
| 479 | 553 |
| 480 DCHECK(media_crypto_ready_cb_.is_null()); | 554 DCHECK(media_crypto_ready_cb_.is_null()); |
| 481 | 555 |
| 482 if (!GetMediaCrypto().is_null()) { | 556 if (!GetMediaCrypto().is_null()) { |
| 483 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); | 557 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); |
| 484 return; | 558 return; |
| 485 } | 559 } |
| 486 | 560 |
| 487 media_crypto_ready_cb_ = closure; | 561 media_crypto_ready_cb_ = closure; |
| 488 } | 562 } |
| 489 | 563 |
| 490 void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject) { | 564 void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) { |
| 565 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; | |
| 566 | |
| 491 DCHECK(!GetMediaCrypto().is_null()); | 567 DCHECK(!GetMediaCrypto().is_null()); |
| 492 if (!media_crypto_ready_cb_.is_null()) | 568 |
| 493 base::ResetAndReturn(&media_crypto_ready_cb_).Run(); | 569 if (media_crypto_ready_cb_.is_null()) |
| 570 return; | |
| 571 | |
| 572 RUN_CB_ON_MEDIA_THREAD(base::ResetAndReturn(&media_crypto_ready_cb_)); | |
| 494 } | 573 } |
| 495 | 574 |
| 496 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, | 575 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env, |
| 497 jobject j_media_drm, | 576 jobject j_media_drm, |
| 498 jint j_promise_id) { | 577 jint j_promise_id) { |
| 499 cdm_promise_adapter_.ResolvePromise(j_promise_id); | 578 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
| 579 RUN_CB_ON_MEDIA_THREAD(internal_promise_resolved_cb_, j_promise_id); | |
| 580 } | |
| 581 | |
| 582 void MediaDrmBridge::InternalPromiseResolved(uint32_t promise_id) { | |
| 583 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ | |
| 584 << ": promise_id:" << promise_id; | |
| 585 cdm_promise_adapter_.ResolvePromise(promise_id); | |
| 500 } | 586 } |
| 501 | 587 |
| 502 void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env, | 588 void MediaDrmBridge::OnPromiseResolvedWithSession(JNIEnv* env, |
| 503 jobject j_media_drm, | 589 jobject j_media_drm, |
| 504 jint j_promise_id, | 590 jint j_promise_id, |
| 505 jbyteArray j_session_id) { | 591 jbyteArray j_session_id) { |
| 506 cdm_promise_adapter_.ResolvePromise(j_promise_id, | 592 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
| 507 GetSessionId(env, j_session_id)); | 593 RUN_CB_ON_MEDIA_THREAD(internal_promise_resolved_with_session_cb_, |
| 594 j_promise_id, GetSessionId(env, j_session_id)); | |
| 595 } | |
| 596 | |
| 597 void MediaDrmBridge::InternalPromiseResolvedWithSession( | |
| 598 uint32_t promise_id, | |
| 599 const std::string& session_id) { | |
| 600 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ | |
| 601 << ": promise_id:" << promise_id << " session_id:" << session_id; | |
| 602 cdm_promise_adapter_.ResolvePromise(promise_id, session_id); | |
| 508 } | 603 } |
| 509 | 604 |
| 510 void MediaDrmBridge::OnPromiseRejected(JNIEnv* env, | 605 void MediaDrmBridge::OnPromiseRejected(JNIEnv* env, |
| 511 jobject j_media_drm, | 606 jobject j_media_drm, |
| 512 jint j_promise_id, | 607 jint j_promise_id, |
| 513 jstring j_error_message) { | 608 jstring j_error_message) { |
| 609 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; | |
| 514 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message); | 610 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message); |
| 515 cdm_promise_adapter_.RejectPromise(j_promise_id, MediaKeys::UNKNOWN_ERROR, 0, | 611 RUN_CB_ON_MEDIA_THREAD(internal_promise_rejected_cb_, j_promise_id, |
| 612 error_message); | |
| 613 } | |
| 614 | |
| 615 void MediaDrmBridge::InternalPromiseRejected(uint32_t promise_id, | |
| 616 const std::string& error_message) { | |
| 617 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ | |
| 618 << ": promise_id:" << promise_id << " error:" << error_message; | |
| 619 cdm_promise_adapter_.RejectPromise(promise_id, MediaKeys::UNKNOWN_ERROR, 0, | |
| 516 error_message); | 620 error_message); |
| 517 } | 621 } |
| 518 | 622 |
| 519 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, | 623 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, |
| 520 jobject j_media_drm, | 624 jobject j_media_drm, |
| 521 jbyteArray j_session_id, | 625 jbyteArray j_session_id, |
| 522 jint j_message_type, | 626 jint j_message_type, |
| 523 jbyteArray j_message, | 627 jbyteArray j_message, |
| 524 jstring j_legacy_destination_url) { | 628 jstring j_legacy_destination_url) { |
| 525 std::vector<uint8> message; | 629 std::vector<uint8> message; |
| 526 JavaByteArrayToByteVector(env, j_message, &message); | 630 JavaByteArrayToByteVector(env, j_message, &message); |
| 527 GURL legacy_destination_url = | 631 GURL legacy_destination_url = |
| 528 GURL(ConvertJavaStringToUTF8(env, j_legacy_destination_url)); | 632 GURL(ConvertJavaStringToUTF8(env, j_legacy_destination_url)); |
| 529 MediaKeys::MessageType message_type = | 633 MediaKeys::MessageType message_type = |
| 530 GetMessageType(static_cast<RequestType>(j_message_type)); | 634 GetMessageType(static_cast<RequestType>(j_message_type)); |
| 531 | 635 |
| 532 session_message_cb_.Run(GetSessionId(env, j_session_id), message_type, | 636 std::string session_id = GetSessionId(env, j_session_id); |
| 533 message, legacy_destination_url); | 637 |
| 638 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ | |
| 639 << " session_id:" << session_id; | |
| 640 | |
| 641 // We need to preserve the order of messages. If the promise-related | |
| 642 // callbacks are posted to the Media thread, we have to do the same with | |
| 643 // all callbacks. See the comment in media_drm_proxy.h. | |
| 644 RUN_CB_ON_MEDIA_THREAD(session_message_cb_, session_id, message_type, message, | |
| 645 legacy_destination_url); | |
| 534 } | 646 } |
| 535 | 647 |
| 536 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, | 648 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, |
| 537 jobject j_media_drm, | 649 jobject j_media_drm, |
| 538 jbyteArray j_session_id) { | 650 jbyteArray j_session_id) { |
| 539 session_closed_cb_.Run(GetSessionId(env, j_session_id)); | 651 std::string session_id = GetSessionId(env, j_session_id); |
| 652 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ | |
| 653 << " session_id:" << session_id; | |
| 654 | |
| 655 RUN_CB_ON_MEDIA_THREAD(session_closed_cb_, session_id); | |
|
ddorwin
2015/09/16 20:42:21
Should it be up to the caller to ensure this? At w
| |
| 540 } | 656 } |
| 541 | 657 |
| 542 void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env, | 658 void MediaDrmBridge::OnSessionKeysChange(JNIEnv* env, |
| 543 jobject j_media_drm, | 659 jobject j_media_drm, |
| 544 jbyteArray j_session_id, | 660 jbyteArray j_session_id, |
| 545 jobjectArray j_keys_info, | 661 jobjectArray j_keys_info, |
| 546 bool has_additional_usable_key) { | 662 bool has_additional_usable_key) { |
| 547 if (has_additional_usable_key) | 663 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__; |
| 548 player_tracker_.NotifyNewKey(); | |
| 549 | 664 |
| 550 CdmKeysInfo cdm_keys_info; | 665 CdmKeysInfo cdm_keys_info; |
| 551 | 666 |
| 552 size_t size = env->GetArrayLength(j_keys_info); | 667 size_t size = env->GetArrayLength(j_keys_info); |
| 553 DCHECK_GT(size, 0u); | 668 DCHECK_GT(size, 0u); |
| 554 | 669 |
| 555 for (size_t i = 0; i < size; ++i) { | 670 for (size_t i = 0; i < size; ++i) { |
| 556 ScopedJavaLocalRef<jobject> j_key_status( | 671 ScopedJavaLocalRef<jobject> j_key_status( |
| 557 env, env->GetObjectArrayElement(j_keys_info, i)); | 672 env, env->GetObjectArrayElement(j_keys_info, i)); |
| 558 | 673 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 572 << key_status; | 687 << key_status; |
| 573 | 688 |
| 574 // TODO(xhwang): Update CdmKeyInformation to take key_id and status in the | 689 // TODO(xhwang): Update CdmKeyInformation to take key_id and status in the |
| 575 // constructor. | 690 // constructor. |
| 576 scoped_ptr<CdmKeyInformation> cdm_key_information(new CdmKeyInformation()); | 691 scoped_ptr<CdmKeyInformation> cdm_key_information(new CdmKeyInformation()); |
| 577 cdm_key_information->key_id = key_id; | 692 cdm_key_information->key_id = key_id; |
| 578 cdm_key_information->status = key_status; | 693 cdm_key_information->status = key_status; |
| 579 cdm_keys_info.push_back(cdm_key_information.release()); | 694 cdm_keys_info.push_back(cdm_key_information.release()); |
| 580 } | 695 } |
| 581 | 696 |
| 582 session_keys_change_cb_.Run(GetSessionId(env, j_session_id), | 697 RUN_CB_ON_MEDIA_THREAD(internal_keys_added_cb_, has_additional_usable_key); |
| 583 has_additional_usable_key, cdm_keys_info.Pass()); | 698 |
| 699 std::string session_id = GetSessionId(env, j_session_id); | |
| 700 | |
| 701 if (run_on_media_thread_ && !GetMediaTaskRunner()->BelongsToCurrentThread()) { | |
| 702 GetMediaTaskRunner()->PostTask( | |
| 703 FROM_HERE, | |
| 704 base::Bind(session_keys_change_cb_, session_id, | |
| 705 has_additional_usable_key, base::Passed(&cdm_keys_info))); | |
| 706 } else { | |
| 707 session_keys_change_cb_.Run(session_id, has_additional_usable_key, | |
| 708 cdm_keys_info.Pass()); | |
| 709 } | |
| 710 } | |
| 711 | |
| 712 void MediaDrmBridge::InternalKeysAdded(bool has_additional_usable_key) { | |
| 713 if (has_additional_usable_key) | |
| 714 player_tracker_.NotifyNewKey(); | |
| 584 } | 715 } |
| 585 | 716 |
| 586 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys | 717 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys |
| 587 // will never expire. This will be translated into a NULL base::Time() [2], | 718 // will never expire. This will be translated into a NULL base::Time() [2], |
| 588 // which will then be mapped to a zero Java time [3]. The zero Java time is | 719 // which will then be mapped to a zero Java time [3]. The zero Java time is |
| 589 // passed to Blink which will then be translated to NaN [4], which is what the | 720 // passed to Blink which will then be translated to NaN [4], which is what the |
| 590 // spec uses to indicate that the license will never expire [5]. | 721 // spec uses to indicate that the license will never expire [5]. |
| 591 // [1] http://developer.android.com/reference/android/media/MediaDrm.OnExpiratio nUpdateListener.html | 722 // [1] http://developer.android.com/reference/android/media/MediaDrm.OnExpiratio nUpdateListener.html |
| 592 // [2] See base::Time::FromDoubleT() | 723 // [2] See base::Time::FromDoubleT() |
| 593 // [3] See base::Time::ToJavaTime() | 724 // [3] See base::Time::ToJavaTime() |
| 594 // [4] See MediaKeySession::expirationChanged() | 725 // [4] See MediaKeySession::expirationChanged() |
| 595 // [5] https://github.com/w3c/encrypted-media/issues/58 | 726 // [5] https://github.com/w3c/encrypted-media/issues/58 |
| 596 void MediaDrmBridge::OnSessionExpirationUpdate(JNIEnv* env, | 727 void MediaDrmBridge::OnSessionExpirationUpdate(JNIEnv* env, |
| 597 jobject j_media_drm, | 728 jobject j_media_drm, |
| 598 jbyteArray j_session_id, | 729 jbyteArray j_session_id, |
| 599 jlong expiry_time_ms) { | 730 jlong expiry_time_ms) { |
| 600 DVLOG(2) << __FUNCTION__ << ": " << expiry_time_ms << " ms"; | 731 std::string session_id = GetSessionId(env, j_session_id); |
| 601 session_expiration_update_cb_.Run( | 732 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ |
| 602 GetSessionId(env, j_session_id), | 733 << ": session_id:" << session_id << " expiration:" << expiry_time_ms |
| 603 base::Time::FromDoubleT(expiry_time_ms / 1000.0)); | 734 << " ms"; |
| 735 | |
| 736 RUN_CB_ON_MEDIA_THREAD(session_expiration_update_cb_, session_id, | |
| 737 base::Time::FromDoubleT(expiry_time_ms / 1000.0)); | |
| 604 } | 738 } |
| 605 | 739 |
| 606 void MediaDrmBridge::OnLegacySessionError(JNIEnv* env, | 740 void MediaDrmBridge::OnLegacySessionError(JNIEnv* env, |
| 607 jobject j_media_drm, | 741 jobject j_media_drm, |
| 608 jbyteArray j_session_id, | 742 jbyteArray j_session_id, |
| 609 jstring j_error_message) { | 743 jstring j_error_message) { |
| 744 std::string session_id = GetSessionId(env, j_session_id); | |
| 610 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message); | 745 std::string error_message = ConvertJavaStringToUTF8(env, j_error_message); |
| 611 legacy_session_error_cb_.Run(GetSessionId(env, j_session_id), | 746 |
| 612 MediaKeys::UNKNOWN_ERROR, 0, error_message); | 747 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << " session_id:" << session_id |
| 748 << " error:" << error_message; | |
| 749 | |
| 750 RUN_CB_ON_MEDIA_THREAD(legacy_session_error_cb_, session_id, | |
| 751 MediaKeys::UNKNOWN_ERROR, 0, error_message); | |
| 613 } | 752 } |
| 614 | 753 |
| 615 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { | 754 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { |
| 616 JNIEnv* env = AttachCurrentThread(); | 755 JNIEnv* env = AttachCurrentThread(); |
| 617 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); | 756 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); |
| 618 } | 757 } |
| 619 | 758 |
| 620 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { | 759 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { |
| 621 JNIEnv* env = AttachCurrentThread(); | 760 JNIEnv* env = AttachCurrentThread(); |
| 622 ScopedJavaLocalRef<jstring> j_security_level = | 761 ScopedJavaLocalRef<jstring> j_security_level = |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 638 void MediaDrmBridge::ResetDeviceCredentials( | 777 void MediaDrmBridge::ResetDeviceCredentials( |
| 639 const ResetCredentialsCB& callback) { | 778 const ResetCredentialsCB& callback) { |
| 640 DCHECK(reset_credentials_cb_.is_null()); | 779 DCHECK(reset_credentials_cb_.is_null()); |
| 641 reset_credentials_cb_ = callback; | 780 reset_credentials_cb_ = callback; |
| 642 JNIEnv* env = AttachCurrentThread(); | 781 JNIEnv* env = AttachCurrentThread(); |
| 643 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 782 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 644 } | 783 } |
| 645 | 784 |
| 646 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 785 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 647 JNIEnv* env, jobject, bool success) { | 786 JNIEnv* env, jobject, bool success) { |
| 648 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 787 DVLOG(1) << "MediaDrmBridge::" << __FUNCTION__ << ": success:" << success; |
| 788 | |
| 789 RUN_CB_ON_MEDIA_THREAD(base::ResetAndReturn(&reset_credentials_cb_), success); | |
| 649 } | 790 } |
| 650 | 791 |
| 651 } // namespace media | 792 } // namespace media |
| OLD | NEW |