15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_child_process_host_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_switches.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/histogram_message_filter.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_message_filter.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/profiler_message_filter.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/tracing/trace_message_filter.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/child_process_host_impl.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_child_process_host_delegate.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_child_process_observer.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/child_process_data.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/process_type.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/mach_broker_mac.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<BrowserChildProcessHostImpl::BrowserChildProcessList> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_child_process_list = LAZY_INSTANCE_INITIALIZER; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<ObserverList<BrowserChildProcessObserver> > 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_observers = LAZY_INSTANCE_INITIALIZER; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotifyProcessHostConnected(const ChildProcessData& data) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessHostConnected(data)); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotifyProcessHostDisconnected(const ChildProcessData& data) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessHostDisconnected(data)); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotifyProcessCrashed(const ChildProcessData& data) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessCrashed(data)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserChildProcessHost* BrowserChildProcessHost::Create( 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int process_type, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserChildProcessHostDelegate* delegate) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new BrowserChildProcessHostImpl(process_type, delegate); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessMetrics::PortProvider* BrowserChildProcessHost::GetPortProvider() { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MachBroker::GetInstance(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserChildProcessHostImpl::BrowserChildProcessList* 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserChildProcessHostImpl::GetIterator() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_child_process_list.Pointer(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserChildProcessHostImpl::AddObserver( 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessObserver* observer) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_observers.Get().AddObserver(observer); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserChildProcessHostImpl::RemoveObserver( 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessObserver* observer) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_observers.Get().RemoveObserver(observer); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserChildProcessHostImpl::BrowserChildProcessHostImpl( 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int process_type, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserChildProcessHostDelegate* delegate) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : data_(process_type), 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) delegate_(delegate), 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) power_monitor_message_broadcaster_(this) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_process_host_.reset(ChildProcessHost::Create(this)); 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddFilter(new TraceMessageFilter); 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddFilter(new ProfilerMessageFilter(process_type)); 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddFilter(new HistogramMessageFilter); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_child_process_list.Get().push_back(this); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetContentClient()->browser()->BrowserChildProcessHostCreated(this); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) power_monitor_message_broadcaster_.Init(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_child_process_list.Get().remove(this); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteProcessWaitableEvent(early_exit_watcher_.GetWatchedEvent()); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::TerminateAll() { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a copy since the BrowserChildProcessHost dtor mutates the original 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserChildProcessList copy = g_child_process_list.Get(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserChildProcessList::iterator it = copy.begin(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != copy.end(); ++it) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::Launch( 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SandboxedProcessLauncherDelegate* delegate, 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::CommandLine* cmd_line) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetContentClient()->browser()->AppendExtraCommandLineSwitches( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line, data_.id); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const base::CommandLine& browser_command_line = 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *base::CommandLine::ForCurrentProcess(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* kForwardSwitches[] = { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kDisableLogging, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kEnableLogging, 1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) switches::kIPCConnectionTimeout, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kLoggingLevel, 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch switches::kTraceToConsole, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kV, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kVModule, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kForwardSwitches)); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_process_.reset(new ChildProcessLauncher( 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_line, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.id, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ChildProcessData& BrowserChildProcessHostImpl::GetData() const { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child_process_host_.get(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessHandle BrowserChildProcessHostImpl::GetHandle() const { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(child_process_.get()) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Requesting a child process handle before launching."; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(child_process_->GetHandle()) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Requesting a child process handle before launch has completed OK."; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child_process_->GetHandle(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserChildProcessHostImpl::SetName(const base::string16& name) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.name = name; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.handle = handle; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::ForceShutdown() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_child_process_list.Get().remove(this); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_process_host_->ForceShutdown(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void BrowserChildProcessHostImpl::SetBackgrounded(bool backgrounded) { 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_process_->SetProcessBackgrounded(backgrounded); 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::SetTerminateChildOnShutdown( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool terminate_on_shutdown) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) child_process_host_->AddFilter(filter->GetFilter()); 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated( 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ChildProcessData& data) { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserChildProcessInstanceCreated(data)); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BrowserChildProcessHostImpl::HistogramBadMessageTerminated( 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int process_type) { 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type, 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PROCESS_TYPE_MAX); 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus( 225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool known_dead, int* exit_code) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!child_process_) // If the delegate doesn't use Launch() helper. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::GetTerminationStatus(data_.handle, exit_code); 229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return child_process_->GetChildTerminationStatus(known_dead, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) exit_code); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserChildProcessHostImpl::OnMessageReceived( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::Message& message) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->OnMessageReceived(message); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::OnChannelConnected(int32 peer_pid) { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // From this point onward, the exit of the child process is detected by an 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // error on the IPC channel. 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteProcessWaitableEvent(early_exit_watcher_.GetWatchedEvent()); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) early_exit_watcher_.StopWatching(); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NotifyProcessHostConnected, data_)); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnChannelConnected(peer_pid); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::OnChannelError() { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnChannelError(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BrowserChildProcessHostImpl::OnBadMessageReceived( 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const IPC::Message& message) { 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) HistogramBadMessageTerminated(data_.process_type); 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switches::kDisableKillAfterBadIPC)) { 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE, false); 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserChildProcessHostImpl::CanShutdown() { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->CanShutdown(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::OnChildDisconnected() { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (child_process_.get() || data_.handle) { 2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(data_.handle != base::kNullProcessHandle); 2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int exit_code; 276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::TerminationStatus status = GetTerminationStatus( 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) true /* known_dead */, &exit_code); 2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch switch (status) { 2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case base::TERMINATION_STATUS_PROCESS_CRASHED: 2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: { 2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnProcessCrashed(exit_code); 2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind(&NotifyProcessCrashed, data_)); 2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2", 2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data_.process_type, 2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PROCESS_TYPE_MAX); 2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: { 2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnProcessCrashed(exit_code); 2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Report that this child process was killed. 2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2", 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data_.process_type, 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PROCESS_TYPE_MAX); 2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case base::TERMINATION_STATUS_STILL_RUNNING: { 2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2", 2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data_.process_type, 3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PROCESS_TYPE_MAX); 3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch default: 3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2", 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data_.process_type, 3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PROCESS_TYPE_MAX); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NotifyProcessHostDisconnected, data_)); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete delegate_; // Will delete us 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserChildProcessHostImpl::Send(IPC::Message* message) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child_process_host_->Send(message); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserChildProcessHostImpl::OnProcessLaunchFailed() { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->OnProcessLaunchFailed(); 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete delegate_; // Will delete us 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserChildProcessHostImpl::OnProcessLaunched() { 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ProcessHandle handle = child_process_->GetHandle(); 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!handle) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete delegate_; // Will delete us 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // child process exits. This watcher is stopped once the IPC channel is 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // connected and the exit of the child process is detecter by an error on the 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // IPC channel thereafter. 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!early_exit_watcher_.GetWatchedEvent()); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) early_exit_watcher_.StartWatching( 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new base::WaitableEvent(handle), 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&BrowserChildProcessHostImpl::OnProcessExitedEarly, 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_.handle = handle; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnProcessLaunched(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserChildProcessHostImpl::DeleteProcessWaitableEvent( 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent* event) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event) 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The WaitableEvent does not own the process handle so ensure it does not 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // close it. 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->Release(); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete event; 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserChildProcessHostImpl::OnProcessExitedEarly( 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent* event) { 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteProcessWaitableEvent(event); 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnChildDisconnected(); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 369