Index: media/base/android/media_drm_bridge.cc |
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc |
index 96821aec43c07a7fd3e78e847c77d1d3ad7c9377..65decbe2e69b3c8b566d74592a0a74b93e038298 100644 |
--- a/media/base/android/media_drm_bridge.cc |
+++ b/media/base/android/media_drm_bridge.cc |
@@ -29,6 +29,7 @@ |
#include "media/base/android/media_codec_util.h" |
#include "media/base/android/media_drm_bridge_delegate.h" |
#include "media/base/android/provision_fetcher.h" |
+#include "media/base/media_permission.h" |
#include "media/base/cdm_key_information.h" |
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
@@ -74,16 +75,16 @@ const uint8_t kWidevineUuid[16] = { |
// Convert |init_data_type| to a string supported by MediaDRM. |
// "audio"/"video" does not matter, so use "video". |
-std::string ConvertInitDataType(media::EmeInitDataType init_data_type) { |
+std::string ConvertInitDataType(EmeInitDataType init_data_type) { |
// TODO(jrummell/xhwang): EME init data types like "webm" and "cenc" are |
// supported in API level >=21 for Widevine key system. Switch to use those |
// strings when they are officially supported in Android for all key systems. |
switch (init_data_type) { |
- case media::EmeInitDataType::WEBM: |
+ case EmeInitDataType::WEBM: |
return "video/webm"; |
- case media::EmeInitDataType::CENC: |
+ case EmeInitDataType::CENC: |
return "video/mp4"; |
- case media::EmeInitDataType::KEYIDS: |
+ case EmeInitDataType::KEYIDS: |
return "keyids"; |
default: |
NOTREACHED(); |
@@ -280,7 +281,9 @@ std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() { |
// static |
scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateInternal( |
const std::string& key_system, |
+ const GURL& security_origin, |
SecurityLevel security_level, |
+ MediaPermission* media_permission, |
const CreateFetcherCB& create_fetcher_cb, |
const SessionMessageCB& session_message_cb, |
const SessionClosedCB& session_closed_cb, |
@@ -295,8 +298,9 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateInternal( |
return nullptr; |
scoped_refptr<MediaDrmBridge> media_drm_bridge(new MediaDrmBridge( |
- scheme_uuid, security_level, create_fetcher_cb, session_message_cb, |
- session_closed_cb, legacy_session_error_cb, session_keys_change_cb, |
+ scheme_uuid, security_origin, security_level, media_permission, |
+ create_fetcher_cb, session_message_cb, session_closed_cb, |
+ legacy_session_error_cb, session_keys_change_cb, |
session_expiration_update_cb)); |
if (media_drm_bridge->j_media_drm_.is_null()) |
@@ -308,7 +312,9 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateInternal( |
// static |
scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create( |
const std::string& key_system, |
+ const GURL& security_origin, |
SecurityLevel security_level, |
+ MediaPermission* media_permission, |
const CreateFetcherCB& create_fetcher_cb, |
const SessionMessageCB& session_message_cb, |
const SessionClosedCB& session_closed_cb, |
@@ -320,10 +326,10 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::Create( |
if (!IsAvailable()) |
return nullptr; |
- return CreateInternal(key_system, security_level, create_fetcher_cb, |
- session_message_cb, session_closed_cb, |
- legacy_session_error_cb, session_keys_change_cb, |
- session_expiration_update_cb); |
+ return CreateInternal(key_system, security_origin, security_level, |
+ media_permission, create_fetcher_cb, session_message_cb, |
+ session_closed_cb, legacy_session_error_cb, |
+ session_keys_change_cb, session_expiration_update_cb); |
} |
// static |
@@ -337,15 +343,15 @@ scoped_refptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport( |
if (!AreMediaDrmApisAvailable()) |
return nullptr; |
- return MediaDrmBridge::Create(key_system, security_level, create_fetcher_cb, |
- SessionMessageCB(), SessionClosedCB(), |
- LegacySessionErrorCB(), SessionKeysChangeCB(), |
- SessionExpirationUpdateCB()); |
+ return MediaDrmBridge::Create( |
+ key_system, GURL(), security_level, nullptr, create_fetcher_cb, |
+ SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(), |
+ SessionKeysChangeCB(), SessionExpirationUpdateCB()); |
} |
void MediaDrmBridge::SetServerCertificate( |
const std::vector<uint8_t>& certificate, |
- scoped_ptr<media::SimpleCdmPromise> promise) { |
+ scoped_ptr<SimpleCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__ << "(" << certificate.size() << " bytes)"; |
@@ -364,65 +370,38 @@ void MediaDrmBridge::SetServerCertificate( |
void MediaDrmBridge::CreateSessionAndGenerateRequest( |
SessionType session_type, |
- media::EmeInitDataType init_data_type, |
+ EmeInitDataType init_data_type, |
const std::vector<uint8_t>& init_data, |
- scoped_ptr<media::NewSessionCdmPromise> promise) { |
+ scoped_ptr<NewSessionCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__; |
- if (session_type != media::MediaKeys::TEMPORARY_SESSION) { |
+ if (session_type != MediaKeys::TEMPORARY_SESSION) { |
NOTIMPLEMENTED() << "EME persistent sessions not yet supported on Android."; |
promise->reject(NOT_SUPPORTED_ERROR, 0, |
"Only the temporary session type is supported."); |
return; |
} |
- JNIEnv* env = AttachCurrentThread(); |
- ScopedJavaLocalRef<jbyteArray> j_init_data; |
- ScopedJavaLocalRef<jobjectArray> j_optional_parameters; |
- |
- MediaClientAndroid* client = GetMediaClientAndroid(); |
- if (client) { |
- MediaDrmBridgeDelegate* delegate = |
- client->GetMediaDrmBridgeDelegate(scheme_uuid_); |
- if (delegate) { |
- std::vector<uint8_t> init_data_from_delegate; |
- std::vector<std::string> optional_parameters_from_delegate; |
- if (!delegate->OnCreateSession(init_data_type, init_data, |
- &init_data_from_delegate, |
- &optional_parameters_from_delegate)) { |
- promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid init data."); |
- return; |
- } |
- if (!init_data_from_delegate.empty()) { |
- j_init_data = |
- base::android::ToJavaByteArray(env, init_data_from_delegate.data(), |
- init_data_from_delegate.size()); |
- } |
- if (!optional_parameters_from_delegate.empty()) { |
- j_optional_parameters = base::android::ToJavaArrayOfStrings( |
- env, optional_parameters_from_delegate); |
- } |
- } |
- } |
- |
- if (j_init_data.is_null()) { |
- j_init_data = |
- base::android::ToJavaByteArray(env, init_data.data(), init_data.size()); |
+ // TODO(xhwang): |media_permission_| is optional here because when running |
+ // in the browser process BrowserCdmManager does the permission check. Make |
+ // |media_permission_| mandatory when BrowserCdmManager is deprecated. |
+ // See http://crbug.com/581746 |
+ if (!media_permission_) { |
+ CreateSessionAndGenerateRequestIfPermitted(init_data_type, init_data, |
+ std::move(promise), true); |
+ } else { |
+ media_permission_->HasPermission( |
+ MediaPermission::PROTECTED_MEDIA_IDENTIFIER, security_origin_, |
+ base::Bind(&MediaDrmBridge::CreateSessionAndGenerateRequestIfPermitted, |
+ weak_factory_.GetWeakPtr(), init_data_type, init_data, |
+ base::Passed(&promise))); |
} |
- |
- ScopedJavaLocalRef<jstring> j_mime = |
- ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); |
- uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
- Java_MediaDrmBridge_createSessionFromNative( |
- env, j_media_drm_.obj(), j_init_data.obj(), j_mime.obj(), |
- j_optional_parameters.obj(), promise_id); |
} |
-void MediaDrmBridge::LoadSession( |
- SessionType session_type, |
- const std::string& session_id, |
- scoped_ptr<media::NewSessionCdmPromise> promise) { |
+void MediaDrmBridge::LoadSession(SessionType session_type, |
+ const std::string& session_id, |
+ scoped_ptr<NewSessionCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__; |
@@ -430,10 +409,9 @@ void MediaDrmBridge::LoadSession( |
promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); |
} |
-void MediaDrmBridge::UpdateSession( |
- const std::string& session_id, |
- const std::vector<uint8_t>& response, |
- scoped_ptr<media::SimpleCdmPromise> promise) { |
+void MediaDrmBridge::UpdateSession(const std::string& session_id, |
+ const std::vector<uint8_t>& response, |
+ scoped_ptr<SimpleCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__; |
@@ -449,7 +427,7 @@ void MediaDrmBridge::UpdateSession( |
} |
void MediaDrmBridge::CloseSession(const std::string& session_id, |
- scoped_ptr<media::SimpleCdmPromise> promise) { |
+ scoped_ptr<SimpleCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__; |
@@ -462,9 +440,8 @@ void MediaDrmBridge::CloseSession(const std::string& session_id, |
promise_id); |
} |
-void MediaDrmBridge::RemoveSession( |
- const std::string& session_id, |
- scoped_ptr<media::SimpleCdmPromise> promise) { |
+void MediaDrmBridge::RemoveSession(const std::string& session_id, |
+ scoped_ptr<SimpleCdmPromise> promise) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DVLOG(2) << __FUNCTION__; |
@@ -762,7 +739,9 @@ void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
MediaDrmBridge::MediaDrmBridge( |
const std::vector<uint8_t>& scheme_uuid, |
+ const GURL& security_origin, |
SecurityLevel security_level, |
+ MediaPermission* media_permission, |
const CreateFetcherCB& create_fetcher_cb, |
const SessionMessageCB& session_message_cb, |
const SessionClosedCB& session_closed_cb, |
@@ -770,6 +749,8 @@ MediaDrmBridge::MediaDrmBridge( |
const SessionKeysChangeCB& session_keys_change_cb, |
const SessionExpirationUpdateCB& session_expiration_update_cb) |
: scheme_uuid_(scheme_uuid), |
+ security_origin_(security_origin), |
+ media_permission_(media_permission), |
create_fetcher_cb_(create_fetcher_cb), |
session_message_cb_(session_message_cb), |
session_closed_cb_(session_closed_cb), |
@@ -862,6 +843,58 @@ void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) { |
IsProtectedSurfaceRequired()); |
} |
+void MediaDrmBridge::CreateSessionAndGenerateRequestIfPermitted( |
+ EmeInitDataType init_data_type, |
+ const std::vector<uint8_t>& init_data, |
+ scoped_ptr<NewSessionCdmPromise> promise, |
+ bool permitted) { |
+ if (!permitted) { |
+ promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
+ return; |
+ } |
+ |
+ JNIEnv* env = AttachCurrentThread(); |
+ ScopedJavaLocalRef<jbyteArray> j_init_data; |
+ ScopedJavaLocalRef<jobjectArray> j_optional_parameters; |
+ |
+ MediaClientAndroid* client = GetMediaClientAndroid(); |
+ if (client) { |
+ MediaDrmBridgeDelegate* delegate = |
+ client->GetMediaDrmBridgeDelegate(scheme_uuid_); |
+ if (delegate) { |
+ std::vector<uint8_t> init_data_from_delegate; |
+ std::vector<std::string> optional_parameters_from_delegate; |
+ if (!delegate->OnCreateSession(init_data_type, init_data, |
+ &init_data_from_delegate, |
+ &optional_parameters_from_delegate)) { |
+ promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid init data."); |
+ return; |
+ } |
+ if (!init_data_from_delegate.empty()) { |
+ j_init_data = |
+ base::android::ToJavaByteArray(env, init_data_from_delegate.data(), |
+ init_data_from_delegate.size()); |
+ } |
+ if (!optional_parameters_from_delegate.empty()) { |
+ j_optional_parameters = base::android::ToJavaArrayOfStrings( |
+ env, optional_parameters_from_delegate); |
+ } |
+ } |
+ } |
+ |
+ if (j_init_data.is_null()) { |
+ j_init_data = |
+ base::android::ToJavaByteArray(env, init_data.data(), init_data.size()); |
+ } |
+ |
+ ScopedJavaLocalRef<jstring> j_mime = |
+ ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type)); |
+ uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
+ Java_MediaDrmBridge_createSessionFromNative( |
+ env, j_media_drm_.obj(), j_init_data.obj(), j_mime.obj(), |
+ j_optional_parameters.obj(), promise_id); |
+} |
+ |
void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url, |
const std::string& request_data) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |