blob: c6faf320cc78de4e0720a5e091c4cc917d13bbdd [file] [log] [blame]
// Copyright 2019 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.
// This file exposes services from the cast browser to child processes.
#include "chromecast/browser/cast_content_browser_client.h"
#include <memory>
#include "base/bind.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chromecast/browser/application_media_info_manager.h"
#include "chromecast/browser/cast_browser_main_parts.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/media/media_caps_impl.h"
#include "chromecast/chromecast_buildflags.h"
#include "chromecast/media/cdm/cast_cdm_factory.h"
#include "components/network_hints/browser/simple_network_hints_handler_impl.h"
#include "content/public/browser/render_process_host.h"
#include "media/mojo/buildflags.h"
#if BUILDFLAG(ENABLE_CAST_RENDERER)
#include "chromecast/media/service/cast_mojo_media_client.h"
#include "chromecast/media/service/video_geometry_setter_service.h"
#include "media/mojo/mojom/constants.mojom.h" // nogncheck
#include "media/mojo/services/media_service.h" // nogncheck
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
#include "chromecast/external_mojo/broker_service/broker_service.h"
#endif
#if BUILDFLAG(ENABLE_CAST_WAYLAND_SERVER)
#include "chromecast/browser/webview/js_channel_service.h"
#include "chromecast/common/mojom/js_channel.mojom.h"
#endif
#if defined(OS_ANDROID)
#include "components/cdm/browser/media_drm_storage_impl.h"
#include "url/origin.h"
#else
#include "chromecast/browser/memory_pressure_controller_impl.h"
#endif // defined(OS_ANDROID)
namespace chromecast {
namespace shell {
namespace {
#if defined(OS_ANDROID)
void CreateOriginId(cdm::MediaDrmStorageImpl::OriginIdObtainedCB callback) {
// TODO(crbug.com/917527): Update this to actually get a pre-provisioned
// origin ID.
std::move(callback).Run(true, base::UnguessableToken::Create());
}
void AllowEmptyOriginIdCB(base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(false);
}
void CreateMediaDrmStorage(content::RenderFrameHost* render_frame_host,
::media::mojom::MediaDrmStorageRequest request) {
DVLOG(1) << __func__;
PrefService* pref_service = CastBrowserProcess::GetInstance()->pref_service();
DCHECK(pref_service);
if (render_frame_host->GetLastCommittedOrigin().opaque()) {
DVLOG(1) << __func__ << ": Unique origin.";
return;
}
// The object will be deleted on connection error, or when the frame navigates
// away.
new cdm::MediaDrmStorageImpl(
render_frame_host, pref_service, base::BindRepeating(&CreateOriginId),
base::BindRepeating(&AllowEmptyOriginIdCB), std::move(request));
}
#endif // defined(OS_ANDROID)
#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
void StartExternalMojoBrokerService(
service_manager::mojom::ServiceRequest request) {
service_manager::Service::RunAsyncUntilTermination(
std::make_unique<external_mojo::BrokerService>(std::move(request)));
}
#endif // BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
} // namespace
void CastContentBrowserClient::ExposeInterfacesToRenderer(
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) {
registry->AddInterface(
base::Bind(&media::MediaCapsImpl::AddReceiver,
base::Unretained(cast_browser_main_parts_->media_caps())),
base::ThreadTaskRunnerHandle::Get());
#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
if (!memory_pressure_controller_) {
memory_pressure_controller_.reset(new MemoryPressureControllerImpl());
}
registry->AddInterface(
base::Bind(&MemoryPressureControllerImpl::AddReceiver,
base::Unretained(memory_pressure_controller_.get())),
base::ThreadTaskRunnerHandle::Get());
#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
}
void CastContentBrowserClient::ExposeInterfacesToMediaService(
service_manager::BinderRegistry* registry,
content::RenderFrameHost* render_frame_host) {
#if defined(OS_ANDROID)
registry->AddInterface(
base::BindRepeating(&CreateMediaDrmStorage, render_frame_host));
#endif // defined(OS_ANDROID)
std::string application_session_id;
bool mixer_audio_enabled;
GetApplicationMediaInfo(&application_session_id, &mixer_audio_enabled,
render_frame_host);
registry->AddInterface(base::BindRepeating(
&media::CreateApplicationMediaInfoManager, render_frame_host,
std::move(application_session_id), mixer_audio_enabled));
}
#if BUILDFLAG(ENABLE_CAST_RENDERER)
void CastContentBrowserClient::CreateMediaService(
service_manager::mojom::ServiceRequest request) {
std::unique_ptr<::media::MediaService> service;
DCHECK(GetMediaTaskRunner() &&
GetMediaTaskRunner()->BelongsToCurrentThread());
if (!video_geometry_setter_service_) {
CreateVideoGeometrySetterServiceOnMediaThread();
}
auto mojo_media_client = std::make_unique<media::CastMojoMediaClient>(
GetCmaBackendFactory(),
base::Bind(&CastContentBrowserClient::CreateCdmFactory,
base::Unretained(this)),
GetVideoModeSwitcher(), GetVideoResolutionPolicy());
mojo_media_client->SetVideoGeometrySetterService(
video_geometry_setter_service_.get());
service = std::make_unique<::media::MediaService>(
std::move(mojo_media_client), std::move(request));
service_manager::Service::RunAsyncUntilTermination(std::move(service));
}
void CastContentBrowserClient::CreateVideoGeometrySetterServiceOnMediaThread() {
DCHECK(GetMediaTaskRunner() &&
GetMediaTaskRunner()->BelongsToCurrentThread());
DCHECK(!video_geometry_setter_service_);
video_geometry_setter_service_ =
std::unique_ptr<media::VideoGeometrySetterService,
base::OnTaskRunnerDeleter>(
new media::VideoGeometrySetterService,
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
}
void CastContentBrowserClient::BindVideoGeometrySetterServiceOnMediaThread(
mojo::GenericPendingReceiver receiver) {
DCHECK(GetMediaTaskRunner() &&
GetMediaTaskRunner()->BelongsToCurrentThread());
if (!video_geometry_setter_service_) {
CreateVideoGeometrySetterServiceOnMediaThread();
}
if (auto r = receiver.As<media::mojom::VideoGeometrySetter>()) {
video_geometry_setter_service_->GetVideoGeometrySetter(std::move(r));
}
}
void CastContentBrowserClient::BindGpuHostReceiver(
mojo::GenericPendingReceiver receiver) {
DCHECK(GetMediaTaskRunner());
GetMediaTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&CastContentBrowserClient::
BindVideoGeometrySetterServiceOnMediaThread,
base::Unretained(this), std::move(receiver)));
}
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
void CastContentBrowserClient::RunServiceInstance(
const service_manager::Identity& identity,
mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {
#if BUILDFLAG(ENABLE_CAST_RENDERER)
if (identity.name() == ::media::mojom::kMediaRendererServiceName) {
service_manager::mojom::ServiceRequest request(std::move(*receiver));
GetMediaTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&CastContentBrowserClient::CreateMediaService,
base::Unretained(this), std::move(request)));
return;
}
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
if (identity.name() == external_mojo::BrokerService::kServiceName) {
StartExternalMojoBrokerService(std::move(*receiver));
return;
}
#endif // BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
}
void CastContentBrowserClient::BindHostReceiverForRenderer(
content::RenderProcessHost* render_process_host,
mojo::GenericPendingReceiver receiver) {
#if BUILDFLAG(ENABLE_CAST_WAYLAND_SERVER)
if (auto r = receiver.As<::chromecast::mojom::JsChannelBindingProvider>()) {
JsChannelService::Create(render_process_host, std::move(r),
base::ThreadTaskRunnerHandle::Get());
return;
}
#endif
if (auto r = receiver.As<::network_hints::mojom::NetworkHintsHandler>()) {
network_hints::SimpleNetworkHintsHandlerImpl::Create(
render_process_host->GetID(), std::move(r));
}
ContentBrowserClient::BindHostReceiverForRenderer(render_process_host,
std::move(receiver));
}
} // namespace shell
} // namespace chromecast