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)); | |
Alexei Svitkine (slow)
2016/08/12 23:14:36
I think it would be better to just have the the Br
bcwhite
2016/08/15 19:43:10
I don't think that would be good. That would forc
Alexei Svitkine (slow)
2016/08/18 07:21:19
The callers wouldn't need to know the persistent c
bcwhite
2016/08/18 15:21:55
This class knows about creating shared memory beca
Alexei Svitkine (slow)
2016/08/18 15:57:28
Let me step back a bit. The concrete things I'm no
bcwhite
2016/08/18 17:42:17
It cares about the shared memory details but that'
Alexei Svitkine (slow)
2016/08/19 15:10:51
I see your point. I still don't like that this cla
bcwhite
2016/08/19 15:55:21
Eventually that will be removed, but it's used her
bcwhite
2016/08/19 15:55:21
New separate method for creating the allocator tha
| |
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 |