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 |