blob: 11f3f2ce2b89e0cc028e1a148a0e8eb290f1fc85 [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"
fdorayba121422016-12-23 19:51:4817#include "base/memory/ptr_util.h"
erikchen55edbff2016-05-03 23:53:1718#include "base/metrics/field_trial.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"
primianoccb26c62016-06-01 21:50:0228#include "components/tracing/common/tracing_switches.h"
Robert Sesek1419427e2017-12-07 15:01:3229#include "content/browser/bad_message.h"
Nicholas Verne91bf4a632017-10-12 21:14:2430#include "content/browser/histogram_controller.h"
[email protected]678c0362012-12-05 08:02:4431#include "content/browser/loader/resource_message_filter.h"
benff461632016-10-06 14:27:3332#include "content/browser/service_manager/service_manager_context.h"
[email protected]3a85b1f2013-02-01 04:47:4033#include "content/browser/tracing/trace_message_filter.h"
[email protected]4734d0b2011-12-03 07:10:4434#include "content/common/child_process_host_impl.h"
bend32292b2016-10-07 00:21:5835#include "content/common/service_manager/child_connection.h"
[email protected]4967f792012-01-20 22:14:4036#include "content/public/browser/browser_child_process_host_delegate.h"
[email protected]f4eaf7b92013-02-28 22:00:4037#include "content/public/browser/browser_child_process_observer.h"
[email protected]57999812013-02-24 05:40:5238#include "content/public/browser/browser_thread.h"
[email protected]4306c3792011-12-02 01:57:5339#include "content/public/browser/child_process_data.h"
[email protected]87f3c082011-10-19 18:07:4440#include "content/public/browser/content_browser_client.h"
ke.he19b5e6a2016-10-27 08:47:0941#include "content/public/common/connection_filter.h"
lawrencewu2c930822016-10-13 13:54:2542#include "content/public/common/content_features.h"
[email protected]c08950d22011-10-13 22:20:2943#include "content/public/common/content_switches.h"
rockotda9887902016-08-19 20:46:4244#include "content/public/common/mojo_channel_switches.h"
[email protected]f3b357692013-03-22 05:16:1345#include "content/public/common/process_type.h"
[email protected]b39ef1cb2011-10-25 04:46:5546#include "content/public/common/result_codes.h"
jcivelli828cd7f2017-01-18 19:50:4647#include "content/public/common/sandboxed_process_launcher_delegate.h"
ke.he19b5e6a2016-10-27 08:47:0948#include "content/public/common/service_manager_connection.h"
rockotc637caf9b2016-02-10 09:57:0849#include "mojo/edk/embedder/embedder.h"
Nicholas Verne91bf4a632017-10-12 21:14:2450#include "mojo/public/cpp/system/platform_handle.h"
ochang6a8400e2017-05-01 21:28:2451#include "services/service_manager/embedder/switches.h"
[email protected]d27893f62010-07-03 05:47:4252
[email protected]f1675202012-07-09 15:18:0053#if defined(OS_MACOSX)
[email protected]458433c2012-02-29 23:43:3954#include "content/browser/mach_broker_mac.h"
[email protected]3838ca12011-11-02 14:37:1555#endif
[email protected]a3a7e2c2011-09-16 23:07:0556
[email protected]130757672012-10-24 00:26:1957namespace content {
[email protected]d27893f62010-07-03 05:47:4258namespace {
59
scottmg5e65e3a2017-03-08 08:48:4660static base::LazyInstance<
61 BrowserChildProcessHostImpl::BrowserChildProcessList>::DestructorAtExit
[email protected]4967f792012-01-20 22:14:4062 g_child_process_list = LAZY_INSTANCE_INITIALIZER;
[email protected]d27893f62010-07-03 05:47:4263
scottmg5e65e3a2017-03-08 08:48:4664base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>>::
Daniel Bratellbfcfe222017-10-17 17:57:0065 DestructorAtExit g_browser_child_process_observers =
66 LAZY_INSTANCE_INITIALIZER;
[email protected]f4eaf7b92013-02-28 22:00:4067
afakhry9cc79002015-10-22 19:25:1568void NotifyProcessLaunchedAndConnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0069 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3170 observer.BrowserChildProcessLaunchedAndConnected(data);
afakhry9cc79002015-10-22 19:25:1571}
72
[email protected]f4eaf7b92013-02-28 22:00:4073void NotifyProcessHostConnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0074 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3175 observer.BrowserChildProcessHostConnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4076}
77
78void NotifyProcessHostDisconnected(const ChildProcessData& data) {
Daniel Bratellbfcfe222017-10-17 17:57:0079 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3180 observer.BrowserChildProcessHostDisconnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4081}
82
wfh22e2f4a22015-04-28 22:39:2183void NotifyProcessCrashed(const ChildProcessData& data, int exit_code) {
Daniel Bratellbfcfe222017-10-17 17:57:0084 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3185 observer.BrowserChildProcessCrashed(data, exit_code);
[email protected]4306c3792011-12-02 01:57:5386}
[email protected]d27893f62010-07-03 05:47:4287
wfhf0003292015-08-18 22:16:4688void NotifyProcessKilled(const ChildProcessData& data, int exit_code) {
Daniel Bratellbfcfe222017-10-17 17:57:0089 for (auto& observer : g_browser_child_process_observers.Get())
ericwilligers254597b2016-10-17 10:32:3190 observer.BrowserChildProcessKilled(data, exit_code);
wfhf0003292015-08-18 22:16:4691}
92
[email protected]d27893f62010-07-03 05:47:4293} // namespace
94
[email protected]4967f792012-01-20 22:14:4095BrowserChildProcessHost* BrowserChildProcessHost::Create(
vadimt379d7fe2015-04-01 00:09:3596 content::ProcessType process_type,
[email protected]4967f792012-01-20 22:14:4097 BrowserChildProcessHostDelegate* delegate) {
rockotda9887902016-08-19 20:46:4298 return Create(process_type, delegate, std::string());
amistry6ad1e812016-06-06 05:36:3099}
100
101BrowserChildProcessHost* BrowserChildProcessHost::Create(
102 content::ProcessType process_type,
103 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:42104 const std::string& service_name) {
105 return new BrowserChildProcessHostImpl(process_type, delegate, service_name);
[email protected]4967f792012-01-20 22:14:40106}
107
amistryfaa231a42015-05-20 01:49:12108BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) {
109 DCHECK_CURRENTLY_ON(BrowserThread::IO);
110 BrowserChildProcessHostImpl::BrowserChildProcessList* process_list =
111 g_child_process_list.Pointer();
112 for (BrowserChildProcessHostImpl* host : *process_list) {
113 if (host->GetData().id == child_process_id)
114 return host;
115 }
116 return nullptr;
117}
118
[email protected]458433c2012-02-29 23:43:39119#if defined(OS_MACOSX)
erikchencd3e0e7b2015-10-01 22:53:51120base::PortProvider* BrowserChildProcessHost::GetPortProvider() {
[email protected]458433c2012-02-29 23:43:39121 return MachBroker::GetInstance();
122}
123#endif
124
[email protected]f4eaf7b92013-02-28 22:00:40125// static
[email protected]4c01d4992012-01-23 23:33:01126BrowserChildProcessHostImpl::BrowserChildProcessList*
127 BrowserChildProcessHostImpl::GetIterator() {
[email protected]4967f792012-01-20 22:14:40128 return g_child_process_list.Pointer();
129}
130
[email protected]f4eaf7b92013-02-28 22:00:40131// static
132void BrowserChildProcessHostImpl::AddObserver(
133 BrowserChildProcessObserver* observer) {
mostynbfbcdc27a2015-03-13 17:58:52134 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Daniel Bratellbfcfe222017-10-17 17:57:00135 g_browser_child_process_observers.Get().AddObserver(observer);
[email protected]f4eaf7b92013-02-28 22:00:40136}
137
138// static
139void BrowserChildProcessHostImpl::RemoveObserver(
140 BrowserChildProcessObserver* observer) {
141 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126.
Daniel Bratellbfcfe222017-10-17 17:57:00142 g_browser_child_process_observers.Get().RemoveObserver(observer);
[email protected]f4eaf7b92013-02-28 22:00:40143}
144
[email protected]4c01d4992012-01-23 23:33:01145BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
vadimt379d7fe2015-04-01 00:09:35146 content::ProcessType process_type,
amistry6ad1e812016-06-06 05:36:30147 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:42148 const std::string& service_name)
[email protected]f3b357692013-03-22 05:16:13149 : data_(process_type),
[email protected]9dd90152013-08-02 22:09:13150 delegate_(delegate),
Ken Rockotea1716a02017-05-11 05:49:10151 broker_client_invitation_(new mojo::edk::OutgoingBrokerClientInvitation),
sadrul6c5aed8c2017-01-11 23:11:44152 channel_(nullptr),
amistry012289f2016-04-01 00:56:37153 is_channel_connected_(false),
rockot229fb28e2016-06-16 04:46:16154 notify_child_disconnected_(false),
155 weak_factory_(this) {
[email protected]4734d0b2011-12-03 07:10:44156 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
[email protected]4306c3792011-12-02 01:57:53157
[email protected]4734d0b2011-12-03 07:10:44158 child_process_host_.reset(ChildProcessHost::Create(this));
ssid72c5d6822015-06-26 15:51:42159 AddFilter(new TraceMessageFilter(data_.id));
[email protected]38917fe2011-04-06 17:29:12160
161 g_child_process_list.Get().push_back(this);
[email protected]130757672012-10-24 00:26:19162 GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
[email protected]30c4c67a2014-07-22 02:33:55163
rockotda9887902016-08-19 20:46:42164 if (!service_name.empty()) {
165 DCHECK_CURRENTLY_ON(BrowserThread::IO);
ben03ac5d012017-04-28 05:12:59166 service_manager::Identity child_identity(
167 service_name, service_manager::mojom::kInheritUserID,
168 base::StringPrintf("%d", data_.id));
rockot1039b822017-02-09 23:19:41169 child_connection_.reset(
Ken Rockotea1716a02017-05-11 05:49:10170 new ChildConnection(child_identity, broker_client_invitation_.get(),
rockot1039b822017-02-09 23:19:41171 ServiceManagerContext::GetConnectorForIOThread(),
172 base::ThreadTaskRunnerHandle::Get()));
rockotda9887902016-08-19 20:46:42173 }
bcwhiteb58a5fe2016-08-22 16:25:56174
175 // Create a persistent memory segment for subprocess histograms.
176 CreateMetricsAllocator();
[email protected]38917fe2011-04-06 17:29:12177}
178
[email protected]4c01d4992012-01-23 23:33:01179BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
[email protected]d3c6c0d72010-12-09 08:15:04180 g_child_process_list.Get().remove(this);
amistry012289f2016-04-01 00:56:37181
182 if (notify_child_disconnected_) {
tzik4fea24af2017-08-23 11:41:47183 BrowserThread::PostTask(
184 BrowserThread::UI, FROM_HERE,
185 base::BindOnce(&NotifyProcessHostDisconnected, data_));
amistry012289f2016-04-01 00:56:37186 }
[email protected]d27893f62010-07-03 05:47:42187}
188
189// static
[email protected]4c01d4992012-01-23 23:33:01190void BrowserChildProcessHostImpl::TerminateAll() {
mostynbfbcdc27a2015-03-13 17:58:52191 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33192 // Make a copy since the BrowserChildProcessHost dtor mutates the original
193 // list.
194 BrowserChildProcessList copy = g_child_process_list.Get();
[email protected]5998d9d2012-03-06 04:25:26195 for (BrowserChildProcessList::iterator it = copy.begin();
196 it != copy.end(); ++it) {
197 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl.
198 }
[email protected]d27893f62010-07-03 05:47:42199}
200
erikchen55edbff2016-05-03 23:53:17201// static
lawrencewu0b4964922016-10-25 16:28:14202void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
erikchen55edbff2016-05-03 23:53:17203 base::CommandLine* cmd_line) {
erikchen55edbff2016-05-03 23:53:17204 // If we run base::FieldTrials, we want to pass to their state to the
205 // child process so that it can act in accordance with each state.
lawrencewu5e03cd32016-12-05 16:23:28206 base::FieldTrialList::CopyFieldTrialStateToFlags(
207 switches::kFieldTrialHandle, switches::kEnableFeatures,
208 switches::kDisableFeatures, cmd_line);
erikchen55edbff2016-05-03 23:53:17209}
210
[email protected]4c01d4992012-01-23 23:33:01211void BrowserChildProcessHostImpl::Launch(
jcivellid20cc0b2016-12-22 03:51:41212 std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
213 std::unique_ptr<base::CommandLine> cmd_line,
sievers954e37a2015-03-28 01:50:24214 bool terminate_on_shutdown) {
mostynbfbcdc27a2015-03-13 17:58:52215 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]b80f68432011-05-02 17:22:30216
jcivellid20cc0b2016-12-22 03:51:41217 GetContentClient()->browser()->AppendExtraCommandLineSwitches(cmd_line.get(),
218 data_.id);
[email protected]b80f68432011-05-02 17:22:30219
[email protected]479278702014-08-11 20:32:09220 const base::CommandLine& browser_command_line =
221 *base::CommandLine::ForCurrentProcess();
thestig418c5052016-04-11 19:39:19222 static const char* const kForwardSwitches[] = {
ochang6a8400e2017-05-01 21:28:24223 service_manager::switches::kDisableInProcessStackTraces,
224 switches::kDisableLogging,
225 switches::kEnableLogging,
226 switches::kIPCConnectionTimeout,
227 switches::kLoggingLevel,
228 switches::kTraceToConsole,
229 switches::kV,
230 switches::kVModule,
[email protected]2b065f82012-10-18 07:11:16231 };
232 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
233 arraysize(kForwardSwitches));
[email protected]719a2052012-07-30 21:00:43234
rockotda9887902016-08-19 20:46:42235 if (child_connection_) {
bend32292b2016-10-07 00:21:58236 cmd_line->AppendSwitchASCII(switches::kServiceRequestChannelToken,
rockotda9887902016-08-19 20:46:42237 child_connection_->service_token());
238 }
239
Ken Rockotea1716a02017-05-11 05:49:10240 DCHECK(broker_client_invitation_);
amistry012289f2016-04-01 00:56:37241 notify_child_disconnected_ = true;
[email protected]d27893f62010-07-03 05:47:42242 child_process_.reset(new ChildProcessLauncher(
rockot1039b822017-02-09 23:19:41243 std::move(delegate), std::move(cmd_line), data_.id, this,
Ken Rockotea1716a02017-05-11 05:49:10244 std::move(broker_client_invitation_),
rockot229fb28e2016-06-16 04:46:16245 base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
246 weak_factory_.GetWeakPtr(),
247 base::ThreadTaskRunnerHandle::Get()),
sievers954e37a2015-03-28 01:50:24248 terminate_on_shutdown));
[email protected]d27893f62010-07-03 05:47:42249}
250
[email protected]4c01d4992012-01-23 23:33:01251const ChildProcessData& BrowserChildProcessHostImpl::GetData() const {
mostynbfbcdc27a2015-03-13 17:58:52252 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40253 return data_;
254}
255
[email protected]4c01d4992012-01-23 23:33:01256ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const {
mostynbfbcdc27a2015-03-13 17:58:52257 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40258 return child_process_host_.get();
259}
260
rvargas5779b382014-11-18 20:44:11261const base::Process& BrowserChildProcessHostImpl::GetProcess() const {
mostynbfbcdc27a2015-03-13 17:58:52262 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]5d84d012010-12-02 17:17:21263 DCHECK(child_process_.get())
264 << "Requesting a child process handle before launching.";
rvargas079d1842014-10-17 22:32:16265 DCHECK(child_process_->GetProcess().IsValid())
[email protected]5d84d012010-12-02 17:17:21266 << "Requesting a child process handle before launch has completed OK.";
rvargas5779b382014-11-18 20:44:11267 return child_process_->GetProcess();
[email protected]5d84d012010-12-02 17:17:21268}
269
bcwhiteb58a5fe2016-08-22 16:25:56270std::unique_ptr<base::SharedPersistentMemoryAllocator>
271BrowserChildProcessHostImpl::TakeMetricsAllocator() {
272 return std::move(metrics_allocator_);
273}
274
[email protected]fcf75d42013-12-03 20:11:26275void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
mostynbfbcdc27a2015-03-13 17:58:52276 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33277 data_.name = name;
278}
279
[email protected]4c01d4992012-01-23 23:33:01280void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
mostynbfbcdc27a2015-03-13 17:58:52281 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33282 data_.handle = handle;
283}
284
Ken Rockotea1716a02017-05-11 05:49:10285service_manager::mojom::ServiceRequest
286BrowserChildProcessHostImpl::TakeInProcessServiceRequest() {
287 DCHECK(broker_client_invitation_);
288 auto invitation = std::move(broker_client_invitation_);
Ken Rockotf4d8a942017-05-13 00:10:37289 return service_manager::mojom::ServiceRequest(
Ken Rockotea1716a02017-05-11 05:49:10290 invitation->ExtractInProcessMessagePipe(
291 child_connection_->service_token()));
sammc2b0375b2016-12-22 01:26:17292}
293
[email protected]4c01d4992012-01-23 23:33:01294void BrowserChildProcessHostImpl::ForceShutdown() {
mostynbfbcdc27a2015-03-13 17:58:52295 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]d3c6c0d72010-12-09 08:15:04296 g_child_process_list.Get().remove(this);
[email protected]4cb43102011-12-02 20:24:49297 child_process_host_->ForceShutdown();
[email protected]d27893f62010-07-03 05:47:42298}
299
[email protected]ba780c12013-10-01 17:07:06300void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
301 child_process_host_->AddFilter(filter->GetFilter());
302}
303
bena06f7d62017-04-04 20:48:52304void BrowserChildProcessHostImpl::BindInterface(
305 const std::string& interface_name,
306 mojo::ScopedMessagePipeHandle interface_pipe) {
rockotda9887902016-08-19 20:46:42307 DCHECK_CURRENTLY_ON(BrowserThread::IO);
308 if (!child_connection_)
bena06f7d62017-04-04 20:48:52309 return;
rockotda9887902016-08-19 20:46:42310
bena06f7d62017-04-04 20:48:52311 child_connection_->BindInterface(interface_name, std::move(interface_pipe));
rockotda9887902016-08-19 20:46:42312}
313
[email protected]ef2f6ba2014-05-15 23:06:07314void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28315 ProcessType process_type) {
[email protected]ef2f6ba2014-05-15 23:06:07316 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
317 PROCESS_TYPE_MAX);
318}
319
[email protected]4c01d4992012-01-23 23:33:01320base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
[email protected]547603d2013-08-27 17:59:19321 bool known_dead, int* exit_code) {
mostynbfbcdc27a2015-03-13 17:58:52322 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]59383c782013-04-17 16:43:27323 if (!child_process_) // If the delegate doesn't use Launch() helper.
[email protected]4967f792012-01-20 22:14:40324 return base::GetTerminationStatus(data_.handle, exit_code);
[email protected]547603d2013-08-27 17:59:19325 return child_process_->GetChildTerminationStatus(known_dead,
[email protected]c7691de2012-12-06 08:31:51326 exit_code);
[email protected]d27893f62010-07-03 05:47:42327}
328
[email protected]4c01d4992012-01-23 23:33:01329bool BrowserChildProcessHostImpl::OnMessageReceived(
330 const IPC::Message& message) {
[email protected]4967f792012-01-20 22:14:40331 return delegate_->OnMessageReceived(message);
[email protected]4cb43102011-12-02 20:24:49332}
333
avib7348942015-12-25 20:57:10334void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
afakhry9cc79002015-10-22 19:25:15335 DCHECK_CURRENTLY_ON(BrowserThread::IO);
336
337 is_channel_connected_ = true;
amistry012289f2016-04-01 00:56:37338 notify_child_disconnected_ = true;
afakhry9cc79002015-10-22 19:25:15339
[email protected]162a9fd2013-03-06 20:47:49340#if defined(OS_WIN)
341 // From this point onward, the exit of the child process is detected by an
342 // error on the IPC channel.
[email protected]162a9fd2013-03-06 20:47:49343 early_exit_watcher_.StopWatching();
344#endif
345
[email protected]f4eaf7b92013-02-28 22:00:40346 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
tzik4fea24af2017-08-23 11:41:47347 base::BindOnce(&NotifyProcessHostConnected, data_));
[email protected]162a9fd2013-03-06 20:47:49348
[email protected]4967f792012-01-20 22:14:40349 delegate_->OnChannelConnected(peer_pid);
afakhry9cc79002015-10-22 19:25:15350
351 if (IsProcessLaunched()) {
bcwhiteb58a5fe2016-08-22 16:25:56352 ShareMetricsAllocatorToProcess();
tzik4fea24af2017-08-23 11:41:47353 BrowserThread::PostTask(
354 BrowserThread::UI, FROM_HERE,
355 base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
afakhry9cc79002015-10-22 19:25:15356 }
[email protected]4967f792012-01-20 22:14:40357}
358
[email protected]4c01d4992012-01-23 23:33:01359void BrowserChildProcessHostImpl::OnChannelError() {
[email protected]4967f792012-01-20 22:14:40360 delegate_->OnChannelError();
[email protected]0d6e9bd2011-10-18 04:29:16361}
362
[email protected]ef2f6ba2014-05-15 23:06:07363void BrowserChildProcessHostImpl::OnBadMessageReceived(
364 const IPC::Message& message) {
sadrul73f39a62017-01-11 04:07:24365 std::string log_message =
366 base::StringPrintf("Bad message received of type: %u", message.type());
367 TerminateOnBadMessageReceived(log_message);
jbauman278b2cc2016-01-08 22:48:53368}
369
sadrul73f39a62017-01-11 04:07:24370void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(
371 const std::string& error) {
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28372 HistogramBadMessageTerminated(static_cast<ProcessType>(data_.process_type));
avi83883c82014-12-23 00:08:49373 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]e44d1342014-05-16 21:29:33374 switches::kDisableKillAfterBadIPC)) {
375 return;
376 }
sadrul73f39a62017-01-11 04:07:24377 LOG(ERROR) << "Terminating child process for bad IPC message: " << error;
wfhaf32d0b2015-04-07 02:21:36378 // Create a memory dump. This will contain enough stack frames to work out
379 // what the bad message was.
380 base::debug::DumpWithoutCrashing();
381
rvargas486b2f562015-03-18 01:36:33382 child_process_->GetProcess().Terminate(RESULT_CODE_KILLED_BAD_MESSAGE, false);
[email protected]ef2f6ba2014-05-15 23:06:07383}
384
[email protected]4c01d4992012-01-23 23:33:01385bool BrowserChildProcessHostImpl::CanShutdown() {
[email protected]4967f792012-01-20 22:14:40386 return delegate_->CanShutdown();
[email protected]4cb43102011-12-02 20:24:49387}
388
sadrul6c5aed8c2017-01-11 23:11:44389void BrowserChildProcessHostImpl::OnChannelInitialized(IPC::Channel* channel) {
390 channel_ = channel;
391}
392
[email protected]4c01d4992012-01-23 23:33:01393void BrowserChildProcessHostImpl::OnChildDisconnected() {
mostynbfbcdc27a2015-03-13 17:58:52394 DCHECK_CURRENTLY_ON(BrowserThread::IO);
jbauman319402e2014-10-21 17:52:21395#if defined(OS_WIN)
396 // OnChildDisconnected may be called without OnChannelConnected, so stop the
397 // early exit watcher so GetTerminationStatus can close the process handle.
398 early_exit_watcher_.StopWatching();
399#endif
[email protected]6d057a0c2013-07-09 21:12:07400 if (child_process_.get() || data_.handle) {
[email protected]6d057a0c2013-07-09 21:12:07401 int exit_code;
[email protected]547603d2013-08-27 17:59:19402 base::TerminationStatus status = GetTerminationStatus(
403 true /* known_dead */, &exit_code);
[email protected]6d057a0c2013-07-09 21:12:07404 switch (status) {
405 case base::TERMINATION_STATUS_PROCESS_CRASHED:
406 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
407 delegate_->OnProcessCrashed(exit_code);
wfh22e2f4a22015-04-28 22:39:21408 BrowserThread::PostTask(
409 BrowserThread::UI, FROM_HERE,
tzik4fea24af2017-08-23 11:41:47410 base::BindOnce(&NotifyProcessCrashed, data_, exit_code));
[email protected]6d057a0c2013-07-09 21:12:07411 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57412 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07413 PROCESS_TYPE_MAX);
414 break;
415 }
derekjchow1b0f3bb2015-07-30 18:51:10416#if defined(OS_ANDROID)
417 case base::TERMINATION_STATUS_OOM_PROTECTED:
418#endif
oshima620225722015-06-04 19:45:27419#if defined(OS_CHROMEOS)
420 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
421#endif
[email protected]6d057a0c2013-07-09 21:12:07422 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
423 delegate_->OnProcessCrashed(exit_code);
wfhf0003292015-08-18 22:16:46424 BrowserThread::PostTask(
425 BrowserThread::UI, FROM_HERE,
tzik4fea24af2017-08-23 11:41:47426 base::BindOnce(&NotifyProcessKilled, data_, exit_code));
[email protected]6d057a0c2013-07-09 21:12:07427 // Report that this child process was killed.
428 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57429 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07430 PROCESS_TYPE_MAX);
431 break;
432 }
433 case base::TERMINATION_STATUS_STILL_RUNNING: {
434 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57435 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07436 PROCESS_TYPE_MAX);
437 }
438 default:
439 break;
[email protected]12fed812011-09-16 05:47:29440 }
[email protected]6d057a0c2013-07-09 21:12:07441 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57442 static_cast<ProcessType>(data_.process_type),
[email protected]6d057a0c2013-07-09 21:12:07443 PROCESS_TYPE_MAX);
oshima620225722015-06-04 19:45:27444#if defined(OS_CHROMEOS)
445 if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
446 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2.OOM",
Wei-Yin Chen (陳威尹)3330991f2017-07-27 17:25:57447 static_cast<ProcessType>(data_.process_type),
oshima620225722015-06-04 19:45:27448 PROCESS_TYPE_MAX);
449 }
450#endif
[email protected]d27893f62010-07-03 05:47:42451 }
sadrul6c5aed8c2017-01-11 23:11:44452 channel_ = nullptr;
[email protected]4967f792012-01-20 22:14:40453 delete delegate_; // Will delete us
[email protected]a3a7e2c2011-09-16 23:07:05454}
455
[email protected]4c01d4992012-01-23 23:33:01456bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
[email protected]4cb43102011-12-02 20:24:49457 return child_process_host_->Send(message);
458}
459
bcwhiteb58a5fe2016-08-22 16:25:56460void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
461 // Create a persistent memory segment for subprocess histograms only if
462 // they're active in the browser.
463 // TODO(bcwhite): Remove this once persistence is always enabled.
464 if (!base::GlobalHistogramAllocator::Get())
465 return;
466
467 // Determine the correct parameters based on the process type.
468 size_t memory_size;
469 base::StringPiece metrics_name;
470 switch (data_.process_type) {
bcwhite2496c83e2016-08-29 17:29:25471 case PROCESS_TYPE_UTILITY:
Matt Menkee5bc4a562017-08-07 23:58:22472 // This needs to be larger for the network service.
473 memory_size = 256 << 10; // 256 KiB
bcwhite2496c83e2016-08-29 17:29:25474 metrics_name = "UtilityMetrics";
475 break;
476
477 case PROCESS_TYPE_ZYGOTE:
bcwhite867f45532017-01-05 17:29:02478 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25479 metrics_name = "ZygoteMetrics";
480 break;
481
482 case PROCESS_TYPE_SANDBOX_HELPER:
bcwhite867f45532017-01-05 17:29:02483 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25484 metrics_name = "SandboxHelperMetrics";
485 break;
486
bcwhiteb58a5fe2016-08-22 16:25:56487 case PROCESS_TYPE_GPU:
bcwhite867f45532017-01-05 17:29:02488 memory_size = 64 << 10; // 64 KiB
bcwhiteb58a5fe2016-08-22 16:25:56489 metrics_name = "GpuMetrics";
490 break;
491
bcwhite2496c83e2016-08-29 17:29:25492 case PROCESS_TYPE_PPAPI_PLUGIN:
bcwhite867f45532017-01-05 17:29:02493 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25494 metrics_name = "PpapiPluginMetrics";
495 break;
496
497 case PROCESS_TYPE_PPAPI_BROKER:
bcwhite867f45532017-01-05 17:29:02498 memory_size = 64 << 10; // 64 KiB
bcwhite2496c83e2016-08-29 17:29:25499 metrics_name = "PpapiBrokerMetrics";
500 break;
501
bcwhiteb58a5fe2016-08-22 16:25:56502 default:
bcwhitec600ac12017-07-12 13:37:13503 // Report new processes. "Custom" ones are renumbered to 1000+ so that
504 // they won't conflict with any standard ones in the future.
505 int process_type = data_.process_type;
506 if (process_type >= PROCESS_TYPE_CONTENT_END)
507 process_type += 1000 - PROCESS_TYPE_CONTENT_END;
508 UMA_HISTOGRAM_SPARSE_SLOWLY(
509 "UMA.SubprocessMetricsProvider.UntrackedProcesses", process_type);
bcwhiteb58a5fe2016-08-22 16:25:56510 return;
511 }
512
513 // Create the shared memory segment and attach an allocator to it.
514 // Mapping the memory shouldn't fail but be safe if it does; everything
515 // will continue to work but just as if persistence weren't available.
516 std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory());
517 if (!shm->CreateAndMapAnonymous(memory_size))
518 return;
519 metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator(
520 std::move(shm), static_cast<uint64_t>(data_.id), metrics_name,
521 /*readonly=*/false));
522}
523
524void BrowserChildProcessHostImpl::ShareMetricsAllocatorToProcess() {
525 if (metrics_allocator_) {
Nicholas Verne91bf4a632017-10-12 21:14:24526 HistogramController::GetInstance()->SetHistogramMemory<ChildProcessHost>(
527 GetHost(),
528 mojo::WrapSharedMemoryHandle(
529 metrics_allocator_->shared_memory()->handle().Duplicate(),
530 metrics_allocator_->shared_memory()->mapped_size(), false));
531 } else {
532 HistogramController::GetInstance()->SetHistogramMemory<ChildProcessHost>(
533 GetHost(), mojo::ScopedSharedBufferHandle());
bcwhiteb58a5fe2016-08-22 16:25:56534 }
535}
536
wfh3adf87d2016-05-03 23:26:06537void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) {
538 delegate_->OnProcessLaunchFailed(error_code);
amistry012289f2016-04-01 00:56:37539 notify_child_disconnected_ = false;
[email protected]fa01e472014-02-11 14:45:35540 delete delegate_; // Will delete us
541}
542
[email protected]4c01d4992012-01-23 23:33:01543void BrowserChildProcessHostImpl::OnProcessLaunched() {
afakhry9cc79002015-10-22 19:25:15544 DCHECK_CURRENTLY_ON(BrowserThread::IO);
545
rvargas079d1842014-10-17 22:32:16546 const base::Process& process = child_process_->GetProcess();
547 DCHECK(process.IsValid());
[email protected]162a9fd2013-03-06 20:47:49548
rockotfe2fecc2017-01-19 20:16:19549 if (child_connection_)
550 child_connection_->SetProcessHandle(process.Handle());
551
jam3c8c50c2015-11-25 18:48:29552#if defined(OS_WIN)
[email protected]162a9fd2013-03-06 20:47:49553 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
554 // child process exits. This watcher is stopped once the IPC channel is
555 // connected and the exit of the child process is detecter by an error on the
556 // IPC channel thereafter.
rvargas079d1842014-10-17 22:32:16557 DCHECK(!early_exit_watcher_.GetWatchedObject());
jam7fab1082015-09-29 02:26:18558 early_exit_watcher_.StartWatchingOnce(process.Handle(), this);
[email protected]162a9fd2013-03-06 20:47:49559#endif
560
rvargas079d1842014-10-17 22:32:16561 // TODO(rvargas) crbug.com/417532: Don't store a handle.
562 data_.handle = process.Handle();
[email protected]4967f792012-01-20 22:14:40563 delegate_->OnProcessLaunched();
afakhry9cc79002015-10-22 19:25:15564
565 if (is_channel_connected_) {
bcwhiteb58a5fe2016-08-22 16:25:56566 ShareMetricsAllocatorToProcess();
tzik4fea24af2017-08-23 11:41:47567 BrowserThread::PostTask(
568 BrowserThread::UI, FROM_HERE,
569 base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
afakhry9cc79002015-10-22 19:25:15570 }
571}
572
573bool BrowserChildProcessHostImpl::IsProcessLaunched() const {
574 DCHECK_CURRENTLY_ON(BrowserThread::IO);
575
576 return child_process_.get() && child_process_->GetProcess().IsValid();
[email protected]d27893f62010-07-03 05:47:42577}
[email protected]130757672012-10-24 00:26:19578
rockot229fb28e2016-06-16 04:46:16579// static
580void BrowserChildProcessHostImpl::OnMojoError(
581 base::WeakPtr<BrowserChildProcessHostImpl> process,
582 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
583 const std::string& error) {
584 if (!task_runner->BelongsToCurrentThread()) {
585 task_runner->PostTask(
tzik4fea24af2017-08-23 11:41:47586 FROM_HERE, base::BindOnce(&BrowserChildProcessHostImpl::OnMojoError,
587 process, task_runner, error));
olka91f1d412016-11-21 15:24:53588 return;
rockot229fb28e2016-06-16 04:46:16589 }
590 if (!process)
591 return;
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28592 HistogramBadMessageTerminated(
593 static_cast<ProcessType>(process->data_.process_type));
rockot229fb28e2016-06-16 04:46:16594 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
595 switches::kDisableKillAfterBadIPC)) {
596 return;
597 }
598 LOG(ERROR) << "Terminating child process for bad Mojo message: " << error;
599
Yuzhu Shen32fcad72017-09-14 23:12:37600 // Create a memory dump with the error message captured in a crash key value.
601 // This will make it easy to determine details about what interface call
602 // failed.
Robert Sesek1419427e2017-12-07 15:01:32603 base::debug::ScopedCrashKeyString scoped_error_key(
604 bad_message::GetMojoErrorCrashKey(), error);
rockot229fb28e2016-06-16 04:46:16605 base::debug::DumpWithoutCrashing();
606 process->child_process_->GetProcess().Terminate(
607 RESULT_CODE_KILLED_BAD_MESSAGE, false);
608}
609
[email protected]162a9fd2013-03-06 20:47:49610#if defined(OS_WIN)
611
rvargas079d1842014-10-17 22:32:16612void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
[email protected]162a9fd2013-03-06 20:47:49613 OnChildDisconnected();
614}
615
616#endif
617
[email protected]130757672012-10-24 00:26:19618} // namespace content