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 <stddef.h> | 7 #include <stddef.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/android/build_info.h" | 11 #include "base/android/build_info.h" |
12 #include "base/android/jni_array.h" | 12 #include "base/android/jni_array.h" |
13 #include "base/android/jni_string.h" | 13 #include "base/android/jni_string.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
16 #include "base/containers/hash_tables.h" | 16 #include "base/containers/hash_tables.h" |
17 #include "base/feature_list.h" | 17 #include "base/feature_list.h" |
18 #include "base/location.h" | 18 #include "base/location.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/macros.h" | 20 #include "base/macros.h" |
| 21 #include "base/memory/ptr_util.h" |
21 #include "base/single_thread_task_runner.h" | 22 #include "base/single_thread_task_runner.h" |
22 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
24 #include "base/sys_byteorder.h" | 25 #include "base/sys_byteorder.h" |
25 #include "base/sys_info.h" | 26 #include "base/sys_info.h" |
26 #include "base/threading/thread_task_runner_handle.h" | 27 #include "base/threading/thread_task_runner_handle.h" |
27 #include "jni/MediaDrmBridge_jni.h" | 28 #include "jni/MediaDrmBridge_jni.h" |
28 #include "media/base/android/android_util.h" | 29 #include "media/base/android/android_util.h" |
29 #include "media/base/android/media_codec_util.h" | 30 #include "media/base/android/media_codec_util.h" |
30 #include "media/base/android/media_drm_bridge_client.h" | 31 #include "media/base/android/media_drm_bridge_client.h" |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 312 |
312 // static | 313 // static |
313 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { | 314 std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { |
314 if (!MediaDrmBridge::IsAvailable()) | 315 if (!MediaDrmBridge::IsAvailable()) |
315 return std::vector<std::string>(); | 316 return std::vector<std::string>(); |
316 | 317 |
317 return GetKeySystemManager()->GetPlatformKeySystemNames(); | 318 return GetKeySystemManager()->GetPlatformKeySystemNames(); |
318 } | 319 } |
319 | 320 |
320 // static | 321 // static |
321 scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateInternal( | 322 void MediaDrmBridge::CreateInternal( |
322 const std::string& key_system, | 323 const std::vector<uint8_t>& scheme_uuid, |
323 const GURL& security_origin, | |
324 SecurityLevel security_level, | 324 SecurityLevel security_level, |
| 325 std::unique_ptr<MediaDrmStorageBridge> storage, |
325 const CreateFetcherCB& create_fetcher_cb, | 326 const CreateFetcherCB& create_fetcher_cb, |
326 const CreateStorageCB& create_storage_cb, | |
327 const SessionMessageCB& session_message_cb, | 327 const SessionMessageCB& session_message_cb, |
328 const SessionClosedCB& session_closed_cb, | 328 const SessionClosedCB& session_closed_cb, |
329 const SessionKeysChangeCB& session_keys_change_cb, | 329 const SessionKeysChangeCB& session_keys_change_cb, |
330 const SessionExpirationUpdateCB& session_expiration_update_cb) { | 330 const SessionExpirationUpdateCB& session_expiration_update_cb, |
| 331 MediaDrmCreatedCB media_drm_created_cb) { |
331 // All paths requires the MediaDrmApis. | 332 // All paths requires the MediaDrmApis. |
332 DCHECK(AreMediaDrmApisAvailable()); | 333 DCHECK(AreMediaDrmApisAvailable()); |
333 | 334 DCHECK(!scheme_uuid.empty()); |
334 UUID scheme_uuid = GetKeySystemManager()->GetUUID(key_system); | |
335 if (scheme_uuid.empty()) | |
336 return nullptr; | |
337 | 335 |
338 scoped_refptr<MediaDrmBridge> media_drm_bridge(new MediaDrmBridge( | 336 scoped_refptr<MediaDrmBridge> media_drm_bridge(new MediaDrmBridge( |
339 scheme_uuid, security_origin, security_level, create_fetcher_cb, | 337 scheme_uuid, security_level, std::move(storage), create_fetcher_cb, |
340 create_storage_cb, session_message_cb, session_closed_cb, | 338 session_message_cb, session_closed_cb, session_keys_change_cb, |
341 session_keys_change_cb, session_expiration_update_cb)); | 339 session_expiration_update_cb)); |
342 | 340 |
343 if (media_drm_bridge->j_media_drm_.is_null()) | 341 if (media_drm_bridge->j_media_drm_.is_null()) |
344 media_drm_bridge = nullptr; | 342 media_drm_bridge = nullptr; |
345 | 343 |
346 return media_drm_bridge; | 344 std::move(media_drm_created_cb).Run(std::move(media_drm_bridge)); |
347 } | 345 } |
348 | 346 |
349 // static | 347 // static |
350 scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create( | 348 void MediaDrmBridge::Create( |
351 const std::string& key_system, | 349 const std::string& key_system, |
352 const GURL& security_origin, | 350 const GURL& security_origin, |
353 SecurityLevel security_level, | 351 SecurityLevel security_level, |
354 const CreateFetcherCB& create_fetcher_cb, | 352 const CreateFetcherCB& create_fetcher_cb, |
355 const CreateStorageCB& create_storage_cb, | 353 const CreateStorageCB& create_storage_cb, |
356 const SessionMessageCB& session_message_cb, | 354 const SessionMessageCB& session_message_cb, |
357 const SessionClosedCB& session_closed_cb, | 355 const SessionClosedCB& session_closed_cb, |
358 const SessionKeysChangeCB& session_keys_change_cb, | 356 const SessionKeysChangeCB& session_keys_change_cb, |
359 const SessionExpirationUpdateCB& session_expiration_update_cb) { | 357 const SessionExpirationUpdateCB& session_expiration_update_cb, |
| 358 MediaDrmCreatedCB media_drm_created_cb) { |
360 DVLOG(1) << __func__; | 359 DVLOG(1) << __func__; |
361 | 360 |
362 if (!IsAvailable()) | 361 if (!IsAvailable()) { |
363 return nullptr; | 362 std::move(media_drm_created_cb).Run(nullptr); |
| 363 return; |
| 364 } |
364 | 365 |
365 return CreateInternal(key_system, security_origin, security_level, | 366 UUID scheme_uuid = GetKeySystemManager()->GetUUID(key_system); |
366 create_fetcher_cb, create_storage_cb, | 367 if (scheme_uuid.empty()) { |
367 session_message_cb, session_closed_cb, | 368 std::move(media_drm_created_cb).Run(nullptr); |
368 session_keys_change_cb, session_expiration_update_cb); | 369 return; |
| 370 } |
| 371 |
| 372 // MediaDrmStorage may be lazy created in MediaDrmStorageBridge. |
| 373 auto storage = base::MakeUnique<MediaDrmStorageBridge>(); |
| 374 MediaDrmStorageBridge* raw_storage = storage.get(); |
| 375 |
| 376 base::OnceClosure create_media_drm_cb = base::BindOnce( |
| 377 &MediaDrmBridge::CreateInternal, scheme_uuid, security_level, |
| 378 base::Passed(&storage), create_fetcher_cb, session_message_cb, |
| 379 session_closed_cb, session_keys_change_cb, session_expiration_update_cb, |
| 380 base::Passed(&media_drm_created_cb)); |
| 381 |
| 382 if (IsPersistentLicenseTypeSupported(key_system) && |
| 383 !security_origin.is_empty() && !create_storage_cb.is_null()) { |
| 384 raw_storage->Initialize(url::Origin(security_origin), create_storage_cb, |
| 385 std::move(create_media_drm_cb)); |
| 386 } else { |
| 387 std::move(create_media_drm_cb).Run(); |
| 388 } |
369 } | 389 } |
370 | 390 |
371 // static | 391 // static |
372 scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport( | 392 void MediaDrmBridge::CreateWithoutSessionSupport( |
373 const std::string& key_system, | 393 const std::string& key_system, |
374 SecurityLevel security_level, | 394 SecurityLevel security_level, |
375 const CreateFetcherCB& create_fetcher_cb) { | 395 const CreateFetcherCB& create_fetcher_cb, |
| 396 MediaDrmCreatedCB media_drm_created_cb) { |
376 DVLOG(1) << __func__; | 397 DVLOG(1) << __func__; |
377 | 398 |
378 // Sessions won't be used so decoding capability is not required. | 399 // Sessions won't be used so decoding capability is not required. |
379 if (!AreMediaDrmApisAvailable()) | 400 if (!AreMediaDrmApisAvailable()) { |
380 return nullptr; | 401 std::move(media_drm_created_cb).Run(nullptr); |
| 402 return; |
| 403 } |
381 | 404 |
382 return MediaDrmBridge::Create( | 405 MediaDrmBridge::Create(key_system, GURL::EmptyGURL(), security_level, |
383 key_system, GURL::EmptyGURL(), security_level, create_fetcher_cb, | 406 create_fetcher_cb, CreateStorageCB(), |
384 CreateStorageCB(), SessionMessageCB(), SessionClosedCB(), | 407 SessionMessageCB(), SessionClosedCB(), |
385 SessionKeysChangeCB(), SessionExpirationUpdateCB()); | 408 SessionKeysChangeCB(), SessionExpirationUpdateCB(), |
| 409 std::move(media_drm_created_cb)); |
386 } | 410 } |
387 | 411 |
388 void MediaDrmBridge::SetServerCertificate( | 412 void MediaDrmBridge::SetServerCertificate( |
389 const std::vector<uint8_t>& certificate, | 413 const std::vector<uint8_t>& certificate, |
390 std::unique_ptr<media::SimpleCdmPromise> promise) { | 414 std::unique_ptr<media::SimpleCdmPromise> promise) { |
391 DCHECK(task_runner_->BelongsToCurrentThread()); | 415 DCHECK(task_runner_->BelongsToCurrentThread()); |
392 DVLOG(2) << __func__ << "(" << certificate.size() << " bytes)"; | 416 DVLOG(2) << __func__ << "(" << certificate.size() << " bytes)"; |
393 | 417 |
394 DCHECK(!certificate.empty()); | 418 DCHECK(!certificate.empty()); |
395 | 419 |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 task_runner_->PostTask( | 811 task_runner_->PostTask( |
788 FROM_HERE, | 812 FROM_HERE, |
789 base::Bind(base::ResetAndReturn(&reset_credentials_cb_), success)); | 813 base::Bind(base::ResetAndReturn(&reset_credentials_cb_), success)); |
790 } | 814 } |
791 | 815 |
792 //------------------------------------------------------------------------------ | 816 //------------------------------------------------------------------------------ |
793 // The following are private methods. | 817 // The following are private methods. |
794 | 818 |
795 MediaDrmBridge::MediaDrmBridge( | 819 MediaDrmBridge::MediaDrmBridge( |
796 const std::vector<uint8_t>& scheme_uuid, | 820 const std::vector<uint8_t>& scheme_uuid, |
797 const GURL& security_origin, | |
798 SecurityLevel security_level, | 821 SecurityLevel security_level, |
| 822 std::unique_ptr<MediaDrmStorageBridge> storage, |
799 const CreateFetcherCB& create_fetcher_cb, | 823 const CreateFetcherCB& create_fetcher_cb, |
800 const CreateStorageCB& create_storage_cb, | |
801 const SessionMessageCB& session_message_cb, | 824 const SessionMessageCB& session_message_cb, |
802 const SessionClosedCB& session_closed_cb, | 825 const SessionClosedCB& session_closed_cb, |
803 const SessionKeysChangeCB& session_keys_change_cb, | 826 const SessionKeysChangeCB& session_keys_change_cb, |
804 const SessionExpirationUpdateCB& session_expiration_update_cb) | 827 const SessionExpirationUpdateCB& session_expiration_update_cb) |
805 : scheme_uuid_(scheme_uuid), | 828 : scheme_uuid_(scheme_uuid), |
806 storage_(url::Origin(security_origin), create_storage_cb), | 829 storage_(std::move(storage)), |
807 create_fetcher_cb_(create_fetcher_cb), | 830 create_fetcher_cb_(create_fetcher_cb), |
808 session_message_cb_(session_message_cb), | 831 session_message_cb_(session_message_cb), |
809 session_closed_cb_(session_closed_cb), | 832 session_closed_cb_(session_closed_cb), |
810 session_keys_change_cb_(session_keys_change_cb), | 833 session_keys_change_cb_(session_keys_change_cb), |
811 session_expiration_update_cb_(session_expiration_update_cb), | 834 session_expiration_update_cb_(session_expiration_update_cb), |
812 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 835 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
813 media_drm_bridge_cdm_context_(this), | 836 media_drm_bridge_cdm_context_(this), |
814 weak_factory_(this) { | 837 weak_factory_(this) { |
815 DVLOG(1) << __func__; | 838 DVLOG(1) << __func__; |
816 | 839 |
817 DCHECK(!create_fetcher_cb_.is_null()); | 840 DCHECK(storage_); |
| 841 DCHECK(create_fetcher_cb_); |
818 | 842 |
819 JNIEnv* env = AttachCurrentThread(); | 843 JNIEnv* env = AttachCurrentThread(); |
820 CHECK(env); | 844 CHECK(env); |
821 | 845 |
822 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 846 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
823 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 847 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
824 | 848 |
825 std::string security_level_str = GetSecurityLevelString(security_level); | 849 std::string security_level_str = GetSecurityLevelString(security_level); |
826 ScopedJavaLocalRef<jstring> j_security_level = | 850 ScopedJavaLocalRef<jstring> j_security_level = |
827 ConvertUTF8ToJavaString(env, security_level_str); | 851 ConvertUTF8ToJavaString(env, security_level_str); |
828 | 852 |
829 bool use_origin_isolated_storage = | 853 bool use_origin_isolated_storage = |
830 // TODO(yucliu): Remove the check once persistent storage is fully | 854 // TODO(yucliu): Remove the check once persistent storage is fully |
831 // supported and check if origin is valid. | 855 // supported and check if origin is valid. |
832 base::FeatureList::IsEnabled(kMediaDrmPersistentLicense) && | 856 base::FeatureList::IsEnabled(kMediaDrmPersistentLicense) && |
833 // MediaDrm implements origin isolated storage on M. | 857 // MediaDrm implements origin isolated storage on M. |
834 base::android::BuildInfo::GetInstance()->sdk_int() >= 23; | 858 base::android::BuildInfo::GetInstance()->sdk_int() >= 23 && |
| 859 !storage_->origin_id().empty(); |
835 | 860 |
836 // TODO(yucliu): Per EME spec on individualization, implementation should not | 861 // TODO(yucliu): Per EME spec on individualization, implementation should not |
837 // expose application-specific information. Considering encode origin before | 862 // expose application-specific information. Considering encode origin before |
838 // passing to MediaDrm. | 863 // passing to MediaDrm. |
839 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString( | 864 ScopedJavaLocalRef<jstring> j_security_origin = ConvertUTF8ToJavaString( |
840 env, use_origin_isolated_storage ? security_origin.spec() : ""); | 865 env, use_origin_isolated_storage ? storage_->origin_id() : ""); |
841 | 866 |
842 // TODO(yucliu): Use |create_storage_cb_| to create MediaDrmStorage which can | 867 // TODO(yucliu): Use |create_storage_cb_| to create MediaDrmStorage which can |
843 // be used by Java side to store/retrieve persistent data. This should only | 868 // be used by Java side to store/retrieve persistent data. This should only |
844 // be used when |use_origin_isolated_storage| is true. | 869 // be used when |use_origin_isolated_storage| is true. |
845 | 870 |
846 // Note: OnMediaCryptoReady() could be called in this call. | 871 // Note: OnMediaCryptoReady() could be called in this call. |
847 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 872 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
848 env, j_scheme_uuid, j_security_origin, j_security_level, | 873 env, j_scheme_uuid, j_security_origin, j_security_level, |
849 reinterpret_cast<intptr_t>(this), reinterpret_cast<intptr_t>(&storage_))); | 874 reinterpret_cast<intptr_t>(this), |
| 875 reinterpret_cast<intptr_t>(storage_.get()))); |
850 } | 876 } |
851 | 877 |
852 MediaDrmBridge::~MediaDrmBridge() { | 878 MediaDrmBridge::~MediaDrmBridge() { |
853 DCHECK(task_runner_->BelongsToCurrentThread()); | 879 DCHECK(task_runner_->BelongsToCurrentThread()); |
854 DVLOG(1) << __func__; | 880 DVLOG(1) << __func__; |
855 | 881 |
856 JNIEnv* env = AttachCurrentThread(); | 882 JNIEnv* env = AttachCurrentThread(); |
857 | 883 |
858 // After the call to Java_MediaDrmBridge_destroy() Java won't call native | 884 // After the call to Java_MediaDrmBridge_destroy() Java won't call native |
859 // methods anymore, this is ensured by MediaDrmBridge.java. | 885 // methods anymore, this is ensured by MediaDrmBridge.java. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 } | 965 } |
940 | 966 |
941 void MediaDrmBridge::OnHasAdditionalUsableKey() { | 967 void MediaDrmBridge::OnHasAdditionalUsableKey() { |
942 DCHECK(task_runner_->BelongsToCurrentThread()); | 968 DCHECK(task_runner_->BelongsToCurrentThread()); |
943 DVLOG(1) << __func__; | 969 DVLOG(1) << __func__; |
944 | 970 |
945 player_tracker_.NotifyNewKey(); | 971 player_tracker_.NotifyNewKey(); |
946 } | 972 } |
947 | 973 |
948 } // namespace media | 974 } // namespace media |
OLD | NEW |