0

Revert "Reland "Move Renderer processes off Service Manager""

This reverts commit 881a65d746.

Reason for revert: breaks graphics on some Chrome OS devices.

Original change's description:
> Move Renderer processes off Service Manager
>
> Migrates Renderer processes to use the simpler ChildProcess IPC
> interface in place of deprecated Service Manager IPC.
>
> Support for preloaded files in service manifest definitions is
> effectively removed in favor of explicit parameters on
> BrowserChildProcessHost and ChildProcessLauncher. The only use case (V8
> snapshot files) has been migrated from manifest data to a simple map
> definition, and it's used during renderer and utility process
> launching.
>
> After this CL, only utility processes remain to be moved off of
> Service
> Manager IPC.
>
> NOPRESUBMIT=true
>
> Bug: 977637
> Change-Id: I1d8205cb73ead904aa21b85d6cbee11cb3fc84f5
> Tbr: boliu@chromium.org
> Tbr: yucliu@chromium.org
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1918375
> Reviewed-by: Martin Barbella <mbarbella@chromium.org>
> Reviewed-by: Robert Sesek <rsesek@chromium.org>
> Reviewed-by: Avi Drissman <avi@chromium.org>
> Commit-Queue: Ken Rockot <rockot@google.com>
> Cr-Commit-Position: refs/heads/master@{#717920}

NOPRESUBMIT=true

Bug: 1028852
Bug: 977637
Tbr: rockot@google.com
Tbr: boliu@chromium.org
Tbr: yucliu@chromium.org
Tbr: mbarbella@chromium.org
Tbr: rsesek@chromium.org
Tbr: avi@chromium.org
Change-Id: I30a52d825cc156b066d7c2ec455c8fb588a408af
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1948663
Commit-Queue: Shuhei Takahashi <nya@chromium.org>
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720939}
This commit is contained in:
Shuhei Takahashi
2019-12-03 13:35:16 +00:00
committed by Commit Bot
parent bfca6c8096
commit d10a4fc5f2
59 changed files with 915 additions and 234 deletions
android_webview/browser
chrome
chromecast/browser
content
tools/ipc_fuzzer
get_accessible_interfaces
message_replay

@@ -36,6 +36,8 @@ source_set("browser") {
"aw_content_browser_client.h",
"aw_content_browser_overlay_manifest.cc",
"aw_content_browser_overlay_manifest.h",
"aw_content_renderer_overlay_manifest.cc",
"aw_content_renderer_overlay_manifest.h",
"aw_contents.cc",
"aw_contents.h",
"aw_contents_client_bridge.cc",

@@ -1,4 +1,8 @@
per-file aw_content_renderer_overlay_manifest.cc=set noparent
per-file aw_content_renderer_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
per-file aw_content_browser_overlay_manifest.h=set noparent
per-file aw_content_browser_overlay_manifest.h=file://ipc/SECURITY_OWNERS
per-file aw_content_renderer_overlay_manifest.h=set noparent
per-file aw_content_renderer_overlay_manifest.h=file://ipc/SECURITY_OWNERS
per-file aw_content_browser_overlay_manifest.cc=set noparent
per-file aw_content_browser_overlay_manifest.cc=file://ipc/SECURITY_OWNERS

@@ -12,6 +12,7 @@
#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_browser_main_parts.h"
#include "android_webview/browser/aw_content_browser_overlay_manifest.h"
#include "android_webview/browser/aw_content_renderer_overlay_manifest.h"
#include "android_webview/browser/aw_contents.h"
#include "android_webview/browser/aw_contents_client_bridge.h"
#include "android_webview/browser/aw_contents_io_thread_client.h"
@@ -702,6 +703,8 @@ base::Optional<service_manager::Manifest>
AwContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
if (name == content::mojom::kBrowserServiceName)
return GetAWContentBrowserOverlayManifest();
if (name == content::mojom::kRendererServiceName)
return GetAWContentRendererOverlayManifest();
return base::nullopt;
}

@@ -0,0 +1,31 @@
// 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.
#include "android_webview/browser/aw_content_renderer_overlay_manifest.h"
#include "android_webview/common/js_java_interaction/interfaces.mojom.h"
#include "base/no_destructor.h"
#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "content/public/common/service_names.mojom.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
namespace android_webview {
const service_manager::Manifest& GetAWContentRendererOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest{
service_manager::ManifestBuilder()
.ExposeInterfaceFilterCapability_Deprecated(
"navigation:frame", "browser",
service_manager::Manifest::InterfaceList<
autofill::mojom::AutofillAgent,
autofill::mojom::PasswordAutofillAgent,
autofill::mojom::PasswordGenerationAgent,
safe_browsing::mojom::ThreatReporter,
mojom::JsJavaConfigurator, mojom::JsToJavaMessaging>())
.Build()};
return *manifest;
}
} // namespace android_webview

@@ -0,0 +1,19 @@
// 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.
#ifndef ANDROID_WEBVIEW_BROWSER_AW_CONTENT_RENDERER_OVERLAY_MANIFEST_H_
#define ANDROID_WEBVIEW_BROWSER_AW_CONTENT_RENDERER_OVERLAY_MANIFEST_H_
#include "services/service_manager/public/cpp/manifest.h"
namespace android_webview {
// Returns the manifest Android WebView amends to Content's content_renderer
// service manifest. This allows WebView to extend the capabilities exposed
// and/or required by content_renderer service instances.
const service_manager::Manifest& GetAWContentRendererOverlayManifest();
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_AW_CONTENT_RENDERER_OVERLAY_MANIFEST_H_

@@ -480,6 +480,47 @@ source_set("chrome_content_browser_overlay_manifest") {
}
}
source_set("chrome_content_renderer_overlay_manifest") {
sources = [
"chrome_content_renderer_overlay_manifest.cc",
"chrome_content_renderer_overlay_manifest.h",
]
deps = [
"//base",
"//base/allocator:buildflags",
"//chrome/common:mojo_bindings",
"//chrome/common:search_mojom",
"//components/autofill/content/common/mojom",
"//components/dom_distiller/content/common/mojom",
"//components/metrics/public/mojom:call_stack_mojo_bindings",
"//components/rappor/public/mojom",
"//components/safe_browsing:buildflags",
"//components/safe_browsing/common:interfaces",
"//components/services/heap_profiling/public/mojom",
"//components/subresource_filter/content/mojom",
"//extensions/buildflags",
"//services/service_manager/public/cpp",
"//third_party/blink/public/common",
]
if (is_linux) {
deps += [ "//chrome/common/performance_manager/mojom" ]
}
if (is_chromeos) {
deps += [ "//chromeos/services/network_config/public/mojom" ]
}
if (is_mac) {
deps += [ "//components/spellcheck/common:interfaces" ]
}
if (enable_extensions) {
deps += [ "//extensions/common:mojom" ]
}
}
source_set("builtin_service_manifests") {
sources = [
"builtin_service_manifests.cc",
@@ -506,5 +547,6 @@ source_set("chrome_service_manifests") {
public_deps = [
":builtin_service_manifests",
":chrome_content_browser_overlay_manifest",
":chrome_content_renderer_overlay_manifest",
]
}

@@ -66,5 +66,17 @@ specific_include_rules = {
"+services/resource_coordinator/public",
"+third_party/blink/public/mojom",
],
"chrome_content_renderer_overlay_manifest\.cc": [
"+base/allocator",
"+chrome/common/performance_manager/mojom",
"+chromeos/services/network_config/public",
"+components/autofill/content/common",
"+components/dom_distiller/content/common",
"+components/spellcheck/common",
"+components/subresource_filter/content/mojom",
"+extensions/buildflags",
"+extensions/common",
"+third_party/blink/public/mojom",
],
}

@@ -62,3 +62,7 @@ per-file chrome_content_browser_overlay_manifest.cc=set noparent
per-file chrome_content_browser_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
per-file chrome_content_browser_overlay_manifest.h=set noparent
per-file chrome_content_browser_overlay_manifest.h=file://ipc/SECURITY_OWNERS
per-file chrome_content_renderer_overlay_manifest.cc=set noparent
per-file chrome_content_renderer_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
per-file chrome_content_renderer_overlay_manifest.h=set noparent
per-file chrome_content_renderer_overlay_manifest.h=file://ipc/SECURITY_OWNERS

@@ -0,0 +1,98 @@
// Copyright 2018 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/app/chrome_content_renderer_overlay_manifest.h"
#include "base/allocator/buildflags.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "chrome/common/chrome_render_frame.mojom.h"
#include "chrome/common/content_settings_agent.mojom.h"
#include "chrome/common/prerender.mojom.h"
#include "chrome/common/search.mojom.h"
#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
#include "components/dom_distiller/content/common/mojom/distiller_page_notifier_service.mojom.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/subresource_filter/content/mojom/subresource_filter_agent.mojom.h"
#include "extensions/buildflags/buildflags.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
#include "third_party/blink/public/mojom/loader/previews_resource_loading_hints.mojom.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
#if BUILDFLAG(USE_TCMALLOC)
#include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h" // nogncheck
#endif // BUILDFLAG(USE_TCMALLOC)
#if defined(OS_ANDROID)
#include "chrome/common/sandbox_status_extension_android.mojom.h"
#include "third_party/blink/public/mojom/document_metadata/copyless_paste.mojom.h"
#endif
#if defined(OS_CHROMEOS)
#include "chromeos/services/network_config/public/mojom/constants.mojom.h" // nogncheck
#endif
#if defined(OS_MACOSX)
#include "components/spellcheck/common/spellcheck_panel.mojom.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/mojom/app_window.mojom.h"
#include "extensions/common/mojom/guest_view.mojom.h"
#endif
const service_manager::Manifest& GetChromeContentRendererOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest {
service_manager::ManifestBuilder()
.ExposeCapability("browser", service_manager::Manifest::InterfaceList<
chrome::mojom::SearchBouncer>())
.ExposeInterfaceFilterCapability_Deprecated(
"navigation:frame", "browser",
service_manager::Manifest::InterfaceList<
#if defined(OS_ANDROID)
blink::mojom::document_metadata::CopylessPaste,
chrome::mojom::SandboxStatusExtension,
#endif
autofill::mojom::AutofillAgent,
autofill::mojom::PasswordAutofillAgent,
autofill::mojom::PasswordGenerationAgent,
blink::mojom::DisplayCutoutClient,
blink::mojom::PauseSubresourceLoadingHandle,
blink::mojom::PreviewsResourceLoadingHintsReceiver,
chrome::mojom::ChromeRenderFrame,
chrome::mojom::ContentSettingsAgent,
chrome::mojom::PrerenderDispatcher,
dom_distiller::mojom::DistillerPageNotifierService,
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::mojom::AppWindow,
extensions::mojom::MimeHandlerViewContainerManager,
#endif // TODO: need gated include back
safe_browsing::mojom::ThreatReporter,
#if BUILDFLAG(FULL_SAFE_BROWSING)
safe_browsing::mojom::PhishingDetector,
#endif
#if defined(OS_MACOSX)
spellcheck::mojom::SpellCheckPanel,
#endif
#if defined(OS_LINUX)
#if BUILDFLAG(USE_TCMALLOC)
tcmalloc::mojom::TcmallocTunables,
#endif // BUILDFLAG(USE_TCMALLOC)
#endif // defined(OS_LINUX)
subresource_filter::mojom::SubresourceFilterAgent>())
#if defined(OS_CHROMEOS)
.RequireInterfaceFilterCapability_Deprecated(
"content_browser", "navigation:frame", "cellular_setup")
.RequireInterfaceFilterCapability_Deprecated(
"content_browser", "navigation:frame", "multidevice_setup")
.RequireInterfaceFilterCapability_Deprecated(
"content_browser", "navigation:frame",
chromeos::network_config::mojom::kNetworkConfigCapability)
#endif
.Build()
};
return *manifest;
}

