| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/browser_child_process_host_impl.h" | 5 #include "content/browser/browser_child_process_host_impl.h" |
| 6 | 6 |
| 7 #include "base/base_switches.h" | 7 #include "base/base_switches.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/dump_without_crashing.h" | 10 #include "base/debug/dump_without_crashing.h" |
| 11 #include "base/feature_list.h" | 11 #include "base/feature_list.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/metrics/field_trial.h" | 16 #include "base/metrics/field_trial.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/metrics/persistent_histogram_allocator.h" |
| 19 #include "base/metrics/persistent_memory_allocator.h" |
| 18 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
| 19 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 20 #include "base/synchronization/waitable_event.h" | 22 #include "base/synchronization/waitable_event.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 23 #include "components/tracing/common/tracing_switches.h" | 25 #include "components/tracing/common/tracing_switches.h" |
| 24 #include "content/browser/histogram_message_filter.h" | 26 #include "content/browser/histogram_message_filter.h" |
| 25 #include "content/browser/loader/resource_message_filter.h" | 27 #include "content/browser/loader/resource_message_filter.h" |
| 26 #include "content/browser/memory/memory_message_filter.h" | 28 #include "content/browser/memory/memory_message_filter.h" |
| 27 #include "content/browser/profiler_message_filter.h" | 29 #include "content/browser/profiler_message_filter.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), | 79 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), |
| 78 BrowserChildProcessKilled(data, exit_code)); | 80 BrowserChildProcessKilled(data, exit_code)); |
| 79 } | 81 } |
| 80 | 82 |
| 81 } // namespace | 83 } // namespace |
| 82 | 84 |
| 83 BrowserChildProcessHost* BrowserChildProcessHost::Create( | 85 BrowserChildProcessHost* BrowserChildProcessHost::Create( |
| 84 content::ProcessType process_type, | 86 content::ProcessType process_type, |
| 85 BrowserChildProcessHostDelegate* delegate) { | 87 BrowserChildProcessHostDelegate* delegate) { |
| 86 return new BrowserChildProcessHostImpl( | 88 return new BrowserChildProcessHostImpl( |
| 87 process_type, delegate, mojo::edk::GenerateRandomToken()); | 89 process_type, delegate, mojo::edk::GenerateRandomToken(), 0, nullptr); |
| 88 } | 90 } |
| 89 | 91 |
| 90 BrowserChildProcessHost* BrowserChildProcessHost::Create( | 92 BrowserChildProcessHost* BrowserChildProcessHost::Create( |
| 91 content::ProcessType process_type, | 93 content::ProcessType process_type, |
| 92 BrowserChildProcessHostDelegate* delegate, | 94 BrowserChildProcessHostDelegate* delegate, |
| 93 const std::string& mojo_child_token) { | 95 const std::string& mojo_child_token) { |
| 94 return new BrowserChildProcessHostImpl( | 96 return new BrowserChildProcessHostImpl(process_type, delegate, |
| 95 process_type, delegate, mojo_child_token); | 97 mojo_child_token, 0, nullptr); |
| 96 } | 98 } |
| 97 | 99 |
| 98 BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) { | 100 BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) { |
| 99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 101 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 100 BrowserChildProcessHostImpl::BrowserChildProcessList* process_list = | 102 BrowserChildProcessHostImpl::BrowserChildProcessList* process_list = |
| 101 g_child_process_list.Pointer(); | 103 g_child_process_list.Pointer(); |
| 102 for (BrowserChildProcessHostImpl* host : *process_list) { | 104 for (BrowserChildProcessHostImpl* host : *process_list) { |
| 103 if (host->GetData().id == child_process_id) | 105 if (host->GetData().id == child_process_id) |
| 104 return host; | 106 return host; |
| 105 } | 107 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 128 // static | 130 // static |
| 129 void BrowserChildProcessHostImpl::RemoveObserver( | 131 void BrowserChildProcessHostImpl::RemoveObserver( |
| 130 BrowserChildProcessObserver* observer) { | 132 BrowserChildProcessObserver* observer) { |
| 131 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126. | 133 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126. |
| 132 g_observers.Get().RemoveObserver(observer); | 134 g_observers.Get().RemoveObserver(observer); |
| 133 } | 135 } |
| 134 | 136 |
| 135 BrowserChildProcessHostImpl::BrowserChildProcessHostImpl( | 137 BrowserChildProcessHostImpl::BrowserChildProcessHostImpl( |
| 136 content::ProcessType process_type, | 138 content::ProcessType process_type, |
| 137 BrowserChildProcessHostDelegate* delegate, | 139 BrowserChildProcessHostDelegate* delegate, |
| 138 const std::string& mojo_child_token) | 140 const std::string& mojo_child_token, |
| 141 size_t shared_metrics_memory_size, |
| 142 base::StringPiece shared_metrics_name) |
| 139 : data_(process_type), | 143 : data_(process_type), |
| 140 delegate_(delegate), | 144 delegate_(delegate), |
| 141 mojo_child_token_(mojo_child_token), | 145 mojo_child_token_(mojo_child_token), |
| 142 power_monitor_message_broadcaster_(this), | 146 power_monitor_message_broadcaster_(this), |
| 143 is_channel_connected_(false), | 147 is_channel_connected_(false), |
| 144 notify_child_disconnected_(false), | 148 notify_child_disconnected_(false), |
| 145 weak_factory_(this) { | 149 weak_factory_(this) { |
| 146 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId(); | 150 data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId(); |
| 147 | 151 |
| 148 #if USE_ATTACHMENT_BROKER | 152 #if USE_ATTACHMENT_BROKER |
| (...skipping 12 matching lines...) Expand all Loading... |
| 161 child_process_host_.reset(ChildProcessHost::Create(this)); | 165 child_process_host_.reset(ChildProcessHost::Create(this)); |
| 162 AddFilter(new TraceMessageFilter(data_.id)); | 166 AddFilter(new TraceMessageFilter(data_.id)); |
| 163 AddFilter(new ProfilerMessageFilter(process_type)); | 167 AddFilter(new ProfilerMessageFilter(process_type)); |
| 164 AddFilter(new HistogramMessageFilter); | 168 AddFilter(new HistogramMessageFilter); |
| 165 AddFilter(new MemoryMessageFilter(this, process_type)); | 169 AddFilter(new MemoryMessageFilter(this, process_type)); |
| 166 | 170 |
| 167 g_child_process_list.Get().push_back(this); | 171 g_child_process_list.Get().push_back(this); |
| 168 GetContentClient()->browser()->BrowserChildProcessHostCreated(this); | 172 GetContentClient()->browser()->BrowserChildProcessHostCreated(this); |
| 169 | 173 |
| 170 power_monitor_message_broadcaster_.Init(); | 174 power_monitor_message_broadcaster_.Init(); |
| 175 |
| 176 // Create a persistent memory segment for subprocess histograms only if |
| 177 // they're active in the browser. |
| 178 if (shared_metrics_memory_size > 0 && base::GlobalHistogramAllocator::Get()) { |
| 179 std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory()); |
| 180 shm->CreateAndMapAnonymous(shared_metrics_memory_size); |
| 181 metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator( |
| 182 std::move(shm), static_cast<uint64_t>(data_.id), shared_metrics_name, |
| 183 /*readonly=*/false)); |
| 184 } |
| 171 } | 185 } |
| 172 | 186 |
| 173 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { | 187 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { |
| 174 g_child_process_list.Get().remove(this); | 188 g_child_process_list.Get().remove(this); |
| 175 | 189 |
| 176 if (notify_child_disconnected_) { | 190 if (notify_child_disconnected_) { |
| 177 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 191 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 178 base::Bind(&NotifyProcessHostDisconnected, data_)); | 192 base::Bind(&NotifyProcessHostDisconnected, data_)); |
| 179 } | 193 } |
| 180 } | 194 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 | 275 |
| 262 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { | 276 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { |
| 263 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 277 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 264 DCHECK(child_process_.get()) | 278 DCHECK(child_process_.get()) |
| 265 << "Requesting a child process handle before launching."; | 279 << "Requesting a child process handle before launching."; |
| 266 DCHECK(child_process_->GetProcess().IsValid()) | 280 DCHECK(child_process_->GetProcess().IsValid()) |
| 267 << "Requesting a child process handle before launch has completed OK."; | 281 << "Requesting a child process handle before launch has completed OK."; |
| 268 return child_process_->GetProcess(); | 282 return child_process_->GetProcess(); |
| 269 } | 283 } |
| 270 | 284 |
| 285 std::unique_ptr<base::SharedPersistentMemoryAllocator> |
| 286 BrowserChildProcessHostImpl::TakeMetricsAllocator() { |
| 287 return std::move(metrics_allocator_); |
| 288 } |
| 289 |
| 271 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { | 290 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { |
| 272 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 291 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 273 data_.name = name; | 292 data_.name = name; |
| 274 } | 293 } |
| 275 | 294 |
| 276 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { | 295 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { |
| 277 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 296 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 278 data_.handle = handle; | 297 data_.handle = handle; |
| 279 } | 298 } |
| 280 | 299 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 // error on the IPC channel. | 347 // error on the IPC channel. |
| 329 early_exit_watcher_.StopWatching(); | 348 early_exit_watcher_.StopWatching(); |
| 330 #endif | 349 #endif |
| 331 | 350 |
| 332 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 351 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 333 base::Bind(&NotifyProcessHostConnected, data_)); | 352 base::Bind(&NotifyProcessHostConnected, data_)); |
| 334 | 353 |
| 335 delegate_->OnChannelConnected(peer_pid); | 354 delegate_->OnChannelConnected(peer_pid); |
| 336 | 355 |
| 337 if (IsProcessLaunched()) { | 356 if (IsProcessLaunched()) { |
| 357 ShareMetricsAllocatorToProcess(); |
| 338 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 358 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 339 base::Bind(&NotifyProcessLaunchedAndConnected, | 359 base::Bind(&NotifyProcessLaunchedAndConnected, |
| 340 data_)); | 360 data_)); |
| 341 } | 361 } |
| 342 } | 362 } |
| 343 | 363 |
| 344 void BrowserChildProcessHostImpl::OnChannelError() { | 364 void BrowserChildProcessHostImpl::OnChannelError() { |
| 345 delegate_->OnChannelError(); | 365 delegate_->OnChannelError(); |
| 346 } | 366 } |
| 347 | 367 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 } | 449 } |
| 430 #endif | 450 #endif |
| 431 } | 451 } |
| 432 delete delegate_; // Will delete us | 452 delete delegate_; // Will delete us |
| 433 } | 453 } |
| 434 | 454 |
| 435 bool BrowserChildProcessHostImpl::Send(IPC::Message* message) { | 455 bool BrowserChildProcessHostImpl::Send(IPC::Message* message) { |
| 436 return child_process_host_->Send(message); | 456 return child_process_host_->Send(message); |
| 437 } | 457 } |
| 438 | 458 |
| 459 void BrowserChildProcessHostImpl::ShareMetricsAllocatorToProcess() { |
| 460 if (metrics_allocator_) { |
| 461 base::SharedMemoryHandle shm_handle; |
| 462 metrics_allocator_->shared_memory()->ShareToProcess(data_.handle, |
| 463 &shm_handle); |
| 464 Send(new ChildProcessMsg_SetHistogramMemory( |
| 465 shm_handle, metrics_allocator_->shared_memory()->mapped_size())); |
| 466 } |
| 467 } |
| 468 |
| 439 void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) { | 469 void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) { |
| 440 delegate_->OnProcessLaunchFailed(error_code); | 470 delegate_->OnProcessLaunchFailed(error_code); |
| 441 notify_child_disconnected_ = false; | 471 notify_child_disconnected_ = false; |
| 442 delete delegate_; // Will delete us | 472 delete delegate_; // Will delete us |
| 443 } | 473 } |
| 444 | 474 |
| 445 void BrowserChildProcessHostImpl::OnProcessLaunched() { | 475 void BrowserChildProcessHostImpl::OnProcessLaunched() { |
| 446 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 476 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 447 | 477 |
| 448 const base::Process& process = child_process_->GetProcess(); | 478 const base::Process& process = child_process_->GetProcess(); |
| 449 DCHECK(process.IsValid()); | 479 DCHECK(process.IsValid()); |
| 450 | 480 |
| 451 #if defined(OS_WIN) | 481 #if defined(OS_WIN) |
| 452 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the | 482 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the |
| 453 // child process exits. This watcher is stopped once the IPC channel is | 483 // child process exits. This watcher is stopped once the IPC channel is |
| 454 // connected and the exit of the child process is detecter by an error on the | 484 // connected and the exit of the child process is detecter by an error on the |
| 455 // IPC channel thereafter. | 485 // IPC channel thereafter. |
| 456 DCHECK(!early_exit_watcher_.GetWatchedObject()); | 486 DCHECK(!early_exit_watcher_.GetWatchedObject()); |
| 457 early_exit_watcher_.StartWatchingOnce(process.Handle(), this); | 487 early_exit_watcher_.StartWatchingOnce(process.Handle(), this); |
| 458 #endif | 488 #endif |
| 459 | 489 |
| 460 // TODO(rvargas) crbug.com/417532: Don't store a handle. | 490 // TODO(rvargas) crbug.com/417532: Don't store a handle. |
| 461 data_.handle = process.Handle(); | 491 data_.handle = process.Handle(); |
| 462 delegate_->OnProcessLaunched(); | 492 delegate_->OnProcessLaunched(); |
| 463 | 493 |
| 464 if (is_channel_connected_) { | 494 if (is_channel_connected_) { |
| 495 ShareMetricsAllocatorToProcess(); |
| 465 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 496 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 466 base::Bind(&NotifyProcessLaunchedAndConnected, | 497 base::Bind(&NotifyProcessLaunchedAndConnected, |
| 467 data_)); | 498 data_)); |
| 468 } | 499 } |
| 469 } | 500 } |
| 470 | 501 |
| 471 bool BrowserChildProcessHostImpl::IsProcessLaunched() const { | 502 bool BrowserChildProcessHostImpl::IsProcessLaunched() const { |
| 472 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 503 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 473 | 504 |
| 474 return child_process_.get() && child_process_->GetProcess().IsValid(); | 505 return child_process_.get() && child_process_->GetProcess().IsValid(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 503 | 534 |
| 504 #if defined(OS_WIN) | 535 #if defined(OS_WIN) |
| 505 | 536 |
| 506 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { | 537 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { |
| 507 OnChildDisconnected(); | 538 OnChildDisconnected(); |
| 508 } | 539 } |
| 509 | 540 |
| 510 #endif | 541 #endif |
| 511 | 542 |
| 512 } // namespace content | 543 } // namespace content |
| OLD | NEW |