blob: 7d9694f290641cc26aaf7c357f49bfb25f6b104f [file] [log] [blame]
// Copyright (c) 2012 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 "chrome/utility/chrome_content_utility_client.h"
#include <stddef.h>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/common/buildflags.h"
#include "chrome/services/noop/noop_service.h"
#include "chrome/services/noop/public/cpp/utils.h"
#include "components/mirroring/mojom/constants.mojom.h"
#include "components/mirroring/service/features.h"
#include "components/mirroring/service/mirroring_service.h"
#include "components/services/heap_profiling/heap_profiling_service.h"
#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
#include "components/services/patch/patch_service.h"
#include "components/services/patch/public/interfaces/constants.mojom.h"
#include "components/services/unzip/public/interfaces/constants.mojom.h"
#include "components/services/unzip/unzip_service.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/simple_connection_filter.h"
#include "content/public/utility/utility_thread.h"
#include "device/vr/buildflags/buildflags.h"
#include "extensions/buildflags/buildflags.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/sandbox/switches.h"
#include "ui/base/buildflags.h"
#if !defined(OS_ANDROID)
#include "chrome/utility/importer/profile_import_impl.h"
#include "chrome/utility/importer/profile_import_service.h"
#include "services/network/url_request_context_builder_mojo.h"
#include "services/proxy_resolver/proxy_resolver_service.h" // nogncheck
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" // nogncheck
#endif // !defined(OS_ANDROID)
#if defined(OS_WIN)
#include "chrome/services/util_win/public/mojom/constants.mojom.h"
#include "chrome/services/util_win/util_win_service.h"
#endif
#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE)
#include "chrome/services/isolated_xr_device/xr_device_service.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/services/removable_storage_writer/public/mojom/constants.mojom.h"
#include "chrome/services/removable_storage_writer/removable_storage_writer_service.h"
#if defined(OS_WIN)
#include "chrome/services/wifi_util_win/public/mojom/constants.mojom.h"
#include "chrome/services/wifi_util_win/wifi_util_win_service.h"
#endif
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_ANDROID)
#include "chrome/services/media_gallery_util/media_gallery_util_service.h"
#include "chrome/services/media_gallery_util/public/mojom/constants.mojom.h"
#endif
#if defined(OS_CHROMEOS)
#include "chrome/utility/mash_service_factory.h"
#include "chromeos/assistant/buildflags.h" // nogncheck
#include "chromeos/services/ime/ime_service.h"
#include "chromeos/services/ime/public/mojom/constants.mojom.h"
#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#include "chromeos/services/assistant/audio_decoder/assistant_audio_decoder_service.h" // nogncheck
#include "chromeos/services/assistant/public/mojom/constants.mojom.h" // nogncheck
#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#endif // defined(OS_CHROMEOS)
#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/common/chrome_content_client.h"
#include "components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h" // nogncheck
#include "components/services/pdf_compositor/public/interfaces/pdf_compositor.mojom.h" // nogncheck
#endif
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) || \
(BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN))
#include "chrome/services/printing/printing_service.h"
#include "chrome/services/printing/public/mojom/constants.mojom.h"
#endif
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
#include "chrome/services/printing/pdf_to_emf_converter_factory.h"
#endif
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && defined(OS_WIN)
#include "chrome/utility/printing_handler.h"
#endif
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_CHROMEOS)
#include "chrome/services/cups_ipp_parser/cups_ipp_parser_service.h" // nogncheck
#include "chrome/services/cups_ipp_parser/public/mojom/constants.mojom.h" // nogncheck
#endif
#if defined(FULL_SAFE_BROWSING) || defined(OS_CHROMEOS)
#include "chrome/services/file_util/file_util_service.h" // nogncheck
#include "chrome/services/file_util/public/mojom/constants.mojom.h" // nogncheck
#endif
#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE_OUT_OF_PROCESS)
#include "services/content/simple_browser/public/mojom/constants.mojom.h" // nogncheck
#include "services/content/simple_browser/simple_browser_service.h" // nogncheck
#endif
namespace {
base::LazyInstance<ChromeContentUtilityClient::NetworkBinderCreationCallback>::
Leaky g_network_binder_creation_callback = LAZY_INSTANCE_INITIALIZER;
void RunServiceAsyncThenTerminateProcess(
std::unique_ptr<service_manager::Service> service) {
service_manager::Service::RunAsyncUntilTermination(
std::move(service),
base::BindOnce([] { content::UtilityThread::Get()->ReleaseProcess(); }));
}
std::unique_ptr<service_manager::Service> CreateHeapProfilingService(
service_manager::mojom::ServiceRequest request) {
return std::make_unique<heap_profiling::HeapProfilingService>(
std::move(request));
}
#if !defined(OS_ANDROID)
std::unique_ptr<service_manager::Service> CreateProxyResolverService(
service_manager::mojom::ServiceRequest request) {
return std::make_unique<proxy_resolver::ProxyResolverService>(
std::move(request));
}
#endif
using ServiceFactory =
base::OnceCallback<std::unique_ptr<service_manager::Service>()>;
void RunServiceOnIOThread(ServiceFactory factory) {
base::OnceClosure terminate_process = base::BindOnce(
base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
base::SequencedTaskRunnerHandle::Get(), FROM_HERE,
base::BindOnce([] { content::UtilityThread::Get()->ReleaseProcess(); }));
content::ChildThread::Get()->GetIOTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
[](ServiceFactory factory, base::OnceClosure terminate_process) {
service_manager::Service::RunAsyncUntilTermination(
std::move(factory).Run(), std::move(terminate_process));
},
std::move(factory), std::move(terminate_process)));
}
} // namespace
ChromeContentUtilityClient::ChromeContentUtilityClient()
: utility_process_running_elevated_(false) {
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && defined(OS_WIN)
printing_handler_ = std::make_unique<printing::PrintingHandler>();
#endif
#if defined(OS_CHROMEOS)
mash_service_factory_ = std::make_unique<MashServiceFactory>();
#endif
}
ChromeContentUtilityClient::~ChromeContentUtilityClient() = default;
void ChromeContentUtilityClient::UtilityThreadStarted() {
#if defined(OS_WIN)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
utility_process_running_elevated_ = command_line->HasSwitch(
service_manager::switches::kNoSandboxAndElevatedPrivileges);
#endif
content::ServiceManagerConnection* connection =
content::ChildThread::Get()->GetServiceManagerConnection();
// NOTE: Some utility process instances are not connected to the Service
// Manager. Nothing left to do in that case.
if (!connection)
return;
auto registry = std::make_unique<service_manager::BinderRegistry>();
// If our process runs with elevated privileges, only add elevated Mojo
// interfaces to the interface registry.
if (!utility_process_running_elevated_) {
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
// TODO(crbug.com/798782): remove when the Cloud print chrome/service is
// removed.
registry->AddInterface(
base::BindRepeating(printing::PdfToEmfConverterFactory::Create),
base::ThreadTaskRunnerHandle::Get());
#endif
}
connection->AddConnectionFilter(
std::make_unique<content::SimpleConnectionFilter>(std::move(registry)));
}
bool ChromeContentUtilityClient::OnMessageReceived(
const IPC::Message& message) {
if (utility_process_running_elevated_)
return false;
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && defined(OS_WIN)
if (printing_handler_->OnMessageReceived(message))
return true;
#endif
return false;
}
bool ChromeContentUtilityClient::HandleServiceRequest(
const std::string& service_name,
service_manager::mojom::ServiceRequest request) {
if (utility_process_running_elevated_) {
// This process is running with elevated privileges. Only handle a limited
// set of service requests in this case.
auto service = MaybeCreateElevatedService(service_name, std::move(request));
if (service) {
RunServiceAsyncThenTerminateProcess(std::move(service));
return true;
}
return false;
}
if (service_name == heap_profiling::mojom::kServiceName) {
RunServiceOnIOThread(
base::BindOnce(&CreateHeapProfilingService, std::move(request)));
return true;
}
#if !defined(OS_ANDROID)
if (service_name == proxy_resolver::mojom::kProxyResolverServiceName) {
RunServiceOnIOThread(
base::BindOnce(&CreateProxyResolverService, std::move(request)));
return true;
}
#endif // !defined(OS_ANDROID)
auto service = MaybeCreateMainThreadService(service_name, std::move(request));
if (service) {
RunServiceAsyncThenTerminateProcess(std::move(service));
return true;
}
return false;
}
std::unique_ptr<service_manager::Service>
ChromeContentUtilityClient::MaybeCreateMainThreadService(
const std::string& service_name,
service_manager::mojom::ServiceRequest request) {
if (service_name == unzip::mojom::kServiceName)
return std::make_unique<unzip::UnzipService>(std::move(request));
if (service_name == patch::mojom::kServiceName)
return std::make_unique<patch::PatchService>(std::move(request));
if (service_name == chrome::mojom::kNoopServiceName &&
chrome::IsNoopServiceEnabled()) {
return std::make_unique<chrome::NoopService>(std::move(request));
}
#if BUILDFLAG(ENABLE_PRINTING)
if (service_name == printing::mojom::kServiceName)
return printing::CreatePdfCompositorService(std::move(request));
#endif
#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE)
if (service_name == device::mojom::kVrIsolatedServiceName)
return std::make_unique<device::XrDeviceService>(std::move(request));
#endif
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) || \
(BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN))
if (service_name == printing::mojom::kChromePrintingServiceName)
return std::make_unique<printing::PrintingService>(std::move(request));
#endif
#if !defined(OS_ANDROID)
if (service_name == chrome::mojom::kProfileImportServiceName)
return std::make_unique<ProfileImportService>(std::move(request));
if (base::FeatureList::IsEnabled(mirroring::features::kMirroringService) &&
base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams) &&
base::FeatureList::IsEnabled(network::features::kNetworkService) &&
service_name == mirroring::mojom::kServiceName) {
return std::make_unique<mirroring::MirroringService>(
std::move(request), content::ChildThread::Get()->GetIOTaskRunner());
}
#endif
#if defined(OS_WIN)
if (service_name == chrome::mojom::kUtilWinServiceName)
return std::make_unique<UtilWinService>(std::move(request));
#endif
#if defined(FULL_SAFE_BROWSING) || defined(OS_CHROMEOS)
if (service_name == chrome::mojom::kFileUtilServiceName)
return std::make_unique<FileUtilService>(std::move(request));
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS) && !defined(OS_WIN)
// On Windows the service is running elevated.
if (service_name == chrome::mojom::kRemovableStorageWriterServiceName)
return std::make_unique<RemovableStorageWriterService>(std::move(request));
#endif // BUILDFLAG(ENABLE_EXTENSIONS) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_ANDROID)
if (service_name == chrome::mojom::kMediaGalleryUtilServiceName)
return std::make_unique<MediaGalleryUtilService>(std::move(request));
#endif // BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_ANDROID)
#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE_OUT_OF_PROCESS)
if (service_name == simple_browser::mojom::kServiceName) {
return std::make_unique<simple_browser::SimpleBrowserService>(
std::move(request), simple_browser::SimpleBrowserService::
UIInitializationMode::kInitializeUI);
}
#endif
#if defined(OS_CHROMEOS)
if (service_name == chromeos::ime::mojom::kServiceName)
return std::make_unique<chromeos::ime::ImeService>(std::move(request));
#if BUILDFLAG(ENABLE_PRINTING)
if (service_name == chrome::mojom::kCupsIppParserServiceName)
return std::make_unique<CupsIppParserService>(std::move(request));
#endif
#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
if (service_name == chromeos::assistant::mojom::kAudioDecoderServiceName) {
return std::make_unique<chromeos::assistant::AssistantAudioDecoderService>(
std::move(request));
}
#endif
return mash_service_factory_->HandleServiceRequest(service_name,
std::move(request));
#else // defined(OS_CHROMEOS)
return nullptr;
#endif // defined(OS_CHROMEOS)
}
std::unique_ptr<service_manager::Service>
ChromeContentUtilityClient::MaybeCreateElevatedService(
const std::string& service_name,
service_manager::mojom::ServiceRequest request) {
DCHECK(utility_process_running_elevated_);
#if defined(OS_WIN) && BUILDFLAG(ENABLE_EXTENSIONS)
if (service_name == chrome::mojom::kWifiUtilWinServiceName)
return std::make_unique<WifiUtilWinService>(std::move(request));
if (service_name == chrome::mojom::kRemovableStorageWriterServiceName)
return std::make_unique<RemovableStorageWriterService>(std::move(request));
#endif
return nullptr;
}
void ChromeContentUtilityClient::RegisterNetworkBinders(
service_manager::BinderRegistry* registry) {
if (g_network_binder_creation_callback.Get())
g_network_binder_creation_callback.Get().Run(registry);
}
// static
void ChromeContentUtilityClient::SetNetworkBinderCreationCallback(
const NetworkBinderCreationCallback& callback) {
g_network_binder_creation_callback.Get() = callback;
}