@@ -0,0 +1,15 @@
// Copyright 2018 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.
#ifndef CHROME_APP_CHROME_CONTENT_RENDERER_OVERLAY_MANIFEST_H_
#define CHROME_APP_CHROME_CONTENT_RENDERER_OVERLAY_MANIFEST_H_
#include "services/service_manager/public/cpp/manifest.h"
// Returns the Manifest Chrome amends to Content's content_renderer service
// manifest. This allows Chrome to extend the set of capabilities exposed and/or
// required by content_renderer service instances.
const service_manager::Manifest& GetChromeContentRendererOverlayManifest();
#endif // CHROME_APP_CHROME_CONTENT_RENDERER_OVERLAY_MANIFEST_H_

@@ -37,6 +37,7 @@
#include "build/build_config.h"
#include "chrome/app/builtin_service_manifests.h"
#include "chrome/app/chrome_content_browser_overlay_manifest.h"
#include "chrome/app/chrome_content_renderer_overlay_manifest.h"
#include "chrome/browser/accessibility/accessibility_labels_service.h"
#include "chrome/browser/accessibility/accessibility_labels_service_factory.h"
#include "chrome/browser/after_startup_task_utils.h"
@@ -3714,6 +3715,8 @@ base::Optional<service_manager::Manifest>
ChromeContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
if (name == content::mojom::kBrowserServiceName)
return GetChromeContentBrowserOverlayManifest();
if (name == content::mojom::kRendererServiceName)
return GetChromeContentRendererOverlayManifest();
return base::nullopt;
}

@@ -653,6 +653,8 @@ CastContentBrowserClient::GetServiceManifestOverlay(
base::StringPiece service_name) {
if (service_name == content::mojom::kBrowserServiceName)
return GetCastContentBrowserOverlayManifest();
if (service_name == content::mojom::kRendererServiceName)
return GetCastContentRendererOverlayManifest();
return base::nullopt;
}

