123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- // 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_helpers.h"
- #include "base/memory/raw_ptr.h"
- #include "components/performance_manager/execution_context/execution_context_registry_impl.h"
- #include "components/performance_manager/graph/frame_node_impl.h"
- #include "components/performance_manager/graph/worker_node_impl.h"
- #include "components/performance_manager/public/execution_context/execution_context.h"
- #include "components/performance_manager/public/mojom/v8_contexts.mojom.h"
- #include "components/performance_manager/test_support/graph_test_harness.h"
- #include "components/performance_manager/test_support/mock_graphs.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace performance_manager {
- namespace v8_memory {
- namespace {
- constexpr char kValidExtensionWorldName[] = "abcdefghijklmnopabcdefghijklmnop";
- constexpr char kInvalidExtensionWorldName[] = "BADEXTENSIONNAME";
- constexpr char kWorldName[] = "worldname";
- class V8ContextTrackerHelpersTest : public GraphTestHarness {
- public:
- V8ContextTrackerHelpersTest() = default;
- ~V8ContextTrackerHelpersTest() override = default;
- void OnGraphCreated(GraphImpl* graph_impl) override {
- registry = graph_impl->PassToGraph(
- std::make_unique<execution_context::ExecutionContextRegistryImpl>());
- mock_graph =
- std::make_unique<MockSinglePageWithMultipleProcessesGraph>(graph());
- }
- raw_ptr<execution_context::ExecutionContextRegistry> registry = nullptr;
- std::unique_ptr<MockSinglePageWithMultipleProcessesGraph> mock_graph;
- mojom::IframeAttributionData fake_iframe_attribution_data;
- };
- } // namespace
- TEST_F(V8ContextTrackerHelpersTest, ToExecutionContextToken) {
- blink::DedicatedWorkerToken dedicated;
- blink::ServiceWorkerToken service;
- blink::SharedWorkerToken shared;
- EXPECT_EQ(blink::ExecutionContextToken(dedicated),
- ToExecutionContextToken(blink::WorkerToken(dedicated)));
- EXPECT_EQ(blink::ExecutionContextToken(service),
- ToExecutionContextToken(blink::WorkerToken(service)));
- EXPECT_EQ(blink::ExecutionContextToken(shared),
- ToExecutionContextToken(blink::WorkerToken(shared)));
- }
- TEST_F(V8ContextTrackerHelpersTest, HasCrossProcessParent) {
- // Fails for a main-frame.
- EXPECT_FALSE(HasCrossProcessParent(mock_graph->frame.get()));
- // Returns true for an actual cross-process child frame.
- EXPECT_TRUE(HasCrossProcessParent(mock_graph->child_frame.get()));
- // Fails for a same-process child frame.
- TestNodeWrapper<FrameNodeImpl> child_frame(graph()->CreateFrameNodeAutoId(
- mock_graph->process.get(), mock_graph->page.get(),
- mock_graph->frame.get()));
- EXPECT_FALSE(HasCrossProcessParent(child_frame.get()));
- }
- TEST_F(V8ContextTrackerHelpersTest, IsValidExtensionId) {
- EXPECT_TRUE(IsValidExtensionId("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
- EXPECT_FALSE(IsValidExtensionId("Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
- EXPECT_FALSE(IsValidExtensionId("qaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
- EXPECT_FALSE(IsValidExtensionId("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
- EXPECT_FALSE(IsValidExtensionId(""));
- }
- TEST_F(V8ContextTrackerHelpersTest, IsWorkletToken) {
- blink::LocalFrameToken local_frame;
- blink::DedicatedWorkerToken dedicated;
- blink::ServiceWorkerToken service;
- blink::SharedWorkerToken shared;
- blink::AnimationWorkletToken animation;
- blink::AudioWorkletToken audio;
- blink::LayoutWorkletToken layout;
- blink::PaintWorkletToken paint;
- EXPECT_FALSE(IsWorkletToken(blink::ExecutionContextToken(local_frame)));
- EXPECT_FALSE(IsWorkletToken(blink::ExecutionContextToken(dedicated)));
- EXPECT_FALSE(IsWorkletToken(blink::ExecutionContextToken(service)));
- EXPECT_FALSE(IsWorkletToken(blink::ExecutionContextToken(shared)));
- EXPECT_TRUE(IsWorkletToken(blink::ExecutionContextToken(animation)));
- EXPECT_TRUE(IsWorkletToken(blink::ExecutionContextToken(audio)));
- EXPECT_TRUE(IsWorkletToken(blink::ExecutionContextToken(layout)));
- EXPECT_TRUE(IsWorkletToken(blink::ExecutionContextToken(paint)));
- }
- TEST_F(V8ContextTrackerHelpersTest, GetExecutionContext) {
- FrameNode* frame_node = mock_graph->frame.get();
- auto* execution_context =
- GetExecutionContext(frame_node->GetFrameToken(), graph());
- ASSERT_TRUE(execution_context);
- EXPECT_EQ(frame_node, execution_context->GetFrameNode());
- }
- TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
- TestNodeWrapper<FrameNodeImpl> child_frame(graph()->CreateFrameNodeAutoId(
- mock_graph->process.get(), mock_graph->page.get(),
- mock_graph->frame.get()));
- // A valid description of a main frame.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt, mock_graph->frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A valid description of a cross-process child frame.
- desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt, mock_graph->child_frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A valid description of a same-process child frame.
- desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt, child_frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(true,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A valid description of a frame, but one that doesn't have a corresponding
- // entry in the graph. In this case its impossible to determine if
- // IframeAttributionData should accompany the V8ContextDescription.
- desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt, blink::LocalFrameToken());
- EXPECT_EQ(absl::nullopt,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A main-world should not have a world name.
- EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorldName,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- kWorldName, mock_graph->frame->frame_token())));
- // A main world must have an |execution_context_token|.
- EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt,
- /* execution_context_token */ absl::nullopt)));
- // A main world must have an blink::LocalFrameToken.
- blink::ExecutionContextToken worker_token((blink::SharedWorkerToken()));
- EXPECT_EQ(V8ContextDescriptionStatus::kMissingLocalFrameToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ absl::nullopt, worker_token)));
- }
- TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionWorkerWorld) {
- blink::DedicatedWorkerToken worker_token;
- auto worker = TestNodeWrapper<WorkerNodeImpl>::Create(
- graph(), WorkerNode::WorkerType::kDedicated, mock_graph->process.get(),
- "browser_context", worker_token);
- // A valid worker description.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ absl::nullopt, worker_token);
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A worker should not have a world name.
- EXPECT_EQ(
- V8ContextDescriptionStatus::kUnexpectedWorldName,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- kWorldName, worker_token)));
- // A worker must have an |execution_context_token|.
- EXPECT_EQ(
- V8ContextDescriptionStatus::kMissingExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ absl::nullopt,
- /* execution_context_token */ absl::nullopt)));
- // A worker must have a valid worker token, not a LocalFrameToken.
- EXPECT_EQ(
- V8ContextDescriptionStatus::kUnexpectedLocalFrameToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ absl::nullopt, blink::LocalFrameToken())));
- }
- TEST_F(V8ContextTrackerHelpersTest,
- ValidateV8ContextDescriptionExtensionWorld) {
- // A valid extension description.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- kValidExtensionWorldName, mock_graph->frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // An extension must have a world name.
- EXPECT_EQ(
- V8ContextDescriptionStatus::kMissingWorldName,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- /* world_name */ absl::nullopt, mock_graph->frame->frame_token())));
- // An invalid extension name should fail.
- EXPECT_EQ(V8ContextDescriptionStatus::kInvalidExtensionWorldName,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- kInvalidExtensionWorldName, mock_graph->frame->frame_token())));
- // An extension must have an |execution_context_token|.
- EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- kValidExtensionWorldName,
- /* execution_context_token */ absl::nullopt)));
- // An extension can't inject into a worklet.
- EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- kValidExtensionWorldName, blink::AudioWorkletToken())));
- }
- TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionIsolatedWorld) {
- // An isolated world may or may not have a |world_name|.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ absl::nullopt, mock_graph->frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated, kWorldName,
- mock_graph->frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // An isolated world must have an |execution_context_token|
- EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ absl::nullopt,
- /* execution_context_token */ absl::nullopt)));
- // An isolated world can not inject into a worklet.
- EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ absl::nullopt, blink::AudioWorkletToken())));
- }
- TEST_F(V8ContextTrackerHelpersTest,
- ValidateV8ContextDescriptionInspectorWorld) {
- // A valid inspector world.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ absl::nullopt, mock_graph->frame->frame_token());
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // An inspector world must have an |execution_context_token|
- EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ absl::nullopt,
- /* execution_context_token */ absl::nullopt)));
- // An inspector world can not inject into a worklet.
- EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ absl::nullopt, blink::AudioWorkletToken())));
- }
- TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionRegExpWorld) {
- // A valid regexp world.
- auto desc = mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
- /* world_name */ absl::nullopt,
- /* execution_context_token */ absl::nullopt);
- EXPECT_EQ(V8ContextDescriptionStatus::kValid,
- ValidateV8ContextDescription(desc));
- EXPECT_EQ(false,
- ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
- // A regexp world must not have a |world_name|.
- EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorldName,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
- kWorldName,
- /* execution_context_token */ absl::nullopt)));
- // A regexp world must not have an |execution_context_token|.
- EXPECT_EQ(
- V8ContextDescriptionStatus::kUnexpectedExecutionContextToken,
- ValidateV8ContextDescription(mojom::V8ContextDescription(
- blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
- /* world_name */ absl::nullopt, mock_graph->frame->frame_token())));
- }
- } // namespace v8_memory
- } // namespace performance_manager
|