blob: 886f64912d703c09af61ecc41f6663cf586e09bb [file] [log] [blame]
// Copyright 2021 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/mojo/services/cdm_service_broker.h"
#include <utility>
#include "base/logging.h"
#include "media/cdm/cdm_module.h"
#include "media/media_buildflags.h"
#if defined(OS_MAC)
#include <vector>
#include "sandbox/mac/seatbelt_extension.h"
#endif // defined(OS_MAC)
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
#include "media/cdm/cdm_host_file.h"
#endif
namespace media {
CdmServiceBroker::CdmServiceBroker(
std::unique_ptr<CdmService::Client> client,
mojo::PendingReceiver<mojom::CdmServiceBroker> receiver)
: client_(std::move(client)), receiver_(this, std::move(receiver)) {
DVLOG(1) << __func__;
DCHECK(client_);
}
CdmServiceBroker::~CdmServiceBroker() = default;
void CdmServiceBroker::GetService(
const base::FilePath& cdm_path,
#if defined(OS_MAC)
mojo::PendingRemote<mojom::SeatbeltExtensionTokenProvider> token_provider,
#endif // defined(OS_MAC)
mojo::PendingReceiver<mojom::CdmService> service_receiver) {
if (!client_) {
DVLOG(1) << __func__ << ": CdmService can only be bound once";
return;
}
bool success = InitializeAndEnsureSandboxed(
#if defined(OS_MAC)
std::move(token_provider),
#endif // defined(OS_MAC)
cdm_path);
if (!success) {
client_.reset();
return;
}
DCHECK(!cdm_service_);
cdm_service_ = std::make_unique<CdmService>(std::move(client_),
std::move(service_receiver));
}
bool CdmServiceBroker::InitializeAndEnsureSandboxed(
#if defined(OS_MAC)
mojo::PendingRemote<mojom::SeatbeltExtensionTokenProvider> token_provider,
#endif // defined(OS_MAC)
const base::FilePath& cdm_path) {
DVLOG(1) << __func__ << ": cdm_path = " << cdm_path.value();
DCHECK(client_);
#if defined(OS_MAC)
std::vector<std::unique_ptr<sandbox::SeatbeltExtension>> extensions;
if (token_provider) {
std::vector<sandbox::SeatbeltExtensionToken> tokens;
CHECK(mojo::Remote<mojom::SeatbeltExtensionTokenProvider>(
std::move(token_provider))
->GetTokens(&tokens));
for (auto&& token : tokens) {
DVLOG(3) << "token: " << token.token();
auto extension = sandbox::SeatbeltExtension::FromToken(std::move(token));
if (!extension->Consume()) {
DVLOG(1) << "Failed to consume sandbox seatbelt extension. This could "
"happen if --no-sandbox is specified.";
}
extensions.push_back(std::move(extension));
}
}
#endif // defined(OS_MAC)
CdmModule* instance = CdmModule::GetInstance();
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
std::vector<CdmHostFilePath> cdm_host_file_paths;
client_->AddCdmHostFilePaths(&cdm_host_file_paths);
bool success = instance->Initialize(cdm_path, cdm_host_file_paths);
#else
bool success = instance->Initialize(cdm_path);
#endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
// This may trigger the sandbox to be sealed. After this call, the process is
// sandboxed.
client_->EnsureSandboxed();
#if defined(OS_MAC)
for (auto&& extension : extensions)
extension->Revoke();
#endif // defined(OS_MAC)
// Always called within the sandbox.
if (success)
instance->InitializeCdmModule();
return success;
}
} // namespace media