blob: 0722387942326790983601268b0324e6219cc508 [file] [log] [blame]
[email protected]02798a982012-01-27 00:45:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d27893f62010-07-03 05:47:422// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4c01d4992012-01-23 23:33:015#include "content/browser/browser_child_process_host_impl.h"
[email protected]d27893f62010-07-03 05:47:426
[email protected]2b065f82012-10-18 07:11:167#include "base/base_switches.h"
[email protected]4306c3792011-12-02 01:57:538#include "base/bind.h"
[email protected]d27893f62010-07-03 05:47:429#include "base/command_line.h"
Yuzhu Shen32fcad72017-09-14 23:12:3710#include "base/debug/crash_logging.h"
wfhaf32d0b2015-04-07 02:21:3611#include "base/debug/dump_without_crashing.h"
erikchen55edbff2016-05-03 23:53:1712#include "base/feature_list.h"
[email protected]57999812013-02-24 05:40:5213#include "base/files/file_path.h"
[email protected]d3c6c0d72010-12-09 08:15:0414#include "base/lazy_instance.h"
[email protected]d27893f62010-07-03 05:47:4215#include "base/logging.h"
avib7348942015-12-25 20:57:1016#include "base/macros.h"
erikchen55edbff2016-05-03 23:53:1717#include "base/metrics/field_trial.h"
Ilya Sherman1c811db2017-12-14 10:36:1818#include "base/metrics/histogram_functions.h"
asvitkine30330812016-08-30 04:01:0819#include "base/metrics/histogram_macros.h"
bcwhiteb58a5fe2016-08-22 16:25:5620#include "base/metrics/persistent_histogram_allocator.h"
21#include "base/metrics/persistent_memory_allocator.h"
[email protected]7286e3fc2011-07-19 22:13:2422#include "base/stl_util.h"
[email protected]10994d132013-06-11 07:16:1823#include "base/strings/string_util.h"
rockotda9887902016-08-19 20:46:4224#include "base/strings/stringprintf.h"
[email protected]162a9fd2013-03-06 20:47:4925#include "base/synchronization/waitable_event.h"
rockot229fb28e2016-06-16 04:46:1626#include "base/threading/thread_task_runner_handle.h"
avib7348942015-12-25 20:57:1027#include "build/build_config.h"
Ehsan Chiniforooshandef633e02018-04-24 02:05:0228#include "components/tracing/common/trace_startup_config.h"
primianoccb26c62016-06-01 21:50:0229#include "components/tracing/common/tracing_switches.h"
Robert Sesek1419427e2017-12-07 15:01:3230#include "content/browser/bad_message.h"
Ehsan Chiniforooshanf192e8a22018-03-27 03:18:2031#include "content/browser/browser_main_loop.h"
Nicholas Verne91bf4a632017-10-12 21:14:2432#include "content/browser/histogram_controller.h"
[email protected]678c0362012-12-05 08:02:4433#include "content/browser/loader/resource_message_filter.h"
benff461632016-10-06 14:27:3334#include "content/browser/service_manager/service_manager_context.h"
[email protected]3a85b1f2013-02-01 04:47:4035#include "content/browser/tracing/trace_message_filter.h"
[email protected]4734d0b2011-12-03 07:10:4436#include "content/common/child_process_host_impl.h"
bend32292b2016-10-07 00:21:5837#include "content/common/service_manager/child_connection.h"
[email protected]4967f792012-01-20 22:14:4038#include "content/public/browser/browser_child_process_host_delegate.h"
[email protected]f4eaf7b92013-02-28 22:00:4039#include "content/public/browser/browser_child_process_observer.h"
[email protected]57999812013-02-24 05:40:5240#include "content/public/browser/browser_thread.h"
[email protected]4306c3792011-12-02 01:57:5341#include "content/public/browser/child_process_data.h"
[email protected]87f3c082011-10-19 18:07:4442#include "content/public/browser/content_browser_client.h"
ke.he19b5e6a2016-10-27 08:47:0943#include "content/public/common/connection_filter.h"
lawrencewu2c930822016-10-13 13:54:2544#include "content/public/common/content_features.h"
[email protected]c08950d22011-10-13 22:20:2945#include "content/public/common/content_switches.h"
[email protected]f3b357692013-03-22 05:16:1346#include "content/public/common/process_type.h"
[email protected]b39ef1cb2011-10-25 04:46:5547#include "content/public/common/result_codes.h"
jcivelli828cd7f2017-01-18 19:50:4648#include "content/public/common/sandboxed_process_launcher_delegate.h"
ke.he19b5e6a2016-10-27 08:47:0949#include "content/public/common/service_manager_connection.h"
rockotc637caf9b2016-02-10 09:57:0850#include "mojo/edk/embedder/embedder.h"
Nicholas Verne91bf4a632017-10-12 21:14:2451#include "mojo/public/cpp/system/platform_handle.h"
ochang6a8400e2017-05-01 21:28:2452#include "services/service_manager/embedder/switches.h"
[email protected]d27893f62010-07-03 05:47:4253
[email protected]f1675202012-07-09 15:18:0054#if defined(OS_MACOSX)
[email protected]458433c2012-02-29 23:43:3955#include "content/browser/mach_broker_mac.h"
[email protected]3838ca12011-11-02 14:37:1556#endif
[email protected]a3a7e2c2011-09-16 23:07:0557
[email protected]130757672012-10-24 00:26:1958namespace content {
[email protected]d27893f62010-07-03 05:47:4259namespace {
60
scottmg5e65e3a2017-03-08 08:48:4661static base::LazyInstance<
62 BrowserChildProcessHostImpl::BrowserChildProcessList>::DestructorAtExit
[email protected]4967f792012-01-20 22:14:4063 g_child_process_list = LAZY_INSTANCE_INITIALIZER;
[email protected]d27893f62010-07-03 05:47:4264
scottmg5e65e3a2017-03-08 08:48:4665base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>>::
Daniel Bratellbfcfe222017-10-17 17:57:0066 DestructorAtExit g_browser_child_process_observers =
67 LAZY_INSTANCE_INITIALIZER;
[email protected]f4eaf7b92013-02-28 22:00:4068
afakhry9cc79002015-10-22 19:25:1569void NotifyProcessLaunchedAndConnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0070 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3171 observer.BrowserChildProcessLaunchedAndConnected(data);
afakhry9cc79002015-10-22 19:25:1572}
73
[email protected]f4eaf7b92013-02-28 22:00:4074void NotifyProcessHostConnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0075 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3176 observer.BrowserChildProcessHostConnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4077}
78
79void NotifyProcessHostDisconnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0080 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3181 observer.BrowserChildProcessHostDisconnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4082}
83
Bo Liue9624612018-04-28 00:39:0884#if !defined(OS_ANDROID)
Bo Liu2a489402018-04-24 23:41:2785void NotifyProcessCrashed(const ChildProcessData& data,
86 const ChildProcessTerminationInfo& info) {
Daniel Bratellbfcfe222017-10-17 17:57:0087 for (auto& observer : g_browser_child_process_observers.Get())
Bo Liu2a489402018-04-24 23:41:2788 observer.BrowserChildProcessCrashed(data, info);
[email protected]4306c3792011-12-02 01:57:5389}
Bo Liue9624612018-04-28 00:39:0890#endif
[email protected]d27893f62010-07-03 05:47:4291
Bo Liu2a489402018-04-24 23:41:2792void NotifyProcessKilled(const ChildProcessData& data,
93 const ChildProcessTerminationInfo& info) {
Daniel Bratellbfcfe222017-10-17 17:57:0094 for (auto& observer : g_browser_child_process_observers.Get())
Bo Liu2a489402018-04-24 23:41:2795 observer.BrowserChildProcessKilled(data, info);
wfhf0003292015-08-18 22:16:4696}
97
[email protected]d27893f62010-07-03 05:47:4298} // namespace
99
[email protected]4967f792012-01-20 22:14:40100BrowserChildProcessHost* BrowserChildProcessHost::Create(
vadimt379d7fe2015-04-01 00:09:35101 content::ProcessType process_type,
[email protected]4967f792012-01-20 22:14:40102 BrowserChildProcessHostDelegate* delegate) {
rockotda9887902016-08-19 20:46:42103 return Create(process_type, delegate, std::string());
amistry6ad1e812016-06-06 05:36:30104}
105
106BrowserChildProcessHost* BrowserChildProcessHost::Create(
107 content::ProcessType process_type,
108 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:42109 const std::string& service_name) {
110 return new BrowserChildProcessHostImpl(process_type, delegate, service_name);
[email protected]4967f792012-01-20 22:14:40111}
112
amistryfaa231a42015-05-20 01:49:12113BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) {
114 DCHECK_CURRENTLY_ON(BrowserThread::IO);
115 BrowserChildProcessHostImpl::BrowserChildProcessList* process_list =
116 g_child_process_list.Pointer();
117 for (BrowserChildProcessHostImpl* host : *process_list) {
118 if (host->GetData().id == child_process_id)
119 return host;
120 }
121 return nullptr;
122}
123
[email protected]458433c2012-02-29 23:43:39124#if defined(OS_MACOSX)
erikchencd3e0e7b2015-10-01 22:53:51125base::PortProvider* BrowserChildProcessHost::GetPortProvider() {
[email protected]458433c2012-02-29 23:43:39126 return MachBroker::GetInstance();
127}
128#endif
129
[email protected]f4eaf7b92013-02-28 22:00:40130// static
[email protected]4c01d4992012-01-23 23:33:01131BrowserChildProcessHostImpl::BrowserChildProcessList*
132 BrowserChildProcessHostImpl::GetIterator() {
[email protected]4967f792012-01-20 22:14:40133 return g_child_process_list.Pointer();
134}
135
[email protected]f4eaf7b92013-02-28 22:00:40136// static
137void BrowserChildProcessHostImpl::AddObserver(
138 BrowserChildProcessObserver* observer) {
mostynbfbcdc27a2015-03-13 17:58:52139 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Daniel Bratellbfcfe222017-10-17 17:57:00140 g_browser_child_process_observers.Get().AddObserver(observer);
[email protected]f4eaf7b92013-02-28 22:00:40141}
142
143// static
144void BrowserChildProcessHostImpl::RemoveObserver(
145 BrowserChildProcessObserver* observer) {
146 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126.
Daniel Bratellbfcfe222017-10-17 17:57:00147 g_browser_child_process_observers.Get().RemoveObserver(observer);
[email protected]f4eaf7b92013-02-28 22:00:40148}
149
[email protected]4c01d4992012-01-23 23:33:01150BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
vadimt379d7fe2015-04-01 00:09:35151 content::ProcessType process_type,
amistry6ad1e812016-06-06 05:36:30152 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:42153 const std::string& service_name)
[email protected]f3b357692013-03-22 05:16:13154 : data_(process_type),
[email protected]9dd90152013-08-02 22:09:13155 delegate_(delegate),
Ken Rockotea1716a02017-05-11 05:49:10156 broker_client_invitation_(new mojo::edk::OutgoingBrokerClientInvitation),
sadrul6c5aed8c2017-01-11 23:11:44157 channel_(nullptr),
amistry012289f2016-04-01 00:56:37158 is_channel_connected_(false),
rockot229fb28e2016-06-16 04:46:16159 notify_child_disconnected_(false),
160 weak_factory_(this) {
[email protected]4734d0b2011-12-03 07:10:44161 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
[email protected]4306c3792011-12-02 01:57:53162
[email protected]4734d0b2011-12-03 07:10:44163 child_process_host_.reset(ChildProcessHost::Create(this));
ssid72c5d6822015-06-26 15:51:42164 AddFilter(new TraceMessageFilter(data_.id));
[email protected]38917fe2011-04-06 17:29:12165
166 g_child_process_list.Get().push_back(this);
[email protected]130757672012-10-24 00:26:19167 GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
[email protected]30c4c67a2014-07-22 02:33:55168
rockotda9887902016-08-19 20:46:42169 if (!service_name.empty()) {
170 DCHECK_CURRENTLY_ON(BrowserThread::IO);
ben03ac5d012017-04-28 05:12:59171 service_manager::Identity child_identity(
172 service_name, service_manager::mojom::kInheritUserID,
173 base::StringPrintf("%d", data_.id));
rockot1039b822017-02-09 23:19:41174 child_connection_.reset(
Ken Rockotea1716a02017-05-11 05:49:10175 new ChildConnection(child_identity, broker_client_invitation_.get(),
rockot1039b822017-02-09 23:19:41176 ServiceManagerContext::GetConnectorForIOThread(),
177 base::ThreadTaskRunnerHandle::Get()));
Will Harrisedb011f2018-06-01 20:28:44178 data_.metrics_name = service_name;
rockotda9887902016-08-19 20:46:42179 }
bcwhiteb58a5fe2016-08-22 16:25:56180
181 // Create a persistent memory segment for subprocess histograms.
182 CreateMetricsAllocator();
[email protected]38917fe2011-04-06 17:29:12183}
184
[email protected]4c01d4992012-01-23 23:33:01185BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
[email protected]d3c6c0d72010-12-09 08:15:04186 g_child_process_list.Get().remove(this);
amistry012289f2016-04-01 00:56:37187
188 if (notify_child_disconnected_) {
tzik4fea24af2017-08-23 11:41:47189 BrowserThread::PostTask(
190 BrowserThread::UI, FROM_HERE,
191 base::BindOnce(&NotifyProcessHostDisconnected, data_));
amistry012289f2016-04-01 00:56:37192 }
[email protected]d27893f62010-07-03 05:47:42193}
194
195// static
[email protected]4c01d4992012-01-23 23:33:01196void BrowserChildProcessHostImpl::TerminateAll() {
mostynbfbcdc27a2015-03-13 17:58:52197 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33198 // Make a copy since the BrowserChildProcessHost dtor mutates the original
199 // list.
200 BrowserChildProcessList copy = g_child_process_list.Get();
[email protected]5998d9d2012-03-06 04:25:26201 for (BrowserChildProcessList::iterator it = copy.begin();
202 it != copy.end(); ++it) {
203 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl.
204 }
[email protected]d27893f62010-07-03 05:47:42205}
206
erikchen55edbff2016-05-03 23:53:17207// static
lawrencewu0b4964922016-10-25 16:28:14208void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
erikchen55edbff2016-05-03 23:53:17209 base::CommandLine* cmd_line) {
erikchen55edbff2016-05-03 23:53:17210 // If we run base::FieldTrials, we want to pass to their state to the
211 // child process so that it can act in accordance with each state.
lawrencewu5e03cd32016-12-05 16:23:28212 base::FieldTrialList::CopyFieldTrialStateToFlags(
213 switches::kFieldTrialHandle, switches::kEnableFeatures,
214 switches::kDisableFeatures, cmd_line);
erikchen55edbff2016-05-03 23:53:17215}
216
Ehsan Chiniforooshanf192e8a22018-03-27 03:18:20217// static
218void BrowserChildProcessHostImpl::CopyTraceStartupFlags(
219 base::CommandLine* cmd_line) {
Ehsan Chiniforooshandef633e02018-04-24 02:05:02220 if (tracing::TraceStartupConfig::GetInstance()->IsEnabled()) {
Ehsan Chiniforooshanf192e8a22018-03-27 03:18:20221 const auto trace_config =
Ehsan Chiniforooshandef633e02018-04-24 02:05:02222 tracing::TraceStartupConfig::GetInstance()->GetTraceConfig();
Ehsan Chiniforooshanf192e8a22018-03-27 03:18:20223 if (!trace_config.IsArgumentFilterEnabled()) {
224 // The only trace option that we can pass through switches is the record
225 // mode. Other trace options should have the default value.
226 //
227 // TODO(chiniforooshan): Add other trace options to switches if, for
228 // example, they are used in a telemetry test that needs startup trace
229 // events from renderer processes.
230 cmd_line->AppendSwitchASCII(switches::kTraceStartup,
231 trace_config.ToCategoryFilterString());
232 cmd_line->AppendSwitchASCII(
233 switches::kTraceStartupRecordMode,
234 base::trace_event::TraceConfig::TraceRecordModeToStr(
235 trace_config.GetTraceRecordMode()));
236 }
237 }
238}
239
[email protected]4c01d4992012-01-23 23:33:01240void BrowserChildProcessHostImpl::Launch(
jcivellid20cc0b2016-12-22 03:51:41241 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
242 std::unique_ptr<base::CommandLine> cmd_line,
sievers954e37a2015-03-28 01:50:24243 bool terminate_on_shutdown) {
mostynbfbcdc27a2015-03-13 17:58:52244 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]b80f68432011-05-02 17:22:30245
jcivellid20cc0b2016-12-22 03:51:41246 GetContentClient()->browser()->AppendExtraCommandLineSwitches(cmd_line.get(),
247 data_.id);
[email protected]b80f68432011-05-02 17:22:30248
[email protected]479278702014-08-11 20:32:09249 const base::CommandLine& browser_command_line =
250 *base::CommandLine::ForCurrentProcess();
thestig418c5052016-04-11 19:39:19251 static const char* const kForwardSwitches[] = {
ochang6a8400e2017-05-01 21:28:24252 service_manager::switches::kDisableInProcessStackTraces,
Francois Doray15194792018-04-05 17:01:09253 switches::kDisableBackgroundTasks,
ochang6a8400e2017-05-01 21:28:24254 switches::kDisableLogging,
255 switches::kEnableLogging,
256 switches::kIPCConnectionTimeout,
257 switches::kLoggingLevel,
258 switches::kTraceToConsole,
259 switches::kV,
260 switches::kVModule,
[email protected]2b065f82012-10-18 07:11:16261 };
262 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
263 arraysize(kForwardSwitches));
[email protected]719a2052012-07-30 21:00:43264
rockotda9887902016-08-19 20:46:42265 if (child_connection_) {
Jay Civelli668c097f2018-05-16 20:44:13266 cmd_line->AppendSwitchASCII(
267 service_manager::switches::kServiceRequestChannelToken,
268 child_connection_->service_token());
rockotda9887902016-08-19 20:46:42269 }
270
Ken Rockotea1716a02017-05-11 05:49:10271 DCHECK(broker_client_invitation_);
Will Harrisedb011f2018-06-01 20:28:44272 // All processes should have a non-empty metrics name.
273 DCHECK(!data_.metrics_name.empty());
amistry012289f2016-04-01 00:56:37274 notify_child_disconnected_ = true;
[email protected]d27893f62010-07-03 05:47:42275 child_process_.reset(new ChildProcessLauncher(
rockot1039b822017-02-09 23:19:41276 std::move(delegate), std::move(cmd_line), data_.id, this,
Ken Rockotea1716a02017-05-11 05:49:10277 std::move(broker_client_invitation_),
rockot229fb28e2016-06-16 04:46:16278 base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
279 weak_factory_.GetWeakPtr(),
280 base::ThreadTaskRunnerHandle::Get()),
sievers954e37a2015-03-28 01:50:24281 terminate_on_shutdown));
[email protected]d27893f62010-07-03 05:47:42282}
283
[email protected]4c01d4992012-01-23 23:33:01284const ChildProcessData& BrowserChildProcessHostImpl::GetData() const {
mostynbfbcdc27a2015-03-13 17:58:52285 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40286 return data_;
287}
288
[email protected]4c01d4992012-01-23 23:33:01289ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const {
mostynbfbcdc27a2015-03-13 17:58:52290 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40291 return child_process_host_.get();
292}
293
rvargas5779b382014-11-18 20:44:11294const base::Process& BrowserChildProcessHostImpl::GetProcess() const {
mostynbfbcdc27a2015-03-13 17:58:52295 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]5d84d012010-12-02 17:17:21296 DCHECK(child_process_.get())
297 << "Requesting a child process handle before launching.";
rvargas079d1842014-10-17 22:32:16298 DCHECK(child_process_->GetProcess().IsValid())
[email protected]5d84d012010-12-02 17:17:21299 << "Requesting a child process handle before launch has completed OK.";
rvargas5779b382014-11-18 20:44:11300 return child_process_->GetProcess();
[email protected]5d84d012010-12-02 17:17:21301}
302
bcwhiteb58a5fe2016-08-22 16:25:56303std::unique_ptr<base::SharedPersistentMemoryAllocator>
304BrowserChildProcessHostImpl::TakeMetricsAllocator() {
305 return std::move(metrics_allocator_);
306}
307
[email protected]fcf75d42013-12-03 20:11:26308void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
mostynbfbcdc27a2015-03-13 17:58:52309 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33310 data_.name = name;
311}
312
Will Harrisedb011f2018-06-01 20:28:44313void BrowserChildProcessHostImpl::SetMetricsName(
314 const std::string& metrics_name) {
315 DCHECK_CURRENTLY_ON(BrowserThread::IO);
316 data_.metrics_name = metrics_name;
317}
318
[email protected]4c01d4992012-01-23 23:33:01319void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
mostynbfbcdc27a2015-03-13 17:58:52320 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33321 data_.handle = handle;
322}
323
Ken Rockotea1716a02017-05-11 05:49:10324service_manager::mojom::ServiceRequest
325BrowserChildProcessHostImpl::TakeInProcessServiceRequest() {
326 DCHECK(broker_client_invitation_);
327 auto invitation = std::move(broker_client_invitation_);
Ken Rockotf4d8a942017-05-13 00:10:37328 return service_manager::mojom::ServiceRequest(
Ken Rockotea1716a02017-05-11 05:49:10329 invitation->ExtractInProcessMessagePipe(
330 child_connection_->service_token()));
sammc2b0375b2016-12-22 01:26:17331}
332
[email protected]4c01d4992012-01-23 23:33:01333void BrowserChildProcessHostImpl::ForceShutdown() {
mostynbfbcdc27a2015-03-13 17:58:52334 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]d3c6c0d72010-12-09 08:15:04335 g_child_process_list.Get().remove(this);
[email protected]4cb43102011-12-02 20:24:49336 child_process_host_->ForceShutdown();
[email protected]d27893f62010-07-03 05:47:42337}
338
[email protected]ba780c12013-10-01 17:07:06339void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
340 child_process_host_->AddFilter(filter->GetFilter());
341}
342
bena06f7d62017-04-04 20:48:52343void BrowserChildProcessHostImpl::BindInterface(
344 const std::string& interface_name,
345 mojo::ScopedMessagePipeHandle interface_pipe) {
rockotda9887902016-08-19 20:46:42346 DCHECK_CURRENTLY_ON(BrowserThread::IO);
347 if (!child_connection_)
bena06f7d62017-04-04 20:48:52348 return;
rockotda9887902016-08-19 20:46:42349
bena06f7d62017-04-04 20:48:52350 child_connection_->BindInterface(interface_name, std::move(interface_pipe));
rockotda9887902016-08-19 20:46:42351}
352
[email protected]ef2f6ba2014-05-15 23:06:07353void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28354 ProcessType process_type) {
[email protected]ef2f6ba2014-05-15 23:06:07355 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
356 PROCESS_TYPE_MAX);
357}
358
Bo Liu0d2a2322018-04-19 00:18:09359ChildProcessTerminationInfo BrowserChildProcessHostImpl::GetTerminationInfo(
360 bool known_dead) {
mostynbfbcdc27a2015-03-13 17:58:52361 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Bo Liu0d2a2322018-04-19 00:18:09362 if (!child_process_) {
363 // If the delegate doesn't use Launch() helper.
364 ChildProcessTerminationInfo info;
365 info.status = base::GetTerminationStatus(data_.handle, &info.exit_code);
366 return info;
367 }
368 return child_process_->GetChildTerminationInfo(known_dead);
[email protected]d27893f62010-07-03 05:47:42369}
370
[email protected]4c01d4992012-01-23 23:33:01371bool BrowserChildProcessHostImpl::OnMessageReceived(
372 const IPC::Message& message) {
[email protected]4967f792012-01-20 22:14:40373 return delegate_->OnMessageReceived(message);
[email protected]4cb43102011-12-02 20:24:49374}
375
avib7348942015-12-25 20:57:10376void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
afakhry9cc79002015-10-22 19:25:15377 DCHECK_CURRENTLY_ON(BrowserThread::IO);
378
379 is_channel_connected_ = true;
amistry012289f2016-04-01 00:56:37380 notify_child_disconnected_ = true;
afakhry9cc79002015-10-22 19:25:15381
[email protected]162a9fd2013-03-06 20:47:49382#if defined(OS_WIN)
383 // From this point onward, the exit of the child process is detected by an
384 // error on the IPC channel.
[email protected]162a9fd2013-03-06 20:47:49385 early_exit_watcher_.StopWatching();
386#endif
387
[email protected]f4eaf7b92013-02-28 22:00:40388 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
tzik4fea24af2017-08-23 11:41:47389 base::BindOnce(&NotifyProcessHostConnected, data_));
[email protected]162a9fd2013-03-06 20:47:49390
[email protected]4967f792012-01-20 22:14:40391 delegate_->OnChannelConnected(peer_pid);
afakhry9cc79002015-10-22 19:25:15392
393 if (IsProcessLaunched()) {
bcwhiteb58a5fe2016-08-22 16:25:56394 ShareMetricsAllocatorToProcess();
tzik4fea24af2017-08-23 11:41:47395 BrowserThread::PostTask(
396 BrowserThread::UI, FROM_HERE,
397 base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
afakhry9cc79002015-10-22 19:25:15398 }
[email protected]4967f792012-01-20 22:14:40399}
400
[email protected]4c01d4992012-01-23 23:33:01401void BrowserChildProcessHostImpl::OnChannelError() {
[email protected]4967f792012-01-20 22:14:40402 delegate_->OnChannelError();
[email protected]0d6e9bd2011-10-18 04:29:16403}
404
[email protected]ef2f6ba2014-05-15 23:06:07405void BrowserChildProcessHostImpl::OnBadMessageReceived(
406 const IPC::Message& message) {
Roman Karaseva43d5b4e2017-12-21 03:06:02407 std::string log_message = "Bad message received of type: ";
408 if (message.IsValid()) {
409 log_message += std::to_string(message.type());
410 } else {
411 log_message += "unknown";
412 }
sadrul73f39a62017-01-11 04:07:24413 TerminateOnBadMessageReceived(log_message);
jbauman278b2cc2016-01-08 22:48:53414}
415
sadrul73f39a62017-01-11 04:07:24416void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(
417 const std::string& error) {
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28418 HistogramBadMessageTerminated(static_cast<ProcessType>(data_.process_type));
avi83883c82014-12-23 00:08:49419 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]e44d1342014-05-16 21:29:33420 switches::kDisableKillAfterBadIPC)) {
421 return;
422 }
sadrul73f39a62017-01-11 04:07:24423 LOG(ERROR) << "Terminating child process for bad IPC message: " << error;
wfhaf32d0b2015-04-07 02:21:36424 // Create a memory dump. This will contain enough stack frames to work out
425 // what the bad message was.
426 base::debug::DumpWithoutCrashing();
427
Bo Liue06143912018-04-20 20:42:30428 child_process_->Terminate(RESULT_CODE_KILLED_BAD_MESSAGE);
[email protected]ef2f6ba2014-05-15 23:06:07429}
430
sadrul6c5aed8c2017-01-11 23:11:44431void BrowserChildProcessHostImpl::OnChannelInitialized(IPC::Channel* channel) {
432 channel_ = channel;
433}
434
[email protected]4c01d4992012-01-23 23:33:01435void BrowserChildProcessHostImpl::OnChildDisconnected() {
mostynbfbcdc27a2015-03-13 17:58:52436 DCHECK_CURRENTLY_ON(BrowserThread::IO);
jbauman319402e2014-10-21 17:52:21437#if defined(OS_WIN)
438 // OnChildDisconnected may be called without OnChannelConnected, so stop the
439 // early exit watcher so GetTerminationStatus can close the process handle.
440 early_exit_watcher_.StopWatching();
441#endif
[email protected]6d057a0c2013-07-09 21:12:07442 if (child_process_.get() || data_.handle) {
Bo Liu0d2a2322018-04-19 00:18:09443 ChildProcessTerminationInfo info =
444 GetTerminationInfo(true /* known_dead */);
Bo Liue9624612018-04-28 00:39:08445#if defined(OS_ANDROID)
446 delegate_->OnProcessCrashed(info.exit_code);
447 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
448 base::BindOnce(&NotifyProcessKilled, data_, info));
449#else // OS_ANDROID
Bo Liu0d2a2322018-04-19 00:18:09450 switch (info.status) {
[email protected]6d057a0c2013-07-09 21:12:07451 case base::TERMINATION_STATUS_PROCESS_CRASHED:
452 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
Bo Liu0d2a2322018-04-19 00:18:09453 delegate_->OnProcessCrashed(info.exit_code);
wfh22e2f4a22015-04-28 22:39:21454 BrowserThread::PostTask(
455 BrowserThread::UI, FROM_HERE,
Bo Liu2a489402018-04-24 23:41:27456 base::BindOnce(&NotifyProcessCrashed, data_, info));
[email protected]6d057a0c2013-07-09 21:12:07457 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57458 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07459 PROCESS_TYPE_MAX);
460 break;
461 }
oshima620225722015-06-04 19:45:27462#if defined(OS_CHROMEOS)
463 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
464#endif
[email protected]6d057a0c2013-07-09 21:12:07465 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
Bo Liu0d2a2322018-04-19 00:18:09466 delegate_->OnProcessCrashed(info.exit_code);
wfhf0003292015-08-18 22:16:46467 BrowserThread::PostTask(
468 BrowserThread::UI, FROM_HERE,
Bo Liu2a489402018-04-24 23:41:27469 base::BindOnce(&NotifyProcessKilled, data_, info));
[email protected]6d057a0c2013-07-09 21:12:07470 // Report that this child process was killed.
471 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57472 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07473 PROCESS_TYPE_MAX);
474 break;
475 }
476 case base::TERMINATION_STATUS_STILL_RUNNING: {
477 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57478 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07479 PROCESS_TYPE_MAX);
Nico Weber9dbefa62018-01-27 01:01:42480 break;
[email protected]6d057a0c2013-07-09 21:12:07481 }
482 default:
483 break;
[email protected]12fed812011-09-16 05:47:29484 }
Bo Liue9624612018-04-28 00:39:08485#endif // OS_ANDROID
[email protected]6d057a0c2013-07-09 21:12:07486 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57487 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07488 PROCESS_TYPE_MAX);
oshima620225722015-06-04 19:45:27489#if defined(OS_CHROMEOS)
Bo Liu0d2a2322018-04-19 00:18:09490 if (info.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
oshima620225722015-06-04 19:45:27491 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2.OOM",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57492 static_cast<ProcessType>(data_.process_type),
oshima620225722015-06-04 19:45:27493 PROCESS_TYPE_MAX);
494 }
495#endif
[email protected]d27893f62010-07-03 05:47:42496 }
sadrul6c5aed8c2017-01-11 23:11:44497 channel_ = nullptr;
[email protected]4967f792012-01-20 22:14:40498 delete delegate_; // Will delete us
[email protected]a3a7e2c2011-09-16 23:07:05499}
500
[email protected]4c01d4992012-01-23 23:33:01501bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
[email protected]4cb43102011-12-02 20:24:49502 return child_process_host_->Send(message);
503}
504
bcwhiteb58a5fe2016-08-22 16:25:56505void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
506 // Create a persistent memory segment for subprocess histograms only if
507 // they're active in the browser.
508 // TODO(bcwhite): Remove this once persistence is always enabled.
509 if (!base::GlobalHistogramAllocator::Get())
510 return;
511
512 // Determine the correct parameters based on the process type.
513 size_t memory_size;
514 base::StringPiece metrics_name;
515 switch (data_.process_type) {
bcwhite2496c83e2016-08-29 17:29:25516 case PROCESS_TYPE_UTILITY:
Matt Menkee5bc4a562017-08-07 23:58:22517 // This needs to be larger for the network service.
518 memory_size = 256 << 10; // 256 KiB
bcwhite2496c83e2016-08-29 17:29:25519 metrics_name = "UtilityMetrics";
520 break;
521
522 case PROCESS_TYPE_ZYGOTE:
bcwhite867f45532017-01-05 17:29:02523 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25524 metrics_name = "ZygoteMetrics";
525 break;
526
527 case PROCESS_TYPE_SANDBOX_HELPER:
bcwhite867f45532017-01-05 17:29:02528 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25529 metrics_name = "SandboxHelperMetrics";
530 break;
531
bcwhiteb58a5fe2016-08-22 16:25:56532 case PROCESS_TYPE_GPU:
bcwhite867f45532017-01-05 17:29:02533 memory_size = 64 << 10; // 64 KiB
bcwhiteb58a5fe2016-08-22 16:25:56534 metrics_name = "GpuMetrics";
535 break;
536
bcwhite2496c83e2016-08-29 17:29:25537 case PROCESS_TYPE_PPAPI_PLUGIN:
bcwhite867f45532017-01-05 17:29:02538 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25539 metrics_name = "PpapiPluginMetrics";
540 break;
541
542 case PROCESS_TYPE_PPAPI_BROKER:
bcwhite867f45532017-01-05 17:29:02543 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25544 metrics_name = "PpapiBrokerMetrics";
545 break;
546
bcwhiteb58a5fe2016-08-22 16:25:56547 default:
bcwhitec600ac12017-07-12 13:37:13548 // Report new processes. "Custom" ones are renumbered to 1000+ so that
549 // they won't conflict with any standard ones in the future.
550 int process_type = data_.process_type;
551 if (process_type >= PROCESS_TYPE_CONTENT_END)
552 process_type += 1000 - PROCESS_TYPE_CONTENT_END;
Ilya Sherman1c811db2017-12-14 10:36:18553 base::UmaHistogramSparse(
bcwhitec600ac12017-07-12 13:37:13554 "UMA.SubprocessMetricsProvider.UntrackedProcesses", process_type);
bcwhiteb58a5fe2016-08-22 16:25:56555 return;
556 }
557
558 // Create the shared memory segment and attach an allocator to it.
559 // Mapping the memory shouldn't fail but be safe if it does; everything
560 // will continue to work but just as if persistence weren't available.
561 std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory());
562 if (!shm->CreateAndMapAnonymous(memory_size))
563 return;
564 metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator(
565 std::move(shm), static_cast<uint64_t>(data_.id), metrics_name,
566 /*readonly=*/false));
567}
568
569void BrowserChildProcessHostImpl::ShareMetricsAllocatorToProcess() {
570 if (metrics_allocator_) {
Nicholas Verne91bf4a632017-10-12 21:14:24571 HistogramController::GetInstance()->SetHistogramMemory<ChildProcessHost>(
572 GetHost(),
573 mojo::WrapSharedMemoryHandle(
574 metrics_allocator_->shared_memory()->handle().Duplicate(),
Ken Rockot673ce952018-01-18 20:59:24575 metrics_allocator_->shared_memory()->mapped_size(),
576 mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite));
Nicholas Verne91bf4a632017-10-12 21:14:24577 } else {
578 HistogramController::GetInstance()->SetHistogramMemory<ChildProcessHost>(
579 GetHost(), mojo::ScopedSharedBufferHandle());
bcwhiteb58a5fe2016-08-22 16:25:56580 }
581}
582
wfh3adf87d2016-05-03 23:26:06583void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) {
584 delegate_->OnProcessLaunchFailed(error_code);
amistry012289f2016-04-01 00:56:37585 notify_child_disconnected_ = false;
[email protected]fa01e472014-02-11 14:45:35586 delete delegate_; // Will delete us
587}
588
[email protected]4c01d4992012-01-23 23:33:01589void BrowserChildProcessHostImpl::OnProcessLaunched() {
afakhry9cc79002015-10-22 19:25:15590 DCHECK_CURRENTLY_ON(BrowserThread::IO);
591
rvargas079d1842014-10-17 22:32:16592 const base::Process& process = child_process_->GetProcess();
593 DCHECK(process.IsValid());
[email protected]162a9fd2013-03-06 20:47:49594
rockotfe2fecc2017-01-19 20:16:19595 if (child_connection_)
596 child_connection_->SetProcessHandle(process.Handle());
597
jam3c8c50c2015-11-25 18:48:29598#if defined(OS_WIN)
[email protected]162a9fd2013-03-06 20:47:49599 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
600 // child process exits. This watcher is stopped once the IPC channel is
601 // connected and the exit of the child process is detecter by an error on the
602 // IPC channel thereafter.
rvargas079d1842014-10-17 22:32:16603 DCHECK(!early_exit_watcher_.GetWatchedObject());
jam7fab1082015-09-29 02:26:18604 early_exit_watcher_.StartWatchingOnce(process.Handle(), this);
[email protected]162a9fd2013-03-06 20:47:49605#endif
606
rvargas079d1842014-10-17 22:32:16607 // TODO(rvargas) crbug.com/417532: Don't store a handle.
608 data_.handle = process.Handle();
[email protected]4967f792012-01-20 22:14:40609 delegate_->OnProcessLaunched();
afakhry9cc79002015-10-22 19:25:15610
611 if (is_channel_connected_) {
bcwhiteb58a5fe2016-08-22 16:25:56612 ShareMetricsAllocatorToProcess();
tzik4fea24af2017-08-23 11:41:47613 BrowserThread::PostTask(
614 BrowserThread::UI, FROM_HERE,
615 base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
afakhry9cc79002015-10-22 19:25:15616 }
617}
618
619bool BrowserChildProcessHostImpl::IsProcessLaunched() const {
620 DCHECK_CURRENTLY_ON(BrowserThread::IO);
621
622 return child_process_.get() && child_process_->GetProcess().IsValid();
[email protected]d27893f62010-07-03 05:47:42623}
[email protected]130757672012-10-24 00:26:19624
rockot229fb28e2016-06-16 04:46:16625// static
626void BrowserChildProcessHostImpl::OnMojoError(
627 base::WeakPtr<BrowserChildProcessHostImpl> process,
628 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
629 const std::string& error) {
630 if (!task_runner->BelongsToCurrentThread()) {
631 task_runner->PostTask(
tzik4fea24af2017-08-23 11:41:47632 FROM_HERE, base::BindOnce(&BrowserChildProcessHostImpl::OnMojoError,
633 process, task_runner, error));
olka91f1d412016-11-21 15:24:53634 return;
rockot229fb28e2016-06-16 04:46:16635 }
636 if (!process)
637 return;
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28638 HistogramBadMessageTerminated(
639 static_cast<ProcessType>(process->data_.process_type));
rockot229fb28e2016-06-16 04:46:16640 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
641 switches::kDisableKillAfterBadIPC)) {
642 return;
643 }
644 LOG(ERROR) << "Terminating child process for bad Mojo message: " << error;
645
Yuzhu Shen32fcad72017-09-14 23:12:37646 // Create a memory dump with the error message captured in a crash key value.
647 // This will make it easy to determine details about what interface call
648 // failed.
Robert Sesek1419427e2017-12-07 15:01:32649 base::debug::ScopedCrashKeyString scoped_error_key(
650 bad_message::GetMojoErrorCrashKey(), error);
rockot229fb28e2016-06-16 04:46:16651 base::debug::DumpWithoutCrashing();
Bo Liue06143912018-04-20 20:42:30652 process->child_process_->Terminate(RESULT_CODE_KILLED_BAD_MESSAGE);
rockot229fb28e2016-06-16 04:46:16653}
654
[email protected]162a9fd2013-03-06 20:47:49655#if defined(OS_WIN)
656
rvargas079d1842014-10-17 22:32:16657void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
[email protected]162a9fd2013-03-06 20:47:49658 OnChildDisconnected();
659}
660
661#endif
662
[email protected]130757672012-10-24 00:26:19663} // namespace content