123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/performance_manager/v8_memory/v8_context_tracker.h"
- #include <memory>
- #include "base/strings/stringprintf.h"
- #include "components/performance_manager/execution_context/execution_context_registry_impl.h"
- #include "components/performance_manager/public/graph/graph.h"
- #include "components/performance_manager/test_support/performance_manager_browsertest_harness.h"
- #include "content/public/browser/render_frame_host.h"
- #include "content/public/test/browser_test.h"
- #include "content/public/test/browser_test_utils.h"
- #include "content/public/test/content_browser_test_utils.h"
- #include "content/shell/browser/shell.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "url/gurl.h"
- namespace performance_manager {
- namespace v8_memory {
- class V8ContextTrackerTest : public PerformanceManagerBrowserTestHarness {
- public:
- using Super = PerformanceManagerBrowserTestHarness;
- V8ContextTrackerTest() = default;
- ~V8ContextTrackerTest() override = default;
- void SetUp() override {
- GetGraphFeatures().EnableV8ContextTracker();
- Super::SetUp();
- }
- void ExpectCounts(size_t v8_context_count,
- size_t execution_context_count,
- size_t detached_v8_context_count,
- size_t destroyed_execution_context_count) {
- RunInGraph([&](Graph* graph) {
- auto* v8ct = V8ContextTracker::GetFromGraph(graph);
- ASSERT_TRUE(v8ct);
- EXPECT_EQ(v8_context_count, v8ct->GetV8ContextCountForTesting());
- EXPECT_EQ(execution_context_count,
- v8ct->GetExecutionContextCountForTesting());
- EXPECT_EQ(detached_v8_context_count,
- v8ct->GetDetachedV8ContextCountForTesting());
- EXPECT_EQ(destroyed_execution_context_count,
- v8ct->GetDestroyedExecutionContextCountForTesting());
- });
- }
- };
- IN_PROC_BROWSER_TEST_F(V8ContextTrackerTest, AboutBlank) {
- ExpectCounts(0, 0, 0, 0);
- ASSERT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
- ExpectCounts(1, 1, 0, 0);
- }
- IN_PROC_BROWSER_TEST_F(V8ContextTrackerTest, SameOriginIframeAttributionData) {
- GURL urla(embedded_test_server()->GetURL("a.com", "/a_embeds_a.html"));
- auto* contents = shell()->web_contents();
- ASSERT_TRUE(
- NavigateAndWaitForConsoleMessage(contents, urla, "a.html loaded"));
- // Get pointers to the RFHs for each frame.
- content::RenderFrameHost* main_rfh = contents->GetPrimaryMainFrame();
- content::RenderFrameHost* child_rfh = ChildFrameAt(main_rfh, 0);
- ASSERT_TRUE(child_rfh);
- auto frame_node =
- PerformanceManager::GetFrameNodeForRenderFrameHost(child_rfh);
- RunInGraph([&frame_node](Graph* graph) {
- ASSERT_TRUE(frame_node);
- auto* v8_context_tracker = V8ContextTracker::GetFromGraph(graph);
- ASSERT_TRUE(v8_context_tracker);
- auto* ec_state = v8_context_tracker->GetExecutionContextState(
- frame_node->GetFrameToken());
- ASSERT_TRUE(ec_state);
- ASSERT_TRUE(ec_state->iframe_attribution_data);
- });
- }
- IN_PROC_BROWSER_TEST_F(V8ContextTrackerTest, CrossOriginIframeAttributionData) {
- GURL urla(embedded_test_server()->GetURL("a.com", "/a_embeds_b.html"));
- auto* contents = shell()->web_contents();
- ASSERT_TRUE(
- NavigateAndWaitForConsoleMessage(contents, urla, "b.html loaded"));
- // Get pointers to the RFHs for each frame.
- content::RenderFrameHost* main_rfh = contents->GetPrimaryMainFrame();
- content::RenderFrameHost* child_rfh = ChildFrameAt(main_rfh, 0);
- ASSERT_TRUE(child_rfh);
- auto frame_node =
- PerformanceManager::GetFrameNodeForRenderFrameHost(child_rfh);
- RunInGraph([&frame_node](Graph* graph) {
- ASSERT_TRUE(frame_node);
- auto* v8_context_tracker = V8ContextTracker::GetFromGraph(graph);
- ASSERT_TRUE(v8_context_tracker);
- auto* ec_state = v8_context_tracker->GetExecutionContextState(
- frame_node->GetFrameToken());
- ASSERT_TRUE(ec_state);
- ASSERT_TRUE(ec_state->iframe_attribution_data)
- << "url " << frame_node->GetURL() << ", current "
- << frame_node->IsCurrent() << ", state "
- << frame_node->GetLifecycleState();
- });
- }
- IN_PROC_BROWSER_TEST_F(V8ContextTrackerTest, SameDocNavigation) {
- ExpectCounts(0, 0, 0, 0);
- auto* contents = shell()->web_contents();
- GURL urla(embedded_test_server()->GetURL("a.com", "/a_embeds_b.html"));
- ASSERT_TRUE(
- NavigateAndWaitForConsoleMessage(contents, urla, "b.html loaded"));
- ExpectCounts(2, 2, 0, 0);
- // Get pointers to the RFHs for each frame.
- content::RenderFrameHost* rfha = contents->GetPrimaryMainFrame();
- content::RenderFrameHost* rfhb = ChildFrameAt(rfha, 0);
- // Execute a same document navigation in the child frame. This causes a
- // v8 context to be detached, and new context attached to the execution
- // context. So there will remain 2 execution contexts, there will be 3
- // v8 contexts, 1 one of which is detached.
- GURL urlb(embedded_test_server()->GetURL("b.com", "/b.html?foo=bar"));
- ASSERT_TRUE(ExecJs(
- rfhb, base::StringPrintf("location.href = \"%s\"", urlb.spec().c_str())));
- WaitForLoad(contents);
- ExpectCounts(3, 2, 1, 0);
- }
- IN_PROC_BROWSER_TEST_F(V8ContextTrackerTest, DetachedContext) {
- ExpectCounts(0, 0, 0, 0);
- auto* contents = shell()->web_contents();
- GURL urla(embedded_test_server()->GetURL("a.com", "/a_embeds_a.html"));
- ASSERT_TRUE(
- NavigateAndWaitForConsoleMessage(contents, urla, "a.html loaded"));
- ExpectCounts(2, 2, 0, 0);
- // Get pointers to the RFHs for each frame.
- content::RenderFrameHost* rfha = contents->GetPrimaryMainFrame();
- // Keep a pointer to the window associated with the child iframe, but
- // unload it.
- ASSERT_TRUE(ExecJs(rfha,
- "let iframe = document.getElementsByTagName('iframe')[0]; "
- "document.body.leakyRef = iframe.contentWindow.window; "
- "iframe.parentNode.removeChild(iframe); "
- "console.log('detached and leaked iframe');"));
- ExpectCounts(2, 2, 1, 1);
- }
- } // namespace v8_memory
- } // namespace performance_manager
|