| Index: media/base/android/media_drm_proxy.cc
|
| diff --git a/media/base/android/media_drm_proxy.cc b/media/base/android/media_drm_proxy.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..385666d761f9cfd7f7120f12d61e2e9c12a15f06
|
| --- /dev/null
|
| +++ b/media/base/android/media_drm_proxy.cc
|
| @@ -0,0 +1,258 @@
|
| +// Copyright (c) 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "media/base/android/media_drm_proxy.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "media/base/android/media_codec_player.h" // for GetMediaTaskRunner()
|
| +#include "media/base/android/media_drm_bridge.h"
|
| +#include "media/base/cdm_key_information.h"
|
| +#include "third_party/widevine/cdm/widevine_cdm_common.h"
|
| +
|
| +#define POST_ON_MEDIA_THREAD_AND_RETURN(method, ...) \
|
| + do { \
|
| + if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \
|
| + GetMediaTaskRunner()->PostTask( \
|
| + FROM_HERE, base::Bind(&MediaDrmProxy::method, media_weak_this_, \
|
| + ##__VA_ARGS__)); \
|
| + return; \
|
| + } \
|
| + } while (0)
|
| +
|
| +namespace media {
|
| +
|
| +// static
|
| +scoped_ptr<MediaDrmProxy, BrowserCdmDeleter> MediaDrmProxy::Create(
|
| + const std::string& key_system,
|
| + MediaDrmBridge::SecurityLevel widevine_security_level,
|
| + const SessionMessageCB& session_message_cb,
|
| + const SessionClosedCB& session_closed_cb,
|
| + const LegacySessionErrorCB& legacy_session_error_cb,
|
| + const SessionKeysChangeCB& session_keys_change_cb,
|
| + const SessionExpirationUpdateCB& session_expiration_update_cb) {
|
| + scoped_ptr<MediaDrmProxy, BrowserCdmDeleter> media_drm_proxy;
|
| +
|
| + // Perform as many checks as we can on the UI thread before we do
|
| + // the creation asynchronously on Media thread.
|
| + if (!MediaDrmBridge::CanCreate(key_system, widevine_security_level))
|
| + return media_drm_proxy.Pass();
|
| +
|
| + media_drm_proxy.reset(
|
| + new MediaDrmProxy(key_system, widevine_security_level, session_message_cb,
|
| + session_closed_cb, legacy_session_error_cb,
|
| + session_keys_change_cb, session_expiration_update_cb));
|
| +
|
| + // The actual work is done on the Media thread and there the creation
|
| + // might fail, but we are still passing a valid pointer.
|
| + return media_drm_proxy.Pass();
|
| +}
|
| +
|
| +MediaDrmProxy::MediaDrmProxy(
|
| + const std::string& key_system,
|
| + MediaDrmBridge::SecurityLevel widevine_security_level,
|
| + const SessionMessageCB& session_message_cb,
|
| + const SessionClosedCB& session_closed_cb,
|
| + const LegacySessionErrorCB& legacy_session_error_cb,
|
| + const SessionKeysChangeCB& session_keys_change_cb,
|
| + const SessionExpirationUpdateCB& session_expiration_update_cb)
|
| + : ui_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + key_system_(key_system),
|
| + widevine_security_level_(widevine_security_level),
|
| + session_message_cb_(session_message_cb),
|
| + session_closed_cb_(session_closed_cb),
|
| + legacy_session_error_cb_(legacy_session_error_cb),
|
| + session_keys_change_cb_(session_keys_change_cb),
|
| + session_expiration_update_cb_(session_expiration_update_cb),
|
| + media_weak_factory_(this) {
|
| + media_weak_this_ = media_weak_factory_.GetWeakPtr();
|
| +
|
| + internal_session_message_cb_ =
|
| + base::Bind(&MediaDrmProxy::OnSessionMessage, media_weak_this_);
|
| + internal_session_closed_cb_ =
|
| + base::Bind(&MediaDrmProxy::OnSessionClosed, media_weak_this_);
|
| + internal_legacy_session_error_cb_ =
|
| + base::Bind(&MediaDrmProxy::OnLegacySessionError, media_weak_this_);
|
| + internal_session_keys_change_cb_ =
|
| + base::Bind(&MediaDrmProxy::OnSessionKeysChange, media_weak_this_);
|
| + internal_session_expiration_update_cb_ =
|
| + base::Bind(&MediaDrmProxy::OnSessionExpirationUpdate, media_weak_this_);
|
| +
|
| + // Perform MediaDrmBridge creation on the Media thread.
|
| + GetMediaTaskRunner()->PostTask(
|
| + FROM_HERE, base::Bind(&MediaDrmProxy::Initialize, media_weak_this_));
|
| +}
|
| +
|
| +MediaDrmProxy::~MediaDrmProxy() {
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +}
|
| +
|
| +void MediaDrmProxy::DeleteOnCorrectThread() {
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + // Post deletion onto Media thread
|
| + GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this);
|
| +}
|
| +
|
| +void MediaDrmProxy::Initialize() {
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + // Pass the original callbacks, those that should be called on UI thread.
|
| + media_drm_bridge_ =
|
| + scoped_ptr<MediaDrmBridge, BrowserCdmDeleter>(MediaDrmBridge::Create(
|
| + key_system_,
|
| + widevine_security_level_,
|
| + internal_session_message_cb_,
|
| + internal_session_closed_cb_,
|
| + internal_legacy_session_error_cb_,
|
| + internal_session_keys_change_cb_,
|
| + internal_session_expiration_update_cb_));
|
| +
|
| + if (!media_drm_bridge_)
|
| + DVLOG(1) << __FUNCTION__ << ": MediaDrmBridge::Create() failed";
|
| +}
|
| +
|
| +void MediaDrmProxy::SetServerCertificate(
|
| + const std::vector<uint8_t>& certificate,
|
| + scoped_ptr<media::SimpleCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(SetServerCertificate, certificate,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->SetServerCertificate(certificate, promise.Pass());
|
| +}
|
| +
|
| +void MediaDrmProxy::CreateSessionAndGenerateRequest(
|
| + SessionType session_type,
|
| + media::EmeInitDataType init_data_type,
|
| + const std::vector<uint8_t>& init_data,
|
| + scoped_ptr<media::NewSessionCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(CreateSessionAndGenerateRequest, session_type,
|
| + init_data_type, init_data,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->CreateSessionAndGenerateRequest(
|
| + session_type, init_data_type, init_data, promise.Pass());
|
| +}
|
| +
|
| +void MediaDrmProxy::LoadSession(
|
| + SessionType session_type,
|
| + const std::string& session_id,
|
| + scoped_ptr<media::NewSessionCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(LoadSession, session_type, session_id,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->LoadSession(session_type, session_id, promise.Pass());
|
| +}
|
| +
|
| +void MediaDrmProxy::UpdateSession(const std::string& session_id,
|
| + const std::vector<uint8_t>& response,
|
| + scoped_ptr<media::SimpleCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(UpdateSession, session_id, response,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->UpdateSession(session_id, response, promise.Pass());
|
| +}
|
| +
|
| +void MediaDrmProxy::CloseSession(const std::string& session_id,
|
| + scoped_ptr<media::SimpleCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(CloseSession, session_id,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->CloseSession(session_id, promise.Pass());
|
| +}
|
| +
|
| +void MediaDrmProxy::RemoveSession(const std::string& session_id,
|
| + scoped_ptr<media::SimpleCdmPromise> promise) {
|
| + POST_ON_MEDIA_THREAD_AND_RETURN(RemoveSession, session_id,
|
| + base::Passed(&promise));
|
| +
|
| + DVLOG(1) << "MediaDrmProxy::" << __FUNCTION__;
|
| +
|
| + media_drm_bridge_->RemoveSession(session_id, promise.Pass());
|
| +}
|
| +
|
| +CdmContext* MediaDrmProxy::GetCdmContext() {
|
| + NOTREACHED();
|
| + return nullptr;
|
| +}
|
| +
|
| +int MediaDrmProxy::RegisterPlayer(const base::Closure& new_key_cb,
|
| + const base::Closure& cdm_unset_cb) {
|
| + NOTREACHED() << __FUNCTION__ << " should be called on MediaDrmBridge";
|
| + return -1;
|
| +}
|
| +
|
| +void MediaDrmProxy::UnregisterPlayer(int registration_id) {
|
| + NOTREACHED() << __FUNCTION__ << " should be called on MediaDrmBridge";
|
| +}
|
| +
|
| +MediaDrmBridge* MediaDrmProxy::GetDrmBridge() {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + return media_drm_bridge_.get();
|
| +}
|
| +
|
| +// Internal callbacks
|
| +
|
| +void MediaDrmProxy::OnSessionMessage(const std::string& session_id,
|
| + MediaKeys::MessageType message_type,
|
| + const std::vector<uint8>& message,
|
| + const GURL& legacy_destination_url) {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + ui_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(session_message_cb_, session_id, message_type,
|
| + message, legacy_destination_url));
|
| +}
|
| +
|
| +void MediaDrmProxy::OnSessionClosed(const std::string& session_id) {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + ui_task_runner_->PostTask(FROM_HERE,
|
| + base::Bind(session_closed_cb_, session_id));
|
| +}
|
| +
|
| +void MediaDrmProxy::OnLegacySessionError(const std::string& session_id,
|
| + MediaKeys::Exception exception_code,
|
| + uint32 system_code,
|
| + const std::string& error_message) {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + ui_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(legacy_session_error_cb_, session_id,
|
| + exception_code, system_code, error_message));
|
| +}
|
| +
|
| +void MediaDrmProxy::OnSessionKeysChange(const std::string& session_id,
|
| + bool has_additional_usable_key,
|
| + CdmKeysInfo keys_info) {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + ui_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(session_keys_change_cb_, session_id, has_additional_usable_key,
|
| + base::Passed(&keys_info)));
|
| +}
|
| +
|
| +void MediaDrmProxy::OnSessionExpirationUpdate(
|
| + const std::string& session_id,
|
| + const base::Time& new_expiry_time) {
|
| + DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
|
| +
|
| + ui_task_runner_->PostTask(FROM_HERE, base::Bind(session_expiration_update_cb_,
|
| + session_id, new_expiry_time));
|
| +}
|
| +
|
| +} // namespace media
|
|
|