| 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/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "jni/MediaDrmBridge_jni.h" | 17 #include "jni/MediaDrmBridge_jni.h" |
| 18 #include "media/base/android/media_player_manager.h" | |
| 19 | 18 |
| 20 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. | 19 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. |
| 21 | 20 |
| 22 using base::android::AttachCurrentThread; | 21 using base::android::AttachCurrentThread; |
| 23 using base::android::ConvertUTF8ToJavaString; | 22 using base::android::ConvertUTF8ToJavaString; |
| 24 using base::android::ConvertJavaStringToUTF8; | 23 using base::android::ConvertJavaStringToUTF8; |
| 25 using base::android::JavaByteArrayToByteVector; | 24 using base::android::JavaByteArrayToByteVector; |
| 26 using base::android::ScopedJavaLocalRef; | 25 using base::android::ScopedJavaLocalRef; |
| 27 | 26 |
| 28 namespace media { | 27 namespace media { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 DCHECK(IsAvailable()); | 215 DCHECK(IsAvailable()); |
| 217 return SECURITY_LEVEL_1 == security_level; | 216 return SECURITY_LEVEL_1 == security_level; |
| 218 } | 217 } |
| 219 | 218 |
| 220 // static | 219 // static |
| 221 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, | 220 bool MediaDrmBridge::IsSecurityLevelSupported(const std::string& key_system, |
| 222 SecurityLevel security_level) { | 221 SecurityLevel security_level) { |
| 223 if (!IsAvailable()) | 222 if (!IsAvailable()) |
| 224 return false; | 223 return false; |
| 225 | 224 |
| 226 // Pass 0 as |cdm_id| and NULL as |manager| as they are not used in | |
| 227 // creation time of MediaDrmBridge. | |
| 228 scoped_ptr<MediaDrmBridge> media_drm_bridge = | 225 scoped_ptr<MediaDrmBridge> media_drm_bridge = |
| 229 MediaDrmBridge::Create(0, key_system, GURL(), NULL); | 226 MediaDrmBridge::Create(key_system); |
| 230 if (!media_drm_bridge) | 227 if (!media_drm_bridge) |
| 231 return false; | 228 return false; |
| 232 | 229 |
| 233 return media_drm_bridge->SetSecurityLevel(security_level); | 230 return media_drm_bridge->SetSecurityLevel(security_level); |
| 234 } | 231 } |
| 235 | 232 |
| 236 // static | 233 // static |
| 237 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { | 234 bool MediaDrmBridge::IsKeySystemSupported(const std::string& key_system) { |
| 238 DCHECK(!key_system.empty()); | 235 DCHECK(!key_system.empty()); |
| 239 return IsKeySystemSupportedWithTypeImpl(key_system, ""); | 236 return IsKeySystemSupportedWithTypeImpl(key_system, ""); |
| 240 } | 237 } |
| 241 | 238 |
| 242 // static | 239 // static |
| 243 bool MediaDrmBridge::IsKeySystemSupportedWithType( | 240 bool MediaDrmBridge::IsKeySystemSupportedWithType( |
| 244 const std::string& key_system, | 241 const std::string& key_system, |
| 245 const std::string& container_mime_type) { | 242 const std::string& container_mime_type) { |
| 246 DCHECK(!key_system.empty() && !container_mime_type.empty()); | 243 DCHECK(!key_system.empty() && !container_mime_type.empty()); |
| 247 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); | 244 return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type); |
| 248 } | 245 } |
| 249 | 246 |
| 250 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { | 247 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) { |
| 251 return RegisterNativesImpl(env); | 248 return RegisterNativesImpl(env); |
| 252 } | 249 } |
| 253 | 250 |
| 254 MediaDrmBridge::MediaDrmBridge(int cdm_id, | 251 MediaDrmBridge::MediaDrmBridge(const std::vector<uint8>& scheme_uuid, |
| 255 const std::vector<uint8>& scheme_uuid, | 252 const SessionCreatedCB& session_created_cb, |
| 256 const GURL& security_origin, | 253 const SessionMessageCB& session_message_cb, |
| 257 MediaPlayerManager* manager) | 254 const SessionReadyCB& session_ready_cb, |
| 258 : cdm_id_(cdm_id), | 255 const SessionClosedCB& session_closed_cb, |
| 259 scheme_uuid_(scheme_uuid), | 256 const SessionErrorCB& session_error_cb) |
| 260 security_origin_(security_origin), | 257 : scheme_uuid_(scheme_uuid), |
| 261 manager_(manager) { | 258 session_created_cb_(session_created_cb), |
| 259 session_message_cb_(session_message_cb), |
| 260 session_ready_cb_(session_ready_cb), |
| 261 session_closed_cb_(session_closed_cb), |
| 262 session_error_cb_(session_error_cb) { |
| 262 JNIEnv* env = AttachCurrentThread(); | 263 JNIEnv* env = AttachCurrentThread(); |
| 263 CHECK(env); | 264 CHECK(env); |
| 264 | 265 |
| 265 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = | 266 ScopedJavaLocalRef<jbyteArray> j_scheme_uuid = |
| 266 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); | 267 base::android::ToJavaByteArray(env, &scheme_uuid[0], scheme_uuid.size()); |
| 267 j_media_drm_.Reset(Java_MediaDrmBridge_create( | 268 j_media_drm_.Reset(Java_MediaDrmBridge_create( |
| 268 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); | 269 env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this))); |
| 269 } | 270 } |
| 270 | 271 |
| 271 MediaDrmBridge::~MediaDrmBridge() { | 272 MediaDrmBridge::~MediaDrmBridge() { |
| 272 JNIEnv* env = AttachCurrentThread(); | 273 JNIEnv* env = AttachCurrentThread(); |
| 273 if (!j_media_drm_.is_null()) | 274 if (!j_media_drm_.is_null()) |
| 274 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); | 275 Java_MediaDrmBridge_release(env, j_media_drm_.obj()); |
| 275 } | 276 } |
| 276 | 277 |
| 277 // static | 278 // static |
| 278 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(int cdm_id, | 279 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( |
| 279 const std::string& key_system, | 280 const std::string& key_system, |
| 280 const GURL& security_origin, | 281 const SessionCreatedCB& session_created_cb, |
| 281 MediaPlayerManager* manager) { | 282 const SessionMessageCB& session_message_cb, |
| 283 const SessionReadyCB& session_ready_cb, |
| 284 const SessionClosedCB& session_closed_cb, |
| 285 const SessionErrorCB& session_error_cb) { |
| 282 scoped_ptr<MediaDrmBridge> media_drm_bridge; | 286 scoped_ptr<MediaDrmBridge> media_drm_bridge; |
| 283 if (!IsAvailable()) | 287 if (!IsAvailable()) |
| 284 return media_drm_bridge.Pass(); | 288 return media_drm_bridge.Pass(); |
| 285 | 289 |
| 286 std::vector<uint8> scheme_uuid = GetUUID(key_system); | 290 std::vector<uint8> scheme_uuid = GetUUID(key_system); |
| 287 if (scheme_uuid.empty()) | 291 if (scheme_uuid.empty()) |
| 288 return media_drm_bridge.Pass(); | 292 return media_drm_bridge.Pass(); |
| 289 | 293 |
| 290 media_drm_bridge.reset( | 294 media_drm_bridge.reset(new MediaDrmBridge(scheme_uuid, |
| 291 new MediaDrmBridge(cdm_id, scheme_uuid, security_origin, manager)); | 295 session_created_cb, |
| 296 session_message_cb, |
| 297 session_ready_cb, |
| 298 session_closed_cb, |
| 299 session_error_cb)); |
| 300 |
| 292 if (media_drm_bridge->j_media_drm_.is_null()) | 301 if (media_drm_bridge->j_media_drm_.is_null()) |
| 293 media_drm_bridge.reset(); | 302 media_drm_bridge.reset(); |
| 294 | 303 |
| 295 return media_drm_bridge.Pass(); | 304 return media_drm_bridge.Pass(); |
| 296 } | 305 } |
| 297 | 306 |
| 307 //static |
| 308 scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create( |
| 309 const std::string& key_system) { |
| 310 return MediaDrmBridge::Create(key_system, |
| 311 SessionCreatedCB(), |
| 312 SessionMessageCB(), |
| 313 SessionReadyCB(), |
| 314 SessionClosedCB(), |
| 315 SessionErrorCB()); |
| 316 } |
| 317 |
| 298 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { | 318 bool MediaDrmBridge::SetSecurityLevel(SecurityLevel security_level) { |
| 299 JNIEnv* env = AttachCurrentThread(); | 319 JNIEnv* env = AttachCurrentThread(); |
| 300 | 320 |
| 301 std::string security_level_str = GetSecurityLevelString(security_level); | 321 std::string security_level_str = GetSecurityLevelString(security_level); |
| 302 if (security_level_str.empty()) | 322 if (security_level_str.empty()) |
| 303 return false; | 323 return false; |
| 304 | 324 |
| 305 ScopedJavaLocalRef<jstring> j_security_level = | 325 ScopedJavaLocalRef<jstring> j_security_level = |
| 306 ConvertUTF8ToJavaString(env, security_level_str); | 326 ConvertUTF8ToJavaString(env, security_level_str); |
| 307 return Java_MediaDrmBridge_setSecurityLevel( | 327 return Java_MediaDrmBridge_setSecurityLevel( |
| 308 env, j_media_drm_.obj(), j_security_level.obj()); | 328 env, j_media_drm_.obj(), j_security_level.obj()); |
| 309 } | 329 } |
| 310 | 330 |
| 311 bool MediaDrmBridge::CreateSession(uint32 session_id, | 331 bool MediaDrmBridge::CreateSession(uint32 session_id, |
| 312 const std::string& content_type, | 332 const std::string& content_type, |
| 313 const uint8* init_data, | 333 const uint8* init_data, |
| 314 int init_data_length) { | 334 int init_data_length) { |
| 335 DCHECK(!session_created_cb_.is_null()); |
| 336 |
| 315 JNIEnv* env = AttachCurrentThread(); | 337 JNIEnv* env = AttachCurrentThread(); |
| 316 ScopedJavaLocalRef<jbyteArray> j_init_data; | 338 ScopedJavaLocalRef<jbyteArray> j_init_data; |
| 317 // Caller should always use "video/*" content types. | 339 // Caller should always use "video/*" content types. |
| 318 DCHECK_EQ(0u, content_type.find("video/")); | 340 DCHECK_EQ(0u, content_type.find("video/")); |
| 319 | 341 |
| 320 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as | 342 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as |
| 321 // the init data when using MP4 container. | 343 // the init data when using MP4 container. |
| 322 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && | 344 if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && |
| 323 content_type == "video/mp4") { | 345 content_type == "video/mp4") { |
| 324 std::vector<uint8> pssh_data; | 346 std::vector<uint8> pssh_data; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 if (!media_crypto_ready_cb_.is_null()) | 404 if (!media_crypto_ready_cb_.is_null()) |
| 383 base::ResetAndReturn(&media_crypto_ready_cb_).Run(); | 405 base::ResetAndReturn(&media_crypto_ready_cb_).Run(); |
| 384 } | 406 } |
| 385 | 407 |
| 386 void MediaDrmBridge::OnSessionCreated(JNIEnv* env, | 408 void MediaDrmBridge::OnSessionCreated(JNIEnv* env, |
| 387 jobject j_media_drm, | 409 jobject j_media_drm, |
| 388 jint j_session_id, | 410 jint j_session_id, |
| 389 jstring j_web_session_id) { | 411 jstring j_web_session_id) { |
| 390 uint32 session_id = j_session_id; | 412 uint32 session_id = j_session_id; |
| 391 std::string web_session_id = ConvertJavaStringToUTF8(env, j_web_session_id); | 413 std::string web_session_id = ConvertJavaStringToUTF8(env, j_web_session_id); |
| 392 manager_->OnSessionCreated(cdm_id_, session_id, web_session_id); | 414 session_created_cb_.Run(session_id, web_session_id); |
| 393 } | 415 } |
| 394 | 416 |
| 395 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, | 417 void MediaDrmBridge::OnSessionMessage(JNIEnv* env, |
| 396 jobject j_media_drm, | 418 jobject j_media_drm, |
| 397 jint j_session_id, | 419 jint j_session_id, |
| 398 jbyteArray j_message, | 420 jbyteArray j_message, |
| 399 jstring j_destination_url) { | 421 jstring j_destination_url) { |
| 400 uint32 session_id = j_session_id; | 422 uint32 session_id = j_session_id; |
| 401 std::vector<uint8> message; | 423 std::vector<uint8> message; |
| 402 JavaByteArrayToByteVector(env, j_message, &message); | 424 JavaByteArrayToByteVector(env, j_message, &message); |
| 403 std::string destination_url = ConvertJavaStringToUTF8(env, j_destination_url); | 425 std::string destination_url = ConvertJavaStringToUTF8(env, j_destination_url); |
| 404 GURL destination_gurl(destination_url); | 426 session_message_cb_.Run(session_id, message, destination_url); |
| 405 if (!destination_gurl.is_valid() && !destination_gurl.is_empty()) { | |
| 406 DLOG(WARNING) << "SessionMessage destination_url is invalid : " | |
| 407 << destination_gurl.possibly_invalid_spec(); | |
| 408 destination_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. | |
| 409 } | |
| 410 | |
| 411 manager_->OnSessionMessage(cdm_id_, session_id, message, destination_gurl); | |
| 412 } | 427 } |
| 413 | 428 |
| 414 void MediaDrmBridge::OnSessionReady(JNIEnv* env, | 429 void MediaDrmBridge::OnSessionReady(JNIEnv* env, |
| 415 jobject j_media_drm, | 430 jobject j_media_drm, |
| 416 jint j_session_id) { | 431 jint j_session_id) { |
| 417 uint32 session_id = j_session_id; | 432 uint32 session_id = j_session_id; |
| 418 manager_->OnSessionReady(cdm_id_, session_id); | 433 session_ready_cb_.Run(session_id); |
| 419 } | 434 } |
| 420 | 435 |
| 421 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, | 436 void MediaDrmBridge::OnSessionClosed(JNIEnv* env, |
| 422 jobject j_media_drm, | 437 jobject j_media_drm, |
| 423 jint j_session_id) { | 438 jint j_session_id) { |
| 424 uint32 session_id = j_session_id; | 439 uint32 session_id = j_session_id; |
| 425 manager_->OnSessionClosed(cdm_id_, session_id); | 440 session_closed_cb_.Run(session_id); |
| 426 } | 441 } |
| 427 | 442 |
| 428 void MediaDrmBridge::OnSessionError(JNIEnv* env, | 443 void MediaDrmBridge::OnSessionError(JNIEnv* env, |
| 429 jobject j_media_drm, | 444 jobject j_media_drm, |
| 430 jint j_session_id) { | 445 jint j_session_id) { |
| 431 uint32 session_id = j_session_id; | 446 uint32 session_id = j_session_id; |
| 432 manager_->OnSessionError(cdm_id_, session_id, MediaKeys::kUnknownError, 0); | 447 session_error_cb_.Run(session_id, MediaKeys::kUnknownError, 0); |
| 433 } | 448 } |
| 434 | 449 |
| 435 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { | 450 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() { |
| 436 JNIEnv* env = AttachCurrentThread(); | 451 JNIEnv* env = AttachCurrentThread(); |
| 437 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); | 452 return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj()); |
| 438 } | 453 } |
| 439 | 454 |
| 440 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { | 455 MediaDrmBridge::SecurityLevel MediaDrmBridge::GetSecurityLevel() { |
| 441 JNIEnv* env = AttachCurrentThread(); | 456 JNIEnv* env = AttachCurrentThread(); |
| 442 ScopedJavaLocalRef<jstring> j_security_level = | 457 ScopedJavaLocalRef<jstring> j_security_level = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 457 JNIEnv* env = AttachCurrentThread(); | 472 JNIEnv* env = AttachCurrentThread(); |
| 458 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); | 473 Java_MediaDrmBridge_resetDeviceCredentials(env, j_media_drm_.obj()); |
| 459 } | 474 } |
| 460 | 475 |
| 461 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( | 476 void MediaDrmBridge::OnResetDeviceCredentialsCompleted( |
| 462 JNIEnv* env, jobject, bool success) { | 477 JNIEnv* env, jobject, bool success) { |
| 463 base::ResetAndReturn(&reset_credentials_cb_).Run(success); | 478 base::ResetAndReturn(&reset_credentials_cb_).Run(success); |
| 464 } | 479 } |
| 465 | 480 |
| 466 } // namespace media | 481 } // namespace media |
| OLD | NEW |