1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
#include <optional>
#include "base/containers/flat_set.h"
#include "base/observer_list_types.h"
#include "base/types/strong_alias.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
#include "components/performance_manager/public/graph/node.h"
#include "components/performance_manager/public/graph/node_set_view.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
#include "components/performance_manager/public/mojom/lifecycle.mojom.h"
#include "components/performance_manager/public/resource_attribution/frame_context.h"
#include "components/performance_manager/public/viewport_intersection.h"
#include "content/public/browser/browsing_instance_id.h"
#include "content/public/browser/site_instance.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "url/origin.h"
class GURL;
namespace performance_manager {
class FrameNodeObserver;
class PageNode;
class ProcessNode;
class RenderFrameHostProxy;
class WorkerNode;
using execution_context_priority::PriorityAndReason;
// Frame nodes form a tree structure, each FrameNode at most has one parent
// that is a FrameNode. Conceptually, a FrameNode corresponds to a
// content::RenderFrameHost (RFH) in the browser, and a
// content::RenderFrameImpl / blink::LocalFrame in a renderer.
//
// TODO(crbug.com/40182881): The naming is misleading. In the browser,
// FrameTreeNode tracks state about a frame and RenderFrameHost tracks state
// about a document loaded into that frame, which can change over time.
// (Although RFH doesn't exactly track documents 1:1 either - see
// docs/render_document.md for more details.) The PM node types should be
// cleaned up to more accurately reflect this.
//
// Each RFH is part of a frame tree made up of content::FrameTreeNodes (FTNs).
// Note that a document in an FTN can be replaced with another, so it is
// possible to have multiple "sibling" FrameNodes corresponding to RFHs in the
// same FTN. Only one of these may contribute to the content being rendered,
// and this node is designated the "current" node in content terminology.
//
// This can occur, for example, when an in-flight navigation creates a new RFH.
// The new RFH will swap with the previously active RFH when the navigation
// commits, but until then the two will coexist for the same FTN.
//
// A swap is effectively atomic but will take place in two steps in the graph:
// the outgoing frame will first be marked as not current, and the incoming
// frame will be marked as current. As such, the graph invariant is that there
// will be 0 or 1 |is_current| FrameNode's for a given FTN.
//
// It is only valid to access this object on the sequence of the graph that owns
// it.
class FrameNode : public TypedNode<FrameNode> {
public:
using NodeSet = base::flat_set<const Node*>;
template <class ReturnType>
using NodeSetView = NodeSetView<NodeSet, ReturnType>;
using LifecycleState = mojom::LifecycleState;
static const char* kDefaultPriorityReason;
enum class Visibility {
kUnknown,
kVisible,
kNotVisible,
};
static constexpr NodeTypeEnum Type() { return NodeTypeEnum::kFrame; }
FrameNode();
FrameNode(const FrameNode&) = delete;
FrameNode& operator=(const FrameNode&) = delete;
~FrameNode() override;
// Returns the parent of this frame node. This may be null if this frame node
// is the main (root) node of a frame tree. This is a constant over the
// lifetime of the frame, except that it will always be null during the
// OnBeforeFrameNodeAdded() and OnFrameNodeRemoved() notifications.
virtual const FrameNode* GetParentFrameNode() const = 0;
// Returns the document owning the frame this RenderFrameHost is located in,
// which will either be a parent (for <iframe>s) or outer document (for
// <fencedframe> or an embedder (e.g. GuestViews)). This is a constant over
// the lifetime of the frame, except that it will always be null during the
// OnBeforeFrameNodeAdded() and OnFrameNodeRemoved() notifications.
//
// This method is equivalent to
// RenderFrameHost::GetParentOrOuterDocumentOrEmbedder().
virtual const FrameNode* GetParentOrOuterDocumentOrEmbedder() const = 0;
// Returns the page node to which this frame belongs. This is a constant over
// the lifetime of the frame, except that it will always be null during the
// OnBeforeFrameNodeAdded() and OnFrameNodeRemoved() notifications.
virtual const PageNode* GetPageNode() const = 0;
// Returns the process node with which this frame belongs. This is a constant
// over the lifetime of the frame, except that it will always be null during
// the OnBeforeFrameNodeAdded() and OnFrameNodeRemoved() notifications.
virtual const ProcessNode* GetProcessNode() const = 0;
// Gets the unique token associated with this frame. This is a constant over
// the lifetime of the frame and unique across all frames for all time.
virtual const blink::LocalFrameToken& GetFrameToken() const = 0;
// Gets the ID of the browsing instance to which this frame belongs. This is a
// constant over the lifetime of the frame.
virtual content::BrowsingInstanceId GetBrowsingInstanceId() const = 0;
// Gets the ID of the SiteInstanceGroup to which this frame belongs. This is a
// constant over the lifetime of the frame.
virtual content::SiteInstanceGroupId GetSiteInstanceGroupId() const = 0;
// Gets the unique token identifying this node for resource attribution. This
// token will not be reused after the node is destroyed.
virtual resource_attribution::FrameContext GetResourceContext() const = 0;
// A frame is a main frame if it has no parent FrameNode. This can be called
// from any thread.
//
// Note that a frame can be considered a main frame without being the
// outermost frame node. This can happen if this is the main frame of an inner
// WebContents (Guest view), or if this is a <fencedframe>.
virtual bool IsMainFrame() const = 0;
// Returns the set of child frames associated with this frame.
virtual NodeSetView<const FrameNode*> GetChildFrameNodes() const = 0;
// Returns the set of opened pages associated with this frame. This can change
// over the lifetime of the frame.
virtual NodeSetView<const PageNode*> GetOpenedPageNodes() const = 0;
// Returns the set of embedded pages associated with this frame. This can
// change over the lifetime of the frame.
virtual NodeSetView<const PageNode*> GetEmbeddedPageNodes() const = 0;
// Returns the current lifecycle state of this frame. See
// FrameNodeObserver::OnFrameLifecycleStateChanged.
virtual LifecycleState GetLifecycleState() const = 0;
// Returns true if this frame had a non-empty before-unload handler at the
// time of its last transition to the frozen lifecycle state. This is only
// meaningful while the object is frozen.
virtual bool HasNonemptyBeforeUnload() const = 0;
// Returns the last committed URL for this frame.
// See FrameNodeObserver::OnURLChanged.
virtual const GURL& GetURL() const = 0;
// Returns the last committed origin for this frame. nullopt if no navigation
// was committed. See FrameNodeObserver::OnOriginChanged.
virtual const std::optional<url::Origin>& GetOrigin() const = 0;
// Returns true if this frame is current (is part of a content::FrameTree).
// See FrameNodeObserver::OnCurrentFrameChanged.
virtual bool IsCurrent() const = 0;
// Returns the current priority of the frame, and the reason for the frame
// having that particular priority.
virtual const PriorityAndReason& GetPriorityAndReason() const = 0;
// Returns true if this frames use of the network is "almost idle", indicating
// that it is not doing any heavy loading work.
virtual bool GetNetworkAlmostIdle() const = 0;
// Returns true if this frame is ad frame. This can change from false to true
// over the lifetime of the frame, but once it is true it will always remain
// true.
virtual bool IsAdFrame() const = 0;
// Returns true if this frame holds at least one Web Lock.
virtual bool IsHoldingWebLock() const = 0;
// Returns true if this frame holds at least one IndexedDB lock that is
// blocking another client.
virtual bool IsHoldingBlockingIndexedDBLock() const = 0;
// Returns true if this frame currently uses WebRTC.
virtual bool UsesWebRTC() const = 0;
// Returns the child workers of this frame. These are either dedicated workers
// or shared workers created by this frame, or a service worker that handles
// this frame's network requests.
virtual NodeSetView<const WorkerNode*> GetChildWorkerNodes() const = 0;
// Returns true if the frame has been interacted with at least once.
virtual bool HadUserActivation() const = 0;
// Returns true if at least one form of the frame has been interacted with.
virtual bool HadFormInteraction() const = 0;
// Returns true if the user has made edits to the page. This is a superset of
// `HadFormInteraction()` but also includes changes to `contenteditable`
// elements.
virtual bool HadUserEdits() const = 0;
// Returns true if the frame is audible, false otherwise.
virtual bool IsAudible() const = 0;
// Returns true if the frame is capturing a media stream (audio or video).
virtual bool IsCapturingMediaStream() const = 0;
// Returns true if the frame is opted-out from freezing via origin trial.
virtual bool HasFreezingOriginTrialOptOut() const = 0;
// Returns the ViewportIntersection of this frame. For the outermost main
// frame, this always returns kIntersecting. For child frames, this is
// initially kUnknown, and is initialized during layout when the viewport
// intersection is first calculated.
virtual ViewportIntersection GetViewportIntersection() const = 0;
// Returns true if the frame is visible. This value is based on the viewport
// intersection of the frame, and the visibility of the page.
//
// Note that for the visibility of the page, page mirroring *is* taken into
// account, as opposed to `PageNode::IsVisible()`.
virtual Visibility GetVisibility() const = 0;
// Returns true if this frame is intersecting with a large area of the
// viewport. Note that this can not return true if `GetViewportIntersection()`
// returns kNotIntersecting. Also, this property is assumed to be true if its
// value is unknown.
virtual bool IsIntersectingLargeArea() const = 0;
// Returns true if the frame is deemed important. This means that the frame
// had been interacted with by the user, or is intersecting with a large area
// of the viewport. Note that this is the importance in the context of the
// containing page. If the page is not visible, the frame should not be
// considered important, regardless of this value.
virtual bool IsImportant() const = 0;
// Returns a proxy to the RenderFrameHost associated with this node. The
// proxy may only be dereferenced on the UI thread.
virtual const RenderFrameHostProxy& GetRenderFrameHostProxy() const = 0;
// TODO(joenotcharles): Move the resource usage estimates to a separate
// class.
// Returns the most recently estimated resident set of the frame, in
// kilobytes. This is an estimate because RSS is computed by process, and a
// process can host multiple frames.
virtual uint64_t GetResidentSetKbEstimate() const = 0;
// Returns the most recently estimated private footprint of the frame, in
// kilobytes. This is an estimate because it is computed by process, and a
// process can host multiple frames.
virtual uint64_t GetPrivateFootprintKbEstimate() const = 0;
};
// Observer interface for frame nodes.
class FrameNodeObserver : public base::CheckedObserver {
public:
FrameNodeObserver();
FrameNodeObserver(const FrameNodeObserver&) = delete;
FrameNodeObserver& operator=(const FrameNodeObserver&) = delete;
~FrameNodeObserver() override;
// Node lifetime notifications.
// Called before a `frame_node` is added to the graph. OnFrameNodeAdded() is
// better for most purposes, but this can be useful if an observer needs to
// check the state of the graph without including `frame_node`, or to set
// initial properties on the node that should be visible to other observers in
// OnFrameNodeAdded().
//
// `pending_parent_frame_node`, `pending_page_node`, `pending_process_node`,
// and `pending_parent_or_outer_document_or_embedder` are the nodes that will
// be returned from GetParentFrameNode(), GetPageNode(), GetProcessNode() and
// GetParentOrOuterDocumentOrEmbedder() after `frame_node` is added to the
// graph.
//
// Observers may make property changes during the scope of this call, as long
// as they don't cause notifications to be sent and don't modify pointers
// to/from other nodes, since the node is still isolated from the graph. To
// change a property that causes notifications, post a task (which will run
// after OnFrameNodeAdded().
//
// Note that observers are notified in an arbitrary order, so property changes
// made here may or may not be visible to other observers in
// OnBeforeFrameNodeAdded().
virtual void OnBeforeFrameNodeAdded(
const FrameNode* frame_node,
const FrameNode* pending_parent_frame_node,
const PageNode* pending_page_node,
const ProcessNode* pending_process_node,
const FrameNode* pending_parent_or_outer_document_or_embedder) {}
// Called after a `frame_node` is added to the graph. Observers may *not* make
// property changes during the scope of this call. To change a property, post
// a task which will run after all observers.
virtual void OnFrameNodeAdded(const FrameNode* frame_node) {}
// Called before a `frame_node` is removed from the graph. Observers may *not*
// make property changes during the scope of this call. The node will be
// deleted before any task posted from this scope runs.
virtual void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) {}
// Called after a `frame_node` is removed from the graph.
// OnBeforeFrameNodeRemoved() is better for most purposes, but this can be
// useful if an observer needs to check the state of the graph without
// including `frame_node`.
//
// `previous_parent_frame_node`, `previous_page_node`,
// `previous_process_node`, and
// `previous_parent_or_outer_document_or_embedder` are the nodes that were
// returned from GetParentFrameNode(), GetPageNode(), GetProcessNode() and
// GetParentOrOuterDocumentOrEmbedder() before `frame_node` was removed from
// the graph.
//
// Observers may *not* make property changes during the scope of this call.
// The node will be deleted before any task posted from this scope runs.
virtual void OnFrameNodeRemoved(
const FrameNode* frame_node,
const FrameNode* previous_parent_frame_node,
const PageNode* previous_page_node,
const ProcessNode* previous_process_node,
const FrameNode* previous_parent_or_outer_document_or_embedder) {}
// Notifications of property changes.
// Invoked when the current frame changes. Both arguments can be nullptr.
virtual void OnCurrentFrameChanged(const FrameNode* previous_frame_node,
const FrameNode* current_frame_node) {}
// Invoked when the NetworkAlmostIdle property changes.
virtual void OnNetworkAlmostIdleChanged(const FrameNode* frame_node) {}
// Invoked when the LifecycleState property changes.
virtual void OnFrameLifecycleStateChanged(const FrameNode* frame_node) {}
// Invoked when the URL property changes.
virtual void OnURLChanged(const FrameNode* frame_node,
const GURL& previous_value) {}
// Invoked when the origin property changes.
virtual void OnOriginChanged(
const FrameNode* frame_node,
const std::optional<url::Origin>& previous_value) {}
// Invoked when the IsAdFrame property changes.
virtual void OnIsAdFrameChanged(const FrameNode* frame_node) {}
// Invoked when the IsHoldingWebLock() property changes.
virtual void OnFrameIsHoldingWebLockChanged(const FrameNode* frame_node) {}
// Invoked when the IsHoldingBlockingIndexedDBLock() property changes.
virtual void OnFrameIsHoldingBlockingIndexedDBLockChanged(
const FrameNode* frame_node) {}
// Invoked when the frame priority and reason changes.
virtual void OnPriorityAndReasonChanged(
const FrameNode* frame_node,
const PriorityAndReason& previous_value) {}
// Called when the frame is interacted with by the user.
virtual void OnHadUserActivationChanged(const FrameNode* frame_node) {}
// Called when the frame receives a form interaction.
virtual void OnHadFormInteractionChanged(const FrameNode* frame_node) {}
// Called the first time the user has edited the content of an element. This
// is a superset of `OnHadFormInteractionChanged()`: form interactions trigger
// both events but changes to e.g. a `<div>` with the `contenteditable`
// property will only trigger `OnHadUserEditsChanged()`.
virtual void OnHadUserEditsChanged(const FrameNode* frame_node) {}
// Called when the frame starts or stops using WebRTC.
virtual void OnFrameUsesWebRTCChanged(const FrameNode* frame_node) {}
// Invoked when the IsAudible property changes.
virtual void OnIsAudibleChanged(const FrameNode* frame_node) {}
// Invoked when the IsCapturingMediaStream property changes.
virtual void OnIsCapturingMediaStreamChanged(const FrameNode* frame_node) {}
// Invoked when the HasFreezingOriginTrialOptOut property changes.
virtual void OnFrameHasFreezingOriginTrialOptOutChanged(
const FrameNode* frame_node) {}
// Invoked when a frame's intersection with the viewport changes. Will only be
// invoked for a child frame, or the main frame of an embedded page, as the
// outermost main frame is always considered to be intersecting with the
// viewport.
virtual void OnViewportIntersectionChanged(const FrameNode* frame_node) {}
// Invoked when the visibility property changes.
virtual void OnFrameVisibilityChanged(const FrameNode* frame_node,
FrameNode::Visibility previous_value) {}
// Invoked when the `IsIntersectingLargeArea()` property changes.
virtual void OnIsIntersectingLargeAreaChanged(const FrameNode* frame_node) {}
// Invoked when the `IsImportant` property changes.
virtual void OnIsImportantChanged(const FrameNode* frame_node) {}
// Events with no property changes.
// Invoked when a non-persistent notification has been issued by the frame.
virtual void OnNonPersistentNotificationCreated(const FrameNode* frame_node) {
}
// Invoked when the frame has had a first contentful paint, as defined here:
// https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint
// This may not fire for all frames, depending on if the load is interrupted
// or if the content is even visible. It will fire at most once for a given
// frame. It will only fire for main-frame nodes.
virtual void OnFirstContentfulPaint(
const FrameNode* frame_node,
base::TimeDelta time_since_navigation_start) {}
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_FRAME_NODE_H_
|