#include "content/browser/media/service_factory.h"
#include <map>
#include <string>
#include <utility>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/service_process_host.h"
#include "content/public/common/content_client.h"
#include "media/base/cdm_context.h"
#include "media/base/media_switches.h"
#include "media/cdm/cdm_type.h"
#include "media/media_buildflags.h"
#include "media/mojo/mojom/cdm_service.mojom.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#if BUILDFLAG(IS_MAC)
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "sandbox/mac/seatbelt_extension.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "media/mojo/mojom/media_foundation_service.mojom.h"
#endif
namespace content {
namespace {
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
const base::FilePath::CharType kSignatureFileExtension[] =
FILE_PATH_LITERAL(".sig");
base::FilePath GetSigFilePath(const base::FilePath& file_path) {
return file_path.AddExtension(kSignatureFileExtension);
}
#endif
class SeatbeltExtensionTokenProviderImpl final
: public media::mojom::SeatbeltExtensionTokenProvider {
public:
explicit SeatbeltExtensionTokenProviderImpl(const base::FilePath& cdm_path)
: cdm_path_(cdm_path) {}
SeatbeltExtensionTokenProviderImpl(
const SeatbeltExtensionTokenProviderImpl&) = delete;
SeatbeltExtensionTokenProviderImpl operator=(
const SeatbeltExtensionTokenProviderImpl&) = delete;
~SeatbeltExtensionTokenProviderImpl() override = default;
void GetTokens(GetTokensCallback callback) override {
DVLOG(1) << __func__;
std::vector<sandbox::SeatbeltExtensionToken> tokens;
auto cdm_token = sandbox::SeatbeltExtension::Issue(
sandbox::SeatbeltExtension::FILE_READ, cdm_path_.value());
if (cdm_token) {
tokens.push_back(std::move(*cdm_token));
} else {
std::move(callback).Run({});
return;
}
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
auto cdm_sig_token =
sandbox::SeatbeltExtension::Issue(sandbox::SeatbeltExtension::FILE_READ,
GetSigFilePath(cdm_path_).value());
if (cdm_sig_token) {
tokens.push_back(std::move(*cdm_sig_token));
} else {
std::move(callback).Run({});
return;
}
#endif
std::move(callback).Run(std::move(tokens));
}
private:
base::FilePath cdm_path_;
};
#endif
#if BUILDFLAG(IS_WIN)
class GpuInfoMonitor : public GpuDataManagerObserver {
public:
static GpuInfoMonitor* GetInstance() {
static GpuInfoMonitor* instance = new GpuInfoMonitor();
return instance;
}
GpuInfoMonitor() { GpuDataManager::GetInstance()->AddObserver(this); }
void RegisterGpuInfoObserver(
mojo::PendingRemote<media::mojom::GpuInfoObserver> observer) {
auto observer_id = gpu_info_observers_.Add(std::move(observer));
gpu_info_observers_.Get(observer_id)
->OnGpuInfoUpdate(GpuDataManager::GetInstance()->GetGPUInfo());
}
void OnGpuInfoUpdate() override {
for (const auto& observer : gpu_info_observers_) {
observer->OnGpuInfoUpdate(GpuDataManager::GetInstance()->GetGPUInfo());
}
}
private:
mojo::RemoteSet<media::mojom::GpuInfoObserver> gpu_info_observers_;
};
void RegisterGpuInfoObserver(
mojo::PendingRemote<media::mojom::GpuInfoObserver> observer) {
GpuInfoMonitor::GetInstance()->RegisterGpuInfoObserver(std::move(observer));
}
#endif
constexpr auto kServiceIdleTimeout = …;
ServiceKey;
std::ostream& operator<<(std::ostream& os, const ServiceKey& key) { … }
template <typename T>
struct ServiceTraits { … };
template <typename BrokerRemoteType>
void InitializeBroker(BrokerRemoteType& broker_remote) { … }
template <>
struct ServiceTraits<media::mojom::CdmService> { … };
#if BUILDFLAG(IS_WIN)
template <>
struct ServiceTraits<media::mojom::MediaFoundationService> {
using BrokerType = media::mojom::MediaFoundationServiceBroker;
};
template <>
void InitializeBroker(
mojo::Remote<media::mojom::MediaFoundationServiceBroker>& broker_remote) {
broker_remote->UpdateGpuInfo(GpuDataManager::GetInstance()->GetGPUInfo(),
base::BindOnce(&RegisterGpuInfoObserver));
}
#endif
template <typename T>
class ServiceMap { … };
template <typename T>
ServiceMap<T>& GetServiceMap() { … }
template <typename T>
void EraseCdmService(const ServiceKey& key) { … }
template <typename T>
T& GetService(const media::CdmType& cdm_type,
BrowserContext* browser_context,
const GURL& site,
const std::string& service_name,
const base::FilePath& cdm_path) { … }
}
media::mojom::CdmService& GetCdmService(BrowserContext* browser_context,
const GURL& site,
const CdmInfo& cdm_info) { … }
#if BUILDFLAG(IS_WIN)
media::mojom::MediaFoundationService& GetMediaFoundationService(
BrowserContext* browser_context,
const GURL& site,
const base::FilePath& cdm_path) {
return GetService<media::mojom::MediaFoundationService>(
media::CdmType(), browser_context, site, "Media Foundation Service",
cdm_path);
}
#endif
}