blob: 1b03b162c6a56b90b333e8a99901b0d5385607b2 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_MEDIA_CDM_REGISTRY_IMPL_H_
#define CONTENT_BROWSER_MEDIA_CDM_REGISTRY_IMPL_H_
#include <vector>
#include "base/callback_list.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/cdm_registry.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/common/cdm_info.h"
#include "media/base/cdm_capability.h"
#include "media/base/key_system_capability.h"
#include "media/mojo/mojom/key_system_support.mojom.h"
namespace content {
// Map from `key_system` string to `KeySystemCapability`.
using KeySystemCapabilities =
base::flat_map<std::string, media::KeySystemCapability>;
using KeySystemCapabilitiesUpdateCB =
base::RepeatingCallback<void(KeySystemCapabilities)>;
class CONTENT_EXPORT CdmRegistryImpl : public CdmRegistry,
public GpuDataManagerObserver {
public:
// Returns the CdmRegistryImpl singleton.
static CdmRegistryImpl* GetInstance();
CdmRegistryImpl(const CdmRegistryImpl&) = delete;
CdmRegistryImpl& operator=(const CdmRegistryImpl&) = delete;
// CdmRegistry implementation.
void Init() override;
void RegisterCdm(const CdmInfo& info) override;
void SetHardwareSecureCdmStatus(CdmInfo::Status status) override;
// GpuDataManagerObserver implementation.
void OnGpuInfoUpdate() override;
// Returns all registered CDMs. There might be multiple CdmInfo registered for
// the same `key_system` and `robustness`. Notes:
// - Only the first registered one will be used in playback.
// - The returned CdmInfo's capability might not have been finalized.
const std::vector<CdmInfo>& GetRegisteredCdms() const;
// Returns CdmInfo registered for `key_system` and `robustness`. Returns null
// if no CdmInfo is registered, or if the CdmInfo registered is invalid. There
// might be multiple CdmInfo registered for the same `key_system` and
// `robustness`, in which case the first registered one will be returned. The
// returned CdmInfo's capability might not have been finalized.
std::unique_ptr<CdmInfo> GetCdmInfo(const std::string& key_system,
CdmInfo::Robustness robustness) const;
// Observes key system capabilities updates. The updated capabilities are
// guaranteed to be finalized. The `cb` is always called on the original
// thread this function was called on. If `allow_hw_secure_capability_check`
// is true, then `this` is allowed to check capability for hardware secure key
// systems.
//
// Returns a `base::CallbackListSubscription` which is owned by the caller. If
// that is destroyed, the `cb` is cancelled.
base::CallbackListSubscription ObserveKeySystemCapabilities(
bool allow_hw_secure_capability_check,
KeySystemCapabilitiesUpdateCB cb);
private:
// Make the test a friend class so it could create CdmRegistryImpl directly,
// to avoid singleton issues.
friend class CdmRegistryImplTest;
// Make constructor/destructor private since this is a singleton.
CdmRegistryImpl();
~CdmRegistryImpl() override;
// Get the capability for `key_system` with robustness `robustness`
// synchronously. If lazy initialization is needed, return
// Status::kUninitialized.
std::pair<std::optional<media::CdmCapability>, CdmInfo::Status> GetCapability(
const std::string& key_system,
CdmInfo::Robustness robustness);
// Get the capability for `key_system` with robustness `robustness`
// synchronously. All initialization should have been completed.
std::pair<std::optional<media::CdmCapability>, CdmInfo::Status>
GetFinalCapability(const std::string& key_system,
CdmInfo::Robustness robustness);
// Finalizes KeySystemCapabilities. May lazy initialize CDM capabilities
// asynchronously if needed.
void FinalizeKeySystemCapabilities();
// Attempt to finalize KeySystemCapability for `key_system` with robustness
// `robustness`. May lazy initialize it asynchronously if needed.
void AttemptToFinalizeKeySystemCapability(const std::string& key_system,
CdmInfo::Robustness robustness);
// Lazily initialize `key_system` with robustness `robustness`, calling
// `cdm_capability_cb`. Callback may be called synchronously
// or asynchronously.
void LazyInitializeCapability(const std::string& key_system,
CdmInfo::Robustness robustness,
media::CdmCapabilityCB cdm_capability_cb);
// Called when initialization of `key_system` with robustness `robustness`
// is complete. `cdm_capability_or_status.has_value()` will be false if the
// key system with specified robustness isn't supported.
// `cdm_capability_or_status.error()` can be used to inspect the reason when
// no capability reported.
void OnCapabilityInitialized(
const std::string& key_system,
const CdmInfo::Robustness robustness,
media::CdmCapabilityOrStatus cdm_capability_or_status);
// Finalizes the CdmInfo corresponding to `key_system` and `robustness` if its
// CdmCapability is null (lazy initialization). No-op if the CdmInfo does not
// exist, or if the CdmInfo's CdmCapability is not null. The CdmInfo will be
// removed if `cdm_capability_or_status.has_value()` is false, since the CDM
// does not support any capability. `cdm_capability_or_status.error()` can be
// used for user-facing information especially when no capability reported.
void FinalizeCapability(const std::string& key_system,
const CdmInfo::Robustness robustness,
media::CdmCapabilityOrStatus cdm_capability_or_status,
CdmInfo::Status status);
// When capabilities for all registered key systems have been determined,
// notify all observers with the updated values. No notification is done
// if the capabilities have not changed.
void UpdateAndNotifyKeySystemCapabilities();
// Returns the set of all registered key systems.
std::set<std::string> GetSupportedKeySystems() const;
// Returns the capabailities for all registered key systems.
KeySystemCapabilities GetKeySystemCapabilities();
// Sets callbacks to query for secure capability for testing.
using CapabilityCB =
base::RepeatingCallback<void(const std::string&,
const CdmInfo::Robustness robustness,
media::CdmCapabilityCB)>;
void SetCapabilityCBForTesting(CapabilityCB cb);
std::vector<CdmInfo> cdms_ GUARDED_BY_CONTEXT(sequence_checker_);
// Observers for `key_system_capabilities_` updates.
base::RepeatingCallbackList<KeySystemCapabilitiesUpdateCB::RunType>
key_system_capabilities_update_callbacks_;
// Cached current KeySystemCapabilities value.
std::optional<KeySystemCapabilities> key_system_capabilities_;
// Key system and robustness pairs pending CdmCapability lazy initialization.
std::set<std::pair<std::string, CdmInfo::Robustness>>
pending_lazy_initializations_;
// Callback for testing to avoid device dependency.
CapabilityCB capability_cb_for_testing_;
// Whether HW secure capability checking is allowed.
bool allow_hw_secure_capability_check_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CdmRegistryImpl> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_MEDIA_CDM_REGISTRY_IMPL_H_