| Index: chrome/browser/metrics/subprocess_metrics_provider.cc
|
| diff --git a/chrome/browser/metrics/subprocess_metrics_provider.cc b/chrome/browser/metrics/subprocess_metrics_provider.cc
|
| index dbc5774479477a6f2161192d80e498bfad3287bd..57aa9ae1344b3c46517db6a5953cc9c0f7fdc445 100644
|
| --- a/chrome/browser/metrics/subprocess_metrics_provider.cc
|
| +++ b/chrome/browser/metrics/subprocess_metrics_provider.cc
|
| @@ -11,17 +11,24 @@
|
| #include "base/metrics/persistent_histogram_allocator.h"
|
| #include "base/metrics/persistent_memory_allocator.h"
|
| #include "components/metrics/metrics_service.h"
|
| +#include "content/public/browser/browser_child_process_host.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/child_process_data.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/notification_types.h"
|
| #include "content/public/browser/render_process_host.h"
|
|
|
| SubprocessMetricsProvider::SubprocessMetricsProvider()
|
| - : scoped_observer_(this) {
|
| + : scoped_observer_(this), weak_ptr_factory_(this) {
|
| + content::BrowserChildProcessObserver::Add(this);
|
| registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
|
| content::NotificationService::AllBrowserContextsAndSources());
|
| }
|
|
|
| -SubprocessMetricsProvider::~SubprocessMetricsProvider() {}
|
| +SubprocessMetricsProvider::~SubprocessMetricsProvider() {
|
| + // Safe even if this object has never been added as an observer.
|
| + content::BrowserChildProcessObserver::Remove(this);
|
| +}
|
|
|
| void SubprocessMetricsProvider::RegisterSubprocessAllocator(
|
| int id,
|
| @@ -29,6 +36,12 @@ void SubprocessMetricsProvider::RegisterSubprocessAllocator(
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| DCHECK(!allocators_by_id_.Lookup(id));
|
|
|
| + // Stop now if this was called without an allocator, typically because
|
| + // GetSubprocessHistogramAllocatorOnIOThread exited early and returned
|
| + // null.
|
| + if (!allocator)
|
| + return;
|
| +
|
| // Map is "MapOwnPointer" so transfer ownership to it.
|
| allocators_by_id_.AddWithID(allocator.release(), id);
|
| }
|
| @@ -83,6 +96,44 @@ void SubprocessMetricsProvider::MergeHistogramDeltas() {
|
| allocators_by_id_.size());
|
| }
|
|
|
| +void SubprocessMetricsProvider::BrowserChildProcessHostConnected(
|
| + const content::ChildProcessData& data) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + // It's necessary to access the BrowserChildProcessHost object that is
|
| + // managing the child in order to extract the metrics memory from it.
|
| + // Unfortunately, the required lookup can only be performed on the IO
|
| + // thread so do the necessary dance.
|
| + content::BrowserThread::PostTaskAndReplyWithResult(
|
| + content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&SubprocessMetricsProvider::
|
| + GetSubprocessHistogramAllocatorOnIOThread,
|
| + data.id),
|
| + base::Bind(&SubprocessMetricsProvider::
|
| + RegisterSubprocessAllocator,
|
| + weak_ptr_factory_.GetWeakPtr(), data.id));
|
| +}
|
| +
|
| +void SubprocessMetricsProvider::BrowserChildProcessHostDisconnected(
|
| + const content::ChildProcessData& data) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DeregisterSubprocessAllocator(data.id);
|
| +}
|
| +
|
| +void SubprocessMetricsProvider::BrowserChildProcessCrashed(
|
| + const content::ChildProcessData& data,
|
| + int exit_code) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DeregisterSubprocessAllocator(data.id);
|
| +}
|
| +
|
| +void SubprocessMetricsProvider::BrowserChildProcessKilled(
|
| + const content::ChildProcessData& data,
|
| + int exit_code) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DeregisterSubprocessAllocator(data.id);
|
| +}
|
| +
|
| void SubprocessMetricsProvider::Observe(
|
| int type,
|
| const content::NotificationSource& source,
|
| @@ -135,3 +186,22 @@ void SubprocessMetricsProvider::RenderProcessHostDestroyed(
|
| DeregisterSubprocessAllocator(host->GetID());
|
| scoped_observer_.Remove(host);
|
| }
|
| +
|
| +// static
|
| +std::unique_ptr<base::PersistentHistogramAllocator>
|
| +SubprocessMetricsProvider::GetSubprocessHistogramAllocatorOnIOThread(int id) {
|
| + // See if the new process has a memory allocator and take control of it if so.
|
| + // This call can only be made on the browser's IO thread.
|
| + content::BrowserChildProcessHost* host =
|
| + content::BrowserChildProcessHost::FromID(id);
|
| + if (!host)
|
| + return nullptr;
|
| +
|
| + std::unique_ptr<base::SharedPersistentMemoryAllocator> allocator =
|
| + host->TakeMetricsAllocator();
|
| + if (!allocator)
|
| + return nullptr;
|
| +
|
| + return base::MakeUnique<base::PersistentHistogramAllocator>(
|
| + std::move(allocator));
|
| +}
|
|
|