blob: 08486fc7fa4c51c6284a25a35ae38b7d80f654c8 [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"
[email protected]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
[email protected]d3c6c0d72010-12-09 08:15:0411#include "base/lazy_instance.h"
[email protected]d27893f62010-07-03 05:47:4212#include "base/logging.h"
[email protected]835d7c82010-10-14 04:38:3813#include "base/metrics/histogram.h"
erikchen8054a8c2015-03-11 02:34:2914#include "base/profiler/scoped_tracker.h"
[email protected]7286e3fc2011-07-19 22:13:2415#include "base/stl_util.h"
[email protected]10994d132013-06-11 07:16:1816#include "base/strings/string_util.h"
[email protected]162a9fd2013-03-06 20:47:4917#include "base/synchronization/waitable_event.h"
[email protected]83ab4a282012-07-12 18:19:4518#include "content/browser/histogram_message_filter.h"
[email protected]678c0362012-12-05 08:02:4419#include "content/browser/loader/resource_message_filter.h"
[email protected]33047f12011-12-01 23:20:2020#include "content/browser/profiler_message_filter.h"
[email protected]3a85b1f2013-02-01 04:47:4021#include "content/browser/tracing/trace_message_filter.h"
[email protected]4734d0b2011-12-03 07:10:4422#include "content/common/child_process_host_impl.h"
[email protected]4967f792012-01-20 22:14:4023#include "content/public/browser/browser_child_process_host_delegate.h"
[email protected]f4eaf7b92013-02-28 22:00:4024#include "content/public/browser/browser_child_process_observer.h"
[email protected]57999812013-02-24 05:40:5225#include "content/public/browser/browser_thread.h"
[email protected]4306c3792011-12-02 01:57:5326#include "content/public/browser/child_process_data.h"
[email protected]87f3c082011-10-19 18:07:4427#include "content/public/browser/content_browser_client.h"
[email protected]c08950d22011-10-13 22:20:2928#include "content/public/common/content_switches.h"
[email protected]f3b357692013-03-22 05:16:1329#include "content/public/common/process_type.h"
[email protected]b39ef1cb2011-10-25 04:46:5530#include "content/public/common/result_codes.h"
[email protected]d27893f62010-07-03 05:47:4231
[email protected]f1675202012-07-09 15:18:0032#if defined(OS_MACOSX)
[email protected]458433c2012-02-29 23:43:3933#include "content/browser/mach_broker_mac.h"
[email protected]3838ca12011-11-02 14:37:1534#endif
[email protected]a3a7e2c2011-09-16 23:07:0535
[email protected]130757672012-10-24 00:26:1936namespace content {
[email protected]d27893f62010-07-03 05:47:4237namespace {
38
[email protected]4c01d4992012-01-23 23:33:0139static base::LazyInstance<BrowserChildProcessHostImpl::BrowserChildProcessList>
[email protected]4967f792012-01-20 22:14:4040 g_child_process_list = LAZY_INSTANCE_INITIALIZER;
[email protected]d27893f62010-07-03 05:47:4241
[email protected]f4eaf7b92013-02-28 22:00:4042base::LazyInstance<ObserverList<BrowserChildProcessObserver> >
43 g_observers = LAZY_INSTANCE_INITIALIZER;
44
45void NotifyProcessHostConnected(const ChildProcessData& data) {
46 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
47 BrowserChildProcessHostConnected(data));
48}
49
50void NotifyProcessHostDisconnected(const ChildProcessData& data) {
51 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
52 BrowserChildProcessHostDisconnected(data));
53}
54
55void NotifyProcessCrashed(const ChildProcessData& data) {
56 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
57 BrowserChildProcessCrashed(data));
[email protected]4306c3792011-12-02 01:57:5358}
[email protected]d27893f62010-07-03 05:47:4259
60} // namespace
61
[email protected]4967f792012-01-20 22:14:4062BrowserChildProcessHost* BrowserChildProcessHost::Create(
vadimt379d7fe2015-04-01 00:09:3563 content::ProcessType process_type,
[email protected]4967f792012-01-20 22:14:4064 BrowserChildProcessHostDelegate* delegate) {
[email protected]f3b357692013-03-22 05:16:1365 return new BrowserChildProcessHostImpl(process_type, delegate);
[email protected]4967f792012-01-20 22:14:4066}
67
[email protected]458433c2012-02-29 23:43:3968#if defined(OS_MACOSX)
69base::ProcessMetrics::PortProvider* BrowserChildProcessHost::GetPortProvider() {
70 return MachBroker::GetInstance();
71}
72#endif
73
[email protected]f4eaf7b92013-02-28 22:00:4074// static
[email protected]4c01d4992012-01-23 23:33:0175BrowserChildProcessHostImpl::BrowserChildProcessList*
76 BrowserChildProcessHostImpl::GetIterator() {
[email protected]4967f792012-01-20 22:14:4077 return g_child_process_list.Pointer();
78}
79
[email protected]f4eaf7b92013-02-28 22:00:4080// static
81void BrowserChildProcessHostImpl::AddObserver(
82 BrowserChildProcessObserver* observer) {
mostynbfbcdc27a2015-03-13 17:58:5283 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]f4eaf7b92013-02-28 22:00:4084 g_observers.Get().AddObserver(observer);
85}
86
87// static
88void BrowserChildProcessHostImpl::RemoveObserver(
89 BrowserChildProcessObserver* observer) {
90 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126.
91 g_observers.Get().RemoveObserver(observer);
92}
93
[email protected]4c01d4992012-01-23 23:33:0194BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
vadimt379d7fe2015-04-01 00:09:3595 content::ProcessType process_type,
[email protected]4967f792012-01-20 22:14:4096 BrowserChildProcessHostDelegate* delegate)
[email protected]f3b357692013-03-22 05:16:1397 : data_(process_type),
[email protected]9dd90152013-08-02 22:09:1398 delegate_(delegate),
99 power_monitor_message_broadcaster_(this) {
[email protected]4734d0b2011-12-03 07:10:44100 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
[email protected]4306c3792011-12-02 01:57:53101
[email protected]4734d0b2011-12-03 07:10:44102 child_process_host_.reset(ChildProcessHost::Create(this));
[email protected]ba780c12013-10-01 17:07:06103 AddFilter(new TraceMessageFilter);
104 AddFilter(new ProfilerMessageFilter(process_type));
105 AddFilter(new HistogramMessageFilter);
[email protected]38917fe2011-04-06 17:29:12106
107 g_child_process_list.Get().push_back(this);
[email protected]130757672012-10-24 00:26:19108 GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
[email protected]30c4c67a2014-07-22 02:33:55109
110 power_monitor_message_broadcaster_.Init();
[email protected]38917fe2011-04-06 17:29:12111}
112
[email protected]4c01d4992012-01-23 23:33:01113BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
[email protected]d3c6c0d72010-12-09 08:15:04114 g_child_process_list.Get().remove(this);
[email protected]d27893f62010-07-03 05:47:42115}
116
117// static
[email protected]4c01d4992012-01-23 23:33:01118void BrowserChildProcessHostImpl::TerminateAll() {
mostynbfbcdc27a2015-03-13 17:58:52119 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33120 // Make a copy since the BrowserChildProcessHost dtor mutates the original
121 // list.
122 BrowserChildProcessList copy = g_child_process_list.Get();
[email protected]5998d9d2012-03-06 04:25:26123 for (BrowserChildProcessList::iterator it = copy.begin();
124 it != copy.end(); ++it) {
125 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl.
126 }
[email protected]d27893f62010-07-03 05:47:42127}
128
[email protected]4c01d4992012-01-23 23:33:01129void BrowserChildProcessHostImpl::Launch(
[email protected]34f48682013-03-20 00:30:18130 SandboxedProcessLauncherDelegate* delegate,
sievers954e37a2015-03-28 01:50:24131 base::CommandLine* cmd_line,
132 bool terminate_on_shutdown) {
mostynbfbcdc27a2015-03-13 17:58:52133 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]b80f68432011-05-02 17:22:30134
[email protected]130757672012-10-24 00:26:19135 GetContentClient()->browser()->AppendExtraCommandLineSwitches(
[email protected]4967f792012-01-20 22:14:40136 cmd_line, data_.id);
[email protected]b80f68432011-05-02 17:22:30137
[email protected]479278702014-08-11 20:32:09138 const base::CommandLine& browser_command_line =
139 *base::CommandLine::ForCurrentProcess();
[email protected]2b065f82012-10-18 07:11:16140 static const char* kForwardSwitches[] = {
[email protected]2b065f82012-10-18 07:11:16141 switches::kDisableLogging,
[email protected]2b065f82012-10-18 07:11:16142 switches::kEnableLogging,
[email protected]65f0ff72014-06-20 20:32:15143 switches::kIPCConnectionTimeout,
[email protected]2b065f82012-10-18 07:11:16144 switches::kLoggingLevel,
[email protected]2bf64a92013-07-11 23:10:40145 switches::kTraceToConsole,
[email protected]2b065f82012-10-18 07:11:16146 switches::kV,
147 switches::kVModule,
148 };
149 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
150 arraysize(kForwardSwitches));
[email protected]719a2052012-07-30 21:00:43151
[email protected]d27893f62010-07-03 05:47:42152 child_process_.reset(new ChildProcessLauncher(
[email protected]34f48682013-03-20 00:30:18153 delegate,
[email protected]d27893f62010-07-03 05:47:42154 cmd_line,
[email protected]40da3e0c2012-10-24 22:03:38155 data_.id,
sievers954e37a2015-03-28 01:50:24156 this,
157 terminate_on_shutdown));
[email protected]d27893f62010-07-03 05:47:42158}
159
[email protected]4c01d4992012-01-23 23:33:01160const ChildProcessData& BrowserChildProcessHostImpl::GetData() const {
mostynbfbcdc27a2015-03-13 17:58:52161 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40162 return data_;
163}
164
[email protected]4c01d4992012-01-23 23:33:01165ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const {
mostynbfbcdc27a2015-03-13 17:58:52166 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4967f792012-01-20 22:14:40167 return child_process_host_.get();
168}
169
rvargas5779b382014-11-18 20:44:11170const base::Process& BrowserChildProcessHostImpl::GetProcess() const {
mostynbfbcdc27a2015-03-13 17:58:52171 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]5d84d012010-12-02 17:17:21172 DCHECK(child_process_.get())
173 << "Requesting a child process handle before launching.";
rvargas079d1842014-10-17 22:32:16174 DCHECK(child_process_->GetProcess().IsValid())
[email protected]5d84d012010-12-02 17:17:21175 << "Requesting a child process handle before launch has completed OK.";
rvargas5779b382014-11-18 20:44:11176 return child_process_->GetProcess();
[email protected]5d84d012010-12-02 17:17:21177}
178
[email protected]fcf75d42013-12-03 20:11:26179void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
mostynbfbcdc27a2015-03-13 17:58:52180 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33181 data_.name = name;
182}
183
[email protected]4c01d4992012-01-23 23:33:01184void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
mostynbfbcdc27a2015-03-13 17:58:52185 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f174efd2012-01-17 18:43:33186 data_.handle = handle;
187}
188
[email protected]4c01d4992012-01-23 23:33:01189void BrowserChildProcessHostImpl::ForceShutdown() {
mostynbfbcdc27a2015-03-13 17:58:52190 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]d3c6c0d72010-12-09 08:15:04191 g_child_process_list.Get().remove(this);
[email protected]4cb43102011-12-02 20:24:49192 child_process_host_->ForceShutdown();
[email protected]d27893f62010-07-03 05:47:42193}
194
[email protected]d36860d2013-05-31 00:04:21195void BrowserChildProcessHostImpl::SetBackgrounded(bool backgrounded) {
196 child_process_->SetProcessBackgrounded(backgrounded);
197}
198
[email protected]ba780c12013-10-01 17:07:06199void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
200 child_process_host_->AddFilter(filter->GetFilter());
201}
202
[email protected]f4eaf7b92013-02-28 22:00:40203void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated(
204 const ChildProcessData& data) {
mostynbfbcdc27a2015-03-13 17:58:52205 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]f4eaf7b92013-02-28 22:00:40206 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
207 BrowserChildProcessInstanceCreated(data));
[email protected]d27893f62010-07-03 05:47:42208}
209
[email protected]ef2f6ba2014-05-15 23:06:07210void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
211 int process_type) {
212 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
213 PROCESS_TYPE_MAX);
214}
215
[email protected]4c01d4992012-01-23 23:33:01216base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
[email protected]547603d2013-08-27 17:59:19217 bool known_dead, int* exit_code) {
mostynbfbcdc27a2015-03-13 17:58:52218 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]59383c782013-04-17 16:43:27219 if (!child_process_) // If the delegate doesn't use Launch() helper.
[email protected]4967f792012-01-20 22:14:40220 return base::GetTerminationStatus(data_.handle, exit_code);
[email protected]547603d2013-08-27 17:59:19221 return child_process_->GetChildTerminationStatus(known_dead,
[email protected]c7691de2012-12-06 08:31:51222 exit_code);
[email protected]d27893f62010-07-03 05:47:42223}
224
[email protected]4c01d4992012-01-23 23:33:01225bool BrowserChildProcessHostImpl::OnMessageReceived(
226 const IPC::Message& message) {
[email protected]4967f792012-01-20 22:14:40227 return delegate_->OnMessageReceived(message);
[email protected]4cb43102011-12-02 20:24:49228}
229
[email protected]4c01d4992012-01-23 23:33:01230void BrowserChildProcessHostImpl::OnChannelConnected(int32 peer_pid) {
[email protected]162a9fd2013-03-06 20:47:49231#if defined(OS_WIN)
232 // From this point onward, the exit of the child process is detected by an
233 // error on the IPC channel.
[email protected]162a9fd2013-03-06 20:47:49234 early_exit_watcher_.StopWatching();
235#endif
236
mostynbfbcdc27a2015-03-13 17:58:52237 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]f4eaf7b92013-02-28 22:00:40238 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
239 base::Bind(&NotifyProcessHostConnected, data_));
[email protected]162a9fd2013-03-06 20:47:49240
[email protected]4967f792012-01-20 22:14:40241 delegate_->OnChannelConnected(peer_pid);
242}
243
[email protected]4c01d4992012-01-23 23:33:01244void BrowserChildProcessHostImpl::OnChannelError() {
[email protected]4967f792012-01-20 22:14:40245 delegate_->OnChannelError();
[email protected]0d6e9bd2011-10-18 04:29:16246}
247
[email protected]ef2f6ba2014-05-15 23:06:07248void BrowserChildProcessHostImpl::OnBadMessageReceived(
249 const IPC::Message& message) {
250 HistogramBadMessageTerminated(data_.process_type);
avi83883c82014-12-23 00:08:49251 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]e44d1342014-05-16 21:29:33252 switches::kDisableKillAfterBadIPC)) {
253 return;
254 }
jamescookda2505812015-03-20 18:01:18255 LOG(ERROR) << "Terminating child process for bad IPC message of type "
256 << message.type();
rvargas486b2f562015-03-18 01:36:33257 child_process_->GetProcess().Terminate(RESULT_CODE_KILLED_BAD_MESSAGE, false);
[email protected]ef2f6ba2014-05-15 23:06:07258}
259
[email protected]4c01d4992012-01-23 23:33:01260bool BrowserChildProcessHostImpl::CanShutdown() {
[email protected]4967f792012-01-20 22:14:40261 return delegate_->CanShutdown();
[email protected]4cb43102011-12-02 20:24:49262}
263
[email protected]4c01d4992012-01-23 23:33:01264void BrowserChildProcessHostImpl::OnChildDisconnected() {
mostynbfbcdc27a2015-03-13 17:58:52265 DCHECK_CURRENTLY_ON(BrowserThread::IO);
jbauman319402e2014-10-21 17:52:21266#if defined(OS_WIN)
267 // OnChildDisconnected may be called without OnChannelConnected, so stop the
268 // early exit watcher so GetTerminationStatus can close the process handle.
269 early_exit_watcher_.StopWatching();
270#endif
[email protected]6d057a0c2013-07-09 21:12:07271 if (child_process_.get() || data_.handle) {
[email protected]6d057a0c2013-07-09 21:12:07272 int exit_code;
[email protected]547603d2013-08-27 17:59:19273 base::TerminationStatus status = GetTerminationStatus(
274 true /* known_dead */, &exit_code);
[email protected]6d057a0c2013-07-09 21:12:07275 switch (status) {
276 case base::TERMINATION_STATUS_PROCESS_CRASHED:
277 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
278 delegate_->OnProcessCrashed(exit_code);
279 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
280 base::Bind(&NotifyProcessCrashed, data_));
281 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
282 data_.process_type,
283 PROCESS_TYPE_MAX);
284 break;
285 }
286 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
287 delegate_->OnProcessCrashed(exit_code);
288 // Report that this child process was killed.
289 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
290 data_.process_type,
291 PROCESS_TYPE_MAX);
292 break;
293 }
294 case base::TERMINATION_STATUS_STILL_RUNNING: {
295 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2",
296 data_.process_type,
297 PROCESS_TYPE_MAX);
298 }
299 default:
300 break;
[email protected]12fed812011-09-16 05:47:29301 }
[email protected]6d057a0c2013-07-09 21:12:07302 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
303 data_.process_type,
304 PROCESS_TYPE_MAX);
[email protected]d27893f62010-07-03 05:47:42305 }
[email protected]f4eaf7b92013-02-28 22:00:40306 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
307 base::Bind(&NotifyProcessHostDisconnected, data_));
[email protected]4967f792012-01-20 22:14:40308 delete delegate_; // Will delete us
[email protected]a3a7e2c2011-09-16 23:07:05309}
310
[email protected]4c01d4992012-01-23 23:33:01311bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
[email protected]4cb43102011-12-02 20:24:49312 return child_process_host_->Send(message);
313}
314
[email protected]fa01e472014-02-11 14:45:35315void BrowserChildProcessHostImpl::OnProcessLaunchFailed() {
316 delegate_->OnProcessLaunchFailed();
317 delete delegate_; // Will delete us
318}
319
[email protected]4c01d4992012-01-23 23:33:01320void BrowserChildProcessHostImpl::OnProcessLaunched() {
erikchen8054a8c2015-03-11 02:34:29321 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841
322 // is fixed.
323 tracked_objects::ScopedTracker tracking_profile(
324 FROM_HERE_WITH_EXPLICIT_FUNCTION(
325 "465841 BrowserChildProcessHostImpl::OnProcessLaunched"));
rvargas079d1842014-10-17 22:32:16326 const base::Process& process = child_process_->GetProcess();
327 DCHECK(process.IsValid());
[email protected]162a9fd2013-03-06 20:47:49328
329#if defined(OS_WIN)
330 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
331 // child process exits. This watcher is stopped once the IPC channel is
332 // connected and the exit of the child process is detecter by an error on the
333 // IPC channel thereafter.
rvargas079d1842014-10-17 22:32:16334 DCHECK(!early_exit_watcher_.GetWatchedObject());
335 early_exit_watcher_.StartWatching(process.Handle(), this);
[email protected]162a9fd2013-03-06 20:47:49336#endif
337
rvargas079d1842014-10-17 22:32:16338 // TODO(rvargas) crbug.com/417532: Don't store a handle.
339 data_.handle = process.Handle();
[email protected]4967f792012-01-20 22:14:40340 delegate_->OnProcessLaunched();
[email protected]d27893f62010-07-03 05:47:42341}
[email protected]130757672012-10-24 00:26:19342
[email protected]162a9fd2013-03-06 20:47:49343#if defined(OS_WIN)
344
rvargas079d1842014-10-17 22:32:16345void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
[email protected]162a9fd2013-03-06 20:47:49346 OnChildDisconnected();
347}
348
349#endif
350
[email protected]130757672012-10-24 00:26:19351} // namespace content