blob: d9809db4ffbe9c535bfd20eeaa8ec19aed21ede1 [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"
wfhaf32d0b2015-04-07 02:21:3610#include "base/debug/dump_without_crashing.h"
erikchen55edbff2016-05-03 23:53:1711#include "base/feature_list.h"
[email protected]57999812013-02-24 05:40:5212#include "base/files/file_path.h"
[email protected]d3c6c0d72010-12-09 08:15:0413#include "base/lazy_instance.h"
[email protected]d27893f62010-07-03 05:47:4214#include "base/logging.h"
avib7348942015-12-25 20:57:1015#include "base/macros.h"
erikchen55edbff2016-05-03 23:53:1716#include "base/metrics/field_trial.h"
asvitkine30330812016-08-30 04:01:0817#include "base/metrics/histogram_macros.h"
bcwhiteb58a5fe2016-08-22 16:25:5618#include "base/metrics/persistent_histogram_allocator.h"
19#include "base/metrics/persistent_memory_allocator.h"
[email protected]7286e3fc2011-07-19 22:13:2420#include "base/stl_util.h"
[email protected]10994d132013-06-11 07:16:1821#include "base/strings/string_util.h"
rockotda9887902016-08-19 20:46:4222#include "base/strings/stringprintf.h"
[email protected]162a9fd2013-03-06 20:47:4923#include "base/synchronization/waitable_event.h"
rockot229fb28e2016-06-16 04:46:1624#include "base/threading/thread_task_runner_handle.h"
avib7348942015-12-25 20:57:1025#include "build/build_config.h"
primianoccb26c62016-06-01 21:50:0226#include "components/tracing/common/tracing_switches.h"
[email protected]83ab4a282012-07-12 18:19:4527#include "content/browser/histogram_message_filter.h"
[email protected]678c0362012-12-05 08:02:4428#include "content/browser/loader/resource_message_filter.h"
petrcermak29bd4052015-09-24 08:28:4829#include "content/browser/memory/memory_message_filter.h"
[email protected]33047f12011-12-01 23:20:2030#include "content/browser/profiler_message_filter.h"
benff461632016-10-06 14:27:3331#include "content/browser/service_manager/service_manager_context.h"
[email protected]3a85b1f2013-02-01 04:47:4032#include "content/browser/tracing/trace_message_filter.h"
[email protected]4734d0b2011-12-03 07:10:4433#include "content/common/child_process_host_impl.h"
John Abd-El-Malekfbada2c2015-11-24 06:38:1534#include "content/common/child_process_messages.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"
lawrencewu2c930822016-10-13 13:54:2541#include "content/public/common/content_features.h"
[email protected]c08950d22011-10-13 22:20:2942#include "content/public/common/content_switches.h"
rockotda9887902016-08-19 20:46:4243#include "content/public/common/mojo_channel_switches.h"
[email protected]f3b357692013-03-22 05:16:1344#include "content/public/common/process_type.h"
[email protected]b39ef1cb2011-10-25 04:46:5545#include "content/public/common/result_codes.h"
erikchend8a3d9022015-10-22 20:02:0246#include "ipc/attachment_broker.h"
47#include "ipc/attachment_broker_privileged.h"
rockotc637caf9b2016-02-10 09:57:0848#include "mojo/edk/embedder/embedder.h"
[email protected]d27893f62010-07-03 05:47:4249
[email protected]f1675202012-07-09 15:18:0050#if defined(OS_MACOSX)
[email protected]458433c2012-02-29 23:43:3951#include "content/browser/mach_broker_mac.h"
[email protected]3838ca12011-11-02 14:37:1552#endif
[email protected]a3a7e2c2011-09-16 23:07:0553
[email protected]130757672012-10-24 00:26:1954namespace content {
[email protected]d27893f62010-07-03 05:47:4255namespace {
56
[email protected]4c01d4992012-01-23 23:33:0157static base::LazyInstance<BrowserChildProcessHostImpl::BrowserChildProcessList>
[email protected]4967f792012-01-20 22:14:4058 g_child_process_list = LAZY_INSTANCE_INITIALIZER;
[email protected]d27893f62010-07-03 05:47:4259
brettwf2a90a22015-06-03 23:42:5460base::LazyInstance<base::ObserverList<BrowserChildProcessObserver>>
[email protected]f4eaf7b92013-02-28 22:00:4061 g_observers = LAZY_INSTANCE_INITIALIZER;
62
afakhry9cc79002015-10-22 19:25:1563void NotifyProcessLaunchedAndConnected(const ChildProcessData& data) {
ericwilligers254597b2016-10-17 10:32:3164 for (auto& observer : g_observers.Get())
65 observer.BrowserChildProcessLaunchedAndConnected(data);
afakhry9cc79002015-10-22 19:25:1566}
67
[email protected]f4eaf7b92013-02-28 22:00:4068void NotifyProcessHostConnected(const ChildProcessData& data) {
ericwilligers254597b2016-10-17 10:32:3169 for (auto& observer : g_observers.Get())
70 observer.BrowserChildProcessHostConnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4071}
72
73void NotifyProcessHostDisconnected(const ChildProcessData& data) {
ericwilligers254597b2016-10-17 10:32:3174 for (auto& observer : g_observers.Get())
75 observer.BrowserChildProcessHostDisconnected(data);
[email protected]f4eaf7b92013-02-28 22:00:4076}
77
wfh22e2f4a22015-04-28 22:39:2178void NotifyProcessCrashed(const ChildProcessData& data, int exit_code) {
ericwilligers254597b2016-10-17 10:32:3179 for (auto& observer : g_observers.Get())
80 observer.BrowserChildProcessCrashed(data, exit_code);
[email protected]4306c3792011-12-02 01:57:5381}
[email protected]d27893f62010-07-03 05:47:4282
wfhf0003292015-08-18 22:16:4683void NotifyProcessKilled(const ChildProcessData& data, int exit_code) {
ericwilligers254597b2016-10-17 10:32:3184 for (auto& observer : g_observers.Get())
85 observer.BrowserChildProcessKilled(data, exit_code);
wfhf0003292015-08-18 22:16:4686}
87
[email protected]d27893f62010-07-03 05:47:4288} // namespace
89
[email protected]4967f792012-01-20 22:14:4090BrowserChildProcessHost* BrowserChildProcessHost::Create(
vadimt379d7fe2015-04-01 00:09:3591 content::ProcessType process_type,
[email protected]4967f792012-01-20 22:14:4092 BrowserChildProcessHostDelegate* delegate) {
rockotda9887902016-08-19 20:46:4293 return Create(process_type, delegate, std::string());
amistry6ad1e812016-06-06 05:36:3094}
95
96BrowserChildProcessHost* BrowserChildProcessHost::Create(
97 content::ProcessType process_type,
98 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:4299 const std::string& service_name) {
100 return new BrowserChildProcessHostImpl(process_type, delegate, service_name);
[email protected]4967f792012-01-20 22:14:40101}
102
amistryfaa231a42015-05-20 01:49:12103BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) {
104 DCHECK_CURRENTLY_ON(BrowserThread::IO);
105 BrowserChildProcessHostImpl::BrowserChildProcessList* process_list =
106 g_child_process_list.Pointer();
107 for (BrowserChildProcessHostImpl* host : *process_list) {
108 if (host->GetData().id == child_process_id)
109 return host;
110 }
111 return nullptr;
112}
113
[email protected]458433c2012-02-29 23:43:39114#if defined(OS_MACOSX)
erikchencd3e0e7b2015-10-01 22:53:51115base::PortProvider* BrowserChildProcessHost::GetPortProvider() {
[email protected]458433c2012-02-29 23:43:39116 return MachBroker::GetInstance();
117}
118#endif
119
[email protected]f4eaf7b92013-02-28 22:00:40120// static
[email protected]4c01d4992012-01-23 23:33:01121BrowserChildProcessHostImpl::BrowserChildProcessList*
122 BrowserChildProcessHostImpl::GetIterator() {
[email protected]4967f792012-01-20 22:14:40123 return g_child_process_list.Pointer();
124}
125
[email protected]f4eaf7b92013-02-28 22:00:40126// static
127void BrowserChildProcessHostImpl::AddObserver(
128 BrowserChildProcessObserver* observer) {
mostynbfbcdc27a2015-03-13 17:58:52129 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]f4eaf7b92013-02-28 22:00:40130 g_observers.Get().AddObserver(observer);
131}
132
133// static
134void BrowserChildProcessHostImpl::RemoveObserver(
135 BrowserChildProcessObserver* observer) {
136 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126.
137 g_observers.Get().RemoveObserver(observer);
138}
139
[email protected]4c01d4992012-01-23 23:33:01140BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
vadimt379d7fe2015-04-01 00:09:35141 content::ProcessType process_type,
amistry6ad1e812016-06-06 05:36:30142 BrowserChildProcessHostDelegate* delegate,
rockotda9887902016-08-19 20:46:42143 const std::string& service_name)
[email protected]f3b357692013-03-22 05:16:13144 : data_(process_type),
[email protected]9dd90152013-08-02 22:09:13145 delegate_(delegate),
rockotda9887902016-08-19 20:46:42146 child_token_(mojo::edk::GenerateRandomToken()),
afakhry9cc79002015-10-22 19:25:15147 power_monitor_message_broadcaster_(this),
amistry012289f2016-04-01 00:56:37148 is_channel_connected_(false),
rockot229fb28e2016-06-16 04:46:16149 notify_child_disconnected_(false),
150 weak_factory_(this) {
[email protected]4734d0b2011-12-03 07:10:44151 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
[email protected]4306c3792011-12-02 01:57:53152
erikchend8a3d9022015-10-22 20:02:02153#if USE_ATTACHMENT_BROKER
154 // Construct the privileged attachment broker early in the life cycle of a
155 // child process. This ensures that when a test is being run in one of the
156 // single process modes, the global attachment broker is the privileged
157 // attachment broker, rather than an unprivileged attachment broker.
jame1f453c2016-03-21 15:51:34158#if defined(OS_MACOSX)
erikchend8a3d9022015-10-22 20:02:02159 IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(
160 MachBroker::GetInstance());
161#else
162 IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
jame1f453c2016-03-21 15:51:34163#endif // defined(OS_MACOSX)
erikchend8a3d9022015-10-22 20:02:02164#endif // USE_ATTACHMENT_BROKER
165
[email protected]4734d0b2011-12-03 07:10:44166 child_process_host_.reset(ChildProcessHost::Create(this));
ssid72c5d6822015-06-26 15:51:42167 AddFilter(new TraceMessageFilter(data_.id));
[email protected]ba780c12013-10-01 17:07:06168 AddFilter(new ProfilerMessageFilter(process_type));
169 AddFilter(new HistogramMessageFilter);
chrishada753d472015-12-08 00:57:13170 AddFilter(new MemoryMessageFilter(this, process_type));
[email protected]38917fe2011-04-06 17:29:12171
172 g_child_process_list.Get().push_back(this);
[email protected]130757672012-10-24 00:26:19173 GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
[email protected]30c4c67a2014-07-22 02:33:55174
175 power_monitor_message_broadcaster_.Init();
rockotda9887902016-08-19 20:46:42176
177 if (!service_name.empty()) {
178 DCHECK_CURRENTLY_ON(BrowserThread::IO);
bend32292b2016-10-07 00:21:58179 child_connection_.reset(new ChildConnection(
rockotda9887902016-08-19 20:46:42180 service_name, base::StringPrintf("%d", data_.id), child_token_,
benff461632016-10-06 14:27:33181 ServiceManagerContext::GetConnectorForIOThread(),
rockotda9887902016-08-19 20:46:42182 base::ThreadTaskRunnerHandle::Get()));
183 }
bcwhiteb58a5fe2016-08-22 16:25:56184
185 // Create a persistent memory segment for subprocess histograms.
186 CreateMetricsAllocator();
[email protected]38917fe2011-04-06 17:29:12187}
188
[email protected]4c01d4992012-01-23 23:33:01189BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
[email protected]d3c6c0d72010-12-09 08:15:04190 g_child_process_list.Get().remove(this);
amistry012289f2016-04-01 00:56:37191
192 if (notify_child_disconnected_) {
193 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
194 base::Bind(&NotifyProcessHostDisconnected, data_));
195 }
[email protected]d27893f62010-07-03 05:47:42196}
197
198// static
[email protected]4c01d4992012-01-23 23:33:01199void BrowserChildProcessHostImpl::TerminateAll() {
mostynbfbcdc27a2015-03-13 17:58:52200 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33201 // Make a copy since the BrowserChildProcessHost dtor mutates the original
202 // list.
203 BrowserChildProcessList copy = g_child_process_list.Get();
[email protected]5998d9d2012-03-06 04:25:26204 for (BrowserChildProcessList::iterator it = copy.begin();
205 it != copy.end(); ++it) {
206 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl.
207 }
[email protected]d27893f62010-07-03 05:47:42208}
209
erikchen55edbff2016-05-03 23:53:17210// static
lawrencewu0b4964922016-10-25 16:28:14211void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
erikchen55edbff2016-05-03 23:53:17212 base::CommandLine* cmd_line) {
213 std::string enabled_features;
214 std::string disabled_features;
215 base::FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features,
216 &disabled_features);
217 if (!enabled_features.empty())
218 cmd_line->AppendSwitchASCII(switches::kEnableFeatures, enabled_features);
219 if (!disabled_features.empty())
220 cmd_line->AppendSwitchASCII(switches::kDisableFeatures, disabled_features);
221
222 // If we run base::FieldTrials, we want to pass to their state to the
223 // child process so that it can act in accordance with each state.
lawrencewu0b4964922016-10-25 16:28:14224 base::FieldTrialList::CopyFieldTrialStateToFlags(switches::kFieldTrialHandle,
225 cmd_line);
erikchen55edbff2016-05-03 23:53:17226}
227
[email protected]4c01d4992012-01-23 23:33:01228void BrowserChildProcessHostImpl::Launch(
[email protected]34f48682013-03-20 00:30:18229 SandboxedProcessLauncherDelegate* delegate,
sievers954e37a2015-03-28 01:50:24230 base::CommandLine* cmd_line,
sievers954e37a2015-03-28 01:50:24231 bool terminate_on_shutdown) {
mostynbfbcdc27a2015-03-13 17:58:52232 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]b80f68432011-05-02 17:22:30233
[email protected]130757672012-10-24 00:26:19234 GetContentClient()->browser()->AppendExtraCommandLineSwitches(
[email protected]4967f792012-01-20 22:14:40235 cmd_line, data_.id);
[email protected]b80f68432011-05-02 17:22:30236
[email protected]479278702014-08-11 20:32:09237 const base::CommandLine& browser_command_line =
238 *base::CommandLine::ForCurrentProcess();
thestig418c5052016-04-11 19:39:19239 static const char* const kForwardSwitches[] = {
[email protected]2b065f82012-10-18 07:11:16240 switches::kDisableLogging,
[email protected]2b065f82012-10-18 07:11:16241 switches::kEnableLogging,
[email protected]65f0ff72014-06-20 20:32:15242 switches::kIPCConnectionTimeout,
[email protected]2b065f82012-10-18 07:11:16243 switches::kLoggingLevel,
[email protected]2bf64a92013-07-11 23:10:40244 switches::kTraceToConsole,
[email protected]2b065f82012-10-18 07:11:16245 switches::kV,
246 switches::kVModule,
247 };
248 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
249 arraysize(kForwardSwitches));
[email protected]719a2052012-07-30 21:00:43250
rockotda9887902016-08-19 20:46:42251 if (child_connection_) {
bend32292b2016-10-07 00:21:58252 cmd_line->AppendSwitchASCII(switches::kServiceRequestChannelToken,
rockotda9887902016-08-19 20:46:42253 child_connection_->service_token());
254 }
255
amistry012289f2016-04-01 00:56:37256 notify_child_disconnected_ = true;
[email protected]d27893f62010-07-03 05:47:42257 child_process_.reset(new ChildProcessLauncher(
lawrencewu0b4964922016-10-25 16:28:14258 delegate, cmd_line, data_.id, this, child_token_,
rockot229fb28e2016-06-16 04:46:16259 base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
260 weak_factory_.GetWeakPtr(),
261 base::ThreadTaskRunnerHandle::Get()),
sievers954e37a2015-03-28 01:50:24262 terminate_on_shutdown));
[email protected]d27893f62010-07-03 05:47:42263}
264
[email protected]4c01d4992012-01-23 23:33:01265const ChildProcessData& BrowserChildProcessHostImpl::GetData() const {
mostynbfbcdc27a2015-03-13 17:58:52266 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40267 return data_;
268}
269
[email protected]4c01d4992012-01-23 23:33:01270ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const {
mostynbfbcdc27a2015-03-13 17:58:52271 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40272 return child_process_host_.get();
273}
274
rvargas5779b382014-11-18 20:44:11275const base::Process& BrowserChildProcessHostImpl::GetProcess() const {
mostynbfbcdc27a2015-03-13 17:58:52276 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]5d84d012010-12-02 17:17:21277 DCHECK(child_process_.get())
278 << "Requesting a child process handle before launching.";
rvargas079d1842014-10-17 22:32:16279 DCHECK(child_process_->GetProcess().IsValid())
[email protected]5d84d012010-12-02 17:17:21280 << "Requesting a child process handle before launch has completed OK.";
rvargas5779b382014-11-18 20:44:11281 return child_process_->GetProcess();
[email protected]5d84d012010-12-02 17:17:21282}
283
bcwhiteb58a5fe2016-08-22 16:25:56284std::unique_ptr<base::SharedPersistentMemoryAllocator>
285BrowserChildProcessHostImpl::TakeMetricsAllocator() {
286 return std::move(metrics_allocator_);
287}
288
[email protected]fcf75d42013-12-03 20:11:26289void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
mostynbfbcdc27a2015-03-13 17:58:52290 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33291 data_.name = name;
292}
293
[email protected]4c01d4992012-01-23 23:33:01294void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
mostynbfbcdc27a2015-03-13 17:58:52295 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33296 data_.handle = handle;
297}
298
[email protected]4c01d4992012-01-23 23:33:01299void BrowserChildProcessHostImpl::ForceShutdown() {
mostynbfbcdc27a2015-03-13 17:58:52300 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]d3c6c0d72010-12-09 08:15:04301 g_child_process_list.Get().remove(this);
[email protected]4cb43102011-12-02 20:24:49302 child_process_host_->ForceShutdown();
[email protected]d27893f62010-07-03 05:47:42303}
304
[email protected]d36860d2013-05-31 00:04:21305void BrowserChildProcessHostImpl::SetBackgrounded(bool backgrounded) {
306 child_process_->SetProcessBackgrounded(backgrounded);
307}
308
[email protected]ba780c12013-10-01 17:07:06309void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
310 child_process_host_->AddFilter(filter->GetFilter());
311}
312
rockot400ea35b2016-10-15 19:15:32313service_manager::InterfaceProvider*
314BrowserChildProcessHostImpl::GetRemoteInterfaces() {
rockotda9887902016-08-19 20:46:42315 DCHECK_CURRENTLY_ON(BrowserThread::IO);
316 if (!child_connection_)
317 return nullptr;
318
319 return child_connection_->GetRemoteInterfaces();
320}
321
[email protected]ef2f6ba2014-05-15 23:06:07322void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
323 int process_type) {
324 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
325 PROCESS_TYPE_MAX);
326}
327
[email protected]4c01d4992012-01-23 23:33:01328base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
[email protected]547603d2013-08-27 17:59:19329 bool known_dead, int* exit_code) {
mostynbfbcdc27a2015-03-13 17:58:52330 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]59383c782013-04-17 16:43:27331 if (!child_process_) // If the delegate doesn't use Launch() helper.
[email protected]4967f792012-01-20 22:14:40332 return base::GetTerminationStatus(data_.handle, exit_code);
[email protected]547603d2013-08-27 17:59:19333 return child_process_->GetChildTerminationStatus(known_dead,
[email protected]c7691de2012-12-06 08:31:51334 exit_code);
[email protected]d27893f62010-07-03 05:47:42335}
336
[email protected]4c01d4992012-01-23 23:33:01337bool BrowserChildProcessHostImpl::OnMessageReceived(
338 const IPC::Message& message) {
[email protected]4967f792012-01-20 22:14:40339 return delegate_->OnMessageReceived(message);
[email protected]4cb43102011-12-02 20:24:49340}
341
avib7348942015-12-25 20:57:10342void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
afakhry9cc79002015-10-22 19:25:15343 DCHECK_CURRENTLY_ON(BrowserThread::IO);
344
345 is_channel_connected_ = true;
amistry012289f2016-04-01 00:56:37346 notify_child_disconnected_ = true;
afakhry9cc79002015-10-22 19:25:15347
[email protected]162a9fd2013-03-06 20:47:49348#if defined(OS_WIN)
349 // From this point onward, the exit of the child process is detected by an
350 // error on the IPC channel.
[email protected]162a9fd2013-03-06 20:47:49351 early_exit_watcher_.StopWatching();
352#endif
353
[email protected]f4eaf7b92013-02-28 22:00:40354 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
355 base::Bind(&NotifyProcessHostConnected, data_));
[email protected]162a9fd2013-03-06 20:47:49356
[email protected]4967f792012-01-20 22:14:40357 delegate_->OnChannelConnected(peer_pid);
afakhry9cc79002015-10-22 19:25:15358
359 if (IsProcessLaunched()) {
bcwhiteb58a5fe2016-08-22 16:25:56360 ShareMetricsAllocatorToProcess();
afakhry9cc79002015-10-22 19:25:15361 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
362 base::Bind(&NotifyProcessLaunchedAndConnected,
363 data_));
364 }
[email protected]4967f792012-01-20 22:14:40365}
366
[email protected]4c01d4992012-01-23 23:33:01367void BrowserChildProcessHostImpl::OnChannelError() {
[email protected]4967f792012-01-20 22:14:40368 delegate_->OnChannelError();
[email protected]0d6e9bd2011-10-18 04:29:16369}
370
[email protected]ef2f6ba2014-05-15 23:06:07371void BrowserChildProcessHostImpl::OnBadMessageReceived(
372 const IPC::Message& message) {
jbauman278b2cc2016-01-08 22:48:53373 TerminateOnBadMessageReceived(message.type());
374}
375
376void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(uint32_t type) {
[email protected]ef2f6ba2014-05-15 23:06:07377 HistogramBadMessageTerminated(data_.process_type);
avi83883c82014-12-23 00:08:49378 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]e44d1342014-05-16 21:29:33379 switches::kDisableKillAfterBadIPC)) {
380 return;
381 }
jamescookda2505812015-03-20 18:01:18382 LOG(ERROR) << "Terminating child process for bad IPC message of type "
jbauman278b2cc2016-01-08 22:48:53383 << type;
wfhaf32d0b2015-04-07 02:21:36384
385 // Create a memory dump. This will contain enough stack frames to work out
386 // what the bad message was.
387 base::debug::DumpWithoutCrashing();
388
rvargas486b2f562015-03-18 01:36:33389 child_process_->GetProcess().Terminate(RESULT_CODE_KILLED_BAD_MESSAGE, false);
[email protected]ef2f6ba2014-05-15 23:06:07390}
391
[email protected]4c01d4992012-01-23 23:33:01392bool BrowserChildProcessHostImpl::CanShutdown() {
[email protected]4967f792012-01-20 22:14:40393 return delegate_->CanShutdown();
[email protected]4cb43102011-12-02 20:24:49394}
395
[email protected]4c01d4992012-01-23 23:33:01396void BrowserChildProcessHostImpl::OnChildDisconnected() {
mostynbfbcdc27a2015-03-13 17:58:52397 DCHECK_CURRENTLY_ON(BrowserThread::IO);
jbauman319402e2014-10-21 17:52:21398#if defined(OS_WIN)
399 // OnChildDisconnected may be called without OnChannelConnected, so stop the
400 // early exit watcher so GetTerminationStatus can close the process handle.
401 early_exit_watcher_.StopWatching();
402#endif
[email protected]6d057a0c2013-07-09 21:12:07403 if (child_process_.get() || data_.handle) {
[email protected]6d057a0c2013-07-09 21:12:07404 int exit_code;
[email protected]547603d2013-08-27 17:59:19405 base::TerminationStatus status = GetTerminationStatus(
406 true /* known_dead */, &exit_code);
[email protected]6d057a0c2013-07-09 21:12:07407 switch (status) {
408 case base::TERMINATION_STATUS_PROCESS_CRASHED:
409 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
410 delegate_->OnProcessCrashed(exit_code);
wfh22e2f4a22015-04-28 22:39:21411 BrowserThread::PostTask(
412 BrowserThread::UI, FROM_HERE,
413 base::Bind(&NotifyProcessCrashed, data_, exit_code));
[email protected]6d057a0c2013-07-09 21:12:07414 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
415 data_.process_type,
416 PROCESS_TYPE_MAX);
417 break;
418 }
derekjchow1b0f3bb2015-07-30 18:51:10419#if defined(OS_ANDROID)
420 case base::TERMINATION_STATUS_OOM_PROTECTED:
421#endif
oshima620225722015-06-04 19:45:27422#if defined(OS_CHROMEOS)
423 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
424#endif
[email protected]6d057a0c2013-07-09 21:12:07425 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
426 delegate_->OnProcessCrashed(exit_code);
wfhf0003292015-08-18 22:16:46427 BrowserThread::PostTask(
428 BrowserThread::UI, FROM_HERE,
429 base::Bind(&NotifyProcessKilled, data_, exit_code));
[email protected]6d057a0c2013-07-09 21:12:07430 // Report that this child process was killed.
431 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
432 data_.process_type,
433 PROCESS_TYPE_MAX);
434 break;
435 }
436 case base::TERMINATION_STATUS_STILL_RUNNING: {
437 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2",
438 data_.process_type,
439 PROCESS_TYPE_MAX);
440 }
441 default:
442 break;
[email protected]12fed812011-09-16 05:47:29443 }
[email protected]6d057a0c2013-07-09 21:12:07444 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
445 data_.process_type,
446 PROCESS_TYPE_MAX);
oshima620225722015-06-04 19:45:27447#if defined(OS_CHROMEOS)
448 if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
449 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2.OOM",
450 data_.process_type,
451 PROCESS_TYPE_MAX);
452 }
453#endif
[email protected]d27893f62010-07-03 05:47:42454 }
[email protected]4967f792012-01-20 22:14:40455 delete delegate_; // Will delete us
[email protected]a3a7e2c2011-09-16 23:07:05456}
457
[email protected]4c01d4992012-01-23 23:33:01458bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
[email protected]4cb43102011-12-02 20:24:49459 return child_process_host_->Send(message);
460}
461
bcwhiteb58a5fe2016-08-22 16:25:56462void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
463 // Create a persistent memory segment for subprocess histograms only if
464 // they're active in the browser.
465 // TODO(bcwhite): Remove this once persistence is always enabled.
466 if (!base::GlobalHistogramAllocator::Get())
467 return;
468
469 // Determine the correct parameters based on the process type.
470 size_t memory_size;
471 base::StringPiece metrics_name;
472 switch (data_.process_type) {
bcwhite2496c83e2016-08-29 17:29:25473 case PROCESS_TYPE_UTILITY:
474 memory_size = 100 << 10; // 100 KiB
475 metrics_name = "UtilityMetrics";
476 break;
477
478 case PROCESS_TYPE_ZYGOTE:
479 memory_size = 100 << 10; // 100 KiB
480 metrics_name = "ZygoteMetrics";
481 break;
482
483 case PROCESS_TYPE_SANDBOX_HELPER:
484 memory_size = 100 << 10; // 100 KiB
485 metrics_name = "SandboxHelperMetrics";
486 break;
487
bcwhiteb58a5fe2016-08-22 16:25:56488 case PROCESS_TYPE_GPU:
489 memory_size = 100 << 10; // 100 KiB
490 metrics_name = "GpuMetrics";
491 break;
492
bcwhite2496c83e2016-08-29 17:29:25493 case PROCESS_TYPE_PPAPI_PLUGIN:
494 memory_size = 100 << 10; // 100 KiB
495 metrics_name = "PpapiPluginMetrics";
496 break;
497
498 case PROCESS_TYPE_PPAPI_BROKER:
499 memory_size = 100 << 10; // 100 KiB
500 metrics_name = "PpapiBrokerMetrics";
501 break;
502
bcwhiteb58a5fe2016-08-22 16:25:56503 default:
bcwhite2496c83e2016-08-29 17:29:25504 UMA_HISTOGRAM_ENUMERATION(
505 "UMA.SubprocessMetricsProvider.UntrackedProcesses",
506 data_.process_type, PROCESS_TYPE_CONTENT_END);
bcwhiteb58a5fe2016-08-22 16:25:56507 return;
508 }
509
510 // Create the shared memory segment and attach an allocator to it.
511 // Mapping the memory shouldn't fail but be safe if it does; everything
512 // will continue to work but just as if persistence weren't available.
513 std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory());
514 if (!shm->CreateAndMapAnonymous(memory_size))
515 return;
516 metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator(
517 std::move(shm), static_cast<uint64_t>(data_.id), metrics_name,
518 /*readonly=*/false));
519}
520
521void BrowserChildProcessHostImpl::ShareMetricsAllocatorToProcess() {
522 if (metrics_allocator_) {
523 base::SharedMemoryHandle shm_handle;
524 metrics_allocator_->shared_memory()->ShareToProcess(data_.handle,
525 &shm_handle);
526 Send(new ChildProcessMsg_SetHistogramMemory(
527 shm_handle, metrics_allocator_->shared_memory()->mapped_size()));
528 }
529}
530
wfh3adf87d2016-05-03 23:26:06531void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) {
532 delegate_->OnProcessLaunchFailed(error_code);
amistry012289f2016-04-01 00:56:37533 notify_child_disconnected_ = false;
[email protected]fa01e472014-02-11 14:45:35534 delete delegate_; // Will delete us
535}
536
[email protected]4c01d4992012-01-23 23:33:01537void BrowserChildProcessHostImpl::OnProcessLaunched() {
afakhry9cc79002015-10-22 19:25:15538 DCHECK_CURRENTLY_ON(BrowserThread::IO);
539
rvargas079d1842014-10-17 22:32:16540 const base::Process& process = child_process_->GetProcess();
541 DCHECK(process.IsValid());
[email protected]162a9fd2013-03-06 20:47:49542
jam3c8c50c2015-11-25 18:48:29543#if defined(OS_WIN)
[email protected]162a9fd2013-03-06 20:47:49544 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
545 // child process exits. This watcher is stopped once the IPC channel is
546 // connected and the exit of the child process is detecter by an error on the
547 // IPC channel thereafter.
rvargas079d1842014-10-17 22:32:16548 DCHECK(!early_exit_watcher_.GetWatchedObject());
jam7fab1082015-09-29 02:26:18549 early_exit_watcher_.StartWatchingOnce(process.Handle(), this);
[email protected]162a9fd2013-03-06 20:47:49550#endif
551
rvargas079d1842014-10-17 22:32:16552 // TODO(rvargas) crbug.com/417532: Don't store a handle.
553 data_.handle = process.Handle();
[email protected]4967f792012-01-20 22:14:40554 delegate_->OnProcessLaunched();
afakhry9cc79002015-10-22 19:25:15555
556 if (is_channel_connected_) {
bcwhiteb58a5fe2016-08-22 16:25:56557 ShareMetricsAllocatorToProcess();
afakhry9cc79002015-10-22 19:25:15558 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
559 base::Bind(&NotifyProcessLaunchedAndConnected,
560 data_));
561 }
562}
563
564bool BrowserChildProcessHostImpl::IsProcessLaunched() const {
565 DCHECK_CURRENTLY_ON(BrowserThread::IO);
566
567 return child_process_.get() && child_process_->GetProcess().IsValid();
[email protected]d27893f62010-07-03 05:47:42568}
[email protected]130757672012-10-24 00:26:19569
rockot229fb28e2016-06-16 04:46:16570// static
571void BrowserChildProcessHostImpl::OnMojoError(
572 base::WeakPtr<BrowserChildProcessHostImpl> process,
573 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
574 const std::string& error) {
575 if (!task_runner->BelongsToCurrentThread()) {
576 task_runner->PostTask(
577 FROM_HERE, base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
578 process, task_runner, error));
579 }
580 if (!process)
581 return;
582 HistogramBadMessageTerminated(process->data_.process_type);
583 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
584 switches::kDisableKillAfterBadIPC)) {
585 return;
586 }
587 LOG(ERROR) << "Terminating child process for bad Mojo message: " << error;
588
589 // Create a memory dump with the error message aliased. This will make it easy
590 // to determine details about what interface call failed.
591 base::debug::Alias(&error);
592 base::debug::DumpWithoutCrashing();
593 process->child_process_->GetProcess().Terminate(
594 RESULT_CODE_KILLED_BAD_MESSAGE, false);
595}
596
[email protected]162a9fd2013-03-06 20:47:49597#if defined(OS_WIN)
598
rvargas079d1842014-10-17 22:32:16599void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
[email protected]162a9fd2013-03-06 20:47:49600 OnChildDisconnected();
601}
602
603#endif
604
[email protected]130757672012-10-24 00:26:19605} // namespace content