@@ -8,8 +8,11 @@
#include "build/build_config.h"
#include "chromecast/chromecast_buildflags.h"
#include "chromecast/common/mojom/application_media_capabilities.mojom.h"
#include "chromecast/common/mojom/feature_manager.mojom.h"
#include "chromecast/common/mojom/media_caps.mojom.h"
#include "chromecast/common/mojom/media_playback_options.mojom.h"
#include "chromecast/common/mojom/memory_pressure.mojom.h"
#include "chromecast/common/mojom/queryable_data_store.mojom.h"
#include "media/mojo/services/media_manifest.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
@@ -20,6 +23,7 @@
#if defined(USE_INTERNAL_OVERLAY_MANIFESTS)
#include "chromecast/internal/shell/browser/cast_content_browser_internal_manifest_overlay.h"
#include "chromecast/internal/shell/browser/cast_content_packaged_services_internal_manifest_overlay.h"
#include "chromecast/internal/shell/browser/cast_content_renderer_internal_manifest_overlay.h"
#endif
namespace chromecast {
@@ -44,6 +48,22 @@ const service_manager::Manifest& GetCastContentBrowserOverlayManifest() {
return *manifest;
}
const service_manager::Manifest& GetCastContentRendererOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest {
service_manager::ManifestBuilder()
.ExposeInterfaceFilterCapability_Deprecated(
"navigation:frame", "browser",
service_manager::Manifest::InterfaceList<
mojom::FeatureManager, mojom::MediaPlaybackOptions,
mojom::QueryableDataStore>())
.Build()
#if defined(USE_INTERNAL_OVERLAY_MANIFESTS)
.Amend(cast_content_renderer_internal_manifest_overlay::GetManifest())
#endif
};
return *manifest;
}
const service_manager::Manifest&
GetCastContentPackagedServicesOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest {

@@ -15,6 +15,11 @@ namespace shell {
// required by content_browser service instances.
const service_manager::Manifest& GetCastContentBrowserOverlayManifest();
// Returns the manifest Cast amends to Content's content_renderer service
// manifest. This allows Cast to extend the capabilities exposed and/or
// required by content_renderer service instances.
const service_manager::Manifest& GetCastContentRendererOverlayManifest();
// Returns the manifest Cast amends to Content's content_packaged_services
// service manifest. This allows Cast to extend the set of in- and out-of-
// process services packaged by the browser.

@@ -104,7 +104,6 @@ jumbo_source_set("browser") {
"//content/common:mojo_bindings",
"//content/public/app:service_manifests",
"//content/public/common:common_sources",
"//content/public/common:content_descriptor_keys",
"//crypto",
"//device/base",
"//device/bluetooth",
@@ -1813,8 +1812,6 @@ jumbo_source_set("browser") {
"utility_process_host.cc",
"utility_process_host.h",
"utility_process_host_receiver_bindings.cc",
"v8_snapshot_files.cc",
"v8_snapshot_files.h",
"video_capture_service.cc",
"wake_lock/wake_lock_context_host.cc",
"wake_lock/wake_lock_context_host.h",

@@ -276,20 +276,10 @@ void BrowserChildProcessHostImpl::Launch(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
bool terminate_on_shutdown) {
LaunchWithPreloadedFiles(std::move(delegate), std::move(cmd_line),
/*files_to_preload=*/{}, terminate_on_shutdown);
}
void BrowserChildProcessHostImpl::LaunchWithPreloadedFiles(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown) {
GetContentClient()->browser()->AppendExtraCommandLineSwitches(cmd_line.get(),
data_.id);
LaunchWithoutExtraCommandLineSwitches(
std::move(delegate), std::move(cmd_line), std::move(files_to_preload),
terminate_on_shutdown);
std::move(delegate), std::move(cmd_line), terminate_on_shutdown);
}
const ChildProcessData& BrowserChildProcessHostImpl::GetData() {
@@ -354,7 +344,6 @@ void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
void BrowserChildProcessHostImpl::LaunchWithoutExtraCommandLineSwitches(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const base::CommandLine& browser_command_line =
@@ -404,7 +393,7 @@ void BrowserChildProcessHostImpl::LaunchWithoutExtraCommandLineSwitches(
base::BindRepeating(&BrowserChildProcessHostImpl::OnMojoError,
weak_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get()),
std::move(files_to_preload), terminate_on_shutdown));
terminate_on_shutdown));
ShareMetricsAllocatorToProcess();
}

@@ -88,11 +88,6 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
void Launch(std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
bool terminate_on_shutdown) override;
void LaunchWithPreloadedFiles(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown) override;
const ChildProcessData& GetData() override;
ChildProcessHost* GetHost() override;
ChildProcessTerminationInfo GetTerminationInfo(bool known_dead) override;
@@ -132,7 +127,6 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
void LaunchWithoutExtraCommandLineSwitches(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown);
static void HistogramBadMessageTerminated(ProcessType process_type);

@@ -8,6 +8,7 @@
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "content/public/app/content_browser_manifest.h"
#include "content/public/app/content_renderer_manifest.h"
#include "content/public/app/content_utility_manifest.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -42,6 +43,7 @@ const std::vector<service_manager::Manifest>& GetBuiltinServiceManifests() {
// browser process, but the distinction between "in-process" and
// "out-of-process" manifests is temporary. For now, this is the right
// place for these manifests.
GetContentRendererManifest(),
GetContentUtilityManifest(),
audio::GetManifest(IsAudioServiceOutOfProcess()

@@ -36,7 +36,6 @@ ChildProcessLauncher::ChildProcessLauncher(
Client* client,
mojo::OutgoingInvitation mojo_invitation,
const mojo::ProcessErrorCallback& process_error_callback,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown)
: client_(client),
starting_(true),
@@ -57,8 +56,7 @@ ChildProcessLauncher::ChildProcessLauncher(
#if defined(OS_ANDROID)
client_->CanUseWarmUpConnection(),
#endif
std::move(mojo_invitation), process_error_callback,
std::move(files_to_preload));
std::move(mojo_invitation), process_error_callback);
helper_->StartLaunchOnClientThread();
}
@@ -158,6 +156,19 @@ bool ChildProcessLauncher::TerminateProcess(const base::Process& process,
return ChildProcessLauncherHelper::TerminateProcess(process, exit_code);
}
// static
void ChildProcessLauncher::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
ChildProcessLauncherHelper::SetRegisteredFilesForService(
service_name, std::move(required_files));
}
// static
void ChildProcessLauncher::ResetRegisteredFilesForTesting() {
ChildProcessLauncherHelper::ResetRegisteredFilesForTesting();
}
#if defined(OS_ANDROID)
void ChildProcessLauncher::DumpProcessStack() {
base::Process to_pass = process_.process.Duplicate();

@@ -164,12 +164,6 @@ class CONTENT_EXPORT ChildProcessLauncher {
// If |process_error_callback| is provided, it will be called if a Mojo error
// is encountered when processing messages from the child process. This
// callback must be safe to call from any thread.
//
// |files_to_preload| is a map of key names to file paths. These files will be
// opened by the browser process and corresponding file descriptors inherited
// by the new child process, accessible using the corresponding key via some
// platform-specific mechanism (such as base::FileDescriptorStore on POSIX).
// Currently only supported on POSIX platforms.
ChildProcessLauncher(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
@@ -177,7 +171,6 @@ class CONTENT_EXPORT ChildProcessLauncher {
Client* client,
mojo::OutgoingInvitation mojo_invitation,
const mojo::ProcessErrorCallback& process_error_callback,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown = true);
~ChildProcessLauncher();
@@ -216,6 +209,16 @@ class CONTENT_EXPORT ChildProcessLauncher {
// previous client.
Client* ReplaceClientForTest(Client* client);
// Sets the files that should be mapped when a new child process is created
// for the service |service_name|.
static void SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files);
// Resets all files registered by |SetRegisteredFilesForService|. Used to
// support multiple shell context creation in unit_tests.
static void ResetRegisteredFilesForTesting();
#if defined(OS_ANDROID)
// Dumps the stack of the child process without crashing it.
void DumpProcessStack();

@@ -75,8 +75,7 @@ ChildProcessLauncherHelper::ChildProcessLauncherHelper(
bool can_use_warm_up_connection,
#endif
mojo::OutgoingInvitation mojo_invitation,
const mojo::ProcessErrorCallback& process_error_callback,
std::map<std::string, base::FilePath> files_to_preload)
const mojo::ProcessErrorCallback& process_error_callback)
: child_process_id_(child_process_id),
client_task_runner_(base::SequencedTaskRunnerHandle::Get()),
command_line_(std::move(command_line)),
@@ -84,8 +83,7 @@ ChildProcessLauncherHelper::ChildProcessLauncherHelper(
child_process_launcher_(child_process_launcher),
terminate_on_shutdown_(terminate_on_shutdown),
mojo_invitation_(std::move(mojo_invitation)),
process_error_callback_(process_error_callback),
files_to_preload_(std::move(files_to_preload))
process_error_callback_(process_error_callback)
#if defined(OS_ANDROID)
,
can_use_warm_up_connection_(can_use_warm_up_connection)

@@ -102,8 +102,7 @@ class ChildProcessLauncherHelper :
bool is_pre_warmup_required,
#endif
mojo::OutgoingInvitation mojo_invitation,
const mojo::ProcessErrorCallback& process_error_callback,
std::map<std::string, base::FilePath> files_to_preload);
const mojo::ProcessErrorCallback& process_error_callback);
// The methods below are defined in the order they are called.
@@ -184,6 +183,12 @@ class ChildProcessLauncherHelper :
base::Process process,
const ChildProcessLauncherPriority& priority);
static void SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files);
static void ResetRegisteredFilesForTesting();
#if defined(OS_ANDROID)
void OnChildProcessStarted(JNIEnv* env,
jint handle);
@@ -236,7 +241,6 @@ class ChildProcessLauncherHelper :
bool terminate_on_shutdown_;
mojo::OutgoingInvitation mojo_invitation_;
const mojo::ProcessErrorCallback process_error_callback_;
const std::map<std::string, base::FilePath> files_to_preload_;
#if defined(OS_MACOSX)
std::unique_ptr<sandbox::SeatbeltExecClient> seatbelt_exec_client_;

@@ -74,9 +74,10 @@ ChildProcessLauncherHelper::GetFilesToMap() {
CHECK(!command_line()->HasSwitch(switches::kSingleProcess));
std::unique_ptr<PosixFileDescriptorInfo> files_to_register =
CreateDefaultPosixFilesToMap(
child_process_id(), mojo_channel_->remote_endpoint(),
files_to_preload_, GetProcessType(), command_line());
CreateDefaultPosixFilesToMap(child_process_id(),
mojo_channel_->remote_endpoint(),
true /* include_service_required_files */,
GetProcessType(), command_line());
#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
base::MemoryMappedFile::Region icu_region;
@@ -241,6 +242,18 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
priority.boost_for_pending_views, static_cast<jint>(priority.importance));
}
// static
void ChildProcessLauncherHelper::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
SetFilesToShareForServicePosix(service_name, std::move(required_files));
}
// static
void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {
ResetFilesToShareForTestingPosix();
}
// static
base::File OpenFileToShare(const base::FilePath& path,
base::MemoryMappedFile::Region* region) {

@@ -63,6 +63,17 @@ bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
return process.Terminate(exit_code, false);
}
// static
void ChildProcessLauncherHelper::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
NOTREACHED() << " for service " << service_name;
}
// static
void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {
}
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK(client_task_runner_->RunsTasksInCurrentSequence());

