211 lines
7.6 KiB
C++
211 lines
7.6 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "components/metrics/content/subprocess_metrics_provider.h"
|
|
|
|
#include <string>
|
|
|
|
#include "base/metrics/histogram.h"
|
|
#include "base/metrics/persistent_histogram_allocator.h"
|
|
#include "base/metrics/persistent_memory_allocator.h"
|
|
#include "content/public/browser/child_process_termination_info.h"
|
|
#include "content/public/test/browser_test.h"
|
|
#include "content/public/test/content_browser_test.h"
|
|
#include "content/public/test/content_browser_test_utils.h"
|
|
#include "content/shell/browser/shell.h"
|
|
#include "net/dns/mock_host_resolver.h"
|
|
|
|
namespace metrics {
|
|
|
|
namespace {
|
|
|
|
// Returns a random histogram in Allocator. It hard to know which metric will
|
|
// not be deprecated and exist after navigation. this will work because we
|
|
// always pick up a histogram from render process and verify if it is copied to
|
|
// the global allocator.
|
|
std::string GetAnyHistogramInAllocator(
|
|
base::PersistentHistogramAllocator* allocator) {
|
|
base::PersistentHistogramAllocator::Iterator iter(allocator);
|
|
std::string histogram_name;
|
|
if (std::unique_ptr<base::HistogramBase> histogram = iter.GetNext())
|
|
histogram_name = histogram->histogram_name();
|
|
return histogram_name;
|
|
}
|
|
|
|
bool HasHistogramInAllocator(base::PersistentHistogramAllocator* allocator,
|
|
const std::string& histogram_name) {
|
|
base::PersistentHistogramAllocator::Iterator iter(allocator);
|
|
while (std::unique_ptr<base::HistogramBase> histogram = iter.GetNext()) {
|
|
if (histogram_name == histogram->histogram_name())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
size_t GetRenderProcessHostCount() {
|
|
auto it = content::RenderProcessHost::AllHostsIterator();
|
|
size_t count = 0;
|
|
while (!it.IsAtEnd()) {
|
|
it.Advance();
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class SubprocessMetricsProviderBrowserTest
|
|
: public content::ContentBrowserTest {
|
|
public:
|
|
void CreateSubprocessMetricsProvider() {
|
|
provider_ = std::make_unique<SubprocessMetricsProvider>();
|
|
}
|
|
|
|
SubprocessMetricsProvider::AllocatorByIdMap& get_allocators_by_id() {
|
|
return provider_->allocators_by_id_;
|
|
}
|
|
|
|
base::ScopedMultiSourceObservation<content::RenderProcessHost,
|
|
content::RenderProcessHostObserver>&
|
|
get_scoped_observations() {
|
|
return provider_->scoped_observations_;
|
|
}
|
|
|
|
base::PersistentHistogramAllocator* GetMainFrameAllocator() {
|
|
return get_allocators_by_id().Lookup(
|
|
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID());
|
|
}
|
|
|
|
void SimulateRenderProcessExit() {
|
|
provider_->RenderProcessExited(
|
|
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess(),
|
|
content::ChildProcessTerminationInfo());
|
|
}
|
|
|
|
void SimulateRenderProcessHostDestroyed() {
|
|
provider_->RenderProcessHostDestroyed(
|
|
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess());
|
|
}
|
|
|
|
protected:
|
|
void SetUpOnMainThread() override {
|
|
content::ContentBrowserTest::SetUpOnMainThread();
|
|
host_resolver()->AddRule("*", "127.0.0.1");
|
|
}
|
|
|
|
void SetUp() override {
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
base::GlobalHistogramAllocator::CreateWithLocalMemory(4 << 20, 0x935DDD43,
|
|
"BrowserMetrics");
|
|
content::ContentBrowserTest::SetUp();
|
|
}
|
|
|
|
void TearDown() override {
|
|
content::ContentBrowserTest::TearDown();
|
|
provider_.reset();
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<SubprocessMetricsProvider> provider_;
|
|
};
|
|
|
|
IN_PROC_BROWSER_TEST_F(SubprocessMetricsProviderBrowserTest,
|
|
RegisterExistingNotReadyRenderProcesses) {
|
|
ASSERT_TRUE(GetRenderProcessHostCount() > 0);
|
|
CreateSubprocessMetricsProvider();
|
|
EXPECT_EQ(get_scoped_observations().GetSourcesCount(),
|
|
GetRenderProcessHostCount());
|
|
EXPECT_EQ(get_allocators_by_id().size(), 0u);
|
|
|
|
GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
|
content::NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
|
|
|
|
// Verify that the number of scoped observer matches the number of
|
|
// RenderProcessHost and the main frame allocator exists.
|
|
EXPECT_EQ(get_scoped_observations().GetSourcesCount(),
|
|
GetRenderProcessHostCount());
|
|
auto* main_frame_allocator = GetMainFrameAllocator();
|
|
EXPECT_TRUE(main_frame_allocator);
|
|
|
|
// Verify the render process's allocator have the render process metrics.
|
|
std::string render_process_histogram =
|
|
GetAnyHistogramInAllocator(main_frame_allocator);
|
|
EXPECT_FALSE(render_process_histogram.empty());
|
|
|
|
// Verify the global histogram allocator have no render process metrics.
|
|
base::GlobalHistogramAllocator* global_histogram_allocator =
|
|
base::GlobalHistogramAllocator::Get();
|
|
ASSERT_TRUE(global_histogram_allocator);
|
|
EXPECT_FALSE(HasHistogramInAllocator(global_histogram_allocator,
|
|
render_process_histogram))
|
|
<< " The histogram in the context is " << render_process_histogram;
|
|
|
|
SimulateRenderProcessExit();
|
|
|
|
// Verify the allocator deregistered.
|
|
EXPECT_FALSE(GetMainFrameAllocator());
|
|
|
|
// Verify the render process metrics were merged to the global histogram
|
|
// allocator.
|
|
EXPECT_TRUE(HasHistogramInAllocator(global_histogram_allocator,
|
|
render_process_histogram))
|
|
<< " The histogram in the context is " << render_process_histogram;
|
|
|
|
auto* main_frame_process_host =
|
|
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess();
|
|
SimulateRenderProcessHostDestroyed();
|
|
// Verify the observer removed.
|
|
EXPECT_FALSE(
|
|
get_scoped_observations().IsObservingSource(main_frame_process_host));
|
|
}
|
|
|
|
IN_PROC_BROWSER_TEST_F(SubprocessMetricsProviderBrowserTest,
|
|
RegisterExistingReadyRenderProcesses) {
|
|
GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
|
|
|
content::NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
|
|
|
|
CreateSubprocessMetricsProvider();
|
|
|
|
// Verify that the number of scoped observer matches the number of
|
|
// RenderProcessHost and the main frame allocator exists.
|
|
EXPECT_EQ(get_scoped_observations().GetSourcesCount(),
|
|
GetRenderProcessHostCount());
|
|
auto* main_frame_allocator = GetMainFrameAllocator();
|
|
EXPECT_TRUE(main_frame_allocator);
|
|
|
|
// Verify the render process's allocator have the render process metrics.
|
|
std::string render_process_histogram =
|
|
GetAnyHistogramInAllocator(main_frame_allocator);
|
|
EXPECT_FALSE(render_process_histogram.empty());
|
|
|
|
// Verify the global histogram allocator have no render process metrics.
|
|
base::GlobalHistogramAllocator* global_histogram_allocator =
|
|
base::GlobalHistogramAllocator::Get();
|
|
ASSERT_TRUE(global_histogram_allocator);
|
|
EXPECT_FALSE(HasHistogramInAllocator(global_histogram_allocator,
|
|
render_process_histogram))
|
|
<< " The histogram in the context is " << render_process_histogram;
|
|
|
|
SimulateRenderProcessExit();
|
|
|
|
// Verify the allocator deregistered.
|
|
EXPECT_FALSE(GetMainFrameAllocator());
|
|
|
|
// Verify the render process metrics were merged to the global histogram
|
|
// allocator.
|
|
EXPECT_TRUE(HasHistogramInAllocator(global_histogram_allocator,
|
|
render_process_histogram))
|
|
<< " The histogram in the context is " << render_process_histogram;
|
|
|
|
auto* main_frame_process_host =
|
|
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess();
|
|
SimulateRenderProcessHostDestroyed();
|
|
// Verify the observer removed.
|
|
EXPECT_FALSE(
|
|
get_scoped_observations().IsObservingSource(main_frame_process_host));
|
|
}
|
|
|
|
} // namespace metrics
|