Commit 6e354da4 authored by Joe Mason's avatar Joe Mason Committed by Commit Bot

[PM] Monitor remote iframe attach/detach for V8ContextTracker

Instruments HTMLFrameOwnerElement to notify RendererResourceCoordinator
whenever the content frame changes. If the new content frame is a
RemoteFrame, RendererResourceCoordinator will notify PerformanceManager
of the frame's RemoteFrameToken and some attribution information for the
iframe. PerformanceManager stores this information in V8ContextTracker.

Also updates frame_test_helpers::CreateProvisional to accept local
frames since the underlying WebLocalFrame::CreateProvisional now allows
this.

Bug: 1085129
Change-Id: I43d7d7f1309db9c4b1760ca32983c0e8a2f51a6d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2363710Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Commit-Queue: Joe Mason <joenotcharles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828284}
parent 4e41c445
......@@ -10,6 +10,7 @@
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/graph_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/public/execution_context/execution_context_registry.h"
#include "components/performance_manager/v8_memory/v8_context_tracker.h"
namespace performance_manager {
......@@ -46,6 +47,7 @@ void ProcessNodeImpl::SetMainThreadTaskLoadIsLow(
void ProcessNodeImpl::OnV8ContextCreated(
mojom::V8ContextDescriptionPtr description,
mojom::IframeAttributionDataPtr iframe_attribution_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) {
tracker->OnV8ContextCreated(PassKey(), this, *description,
std::move(iframe_attribution_data));
......@@ -54,16 +56,55 @@ void ProcessNodeImpl::OnV8ContextCreated(
void ProcessNodeImpl::OnV8ContextDetached(
const blink::V8ContextToken& v8_context_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph()))
tracker->OnV8ContextDetached(PassKey(), this, v8_context_token);
}
void ProcessNodeImpl::OnV8ContextDestroyed(
const blink::V8ContextToken& v8_context_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph()))
tracker->OnV8ContextDestroyed(PassKey(), this, v8_context_token);
}
void ProcessNodeImpl::OnRemoteIframeAttached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) {
auto* ec_registry =
execution_context::ExecutionContextRegistry::GetFromGraph(graph());
DCHECK(ec_registry);
auto* parent_frame_node =
ec_registry->GetFrameNodeByFrameToken(parent_frame_token);
if (parent_frame_node) {
tracker->OnRemoteIframeAttached(
PassKey(), FrameNodeImpl::FromNode(parent_frame_node),
remote_frame_token, std::move(iframe_attribution_data));
}
}
}
void ProcessNodeImpl::OnRemoteIframeDetached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) {
auto* ec_registry =
execution_context::ExecutionContextRegistry::GetFromGraph(graph());
DCHECK(ec_registry);
auto* parent_frame_node =
ec_registry->GetFrameNodeByFrameToken(parent_frame_token);
if (parent_frame_node) {
tracker->OnRemoteIframeDetached(
PassKey(), FrameNodeImpl::FromNode(parent_frame_node),
remote_frame_token);
}
}
}
void ProcessNodeImpl::SetProcessExitStatus(int32_t exit_status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This may occur as the first event seen in the case where the process
......
......@@ -24,6 +24,7 @@
#include "components/performance_manager/public/render_process_host_proxy.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/common/tokens/tokens.h"
namespace performance_manager {
......@@ -66,6 +67,13 @@ class ProcessNodeImpl
const blink::V8ContextToken& v8_context_token) override;
void OnV8ContextDestroyed(
const blink::V8ContextToken& v8_context_token) override;
void OnRemoteIframeAttached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) override;
void OnRemoteIframeDetached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token) override;
void SetProcessExitStatus(int32_t exit_status);
void SetProcess(base::Process process, base::Time launch_time);
......
......@@ -7,8 +7,8 @@ module performance_manager.mojom;
import "mojo/public/mojom/base/process_id.mojom";
import "mojo/public/mojom/base/time.mojom";
import "components/performance_manager/public/mojom/lifecycle.mojom";
import "components/performance_manager/public/mojom/web_memory.mojom";
import "components/performance_manager/public/mojom/v8_contexts.mojom";
import "components/performance_manager/public/mojom/web_memory.mojom";
import "third_party/blink/public/mojom/tokens/tokens.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
......@@ -78,6 +78,8 @@ interface DocumentCoordinationUnit {
(WebMemoryMeasurement measurement);
};
// Interface used by the RendererResourceCoordinator singleton to send state
// associated with resource management of a renderer process to the embedder.
interface ProcessCoordinationUnit {
// Property signals.
SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low);
......@@ -113,4 +115,19 @@ interface ProcessCoordinationUnit {
// is never called for contexts in a renderer processes that crashes or is
// otherwise terminated.
OnV8ContextDestroyed(blink.mojom.V8ContextToken v8_context_token);
// Called when a RemoteFrame is attached as the content of a local iframe.
// The browser process will use this to maintain a map from the RemoteFrame's
// token to the iframe's attribution information as seen by the renderer
// process.
OnRemoteIframeAttached(blink.mojom.LocalFrameToken parent_frame_token,
blink.mojom.RemoteFrameToken remote_frame_token,
IframeAttributionData iframe_attribution_data);
// Called when a RemoteFrame that was the content of a local iframe is
// removed from the frame. Only the frame token is needed because the
// iframe's attribution information was previously associated with the token
// by OnRemoteIframeAttached.
OnRemoteIframeDetached(blink.mojom.LocalFrameToken parent_frame_token,
blink.mojom.RemoteFrameToken remote_frame_token);
};
......@@ -196,7 +196,7 @@ void V8ContextTracker::OnV8ContextDestroyed(
}
void V8ContextTracker::OnRemoteIframeAttached(
util::PassKey<FrameNodeImpl> key,
util::PassKey<ProcessNodeImpl> key,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) {
......@@ -218,6 +218,7 @@ void V8ContextTracker::OnRemoteIframeAttached(
blink::RemoteFrameToken remote_frame_token;
mojom::IframeAttributionDataPtr iframe_attribution_data;
base::WeakPtr<FrameNode> frame_node;
base::WeakPtr<FrameNode> parent_frame_node;
};
std::unique_ptr<Data> data(
new Data{mojo::GetBadMessageCallback(), remote_frame_token,
......@@ -227,12 +228,32 @@ void V8ContextTracker::OnRemoteIframeAttached(
DCHECK(data);
DCHECK(graph);
DCHECK_ON_GRAPH_SEQUENCE(graph);
if (data->frame_node) {
// Only dispatch if the frame and its parent still exist after the
// round-trip through the UI thread. If the frame still exists but now has
// no parent, we don't need to record IframeAttribution data for it since
// it's now unreachable.
//
// An example of this is the custom <webview> element used in Chrome UI
// (extensions/renderer/resources/guest_view/web_view/web_view.js). This
// element has an inner web contents with an opener relationship to the
// webview, but no parent-child relationship. However since it is a custom
// element implemented on top of <iframe>, the renderer has no way to
// distinguish it from a regular iframe. At the moment the contents is
// attached it has a transient parent frame, which is reported through
// OnRemoteIframeAttached, but the parent frame disappears shortly
// afterward.
//
// TODO(crbug.com/1085129): Write an end-to-end browsertest that covers
// this case once all parts of the measure memory API are hooked up.
if (data->frame_node && data->parent_frame_node) {
auto* frame_node = FrameNodeImpl::FromNode(data->frame_node.get());
auto* parent_frame_node =
FrameNodeImpl::FromNode(data->parent_frame_node.get());
if (auto* tracker = V8ContextTracker::GetFromGraph(graph)) {
tracker->OnRemoteIframeAttachedImpl(
std::move(data->bad_message_callback), frame_node,
data->remote_frame_token, std::move(data->iframe_attribution_data));
parent_frame_node, data->remote_frame_token,
std::move(data->iframe_attribution_data));
}
}
});
......@@ -263,7 +284,7 @@ void V8ContextTracker::OnRemoteIframeAttached(
}
void V8ContextTracker::OnRemoteIframeDetached(
util::PassKey<FrameNodeImpl> key,
util::PassKey<ProcessNodeImpl> key,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token) {
DCHECK_ON_GRAPH_SEQUENCE(parent_frame_node->graph());
......@@ -306,10 +327,11 @@ void V8ContextTracker::OnRemoteIframeDetached(
void V8ContextTracker::OnRemoteIframeAttachedForTesting(
FrameNodeImpl* frame_node,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) {
OnRemoteIframeAttachedImpl(base::BindOnce(&FakeReportBadMessageForTesting),
frame_node, remote_frame_token,
frame_node, parent_frame_node, remote_frame_token,
std::move(iframe_attribution_data));
}
......@@ -449,11 +471,18 @@ void V8ContextTracker::OnBeforeProcessNodeRemoved(const ProcessNode* node) {
void V8ContextTracker::OnRemoteIframeAttachedImpl(
mojo::ReportBadMessageCallback bad_message_callback,
FrameNodeImpl* frame_node,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) {
DCHECK(bad_message_callback);
DCHECK_ON_GRAPH_SEQUENCE(frame_node->graph());
if (frame_node->parent_frame_node() != parent_frame_node) {
std::move(bad_message_callback)
.Run("OnRemoteIframeAttached has wrong parent frame");
return;
}
if (data_store_->Get(remote_frame_token)) {
std::move(bad_message_callback).Run("repeated OnRemoteIframeAttached");
return;
......
......@@ -165,7 +165,7 @@ class V8ContextTracker final
// be called for bookkeeping. This should only be called once for a given
// |remote_frame_token|.
void OnRemoteIframeAttached(
util::PassKey<FrameNodeImpl> key,
util::PassKey<ProcessNodeImpl> key,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data);
......@@ -180,7 +180,7 @@ class V8ContextTracker final
// |remote_frame_token|, and only after a matching "OnRemoteIframeAttached"
// call.
void OnRemoteIframeDetached(
util::PassKey<FrameNodeImpl> key,
util::PassKey<ProcessNodeImpl> key,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token);
......@@ -189,6 +189,7 @@ class V8ContextTracker final
void OnRemoteIframeAttachedForTesting(
FrameNodeImpl* frame_node,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data);
......@@ -229,6 +230,7 @@ class V8ContextTracker final
void OnRemoteIframeAttachedImpl(
mojo::ReportBadMessageCallback bad_message_callback,
FrameNodeImpl* frame_node,
FrameNodeImpl* parent_frame_node,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data);
......
......@@ -140,13 +140,20 @@ TEST_F(V8ContextTrackerDeathTest, MissingContextExplodes) {
}
TEST_F(V8ContextTrackerDeathTest, DoubleRemoteFrameCreatedExplodes) {
tracker->OnRemoteIframeAttachedForTesting(mock_graph.child_frame.get(),
kChildFrameRemoteToken,
GetFakeIframeAttributionDataPtr());
tracker->OnRemoteIframeAttachedForTesting(
mock_graph.child_frame.get(), mock_graph.frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr());
EXPECT_DCHECK_DEATH(tracker->OnRemoteIframeAttachedForTesting(
mock_graph.child_frame.get(), kChildFrameRemoteToken,
GetFakeIframeAttributionDataPtr()));
mock_graph.child_frame.get(), mock_graph.frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr()));
}
TEST_F(V8ContextTrackerDeathTest, RemoteFrameWithBadParentExplodes) {
// child_frame's real parent is frame.
EXPECT_DCHECK_DEATH(tracker->OnRemoteIframeAttachedForTesting(
mock_graph.child_frame.get(), mock_graph.child_frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr()));
}
TEST_F(V8ContextTrackerDeathTest, IframeAttributionDataForMainFrameExplodes) {
......@@ -170,7 +177,7 @@ TEST_F(V8ContextTrackerDeathTest, IframeAttributionDataForInProcessChildFrame) {
// notification should explode because |child2_frame| is in the same process
// as its parent.
EXPECT_DCHECK_DEATH(tracker->OnRemoteIframeAttachedForTesting(
child2_frame.get(), blink::RemoteFrameToken(),
child2_frame.get(), mock_graph.frame.get(), blink::RemoteFrameToken(),
GetFakeIframeAttributionDataPtr()));
// This should succeed because iframe data is provided.
......@@ -344,8 +351,8 @@ TEST_F(V8ContextTrackerTest, MultipleV8ContextsForExecutionContext) {
{
SCOPED_TRACE("");
tracker->OnRemoteIframeAttachedForTesting(
mock_graph.child_frame.get(), kChildFrameRemoteToken,
GetFakeIframeAttributionDataPtr());
mock_graph.child_frame.get(), mock_graph.frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr());
EXPECT_THAT(tracker, CountsMatch(4, 2));
EXPECT_THAT(tracker, DetachedCountsMatch(0, 0));
}
......@@ -483,8 +490,8 @@ TEST_F(V8ContextTrackerTest, AllEventOrders) {
auto iframeattach = [self = this]() {
SCOPED_TRACE("");
self->tracker->OnRemoteIframeAttachedForTesting(
self->mock_graph.child_frame.get(), kChildFrameRemoteToken,
GetFakeIframeAttributionDataPtr());
self->mock_graph.child_frame.get(), self->mock_graph.frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr());
};
// Detaches a child iframe. This message is sent over the interface associated
......@@ -757,9 +764,9 @@ TEST_F(V8ContextTrackerTest, PublicApi) {
// Provide iframe data for the child frame.
ASSERT_FALSE(ec_state->iframe_attribution_data);
tracker->OnRemoteIframeAttachedForTesting(mock_graph.child_frame.get(),
kChildFrameRemoteToken,
GetFakeIframeAttributionDataPtr());
tracker->OnRemoteIframeAttachedForTesting(
mock_graph.child_frame.get(), mock_graph.frame.get(),
kChildFrameRemoteToken, GetFakeIframeAttributionDataPtr());
const auto& iad = ec_state->iframe_attribution_data;
ASSERT_TRUE(iad);
......
......@@ -28,9 +28,9 @@ namespace blink {
// counterpart in the browser.
using LocalFrameToken = util::TokenType<class LocalFrameTokenTypeMarker>;
// Uniquely identifies an blink::RemoteFrame / blink::WebRemoteFrame /
// Uniquely identifies a blink::RemoteFrame / blink::WebRemoteFrame /
// content::RenderFrameProxy in a renderer process, and its
// ontent::RenderFrameProxyHost counterpart in the browser. There can be
// content::RenderFrameProxyHost counterpart in the browser. There can be
// multiple RemoteFrames corresponding to a single LocalFrame, and each token
// will be distinct.
using RemoteFrameToken = util::TokenType<class RemoteFrameTokenTypeMarker>;
......
......@@ -195,6 +195,7 @@ source_set("blink_unittests_sources") {
testonly = true
sources = [
"performance_manager/renderer_resource_coordinator_impl_test.cc",
"performance_manager/v8_detailed_memory_reporter_impl_test.cc",
"performance_manager/v8_worker_memory_reporter_test.cc",
"tests/run_all_tests.cc",
......@@ -224,6 +225,7 @@ source_set("blink_unittests_sources") {
"//base:i18n",
"//base/test:test_support",
"//components/payments/mojom:mojom_blink",
"//components/performance_manager/public/mojom:mojom_blink",
"//content/test:test_support",
"//gpu:test_support",
"//testing/gmock",
......
......@@ -4,13 +4,20 @@
#include "third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.h"
#include <utility>
#include "base/bind.h"
#include "base/check.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
......@@ -18,24 +25,30 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
using performance_manager::mojom::blink::IframeAttributionData;
using performance_manager::mojom::blink::IframeAttributionDataPtr;
using performance_manager::mojom::blink::ProcessCoordinationUnit;
using performance_manager::mojom::blink::V8ContextDescription;
using performance_manager::mojom::blink::V8ContextDescriptionPtr;
using performance_manager::mojom::blink::V8ContextWorldType;
namespace WTF {
// Copies the data by move.
template <>
struct CrossThreadCopier<
performance_manager::mojom::blink::V8ContextDescriptionPtr>
: public WTF::CrossThreadCopierByValuePassThrough<
performance_manager::mojom::blink::V8ContextDescriptionPtr> {};
struct CrossThreadCopier<V8ContextDescriptionPtr>
: public WTF::CrossThreadCopierByValuePassThrough<V8ContextDescriptionPtr> {
};
// Copies the data by move.
template <>
struct CrossThreadCopier<
performance_manager::mojom::blink::IframeAttributionDataPtr>
struct CrossThreadCopier<IframeAttributionDataPtr>
: public WTF::CrossThreadCopierByValuePassThrough<
performance_manager::mojom::blink::IframeAttributionDataPtr> {};
IframeAttributionDataPtr> {};
// Copies the data using the copy constructor.
template <>
......@@ -46,9 +59,9 @@ struct CrossThreadCopier<blink::V8ContextToken>
namespace blink {
namespace {
using mojom::blink::FrameOwnerElementType;
using performance_manager::mojom::blink::V8ContextWorldType;
namespace {
// Determines if the given stable world ID is an extension world ID.
// Extensions IDs are 32-character strings containing characters in the range of
......@@ -67,6 +80,33 @@ bool IsExtensionStableWorldId(const String& stable_world_id) {
return true;
}
// Returns true if |owner| is an iframe, false otherwise.
// This will also return true for custom elements built on iframe, like
// <webview> and <guestview>. Since the renderer has no knowledge of these they
// must be filtered out on the browser side.
bool ShouldSendIframeNotificationsFor(const HTMLFrameOwnerElement& owner) {
return owner.OwnerType() == FrameOwnerElementType::kIframe;
}
// If |frame| is a RemoteFrame with a local parent, returns the parent.
// Otherwise returns nullptr.
LocalFrame* GetLocalParentOfRemoteFrame(const Frame& frame) {
if (IsA<RemoteFrame>(frame)) {
if (Frame* parent = frame.Tree().Parent()) {
return DynamicTo<LocalFrame>(parent);
}
}
return nullptr;
}
IframeAttributionDataPtr AttributionDataForOwner(
const HTMLFrameOwnerElement& owner) {
auto attribution_data = IframeAttributionData::New();
attribution_data->id = owner.FastGetAttribute(html_names::kIdAttr);
attribution_data->src = owner.FastGetAttribute(html_names::kSrcAttr);
return attribution_data;
}
} // namespace
RendererResourceCoordinatorImpl::~RendererResourceCoordinatorImpl() = default;
......@@ -80,9 +120,7 @@ void RendererResourceCoordinatorImpl::MaybeInitialize() {
DCHECK(IsMainThread());
DCHECK(platform);
mojo::PendingRemote<
performance_manager::mojom::blink::ProcessCoordinationUnit>
remote;
mojo::PendingRemote<ProcessCoordinationUnit> remote;
platform->GetBrowserInterfaceBroker()->GetInterface(
remote.InitWithNewPipeAndPassReceiver());
RendererResourceCoordinator::Set(
......@@ -91,8 +129,7 @@ void RendererResourceCoordinatorImpl::MaybeInitialize() {
void RendererResourceCoordinatorImpl::SetMainThreadTaskLoadIsLow(
bool main_thread_task_load_is_low) {
if (!service_)
return;
DCHECK(service_);
service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low);
}
......@@ -100,14 +137,12 @@ void RendererResourceCoordinatorImpl::OnScriptStateCreated(
ScriptState* script_state,
ExecutionContext* execution_context) {
DCHECK(script_state);
if (!service_)
return;
DCHECK(service_);
auto v8_desc = performance_manager::mojom::blink::V8ContextDescription::New();
auto v8_desc = V8ContextDescription::New();
v8_desc->token = script_state->GetToken();
performance_manager::mojom::blink::IframeAttributionDataPtr
iframe_attribution_data;
IframeAttributionDataPtr iframe_attribution_data;
// Default the world name to being empty.
......@@ -162,12 +197,7 @@ void RendererResourceCoordinatorImpl::OnScriptStateCreated(
// frame.
auto* owner = To<HTMLFrameOwnerElement>(local_frame->Owner());
DCHECK(owner);
iframe_attribution_data =
performance_manager::mojom::blink::IframeAttributionData::New();
iframe_attribution_data->id =
owner->FastGetAttribute(html_names::kIdAttr);
iframe_attribution_data->src =
owner->FastGetAttribute(html_names::kSrcAttr);
iframe_attribution_data = AttributionDataForOwner(*owner);
}
}
}
......@@ -189,18 +219,42 @@ void RendererResourceCoordinatorImpl::OnScriptStateDestroyed(
DispatchOnV8ContextDestroyed(script_state->GetToken());
}
void RendererResourceCoordinatorImpl::OnBeforeContentFrameAttached(
const Frame& frame,
const HTMLFrameOwnerElement& owner) {
DCHECK(service_);
if (!ShouldSendIframeNotificationsFor(owner))
return;
LocalFrame* parent = GetLocalParentOfRemoteFrame(frame);
if (!parent)
return;
service_->OnRemoteIframeAttached(LocalFrameToken(parent->GetFrameToken()),
RemoteFrameToken(frame.GetFrameToken()),
AttributionDataForOwner(owner));
}
void RendererResourceCoordinatorImpl::OnBeforeContentFrameDetached(
const Frame& frame,
const HTMLFrameOwnerElement& owner) {
DCHECK(service_);
if (!ShouldSendIframeNotificationsFor(owner))
return;
LocalFrame* parent = GetLocalParentOfRemoteFrame(frame);
if (!parent)
return;
service_->OnRemoteIframeDetached(LocalFrameToken(parent->GetFrameToken()),
RemoteFrameToken(frame.GetFrameToken()));
}
RendererResourceCoordinatorImpl::RendererResourceCoordinatorImpl(
mojo::PendingRemote<
performance_manager::mojom::blink::ProcessCoordinationUnit> remote) {
mojo::PendingRemote<ProcessCoordinationUnit> remote) {
service_.Bind(std::move(remote));
}
void RendererResourceCoordinatorImpl::DispatchOnV8ContextCreated(
performance_manager::mojom::blink::V8ContextDescriptionPtr v8_desc,
performance_manager::mojom::blink::IframeAttributionDataPtr
iframe_attribution_data) {
if (!service_)
return;
V8ContextDescriptionPtr v8_desc,
IframeAttributionDataPtr iframe_attribution_data) {
DCHECK(service_);
// Calls to this can arrive on any thread (due to workers, etc), but the
// interface itself is bound to the main thread. In this case, once we've
// collated the necessary data we bounce over to the main thread. Note that
......@@ -221,8 +275,7 @@ void RendererResourceCoordinatorImpl::DispatchOnV8ContextCreated(
void RendererResourceCoordinatorImpl::DispatchOnV8ContextDetached(
const blink::V8ContextToken& token) {
if (!service_)
return;
DCHECK(service_);
// See DispatchOnV8ContextCreated for why this is both needed and safe.
if (!IsMainThread()) {
blink::PostCrossThreadTask(
......@@ -236,8 +289,7 @@ void RendererResourceCoordinatorImpl::DispatchOnV8ContextDetached(
}
void RendererResourceCoordinatorImpl::DispatchOnV8ContextDestroyed(
const blink::V8ContextToken& token) {
if (!service_)
return;
DCHECK(service_);
// See DispatchOnV8ContextCreated for why this is both needed and safe.
if (!IsMainThread()) {
blink::PostCrossThreadTask(
......
......@@ -37,8 +37,14 @@ class CONTROLLER_EXPORT RendererResourceCoordinatorImpl final
ExecutionContext* execution_context) final;
void OnScriptStateDetached(ScriptState* script_state) final;
void OnScriptStateDestroyed(ScriptState* script_state) final;
void OnBeforeContentFrameAttached(const Frame& frame,
const HTMLFrameOwnerElement& owner) final;
void OnBeforeContentFrameDetached(const Frame& frame,
const HTMLFrameOwnerElement& owner) final;
private:
friend class RendererResourceCoordinatorImplTest;
explicit RendererResourceCoordinatorImpl(
mojo::PendingRemote<
performance_manager::mojom::blink::ProcessCoordinationUnit> remote);
......
......@@ -253,7 +253,7 @@ WebLocalFrameImpl* CreateLocalChild(
return frame;
}
WebLocalFrameImpl* CreateProvisional(WebRemoteFrame& old_frame,
WebLocalFrameImpl* CreateProvisional(WebFrame& old_frame,
TestWebFrameClient* client) {
std::unique_ptr<TestWebFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
......
......@@ -161,9 +161,9 @@ WebLocalFrameImpl* CreateLocalChild(WebLocalFrame& parent,
blink::mojom::blink::TreeScopeType,
std::unique_ptr<TestWebFrameClient>);
// Helper for creating a provisional local frame that can replace a remote
// frame.
WebLocalFrameImpl* CreateProvisional(WebRemoteFrame& old_frame,
// Helper for creating a provisional local frame that can replace a local or
// remote frame.
WebLocalFrameImpl* CreateProvisional(WebFrame& old_frame,
TestWebFrameClient* = nullptr);
// Helper for creating a remote frame. Generally used when creating a remote
......
......@@ -53,6 +53,7 @@
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
......@@ -197,6 +198,12 @@ void HTMLFrameOwnerElement::SetContentFrame(Frame& frame) {
DCHECK(!lazy_load_frame_observer_ ||
!lazy_load_frame_observer_->IsLazyLoadPending());
DCHECK_NE(content_frame_, &frame);
auto* resource_coordinator = RendererResourceCoordinator::Get();
if (content_frame_)
resource_coordinator->OnBeforeContentFrameDetached(*content_frame_, *this);
resource_coordinator->OnBeforeContentFrameAttached(frame, *this);
content_frame_ = &frame;
// Invalidate compositing inputs, because a remote frame child can cause the
......@@ -225,6 +232,9 @@ void HTMLFrameOwnerElement::ClearContentFrame() {
CancelPendingLazyLoad();
DCHECK_EQ(content_frame_->Owner(), this);
RendererResourceCoordinator::Get()->OnBeforeContentFrameDetached(
*content_frame_, *this);
content_frame_ = nullptr;
for (ContainerNode* node = this; node; node = node->ParentOrShadowHostNode())
......
......@@ -34,6 +34,10 @@ class DummyRendererResourceCoordinator final
ExecutionContext* execution_context) final {}
void OnScriptStateDetached(ScriptState* script_state) final {}
void OnScriptStateDestroyed(ScriptState* script_state) final {}
void OnBeforeContentFrameAttached(const Frame& frame,
const HTMLFrameOwnerElement& owner) final {}
void OnBeforeContentFrameDetached(const Frame& frame,
const HTMLFrameOwnerElement& owner) final {}
};
} // namespace
......
......@@ -11,6 +11,8 @@ namespace blink {
// TODO(chrisha): Remove knowledge of ExecutionContext class from this code!
class ExecutionContext;
class Frame;
class HTMLFrameOwnerElement;
class ScriptState;
class PLATFORM_EXPORT RendererResourceCoordinator {
......@@ -48,6 +50,15 @@ class PLATFORM_EXPORT RendererResourceCoordinator {
virtual void OnScriptStateDetached(ScriptState* script_state) = 0;
// Called when the |script_state| itself is garbage collected.
virtual void OnScriptStateDestroyed(ScriptState* script_state) = 0;
// Called when |frame| is about to be set as the ContentFrame of |owner|.
virtual void OnBeforeContentFrameAttached(
const Frame& frame,
const HTMLFrameOwnerElement& owner) = 0;
// Called when |frame| is about to be unset as the ContentFrame of |owner|.
virtual void OnBeforeContentFrameDetached(
const Frame& frame,
const HTMLFrameOwnerElement& owner) = 0;
};
} // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment