blob: 1e013333a9f040790e9720625fb07334929f33e4 [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/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/file_patcher.mojom.h"
#include "chrome/common/safe_browsing/zip_analyzer.h"
#include "chrome/common/safe_browsing/zip_analyzer_results.h"
#include "chrome/utility/utility_message_handler.h"
#include "components/safe_json/utility/safe_json_parser_mojo_impl.h"
#include "content/public/child/image_decoder_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_info.h"
#include "content/public/utility/utility_thread.h"
#include "courgette/courgette.h"
#include "courgette/third_party/bsdiff/bsdiff.h"
#include "extensions/features/features.h"
#include "ipc/ipc_channel.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "printing/features/features.h"
#include "services/image_decoder/image_decoder_service.h"
#include "services/image_decoder/public/interfaces/constants.mojom.h"
#include "services/service_manager/public/cpp/interface_registry.h"
#include "third_party/zlib/google/zip.h"
#include "ui/gfx/geometry/size.h"
#if !defined(OS_ANDROID)
#include "chrome/common/resource_usage_reporter.mojom.h"
#include "chrome/utility/profile_import_handler.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
#include "net/proxy/proxy_resolver_v8.h"
#endif
#if defined(OS_CHROMEOS)
#include "chrome/common/zip_file_creator.mojom.h"
#endif
#if defined(OS_WIN)
#include "chrome/utility/ipc_shell_handler_win.h"
#include "chrome/utility/shell_handler_impl_win.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/utility/extensions/extensions_handler.h"
#endif
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) || \
(BUILDFLAG(ENABLE_BASIC_PRINTING) && defined(OS_WIN))
#include "chrome/utility/printing_handler.h"
#endif
#if defined(OS_MACOSX) && defined(FULL_SAFE_BROWSING)
#include "chrome/utility/safe_browsing/mac/dmg_analyzer.h"
#endif
namespace {
class FilePatcherImpl : public chrome::mojom::FilePatcher {
public:
FilePatcherImpl() = default;
~FilePatcherImpl() override = default;
static void Create(chrome::mojom::FilePatcherRequest request) {
mojo::MakeStrongBinding(base::MakeUnique<FilePatcherImpl>(),
std::move(request));
}
private:
// chrome::mojom::FilePatcher:
void PatchFileBsdiff(base::File input_file,
base::File patch_file,
base::File output_file,
const PatchFileBsdiffCallback& callback) override {
const int patch_result_status = bsdiff::ApplyBinaryPatch(
std::move(input_file), std::move(patch_file), std::move(output_file));
callback.Run(patch_result_status);
}
void PatchFileCourgette(base::File input_file,
base::File patch_file,
base::File output_file,
const PatchFileCourgetteCallback& callback) override {
const int patch_result_status = courgette::ApplyEnsemblePatch(
std::move(input_file), std::move(patch_file), std::move(output_file));
callback.Run(patch_result_status);
}
DISALLOW_COPY_AND_ASSIGN(FilePatcherImpl);
};
#if defined(OS_CHROMEOS)
class ZipFileCreatorImpl : public chrome::mojom::ZipFileCreator {
public:
ZipFileCreatorImpl() = default;
~ZipFileCreatorImpl() override = default;
static void Create(chrome::mojom::ZipFileCreatorRequest request) {
mojo::MakeStrongBinding(base::MakeUnique<ZipFileCreatorImpl>(),
std::move(request));
}
private:
// chrome::mojom::ZipFileCreator:
void CreateZipFile(const base::FilePath& source_dir,
const std::vector<base::FilePath>& source_relative_paths,
base::File zip_file,
const CreateZipFileCallback& callback) override {
DCHECK(zip_file.IsValid());
for (const auto& path : source_relative_paths) {
if (path.IsAbsolute() || path.ReferencesParent()) {
callback.Run(false);
return;
}
}
callback.Run(zip::ZipFiles(source_dir, source_relative_paths,
zip_file.GetPlatformFile()));
}
DISALLOW_COPY_AND_ASSIGN(ZipFileCreatorImpl);
};
#endif // defined(OS_CHROMEOS)
#if !defined(OS_ANDROID)
void CreateProxyResolverFactory(
net::interfaces::ProxyResolverFactoryRequest request) {
mojo::MakeStrongBinding(base::MakeUnique<net::MojoProxyResolverFactoryImpl>(),
std::move(request));
}
class ResourceUsageReporterImpl : public chrome::mojom::ResourceUsageReporter {
public:
ResourceUsageReporterImpl() {}
~ResourceUsageReporterImpl() override {}
private:
void GetUsageData(const GetUsageDataCallback& callback) override {
chrome::mojom::ResourceUsageDataPtr data =
chrome::mojom::ResourceUsageData::New();
size_t total_heap_size = net::ProxyResolverV8::GetTotalHeapSize();
if (total_heap_size) {
data->reports_v8_stats = true;
data->v8_bytes_allocated = total_heap_size;
data->v8_bytes_used = net::ProxyResolverV8::GetUsedHeapSize();
}
callback.Run(std::move(data));
}
DISALLOW_COPY_AND_ASSIGN(ResourceUsageReporterImpl);
};
void CreateResourceUsageReporter(
mojo::InterfaceRequest<chrome::mojom::ResourceUsageReporter> request) {
mojo::MakeStrongBinding(base::MakeUnique<ResourceUsageReporterImpl>(),
std::move(request));
}
#endif // !defined(OS_ANDROID)
std::unique_ptr<service_manager::Service> CreateImageDecoderService() {
content::UtilityThread::Get()->EnsureBlinkInitialized();
return image_decoder::ImageDecoderService::Create();
}
} // namespace
ChromeContentUtilityClient::ChromeContentUtilityClient()
: utility_process_running_elevated_(false) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
handlers_.push_back(new extensions::ExtensionsHandler());
#endif
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) || \
(BUILDFLAG(ENABLE_BASIC_PRINTING) && defined(OS_WIN))
handlers_.push_back(new printing::PrintingHandler());
#endif
#if defined(OS_WIN)
handlers_.push_back(new IPCShellHandler());
#endif
}
ChromeContentUtilityClient::~ChromeContentUtilityClient() = default;
void ChromeContentUtilityClient::UtilityThreadStarted() {
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::UtilityHandler::UtilityThreadStarted();
#endif
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUtilityProcessRunningElevated))
utility_process_running_elevated_ = true;
}
bool ChromeContentUtilityClient::OnMessageReceived(
const IPC::Message& message) {
if (utility_process_running_elevated_)
return false;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient, message)
#if defined(FULL_SAFE_BROWSING)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
OnAnalyzeZipFileForDownloadProtection)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeDmgFileForDownloadProtection,
OnAnalyzeDmgFileForDownloadProtection)
#endif // defined(OS_MACOSX)
#endif // defined(FULL_SAFE_BROWSING)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
if (handled)
return true;
for (auto* handler : handlers_) {
if (handler->OnMessageReceived(message))
return true;
}
return false;
}
void ChromeContentUtilityClient::ExposeInterfacesToBrowser(
service_manager::InterfaceRegistry* registry) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::ExtensionsHandler::ExposeInterfacesToBrowser(
registry, utility_process_running_elevated_);
#endif
// If our process runs with elevated privileges, only add elevated Mojo
// services to the interface registry.
if (utility_process_running_elevated_)
return;
registry->AddInterface(base::Bind(&FilePatcherImpl::Create));
#if !defined(OS_ANDROID)
registry->AddInterface<net::interfaces::ProxyResolverFactory>(
base::Bind(CreateProxyResolverFactory));
registry->AddInterface(base::Bind(CreateResourceUsageReporter));
registry->AddInterface(base::Bind(&ProfileImportHandler::Create));
#endif
registry->AddInterface(
base::Bind(&safe_json::SafeJsonParserMojoImpl::Create));
#if defined(OS_WIN)
registry->AddInterface(base::Bind(&ShellHandlerImpl::Create));
#endif
#if defined(OS_CHROMEOS)
registry->AddInterface(base::Bind(&ZipFileCreatorImpl::Create));
#endif
}
void ChromeContentUtilityClient::RegisterServices(StaticServiceMap* services) {
content::ServiceInfo image_decoder_info;
image_decoder_info.factory = base::Bind(&CreateImageDecoderService);
services->insert(
std::make_pair(image_decoder::mojom::kServiceName, image_decoder_info));
}
// static
void ChromeContentUtilityClient::PreSandboxStartup() {
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::ExtensionsHandler::PreSandboxStartup();
#endif
}
#if defined(FULL_SAFE_BROWSING)
void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
const IPC::PlatformFileForTransit& zip_file,
const IPC::PlatformFileForTransit& temp_file) {
safe_browsing::zip_analyzer::Results results;
safe_browsing::zip_analyzer::AnalyzeZipFile(
IPC::PlatformFileForTransitToFile(zip_file),
IPC::PlatformFileForTransitToFile(temp_file), &results);
content::UtilityThread::Get()->Send(
new ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished(
results));
content::UtilityThread::Get()->ReleaseProcessIfNeeded();
}
#if defined(OS_MACOSX)
void ChromeContentUtilityClient::OnAnalyzeDmgFileForDownloadProtection(
const IPC::PlatformFileForTransit& dmg_file) {
safe_browsing::zip_analyzer::Results results;
safe_browsing::dmg::AnalyzeDMGFile(
IPC::PlatformFileForTransitToFile(dmg_file), &results);
content::UtilityThread::Get()->Send(
new ChromeUtilityHostMsg_AnalyzeDmgFileForDownloadProtection_Finished(
results));
content::UtilityThread::Get()->ReleaseProcessIfNeeded();
}
#endif // defined(OS_MACOSX)
#endif // defined(FULL_SAFE_BROWSING)