| 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/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
| 21 #include "base/synchronization/waitable_event.h" | 23 #include "base/synchronization/waitable_event.h" |
| 22 #include "base/threading/thread_task_runner_handle.h" | 24 #include "base/threading/thread_task_runner_handle.h" |
| 23 #include "build/build_config.h" | 25 #include "build/build_config.h" |
| 24 #include "components/tracing/common/tracing_switches.h" | 26 #include "components/tracing/common/tracing_switches.h" |
| 25 #include "content/browser/histogram_message_filter.h" | 27 #include "content/browser/histogram_message_filter.h" |
| 26 #include "content/browser/loader/resource_message_filter.h" | 28 #include "content/browser/loader/resource_message_filter.h" |
| 27 #include "content/browser/memory/memory_message_filter.h" | 29 #include "content/browser/memory/memory_message_filter.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 173 |
| 172 power_monitor_message_broadcaster_.Init(); | 174 power_monitor_message_broadcaster_.Init(); |
| 173 | 175 |
| 174 if (!service_name.empty()) { | 176 if (!service_name.empty()) { |
| 175 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 177 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 176 child_connection_.reset(new MojoChildConnection( | 178 child_connection_.reset(new MojoChildConnection( |
| 177 service_name, base::StringPrintf("%d", data_.id), child_token_, | 179 service_name, base::StringPrintf("%d", data_.id), child_token_, |
| 178 MojoShellContext::GetConnectorForIOThread(), | 180 MojoShellContext::GetConnectorForIOThread(), |
| 179 base::ThreadTaskRunnerHandle::Get())); | 181 base::ThreadTaskRunnerHandle::Get())); |
| 180 } | 182 } |
| 183 |
| 184 // Create a persistent memory segment for subprocess histograms. |
| 185 CreateMetricsAllocator(); |
| 181 } | 186 } |
| 182 | 187 |
| 183 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { | 188 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { |
| 184 g_child_process_list.Get().remove(this); | 189 g_child_process_list.Get().remove(this); |
| 185 | 190 |
| 186 if (notify_child_disconnected_) { | 191 if (notify_child_disconnected_) { |
| 187 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 192 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 188 base::Bind(&NotifyProcessHostDisconnected, data_)); | 193 base::Bind(&NotifyProcessHostDisconnected, data_)); |
| 189 } | 194 } |
| 190 } | 195 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 | 281 |
| 277 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { | 282 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { |
| 278 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 283 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 279 DCHECK(child_process_.get()) | 284 DCHECK(child_process_.get()) |
| 280 << "Requesting a child process handle before launching."; | 285 << "Requesting a child process handle before launching."; |
| 281 DCHECK(child_process_->GetProcess().IsValid()) | 286 DCHECK(child_process_->GetProcess().IsValid()) |
| 282 << "Requesting a child process handle before launch has completed OK."; | 287 << "Requesting a child process handle before launch has completed OK."; |
| 283 return child_process_->GetProcess(); | 288 return child_process_->GetProcess(); |
| 284 } | 289 } |
| 285 | 290 |
| 291 std::unique_ptr<base::SharedPersistentMemoryAllocator> |
| 292 BrowserChildProcessHostImpl::TakeMetricsAllocator() { |
| 293 return std::move(metrics_allocator_); |
| 294 } |
| 295 |
| 286 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { | 296 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { |
| 287 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 297 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 288 data_.name = name; | 298 data_.name = name; |
| 289 } | 299 } |
| 290 | 300 |
| 291 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { | 301 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { |
| 292 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 302 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 293 data_.handle = handle; | 303 data_.handle = handle; |
| 294 } | 304 } |
| 295 | 305 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 // error on the IPC channel. | 356 // error on the IPC channel. |
| 347 early_exit_watcher_.StopWatching(); | 357 early_exit_watcher_.StopWatching(); |
| 348 #endif | 358 #endif |
| 349 | 359 |
| 350 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 360 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 351 base::Bind(&NotifyProcessHostConnected, data_)); | 361 base::Bind(&NotifyProcessHostConnected, data_)); |
| 352 | 362 |
| 353 delegate_->OnChannelConnected(peer_pid); | 363 delegate_->OnChannelConnected(peer_pid); |
| 354 | 364 |
| 355 if (IsProcessLaunched()) { | 365 if (IsProcessLaunched()) { |
| 366 ShareMetricsAllocatorToProcess(); |
| 356 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 367 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 357 base::Bind(&NotifyProcessLaunchedAndConnected, | 368 base::Bind(&NotifyProcessLaunchedAndConnected, |
| 358 data_)); | 369 data_)); |
| 359 } | 370 } |
| 360 } | 371 } |
| 361 | 372 |
| 362 void BrowserChildProcessHostImpl::OnChannelError() { | 373 void BrowserChildProcessHostImpl::OnChannelError() { |
| 363 delegate_->OnChannelError(); | 374 delegate_->OnChannelError(); |
| 364 } | 375 } |
| 365 | 376 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 } | 458 } |
| 448 #endif | 459 #endif |
| 449 } | 460 } |
| 450 delete delegate_; // Will delete us | 461 delete delegate_; // Will delete us |
| 451 } | 462 } |
| 452 | 463 |
| 453 bool BrowserChildProcessHostImpl::Send(IPC::Message* message) { | 464 bool BrowserChildProcessHostImpl::Send(IPC::Message* message) { |
| 454 return child_process_host_->Send(message); | 465 return child_process_host_->Send(message); |
| 455 } | 466 } |
| 456 | 467 |
| 468 void BrowserChildProcessHostImpl::CreateMetricsAllocator() { |
| 469 // Create a persistent memory segment for subprocess histograms only if |
| 470 // they're active in the browser. |
| 471 // TODO(bcwhite): Remove this once persistence is always enabled. |
| 472 if (!base::GlobalHistogramAllocator::Get()) |
| 473 return; |
| 474 |
| 475 // Determine the correct parameters based on the process type. |
| 476 size_t memory_size; |
| 477 base::StringPiece metrics_name; |
| 478 switch (data_.process_type) { |
| 479 case PROCESS_TYPE_GPU: |
| 480 memory_size = 100 << 10; // 100 KiB |
| 481 metrics_name = "GpuMetrics"; |
| 482 break; |
| 483 |
| 484 default: |
| 485 return; |
| 486 } |
| 487 |
| 488 // Create the shared memory segment and attach an allocator to it. |
| 489 // Mapping the memory shouldn't fail but be safe if it does; everything |
| 490 // will continue to work but just as if persistence weren't available. |
| 491 std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory()); |
| 492 if (!shm->CreateAndMapAnonymous(memory_size)) |
| 493 return; |
| 494 metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator( |
| 495 std::move(shm), static_cast<uint64_t>(data_.id), metrics_name, |
| 496 /*readonly=*/false)); |
| 497 } |
| 498 |
| 499 void BrowserChildProcessHostImpl::ShareMetricsAllocatorToProcess() { |
| 500 if (metrics_allocator_) { |
| 501 base::SharedMemoryHandle shm_handle; |
| 502 metrics_allocator_->shared_memory()->ShareToProcess(data_.handle, |
| 503 &shm_handle); |
| 504 Send(new ChildProcessMsg_SetHistogramMemory( |
| 505 shm_handle, metrics_allocator_->shared_memory()->mapped_size())); |
| 506 } |
| 507 } |
| 508 |
| 457 void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) { | 509 void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) { |
| 458 delegate_->OnProcessLaunchFailed(error_code); | 510 delegate_->OnProcessLaunchFailed(error_code); |
| 459 notify_child_disconnected_ = false; | 511 notify_child_disconnected_ = false; |
| 460 delete delegate_; // Will delete us | 512 delete delegate_; // Will delete us |
| 461 } | 513 } |
| 462 | 514 |
| 463 void BrowserChildProcessHostImpl::OnProcessLaunched() { | 515 void BrowserChildProcessHostImpl::OnProcessLaunched() { |
| 464 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 516 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 465 | 517 |
| 466 const base::Process& process = child_process_->GetProcess(); | 518 const base::Process& process = child_process_->GetProcess(); |
| 467 DCHECK(process.IsValid()); | 519 DCHECK(process.IsValid()); |
| 468 | 520 |
| 469 #if defined(OS_WIN) | 521 #if defined(OS_WIN) |
| 470 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the | 522 // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the |
| 471 // child process exits. This watcher is stopped once the IPC channel is | 523 // child process exits. This watcher is stopped once the IPC channel is |
| 472 // connected and the exit of the child process is detecter by an error on the | 524 // connected and the exit of the child process is detecter by an error on the |
| 473 // IPC channel thereafter. | 525 // IPC channel thereafter. |
| 474 DCHECK(!early_exit_watcher_.GetWatchedObject()); | 526 DCHECK(!early_exit_watcher_.GetWatchedObject()); |
| 475 early_exit_watcher_.StartWatchingOnce(process.Handle(), this); | 527 early_exit_watcher_.StartWatchingOnce(process.Handle(), this); |
| 476 #endif | 528 #endif |
| 477 | 529 |
| 478 // TODO(rvargas) crbug.com/417532: Don't store a handle. | 530 // TODO(rvargas) crbug.com/417532: Don't store a handle. |
| 479 data_.handle = process.Handle(); | 531 data_.handle = process.Handle(); |
| 480 delegate_->OnProcessLaunched(); | 532 delegate_->OnProcessLaunched(); |
| 481 | 533 |
| 482 if (is_channel_connected_) { | 534 if (is_channel_connected_) { |
| 535 ShareMetricsAllocatorToProcess(); |
| 483 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 536 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 484 base::Bind(&NotifyProcessLaunchedAndConnected, | 537 base::Bind(&NotifyProcessLaunchedAndConnected, |
| 485 data_)); | 538 data_)); |
| 486 } | 539 } |
| 487 } | 540 } |
| 488 | 541 |
| 489 bool BrowserChildProcessHostImpl::IsProcessLaunched() const { | 542 bool BrowserChildProcessHostImpl::IsProcessLaunched() const { |
| 490 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 543 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 491 | 544 |
| 492 return child_process_.get() && child_process_->GetProcess().IsValid(); | 545 return child_process_.get() && child_process_->GetProcess().IsValid(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 521 | 574 |
| 522 #if defined(OS_WIN) | 575 #if defined(OS_WIN) |
| 523 | 576 |
| 524 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { | 577 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { |
| 525 OnChildDisconnected(); | 578 OnChildDisconnected(); |
| 526 } | 579 } |
| 527 | 580 |
| 528 #endif | 581 #endif |
| 529 | 582 |
| 530 } // namespace content | 583 } // namespace content |
| OLD | NEW |