@@ -37,9 +37,10 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
std::unique_ptr<FileMappedForLaunch>
ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
return CreateDefaultPosixFilesToMap(
child_process_id(), mojo_channel_->remote_endpoint(), files_to_preload_,
GetProcessType(), command_line());
return CreateDefaultPosixFilesToMap(child_process_id(),
mojo_channel_->remote_endpoint(),
true /* include_service_required_files */,
GetProcessType(), command_line());
}
bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
@@ -160,6 +161,18 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
process.SetProcessBackgrounded(priority.is_background());
}
// static
void ChildProcessLauncherHelper::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
SetFilesToShareForServicePosix(service_name, std::move(required_files));
}
// static
void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {
ResetFilesToShareForTestingPosix();
}
// static
base::File OpenFileToShare(const base::FilePath& path,
base::MemoryMappedFile::Region* region) {

@@ -46,7 +46,8 @@ ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
return CreateDefaultPosixFilesToMap(
child_process_id(), mojo_channel_->remote_endpoint(),
/*files_to_preload=*/{}, GetProcessType(), command_line());
false /* include_service_required_files */, GetProcessType(),
command_line());
}
bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
@@ -173,6 +174,17 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
}
}
// static
void ChildProcessLauncherHelper::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
// No file passing from the manifest on Mac yet.
DCHECK(required_files.empty());
}
// static
void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {}
// static
base::File OpenFileToShare(const base::FilePath& path,
base::MemoryMappedFile::Region* region) {

@@ -24,6 +24,30 @@ namespace internal {
namespace {
using RequiredFilesByServiceMap =
std::map<std::string, std::map<std::string, base::FilePath>>;
RequiredFilesByServiceMap& GetRequiredFilesByServiceMap() {
static auto* required_files_by_service = new RequiredFilesByServiceMap();
return *required_files_by_service;
}
std::map<std::string, std::string>& GetServiceNameByProcessTypeMap() {
static auto* service_name_resolver = new std::map<std::string, std::string>(
{// The service names are defined in the JSON manifests, so we don't have
// a constant accessible for them.
// TODO(jcivelli): remove this map once the service name is accessible
// from the command line crbug.com/687250
{switches::kGpuProcess, "content_gpu"},
{switches::kPpapiPluginProcess, "content_plugin"},
{switches::kRendererProcess, "content_renderer"},
{switches::kUtilityProcess, "content_utility"},
{"ppapi-broker", "ppapi_broker"},
{"nacl-loader", "nacl_loader"},
{"nacl-loader-nonsfi", "nacl_loader_nonsfi"}});
return *service_name_resolver;
}
base::PlatformFile OpenFileIfNecessary(const base::FilePath& path,
base::MemoryMappedFile::Region* region) {
static auto* opened_files = new std::map<
@@ -50,7 +74,7 @@ base::PlatformFile OpenFileIfNecessary(const base::FilePath& path,
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
const mojo::PlatformChannelEndpoint& mojo_channel_remote_endpoint,
std::map<std::string, base::FilePath> files_to_preload,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line) {
std::unique_ptr<PosixFileDescriptorInfo> files_to_register(
@@ -73,27 +97,60 @@ std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
*command_line, child_process_id, files_to_register.get());
#endif
// Also include the files specified explicitly by |files_to_preload|.
base::GlobalDescriptors::Key key = kContentDynamicDescriptorStart;
service_manager::SharedFileSwitchValueBuilder file_switch_value_builder;
for (const auto& key_path_iter : files_to_preload) {
base::MemoryMappedFile::Region region;
base::PlatformFile file =
OpenFileIfNecessary(key_path_iter.second, &region);
if (file == base::kInvalidPlatformFile) {
DLOG(WARNING) << "Ignoring invalid file " << key_path_iter.second.value();
continue;
if (!include_service_required_files)
return files_to_register;
// Also include the files specified in the services' manifests.
auto service_name_iter = GetServiceNameByProcessTypeMap().find(process_type);
DCHECK(service_name_iter != GetServiceNameByProcessTypeMap().end())
<< "No service found for process type " << process_type;
const std::string& service_name = service_name_iter->second;
auto files_iter = GetRequiredFilesByServiceMap().find(service_name);
if (files_iter != GetRequiredFilesByServiceMap().end()) {
const std::map<std::string, base::FilePath>& required_files_map =
files_iter->second;
base::GlobalDescriptors::Key key = kContentDynamicDescriptorStart;
service_manager::SharedFileSwitchValueBuilder file_switch_value_builder;
for (const auto& key_path_iter : required_files_map) {
base::MemoryMappedFile::Region region;
base::PlatformFile file =
OpenFileIfNecessary(key_path_iter.second, &region);
if (file == base::kInvalidPlatformFile) {
DLOG(WARNING) << "Ignoring invalid file "
<< key_path_iter.second.value();
continue;
}
file_switch_value_builder.AddEntry(key_path_iter.first, key);
files_to_register->ShareWithRegion(key, file, region);
key++;
DCHECK(key < kContentDynamicDescriptorMax);
}
file_switch_value_builder.AddEntry(key_path_iter.first, key);
files_to_register->ShareWithRegion(key, file, region);
key++;
DCHECK(key < kContentDynamicDescriptorMax);
command_line->AppendSwitchASCII(service_manager::switches::kSharedFiles,
file_switch_value_builder.switch_value());
}
command_line->AppendSwitchASCII(service_manager::switches::kSharedFiles,
file_switch_value_builder.switch_value());
return files_to_register;
}
void SetFilesToShareForServicePosix(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
if (required_files.empty())
return;
if (!base::StartsWith(service_name, "content_",
base::CompareCase::INSENSITIVE_ASCII)) {
// Not a content child service, ignore.
return;
}
DCHECK(GetRequiredFilesByServiceMap().count(service_name) == 0);
GetRequiredFilesByServiceMap()[service_name] = std::move(required_files);
}
void ResetFilesToShareForTestingPosix() {
GetRequiredFilesByServiceMap().clear();
}
} // namespace internal
} // namespace content

@@ -32,10 +32,19 @@ namespace internal {
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
const mojo::PlatformChannelEndpoint& mojo_channel_remote_endpoint,
std::map<std::string, base::FilePath> files_to_preload,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line);
// Called by the service manager to register the files that should be mapped for
// a service in the child process.
void SetFilesToShareForServicePosix(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files);
// Called from unit_tests in order to reset all previously registered files.
void ResetFilesToShareForTestingPosix();
// Opens the file in read mode at the given path. Note that the path should be
// relative and the way it is resolved is platform specific.
// |region| is set to the region of the file that should be read.

@@ -118,5 +118,16 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
process.SetProcessBackgrounded(priority.is_background());
}
// static
void ChildProcessLauncherHelper::SetRegisteredFilesForService(
const std::string& service_name,
std::map<std::string, base::FilePath> required_files) {
// No file passing from the manifest on Windows yet.
DCHECK(required_files.empty());
}
// static
void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {}
} // namespace internal
} // namespace content

@@ -1116,8 +1116,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
// AppendExtraCommandLineSwitches will be called again in process_->Launch(),
// Call LaunchWithoutExtraCommandLineSwitches() so the command line switches
// will not be appended twice.
process_->LaunchWithoutExtraCommandLineSwitches(
std::move(delegate), std::move(cmd_line), /*files_to_preload=*/{}, true);
process_->LaunchWithoutExtraCommandLineSwitches(std::move(delegate),
std::move(cmd_line), true);
process_launched_ = true;
if (kind_ == GPU_PROCESS_KIND_SANDBOXED) {

@@ -139,7 +139,6 @@
#include "content/browser/storage_partition_impl.h"
#include "content/browser/theme_helper.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/v8_snapshot_files.h"
#include "content/browser/websockets/websocket_connector_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/child_process.mojom.h"
@@ -148,6 +147,7 @@
#include "content/common/frame_messages.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/resource_messages.h"
#include "content/common/service_manager/child_connection.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/view_messages.h"
@@ -1685,7 +1685,7 @@ bool RenderProcessHostImpl::Init() {
in_process_renderer_.reset(g_renderer_main_thread_factory(
InProcessChildThreadParams(
base::CreateSingleThreadTaskRunner({BrowserThread::IO}),
&mojo_invitation_),
&mojo_invitation_, child_connection_->service_token()),
base::checked_cast<int32_t>(id_)));
base::Thread::Options options;
@@ -1725,8 +1725,7 @@ bool RenderProcessHostImpl::Init() {
child_process_launcher_ = std::make_unique<ChildProcessLauncher>(
std::make_unique<RendererSandboxedProcessLauncherDelegate>(),
std::move(cmd_line), GetID(), this, std::move(mojo_invitation_),
base::BindRepeating(&RenderProcessHostImpl::OnMojoError, id_),
GetV8SnapshotFilesToPreload());
base::BindRepeating(&RenderProcessHostImpl::OnMojoError, id_));
channel_->Pause();
// In single process mode, browser-side tracing and memory will cover the
@@ -1754,23 +1753,50 @@ void RenderProcessHostImpl::InitializeChannelProxy() {
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
base::CreateSingleThreadTaskRunner({BrowserThread::IO});
// Establish a ChildProcess interface connection to the new renderer. This is
// connected as the primordial message pipe via a Mojo invitation to the
// process.
mojo_invitation_ = {};
child_process_.reset();
child_process_.Bind(mojo::PendingRemote<mojom::ChildProcess>(
mojo_invitation_.AttachMessagePipe(0), /*version=*/0));
// Acquire a Connector which will route connections to a new instance of the
// renderer service.
service_manager::Connector* connector =
BrowserContext::GetConnectorFor(browser_context_);
if (!connector) {
// Note that some embedders (e.g. Android WebView) may not initialize a
// Connector per BrowserContext. In those cases we fall back to the
// browser-wide Connector.
connector = GetSystemConnector();
if (!connector && !ServiceManagerConnection::GetForProcess()) {
// Additionally, some test code may not initialize the system Connector.
// We initialize one that the ChildConnection below can use.
// TODO(crbug.com/904240): Figure out why some unit tests fail when this
// doesn't create a full ServiceManagerConnection.
service_manager::mojom::ServicePtr unused_service;
ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
mojo::MakeRequest(&unused_service), io_task_runner));
connector = ServiceManagerConnection::GetForProcess()->GetConnector();
}
}
// Bootstrap the IPC Channel.
mojo::PendingRemote<IPC::mojom::ChannelBootstrap> bootstrap;
child_process_->BootstrapLegacyIpc(
bootstrap.InitWithNewPipeAndPassReceiver());
// Establish a ServiceManager connection for the new render service instance.
mojo_invitation_ = {};
child_connection_ = std::make_unique<ChildConnection>(
service_manager::Identity(
mojom::kRendererServiceName,
BrowserContext::GetServiceInstanceGroupFor(GetBrowserContext()),
base::Token::CreateRandom(), base::Token::CreateRandom()),
&mojo_invitation_, connector, io_task_runner);
// Send an interface request to bootstrap the IPC::Channel. Note that this
// request will happily sit on the pipe until the process is launched and
// connected to the ServiceManager. We take the other end immediately and
// plug it into a new ChannelProxy.
mojo::MessagePipe pipe;
BindInterface(IPC::mojom::ChannelBootstrap::Name_, std::move(pipe.handle1));
std::unique_ptr<IPC::ChannelFactory> channel_factory =
IPC::ChannelMojo::CreateServerFactory(
bootstrap.PassPipe(), io_task_runner,
std::move(pipe.handle0), io_task_runner,
base::ThreadTaskRunnerHandle::Get());
child_process_.reset();
content::BindInterface(this, child_process_.BindNewPipeAndPassReceiver());
ResetChannelProxy();
// Do NOT expand ifdef or run time condition checks here! Synchronous
@@ -2453,11 +2479,26 @@ int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
void RenderProcessHostImpl::BindInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
child_connection_->BindInterface(interface_name, std::move(interface_pipe));
}
void RenderProcessHostImpl::BindReceiver(
mojo::GenericPendingReceiver receiver) {
child_process_->BindReceiver(std::move(receiver));
}
const service_manager::Identity& RenderProcessHostImpl::GetChildIdentity() {
// GetChildIdentity should only be called if the RPH is (or soon will be)
// backed by an actual renderer process. This helps prevent leaks similar to
// the ones raised in https://crbug.com/813045.
DCHECK(IsInitializedAndNotDead());
return child_connection_->child_identity();
}
std::unique_ptr<base::PersistentMemoryAllocator>
RenderProcessHostImpl::TakeMetricsAllocator() {
return std::move(metrics_allocator_);
@@ -3020,6 +3061,9 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
AppendCompositorCommandLineFlags(command_line);
command_line->AppendSwitchASCII(
service_manager::switches::kServiceRequestChannelToken,
child_connection_->service_token());
command_line->AppendSwitchASCII(switches::kRendererClientId,
std::to_string(GetID()));
@@ -3944,6 +3988,18 @@ RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
return GetAllHosts().Lookup(render_process_id);
}
// static
RenderProcessHost* RenderProcessHost::FromRendererInstanceId(
const base::Token& instance_id) {
for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
RenderProcessHost* process = i.GetCurrentValue();
if (process->GetChildIdentity().instance_id() == instance_id)
return process;
}
return nullptr;
}
// static
bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
BrowserContext* browser_context,
@@ -4625,6 +4681,11 @@ void RenderProcessHostImpl::OnProcessLaunched() {
// preempt already queued messages.
channel_->Unpause(false /* flush */);
if (child_connection_) {
child_connection_->SetProcess(
child_process_launcher_->GetProcess().Duplicate());
}
if (coordinator_connector_receiver_.is_bound())
coordinator_connector_receiver_.Resume();

@@ -47,6 +47,7 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/service_manager_connection.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_platform_file.h"
#include "media/media_buildflags.h"
@@ -66,6 +67,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/tracing/public/mojom/traced_process.mojom.h"
#include "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom.h"
#include "services/viz/public/mojom/gpu.mojom.h"
@@ -102,6 +104,7 @@ class GpuClient;
namespace content {
class AgentMetricsCollectorHost;
class BrowserPluginMessageFilter;
class ChildConnection;
class CodeCacheHostImpl;
class FileSystemManagerImpl;
class IndexedDBDispatcherHost;
@@ -227,7 +230,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
const WebRtcRtpPacketCallback& packet_callback) override;
void EnableWebRtcEventLogOutput(int lid, int output_period_ms) override;
void DisableWebRtcEventLogOutput(int lid) override;
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
void BindReceiver(mojo::GenericPendingReceiver receiver) override;
const service_manager::Identity& GetChildIdentity() override;
std::unique_ptr<base::PersistentMemoryAllocator> TakeMetricsAllocator()
override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() override;
@@ -914,6 +920,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
mojo::OutgoingInvitation mojo_invitation_;
std::unique_ptr<ChildConnection> child_connection_;
size_t keep_alive_ref_count_;
// Set in DisableKeepAliveRefCount(). When true, |keep_alive_ref_count_| must

@@ -217,7 +217,8 @@ class RenderWidgetHostInputEventRouterTest : public testing::Test {
// connected on the other end, as we really don't want it to respond
// anyways.
mojo::Remote<viz::mojom::InputTargetClient> input_target_client;
ignore_result(input_target_client.BindNewPipeAndPassReceiver());
service_manager::InterfaceProvider().GetInterface(
input_target_client.BindNewPipeAndPassReceiver());
widget_host_root_->SetInputTargetClient(std::move(input_target_client));
EXPECT_EQ(view_root_.get(),

@@ -530,6 +530,13 @@ ServiceManagerContext::ServiceManagerContext(
manifest.service_name);
if (overlay)
manifest.Amend(*overlay);
if (!manifest.preloaded_files.empty()) {
std::map<std::string, base::FilePath> preloaded_files_map;
for (const auto& info : manifest.preloaded_files)
preloaded_files_map.emplace(info.key, info.path);
ChildProcessLauncher::SetRegisteredFilesForService(
manifest.service_name, std::move(preloaded_files_map));
}
}
for (auto& extra_manifest :
GetContentClient()->browser()->GetExtraServiceManifests()) {

@@ -20,7 +20,6 @@
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/v8_snapshot_files.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/service_manager/child_connection.h"
@@ -459,8 +458,7 @@ bool UtilityProcessHost::StartProcess() {
std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
sandbox_type_, env_, *cmd_line);
process_->LaunchWithPreloadedFiles(std::move(delegate), std::move(cmd_line),
GetV8SnapshotFilesToPreload(), true);
process_->Launch(std::move(delegate), std::move(cmd_line), true);
}
return true;

@@ -1,46 +0,0 @@
// 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.
#include "content/browser/v8_snapshot_files.h"
#include "build/build_config.h"
#include "content/public/common/content_descriptor_keys.h"
namespace content {
std::map<std::string, base::FilePath> GetV8SnapshotFilesToPreload() {
#if defined(OS_LINUX)
#if defined(USE_V8_CONTEXT_SNAPSHOT)
return {{kV8ContextSnapshotDataDescriptor,
base::FilePath(FILE_PATH_LITERAL("v8_context_snapshot.bin"))}};
#else
return {{kV8SnapshotDataDescriptor,
base::FilePath(FILE_PATH_LITERAL("snapshot_blob.bin"))}};
#endif
#elif defined(OS_ANDROID)
#if defined(USE_V8_CONTEXT_SNAPSHOT)
#if defined(ARCH_CPU_64_BITS)
return {
{kV8Snapshot64DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/v8_context_snapshot_64.bin"))}};
#else
return {
{kV8Snapshot32DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/v8_context_snapshot_32.bin"))}};
#endif
#else
#if defined(ARCH_CPU_64_BITS)
return {{kV8Snapshot64DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/snapshot_blob_64.bin"))}};
#else
return {{kV8Snapshot32DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/snapshot_blob_32.bin"))}};
#endif
#endif
#else
return {};
#endif
}
} // namespace content

@@ -1,25 +0,0 @@
// 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.
#ifndef CONTENT_BROWSER_V8_SNAPSHOT_FILES_H_
#define CONTENT_BROWSER_V8_SNAPSHOT_FILES_H_
#include <map>
#include <string>
#include "base/files/file_path.h"
namespace content {
// Returns a mapping of V8 snapshot files to be preloaded for child processes
// that use V8. Note that this is defined on all platforms even though it may
// be empty or unused on some.
//
// This mapping can be passed to
// |BrowserChildProcessHost::LaunchWithPreloadedFiles()|.
std::map<std::string, base::FilePath> GetV8SnapshotFilesToPreload();
} // namespace content
#endif // CONTENT_BROWSER_V8_SNAPSHOT_FILES_H_

@@ -33,10 +33,7 @@ source_set("common") {
# In addition, targets outside of the content component (shell and tests)
# must not link to this because it will duplicate the code in the component
# build.
visibility = [
"//content/*",
"//tools/ipc_fuzzer/message_replay:ipc_fuzzer_replay",
]
visibility = [ "//content/*" ]
sources = [
"accessibility_messages.h",

@@ -182,6 +182,7 @@ source_set("content_browser_manifest") {
]
deps = [
":v8_snapshot_overlay_manifest",
"//base",
"//content/public/common:service_names",
"//services/content/public/cpp:manifest",
@@ -192,6 +193,23 @@ source_set("content_browser_manifest") {
]
}
source_set("content_renderer_manifest") {
sources = [
"content_renderer_manifest.cc",
"content_renderer_manifest.h",
]
deps = [
":v8_snapshot_overlay_manifest",
"//base",
"//content/public/common:service_names",
]
public_deps = [
"//services/service_manager/public/cpp",
]
}
source_set("content_utility_manifest") {
sources = [
"content_utility_manifest.cc",
@@ -199,6 +217,7 @@ source_set("content_utility_manifest") {
]
deps = [
":v8_snapshot_overlay_manifest",
"//base",
"//content/public/common:service_names",
]
@@ -208,9 +227,28 @@ source_set("content_utility_manifest") {
]
}
source_set("v8_snapshot_overlay_manifest") {
sources = [
"v8_snapshot_overlay_manifest.cc",
"v8_snapshot_overlay_manifest.h",
]
deps = [
"//base",
"//content/public/common:content_descriptor_keys",
]
public_deps = [
"//services/service_manager/public/cpp",
]
configs += [ "//tools/v8_context_snapshot:use_v8_context_snapshot" ]
}
group("service_manifests") {
public_deps = [
":content_browser_manifest",
":content_renderer_manifest",
":content_utility_manifest",
]
}

@@ -6,8 +6,17 @@ per-file content_browser_manifest.cc=file://ipc/SECURITY_OWNERS
per-file content_browser_manifest.h=set noparent
per-file content_browser_manifest.h=file://ipc/SECURITY_OWNERS
per-file content_renderer_manifest.cc=set noparent
per-file content_renderer_manifest.cc=file://ipc/SECURITY_OWNERS
per-file content_renderer_manifest.h=set noparent
per-file content_renderer_manifest.h=file://ipc/SECURITY_OWNERS
per-file content_utility_manifest.cc=set noparent
per-file content_utility_manifest.cc=file://ipc/SECURITY_OWNERS
per-file content_utility_manifest.h=set noparent
per-file content_utility_manifest.h=file://ipc/SECURITY_OWNERS
per-file v8_snapshot_overlay_manifest.cc=set noparent
per-file v8_snapshot_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
per-file v8_snapshot_overlay_manifest.h=set noparent
per-file v8_snapshot_overlay_manifest.h=file://ipc/SECURITY_OWNERS

@@ -121,6 +121,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
.RequireCapability("file", "file:leveldb")
.RequireCapability("network", "network_service")
.RequireCapability("network", "test")
.RequireCapability(mojom::kRendererServiceName, "browser")
.RequireCapability("media", "media:media")
.RequireCapability("media_renderer", "media:media")
.RequireCapability("*", "app")
@@ -187,6 +188,8 @@ const service_manager::Manifest& GetContentBrowserManifest() {
"content.mojom.RendererAudioOutputStreamFactory",
"discardable_memory.mojom.DiscardableSharedMemoryManager",
"viz.mojom.Gpu"})
.RequireInterfaceFilterCapability_Deprecated(
mojom::kRendererServiceName, "navigation:frame", "browser")
.PackageService(content::GetManifest())
.Build()};
return *manifest;

@@ -0,0 +1,86 @@
// 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.
#include "content/public/app/content_renderer_manifest.h"
#include "base/no_destructor.h"
#include "content/public/app/v8_snapshot_overlay_manifest.h"
#include "content/public/common/service_names.mojom.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
namespace content {
const service_manager::Manifest& GetContentRendererManifest() {
static base::NoDestructor<service_manager::Manifest> manifest{
service_manager::ManifestBuilder()
.WithServiceName(mojom::kRendererServiceName)
.WithDisplayName("Content (renderer process)")
.ExposeCapability(
"browser",
std::set<const char*>{
"blink.mojom.CodeCacheHost",
"blink.mojom.CrashMemoryMetricsReporter",
"blink.mojom.EmbeddedWorkerInstanceClient",
"blink.mojom.LeakDetector",
"blink.mojom.OomIntervention",
"blink.mojom.PeerConnectionManager",
"blink.mojom.SharedWorkerFactory",
"blink.mojom.WebDatabase",
"content.mojom.Child",
"content.mojom.ChildHistogramFetcher",
"content.mojom.ChildHistogramFetcherFactory",
"content.mojom.ChildProcess",
"content.mojom.FrameFactory",
"content.mojom.MhtmlFileWriter",
"content.mojom.RenderWidgetWindowTreeClientFactory",
"content.mojom.ResourceUsageReporter",
"IPC.mojom.ChannelBootstrap",
"visitedlink.mojom.VisitedLinkNotificationSink",
"web_cache.mojom.WebCache",
})
.RequireCapability("font_service", "font_service")
.RequireCapability("*", "app")
.RequireCapability("metrics", "url_keyed_metrics")
.RequireCapability("ui", "discardable_memory")
.RequireCapability("ui", "gpu_client")
.RequireCapability("device", "device:hid")
.RequireCapability("device", "device:power_monitor")
.RequireCapability("device", "device:screen_orientation")
.RequireCapability("device", "device:time_zone_monitor")
.RequireCapability(mojom::kBrowserServiceName, "dwrite_font_proxy")
.RequireCapability(mojom::kSystemServiceName, "dwrite_font_proxy")
.RequireCapability(mojom::kSystemServiceName, "field_trials")
.RequireCapability(mojom::kBrowserServiceName, "renderer")
.RequireCapability(mojom::kSystemServiceName, "renderer")
.RequireCapability(mojom::kSystemServiceName, "sandbox_support")
.RequireInterfaceFilterCapability_Deprecated(
mojom::kBrowserServiceName, "navigation:shared_worker",
"renderer")
.RequireInterfaceFilterCapability_Deprecated(
mojom::kBrowserServiceName, "navigation:dedicated_worker",
"renderer")
.RequireInterfaceFilterCapability_Deprecated(
mojom::kBrowserServiceName, "navigation:service_worker",
"renderer")
.ExposeInterfaceFilterCapability_Deprecated(
"navigation:frame", "browser",
std::set<const char*>{
"blink.mojom.AppBannerController",
"blink.mojom.EngagementClient", "blink.mojom.ImageDownloader",
"blink.mojom.InstallationService",
"blink.mojom.ManifestManager",
"blink.mojom.MediaStreamDeviceObserver",
"blink.mojom.TextSuggestionBackend",
"blink.mojom.WebLaunchService",
"content.mojom.FrameInputHandler",
"content.mojom.FullscreenVideoElementHandler",
"content.mojom.Widget", "viz.mojom.InputTargetClient"})
.RequireInterfaceFilterCapability_Deprecated(
mojom::kBrowserServiceName, "navigation:frame", "renderer")
.Build()
.Amend(GetV8SnapshotOverlayManifest())};
return *manifest;
}
} // namespace content

@@ -0,0 +1,20 @@
// 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.
#ifndef CONTENT_PUBLIC_APP_CONTENT_RENDERER_MANIFEST_H_
#define CONTENT_PUBLIC_APP_CONTENT_RENDERER_MANIFEST_H_
#include "services/service_manager/public/cpp/manifest.h"
namespace content {
// Returns the service manifest for the "content_renderer" service. Every
// renderer process is an instance of this service, so this manifest determines
// what capabilities are directly exposed and required by renderer processes
// through the Service Manager.
const service_manager::Manifest& GetContentRendererManifest();
} // namespace content
#endif // CONTENT_PUBLIC_APP_CONTENT_RENDERER_MANIFEST_H_

@@ -5,6 +5,7 @@
#include "content/public/app/content_utility_manifest.h"
#include "base/no_destructor.h"
#include "content/public/app/v8_snapshot_overlay_manifest.h"
#include "content/public/common/service_names.mojom.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
@@ -34,7 +35,8 @@ const service_manager::Manifest& GetContentUtilityManifest() {
.RequireCapability(mojom::kSystemServiceName, "sandbox_support")
.RequireCapability("*", "app")
.RequireCapability("font_service", "font_service")
.Build()};
.Build()
.Amend(GetV8SnapshotOverlayManifest())};
return *manifest;
}

@@ -0,0 +1,55 @@
// 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.
#include "content/public/app/v8_snapshot_overlay_manifest.h"
#include "base/files/file_path.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "content/public/common/content_descriptor_keys.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
namespace content {
const service_manager::Manifest& GetV8SnapshotOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest {
service_manager::ManifestBuilder()
#if defined(OS_LINUX)
#if defined(USE_V8_CONTEXT_SNAPSHOT)
.PreloadFile(
kV8ContextSnapshotDataDescriptor,
base::FilePath(FILE_PATH_LITERAL("v8_context_snapshot.bin")))
#else
.PreloadFile(kV8SnapshotDataDescriptor,
base::FilePath(FILE_PATH_LITERAL("snapshot_blob.bin")))
#endif // defined(USE_V8_CONTEXT_SNAPSHOT)
#elif defined(OS_ANDROID)
#if defined(USE_V8_CONTEXT_SNAPSHOT)
#if defined(ARCH_CPU_64_BITS)
.PreloadFile(kV8Snapshot64DataDescriptor,
base::FilePath(FILE_PATH_LITERAL(
"assets/v8_context_snapshot_64.bin")))
#else
.PreloadFile(kV8Snapshot32DataDescriptor,
base::FilePath(FILE_PATH_LITERAL(
"assets/v8_context_snapshot_32.bin")))
#endif
#else
#if defined(ARCH_CPU_64_BITS)
.PreloadFile(
kV8Snapshot64DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/snapshot_blob_64.bin")))
#else
.PreloadFile(
kV8Snapshot32DataDescriptor,
base::FilePath(FILE_PATH_LITERAL("assets/snapshot_blob_32.bin")))
#endif
#endif // defined(USE_V8_CONTEXT_SNAPSHOT)
#endif
.Build()
};
return *manifest;
}
} // namespace content

@@ -0,0 +1,19 @@
// 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.
#ifndef CONTENT_PUBLIC_APP_V8_SNAPSHOT_OVERLAY_MANIFEST_H_
#define CONTENT_PUBLIC_APP_V8_SNAPSHOT_OVERLAY_MANIFEST_H_
#include "services/service_manager/public/cpp/manifest.h"
namespace content {
// Returns a service manifest overlay that should be amended to the manifest of
// any service which initializes V8. This gives the service access to preloaded
// snapshot files on startup.
const service_manager::Manifest& GetV8SnapshotOverlayManifest();
} // namespace content
#endif // CONTENT_PUBLIC_APP_V8_SNAPSHOT_OVERLAY_MANIFEST_H_

@@ -5,9 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_CHILD_PROCESS_HOST_H_
#define CONTENT_PUBLIC_BROWSER_BROWSER_CHILD_PROCESS_HOST_H_
#include <map>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/environment.h"
@@ -63,16 +61,6 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
std::unique_ptr<base::CommandLine> cmd_line,
bool terminate_on_shutdown) = 0;
// Same as above, but the process is launched with preloaded files from
// |files_to_preload| opened by the browser and passed as corresponding file
// descriptors in the child process. |files_to_preload| is currently ignored
// on platforms other than Linux and Android.
virtual void LaunchWithPreloadedFiles(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> cmd_line,
std::map<std::string, base::FilePath> files_to_preload,
bool terminate_on_shutdown) = 0;
virtual const ChildProcessData& GetData() = 0;
// Returns the ChildProcessHost object used by this object.

@@ -56,6 +56,10 @@ class TimeDelta;
class Token;
}
namespace service_manager {
class Identity;
}
namespace url {
class Origin;
}
@@ -346,6 +350,12 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual void EnableWebRtcEventLogOutput(int lid, int output_period_ms) = 0;
virtual void DisableWebRtcEventLogOutput(int lid) = 0;
// Binds interfaces exposed to the browser process from the renderer.
//
// DEPRECATED: Use |BindReceiver()| instead.
virtual void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) = 0;
// Asks the renderer process to bind |receiver|. |receiver| arrives in the
// renderer process and is carried through the following flow, stopping if any
// step decides to bind it:
@@ -356,6 +366,9 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// 4. Possibly more stpes, depending on the ChildThreadImpl subclass.
virtual void BindReceiver(mojo::GenericPendingReceiver receiver) = 0;
// Can only be called when IsInitializedAndNotDead() is true.
virtual const service_manager::Identity& GetChildIdentity() = 0;
// Extracts any persistent-memory-allocator used for renderer metrics.
// Ownership is passed to the caller. To support sharing of histogram data
// between the Renderer and the Browser, the allocator is created when the

@@ -19,6 +19,10 @@ const string kBrowserServiceName = "content_browser";
// instance which packages other browser-wide services.
const string kPackagedServicesServiceName = "content_packaged_services";
// The default service name used to identify render processes when connecting
// them to the Service Manager.
const string kRendererServiceName = "content_renderer";
// The default service name used to identify utility processes when connecting
// them to the Service Manager.
const string kUtilityServiceName = "content_utility";

@@ -16,6 +16,7 @@
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/token.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -34,6 +35,8 @@
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "content/test/not_implemented_network_url_loader_factory.h"
#include "media/media_buildflags.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -65,6 +68,11 @@ MockRenderProcessHost::MockRenderProcessHost(BrowserContext* browser_context)
is_unused_(true),
keep_alive_ref_count_(0),
foreground_service_worker_count_(0),
child_identity_(
mojom::kRendererServiceName,
BrowserContext::GetServiceInstanceGroupFor(browser_context),
base::Token::CreateRandom(),
base::Token::CreateRandom()),
url_loader_factory_(nullptr) {
// Child process security operations can't be unit tested unless we add
// ourselves as an existing child process.
@@ -337,6 +345,14 @@ base::TimeDelta MockRenderProcessHost::GetChildProcessIdleTime() {
return base::TimeDelta::FromMilliseconds(0);
}
void MockRenderProcessHost::BindInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
auto it = binder_overrides_.find(interface_name);
if (it != binder_overrides_.end())
it->second.Run(std::move(interface_pipe));
}
void MockRenderProcessHost::BindReceiver(
mojo::GenericPendingReceiver receiver) {
auto it = binder_overrides_.find(*receiver.interface_name());
@@ -344,6 +360,10 @@ void MockRenderProcessHost::BindReceiver(
it->second.Run(receiver.PassPipe());
}
const service_manager::Identity& MockRenderProcessHost::GetChildIdentity() {
return child_identity_;
}
std::unique_ptr<base::PersistentMemoryAllocator>
MockRenderProcessHost::TakeMetricsAllocator() {
return nullptr;

@@ -29,6 +29,8 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/network_isolation_key.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#if defined(OS_ANDROID)
#include "content/public/browser/android/child_process_importance.h"
@@ -141,7 +143,10 @@ class MockRenderProcessHost : public RenderProcessHost {
const WebRtcRtpPacketCallback& packet_callback) override;
void EnableWebRtcEventLogOutput(int lid, int output_period_ms) override;
void DisableWebRtcEventLogOutput(int lid) override;
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
void BindReceiver(mojo::GenericPendingReceiver receiver) override;
const service_manager::Identity& GetChildIdentity() override;
std::unique_ptr<base::PersistentMemoryAllocator> TakeMetricsAllocator()
override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() override;
@@ -283,6 +288,7 @@ class MockRenderProcessHost : public RenderProcessHost {
int foreground_service_worker_count_;
std::unique_ptr<mojo::AssociatedRemote<mojom::Renderer>> renderer_interface_;
std::map<std::string, InterfaceBinder> binder_overrides_;
service_manager::Identity child_identity_;
bool is_renderer_locked_to_site_ = false;
network::mojom::URLLoaderFactory* url_loader_factory_;
mojo::PendingReceiver<blink::mojom::CacheStorage> cache_storage_receiver_;

@@ -20,6 +20,7 @@ TestServiceManagerContext::TestServiceManagerContext() {
}
TestServiceManagerContext::~TestServiceManagerContext() {
ChildProcessLauncher::ResetRegisteredFilesForTesting();
ServiceManagerConnection::DestroyForProcess();
}

@@ -28,25 +28,33 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/app/mojo/mojo_init.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/service_manager/child_connection.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/child_process_host_delegate.h"
#include "content/public/browser/system_connector.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_content_client_initializer.h"
#include "content/public/test/test_launcher.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/renderer/render_process_impl.h"
#include "content/test/mock_render_process.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/config/gpu_switches.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel_mojo.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/system/invitation.h"
#include "services/service_manager/public/cpp/constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -144,8 +152,7 @@ class QuitOnTestMsgFilter : public IPC::MessageFilter {
base::OnceClosure quit_closure_;
};
class RenderThreadImplBrowserTest : public testing::Test,
public ChildProcessHostDelegate {
class RenderThreadImplBrowserTest : public testing::Test {
public:
RenderThreadImplBrowserTest() {}
@@ -159,9 +166,26 @@ class RenderThreadImplBrowserTest : public testing::Test,
base::CreateSingleThreadTaskRunner({BrowserThread::IO});
InitializeMojo();
process_host_ =
ChildProcessHost::Create(this, ChildProcessHost::IpcMode::kNormal);
process_host_->CreateChannelMojo();
mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
io_task_runner, mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
shell_context_.reset(new TestServiceManagerContext);
mojo::OutgoingInvitation invitation;
child_connection_ = std::make_unique<ChildConnection>(
service_manager::Identity(mojom::kRendererServiceName,
service_manager::kSystemInstanceGroup,
base::Token{}, base::Token::CreateRandom()),
&invitation, GetSystemConnector(), io_task_runner);
mojo::MessagePipe pipe;
child_connection_->BindInterface(IPC::mojom::ChannelBootstrap::Name_,
std::move(pipe.handle1));
channel_ = IPC::ChannelProxy::Create(
IPC::ChannelMojo::CreateServerFactory(
std::move(pipe.handle0), io_task_runner,
blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
nullptr, io_task_runner,
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
mock_process_.reset(new MockRenderProcess);
test_task_counter_ = base::MakeRefCounted<TestTaskCounter>();
@@ -187,8 +211,8 @@ class RenderThreadImplBrowserTest : public testing::Test,
base::FieldTrialList::CreateTrialsFromCommandLine(
*cmd, switches::kFieldTrialHandle, -1);
thread_ = new RenderThreadImpl(
InProcessChildThreadParams(io_task_runner,
&process_host_->GetMojoInvitation().value()),
InProcessChildThreadParams(io_task_runner, &invitation,
child_connection_->service_token()),
/*renderer_client_id=*/1, std::move(main_thread_scheduler));
cmd->InitFromArgv(old_argv);
@@ -213,12 +237,8 @@ class RenderThreadImplBrowserTest : public testing::Test,
}
}
// ChildProcessHostDelegate implementation:
bool OnMessageReceived(const IPC::Message&) override { return true; }
const base::Process& GetProcess() override { return null_process_; }
protected:
IPC::Sender* sender() { return process_host_.get(); }
IPC::Sender* sender() { return channel_.get(); }
void SetBackgroundState(
mojom::RenderProcessBackgroundState background_state) {
@@ -246,8 +266,10 @@ class RenderThreadImplBrowserTest : public testing::Test,
std::unique_ptr<ContentRendererClient> content_renderer_client_;
std::unique_ptr<BrowserTaskEnvironment> browser_threads_;
const base::Process null_process_;
std::unique_ptr<ChildProcessHost> process_host_;
std::unique_ptr<TestServiceManagerContext> shell_context_;
std::unique_ptr<ChildConnection> child_connection_;
std::unique_ptr<IPC::ChannelProxy> channel_;
std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
std::unique_ptr<MockRenderProcess> mock_process_;
scoped_refptr<QuitOnTestMsgFilter> test_msg_filter_;

@@ -163,6 +163,20 @@ const service_manager::Manifest& GetContentBrowserOverlayManifest() {
return *manifest;
}
const service_manager::Manifest& GetContentRendererOverlayManifest() {
static base::NoDestructor<service_manager::Manifest> manifest{
service_manager::ManifestBuilder()
.ExposeCapability(
"browser",
service_manager::Manifest::InterfaceList<mojom::PowerMonitorTest,
mojom::TestService>())
.ExposeInterfaceFilterCapability_Deprecated(
"navigation:frame", "browser",
service_manager::Manifest::InterfaceList<mojom::WebTestControl>())
.Build()};
return *manifest;
}
} // namespace
std::string GetShellUserAgent() {
@@ -285,6 +299,8 @@ base::Optional<service_manager::Manifest>
ShellContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
if (name == content::mojom::kBrowserServiceName)
return GetContentBrowserOverlayManifest();
if (name == content::mojom::kRendererServiceName)
return GetContentRendererOverlayManifest();
return base::nullopt;
}

@@ -6,7 +6,6 @@ executable("get_accessible_interfaces") {
deps = [
"//base",
"//chrome/app:chrome_service_manifests",
"//chrome/common",
"//content/public/app:service_manifests",
]
}

@@ -6,13 +6,11 @@ executable("ipc_fuzzer_replay") {
testonly = true
configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
deps = [
"//content/common",
"//mojo/core/embedder",
"//tools/ipc_fuzzer/message_lib:ipc_message_lib",
]
public_deps = [
"//ipc",
"//mojo/public/cpp/bindings",
]
sources = [
"replay.cc",

@@ -1,6 +1,5 @@
include_rules = [
"+chrome/common",
"+content/common",
"+content/public/common",
"+mojo/core/embedder",
"+mojo/public",

@@ -17,17 +17,14 @@
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "content/common/child_process.mojom-test-utils.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel_mojo.h"
#include "mojo/core/embedder/configuration.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "mojo/public/cpp/system/invitation.h"
@@ -39,39 +36,30 @@
#endif
namespace ipc_fuzzer {
namespace {
// Used to simulate a basic child process IPC endpoint and bootstrap the legacy
// IPC channel driven by this process.
class FakeChildProcessImpl
: public content::mojom::ChildProcessInterceptorForTesting {
class IPCChannelBootstrapper : public content::ConnectionFilter {
public:
explicit FakeChildProcessImpl(
mojo::PendingRemote<IPC::mojom::ChannelBootstrap> legacy_ipc_bootstrap)
: legacy_ipc_bootstrap_(std::move(legacy_ipc_bootstrap)) {
ignore_result(disconnected_process_.BindNewPipeAndPassReceiver());
}
// content::mojom::ChildProcessInterceptorForTesting overrides:
content::mojom::ChildProcess* GetForwardingInterface() override {
return disconnected_process_.get();
}
void Initialize(mojo::PendingRemote<content::mojom::ChildProcessHostBootstrap>
bootstrap) override {
bootstrap_.Bind(std::move(bootstrap));
}
void BootstrapLegacyIpc(
mojo::PendingReceiver<IPC::mojom::ChannelBootstrap> receiver) override {
mojo::FusePipes(std::move(receiver), std::move(legacy_ipc_bootstrap_));
}
explicit IPCChannelBootstrapper(
mojo::ScopedMessagePipeHandle bootstrap_handle)
: bootstrap_handle_(std::move(bootstrap_handle)) {}
private:
mojo::PendingRemote<IPC::mojom::ChannelBootstrap> legacy_ipc_bootstrap_;
mojo::Remote<content::mojom::ChildProcessHostBootstrap> bootstrap_;
mojo::Remote<content::mojom::ChildProcess> disconnected_process_;
void OnBindInterface(const service_manager::BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe,
service_manager::Connector* connector) override {
if (interface_name != IPC::mojom::ChannelBootstrap::Name_)
return;
DCHECK(bootstrap_handle_.is_valid());
mojo::FuseMessagePipes(std::move(*interface_pipe),
std::move(bootstrap_handle_));
}
mojo::ScopedMessagePipeHandle bootstrap_handle_;
DISALLOW_COPY_AND_ASSIGN(IPCChannelBootstrapper);
};
} // namespace
@@ -152,15 +140,19 @@ bool ReplayProcess::Initialize(int argc, const char** argv) {
void ReplayProcess::OpenChannel() {
DCHECK(mojo_invitation_);
mojo::PendingRemote<IPC::mojom::ChannelBootstrap> bootstrap;
auto bootstrap_receiver = bootstrap.InitWithNewPipeAndPassReceiver();
mojo::MakeSelfOwnedReceiver(
std::make_unique<FakeChildProcessImpl>(std::move(bootstrap)),
mojo::PendingReceiver<content::mojom::ChildProcess>(
mojo_invitation_->ExtractMessagePipe(0)));
service_manager_connection_ = content::ServiceManagerConnection::Create(
service_manager::mojom::ServiceRequest(
mojo_invitation_->ExtractMessagePipe(
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
service_manager::switches::kServiceRequestChannelToken))),
io_thread_.task_runner());
mojo::MessagePipe ipc_pipe;
service_manager_connection_->AddConnectionFilter(
std::make_unique<IPCChannelBootstrapper>(std::move(ipc_pipe.handle0)));
service_manager_connection_->Start();
channel_ = IPC::ChannelProxy::Create(
IPC::ChannelMojo::CreateClientFactory(
bootstrap_receiver.PassPipe(), io_thread_.task_runner(),
std::move(ipc_pipe.handle1), io_thread_.task_runner(),
base::ThreadTaskRunnerHandle::Get()),
this, io_thread_.task_runner(), base::ThreadTaskRunnerHandle::Get());
}

@@ -19,6 +19,10 @@
#include "ipc/ipc_message.h"
#include "tools/ipc_fuzzer/message_lib/message_file.h"
namespace content {
class ServiceManagerConnection;
}
namespace mojo {
class IncomingInvitation;
namespace core {
@@ -56,6 +60,8 @@ class ReplayProcess : public IPC::Listener {
std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
std::unique_ptr<mojo::IncomingInvitation> mojo_invitation_;
std::unique_ptr<content::ServiceManagerConnection>
service_manager_connection_;
std::unique_ptr<IPC::ChannelProxy> channel_;
base::SingleThreadTaskExecutor main_task_executor_;
base::Thread io_thread_;