blob: 4417e0428708cee053e134d4dd0ec4cd10c2ead2 [file] [log] [blame]
// Copyright 2014 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.
#ifndef MEDIA_MOJO_CLIENTS_MOJO_CDM_H_
#define MEDIA_MOJO_CLIENTS_MOJO_CDM_H_
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_context.h"
#include "media/base/cdm_initialized_promise.h"
#include "media/base/cdm_promise_adapter.h"
#include "media/base/cdm_session_tracker.h"
#include "media/base/content_decryption_module.h"
#include "media/mojo/mojom/content_decryption_module.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace media {
class MojoDecryptor;
// A ContentDecryptionModule that proxies to a mojom::ContentDecryptionModule.
// That mojom::ContentDecryptionModule proxies back to the MojoCdm via the
// mojom::ContentDecryptionModuleClient interface.
class MojoCdm final : public ContentDecryptionModule,
public CdmContext,
public mojom::ContentDecryptionModuleClient {
public:
using MessageType = CdmMessageType;
// All parameters must be non-null.
MojoCdm(mojo::Remote<mojom::ContentDecryptionModule> remote_cdm,
media::mojom::CdmContextPtr cdm_context,
const SessionMessageCB& session_message_cb,
const SessionClosedCB& session_closed_cb,
const SessionKeysChangeCB& session_keys_change_cb,
const SessionExpirationUpdateCB& session_expiration_update_cb);
// ContentDecryptionModule implementation.
void SetServerCertificate(const std::vector<uint8_t>& certificate,
std::unique_ptr<SimpleCdmPromise> promise) final;
void GetStatusForPolicy(HdcpVersion min_hdcp_version,
std::unique_ptr<KeyStatusCdmPromise> promise) final;
void CreateSessionAndGenerateRequest(
CdmSessionType session_type,
EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
std::unique_ptr<NewSessionCdmPromise> promise) final;
void LoadSession(CdmSessionType session_type,
const std::string& session_id,
std::unique_ptr<NewSessionCdmPromise> promise) final;
void UpdateSession(const std::string& session_id,
const std::vector<uint8_t>& response,
std::unique_ptr<SimpleCdmPromise> promise) final;
void CloseSession(const std::string& session_id,
std::unique_ptr<SimpleCdmPromise> promise) final;
void RemoveSession(const std::string& session_id,
std::unique_ptr<SimpleCdmPromise> promise) final;
CdmContext* GetCdmContext() final;
// CdmContext implementation. Can be called on a different thread.
// All GetDecryptor() calls must be made on the same thread.
std::unique_ptr<CallbackRegistration> RegisterEventCB(EventCB event_cb) final;
Decryptor* GetDecryptor() final;
absl::optional<base::UnguessableToken> GetCdmId() const final;
#if defined(OS_WIN)
bool RequiresMediaFoundationRenderer() final;
#endif // defined(OS_WIN)
private:
~MojoCdm() final;
void OnConnectionError(uint32_t custom_reason,
const std::string& description);
// mojom::ContentDecryptionModuleClient implementation.
void OnSessionMessage(const std::string& session_id,
MessageType message_type,
const std::vector<uint8_t>& message) final;
void OnSessionClosed(const std::string& session_id,
CdmSessionClosedReason reason) final;
void OnSessionKeysChange(
const std::string& session_id,
bool has_additional_usable_key,
std::vector<std::unique_ptr<CdmKeyInformation>> keys_info) final;
void OnSessionExpirationUpdate(const std::string& session_id,
double new_expiry_time_sec) final;
// Callbacks to handle CDM promises.
void OnSimpleCdmPromiseResult(uint32_t promise_id,
mojom::CdmPromiseResultPtr result);
void OnKeyStatusCdmPromiseResult(uint32_t promise_id,
mojom::CdmPromiseResultPtr result,
CdmKeyInformation::KeyStatus key_status);
void OnNewSessionCdmPromiseResult(uint32_t promise_id,
mojom::CdmPromiseResultPtr result,
const std::string& session_id);
THREAD_CHECKER(thread_checker_);
mojo::Remote<mojom::ContentDecryptionModule> remote_cdm_;
mojo::AssociatedReceiver<ContentDecryptionModuleClient> client_receiver_{
this};
// Protects |cdm_id_|, |decryptor_remote_|, |decryptor_|,
// |decryptor_task_runner_| and |requires_media_foundation_renderer_|, which
// could be accessed from other threads. See CdmContext implementation above.
mutable base::Lock lock_;
// CDM ID of the remote CDM. Set after initialization is completed. Must not
// be invalid if initialization succeeded.
absl::optional<base::UnguessableToken> cdm_id_ GUARDED_BY(lock_);
// The mojo::PendingRemote<mojom::Decryptor> exposed by the remote CDM. Set
// after initialization is completed and cleared after |decryptor_| is
// created. May be invalid after initialization if the CDM doesn't support a
// Decryptor.
mojo::PendingRemote<mojom::Decryptor> decryptor_remote_ GUARDED_BY(lock_);
// Decryptor based on |decryptor_remote_|, lazily created in
// GetDecryptor(). Since GetDecryptor() can be called on a different thread,
// use |decryptor_task_runner_| to bind |decryptor_| to that thread.
std::unique_ptr<MojoDecryptor> decryptor_ GUARDED_BY(lock_);
scoped_refptr<base::SingleThreadTaskRunner> decryptor_task_runner_
GUARDED_BY(lock_);
#if defined(OS_WIN)
bool requires_media_foundation_renderer_ GUARDED_BY(lock_) = false;
#endif // defined(OS_WIN)
// Callbacks for firing session events.
SessionMessageCB session_message_cb_;
SessionClosedCB session_closed_cb_;
SessionKeysChangeCB session_keys_change_cb_;
SessionExpirationUpdateCB session_expiration_update_cb_;
// Keep track of current sessions.
CdmSessionTracker cdm_session_tracker_;
// Keep track of outstanding promises.
CdmPromiseAdapter cdm_promise_adapter_;
CallbackRegistry<EventCB::RunType> event_callbacks_;
// This must be the last member.
base::WeakPtrFactory<MojoCdm> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(MojoCdm);
};
} // namespace media
#endif // MEDIA_MOJO_CLIENTS_MOJO_CDM_H_