blob: a1d345038c7490b89f0b79f449122d755531c91d [file] [log] [blame]
// 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_PAGE_NODE_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
#include <iosfwd>
#include <optional>
#include <string>
#include "base/containers/flat_set.h"
#include "base/observer_list_types.h"
#include "base/time/time.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/lifecycle.mojom.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
class GURL;
namespace content {
class WebContents;
}
namespace resource_attribution {
class PageContext;
}
namespace performance_manager {
class FrameNode;
class PageNodeObserver;
enum class PageType {
// A browser tab.
kTab,
// An extension background page.
kExtension,
// Anything else.
kUnknown,
};
// A PageNode represents the root of a FrameTree, or equivalently a WebContents.
// These may correspond to normal tabs, WebViews, Chrome Apps or Extensions.
class PageNode : public TypedNode<PageNode> {
public:
using NodeSet = base::flat_set<const Node*>;
template <class NodeViewPtr>
using NodeSetView = NodeSetView<NodeSet, NodeViewPtr>;
using LifecycleState = mojom::LifecycleState;
// Loading state of a page.
enum class LoadingState {
// No top-level document has started loading yet.
kLoadingNotStarted,
// A different top-level document is loading. The load started less than 5
// seconds ago or the initial response was received.
kLoading,
// A different top-level document is loading. The load started more than 5
// seconds ago and no response was received yet. Note: The state will
// transition back to |kLoading| if a response is received.
kLoadingTimedOut,
// A different top-level document finished loading, but the page did not
// reach CPU and network quiescence since then. Note: A page is considered
// to have reached CPU and network quiescence after 1 minute, even if the
// CPU and network are still busy - see page_load_tracker_decorator.h.
kLoadedBusy,
// The page reached CPU and network quiescence after loading the current
// top-level document, or the load failed.
kLoadedIdle,
};
// Returns a string for an enumeration value.
static const char* ToString(PageType type);
static const char* ToString(PageNode::LoadingState loading_state);
static constexpr NodeTypeEnum Type() { return NodeTypeEnum::kPage; }
PageNode();
PageNode(const PageNode&) = delete;
PageNode& operator=(const PageNode&) = delete;
~PageNode() override;
// Returns the unique ID of the browser context that this page belongs to.
virtual const std::string& GetBrowserContextID() const = 0;
// Returns the opener frame node, if there is one. This may change over the
// lifetime of this page. See "OnOpenerFrameNodeChanged".
virtual const FrameNode* GetOpenerFrameNode() const = 0;
// Returns the embedder frame node, if there is one. This may change over the
// lifetime of this page. See "OnEmbedderFrameNodeChanged".
virtual const FrameNode* GetEmbedderFrameNode() 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::PageContext GetResourceContext() const = 0;
// Returns the type of the page.
virtual PageType GetType() const = 0;
// Returns true if this page has the focus.
virtual bool IsFocused() const = 0;
// Returns true if this page is currently visible, false otherwise.
// See PageNodeObserver::OnIsVisibleChanged.
virtual bool IsVisible() const = 0;
// Returns the time of the last visibility change. It is always well defined
// as the visibility property is set at node creation.
virtual base::TimeTicks GetLastVisibilityChangeTime() const = 0;
// Returns true if this page is currently audible, false otherwise.
// See PageNodeObserver::OnIsAudibleChanged.
virtual bool IsAudible() const = 0;
// Returns the time since the last audible change. Unlike
// GetLastVisibilityChangeTime(), this returns nullopt for a node which has
// never been audible. If a node is audible when created, it is considered to
// change from inaudible to audible at that point.
virtual std::optional<base::TimeDelta> GetTimeSinceLastAudibleChange()
const = 0;
// Returns true if this page is displaying content in a picture-in-picture
// window, false otherwise.
virtual bool HasPictureInPicture() const = 0;
// Returns true if this page is opted-out from freezing via origin trial, i.e.
// if any of its current frames sets the origin trial.
virtual bool HasFreezingOriginTrialOptOut() const = 0;
// Returns true if this page is off the record, false otherwise.
// A tab is off the record when it is open in incognito or guest mode.
virtual bool IsOffTheRecord() const = 0;
// Returns the page's loading state.
virtual LoadingState GetLoadingState() const = 0;
// Returns the UKM source ID associated with the URL of the main frame of
// this page.
// See PageNodeObserver::OnUkmSourceIdChanged.
virtual ukm::SourceId GetUkmSourceID() const = 0;
// Returns the lifecycle state of this page. This is aggregated from the
// lifecycle state of each frame in the frame tree. See
// PageNodeObserver::OnPageLifecycleStateChanged.
virtual LifecycleState GetLifecycleState() const = 0;
// Returns true if at least one of the frame in this page is currently
// holding a WebLock.
virtual bool IsHoldingWebLock() const = 0;
// Returns true if at least one of the frame in this page is currently
// holding an IndexedDB lock that is blocking another client.
virtual bool IsHoldingBlockingIndexedDBLock() const = 0;
// Returns whether at least one frame on this page currently uses WebRTC.
virtual bool UsesWebRTC() const = 0;
// Returns the navigation ID associated with the last committed navigation
// event for the main frame of this page.
// See PageNodeObserver::OnMainFrameNavigationCommitted.
virtual int64_t GetNavigationID() const = 0;
// Returns the MIME type for the last committed main frame navigation.
virtual const std::string& GetContentsMimeType() const = 0;
// Returns the notification permission status for the last committed main
// frame navigation (nullopt if it wasn't retrieved).
virtual std::optional<blink::mojom::PermissionStatus>
GetNotificationPermissionStatus() const = 0;
// Returns "zero" if no navigation has happened, otherwise returns the time
// since the last navigation commit.
virtual base::TimeDelta GetTimeSinceLastNavigation() const = 0;
// Returns the current main frame node (if there is one), otherwise returns
// any of the potentially multiple main frames that currently exist. If there
// are no main frames at the moment, returns nullptr.
virtual const FrameNode* GetMainFrameNode() const = 0;
// Returns all of the main frame nodes, both current and otherwise. If there
// are no main frames at the moment, returns the empty set.
virtual NodeSetView<const FrameNode*> GetMainFrameNodes() const = 0;
// Returns the URL the main frame last committed a navigation to, or the
// initial URL of the page before navigation. The latter case is distinguished
// by a zero navigation ID.
// See PageNodeObserver::OnMainFrameNavigationCommitted.
virtual const GURL& GetMainFrameUrl() const = 0;
// Returns the private memory footprint size of the main frame and its
// children. This differs from EstimatePrivateFootprintSize which includes
// all the frames under the page node.
virtual uint64_t EstimateMainFramePrivateFootprintSize() const = 0;
// Indicates if at least one of the frames in the page has received some form
// interactions.
virtual bool HadFormInteraction() const = 0;
// Indicates if at least one of the frames in the page has received
// user-initiated edits. This is a superset of `HadFormInteraction()` that
// also includes changes to `contenteditable` elements.
virtual bool HadUserEdits() const = 0;
// Returns the web contents associated with this page node. It is valid to
// call this function on any thread but the weak pointer must only be
// dereferenced on the UI thread.
virtual base::WeakPtr<content::WebContents> GetWebContents() const = 0;
virtual uint64_t EstimateResidentSetSize() const = 0;
virtual uint64_t EstimatePrivateFootprintSize() const = 0;
// Returns a weak pointer to this page node.
virtual base::WeakPtr<PageNode> GetWeakPtr() = 0;
virtual base::WeakPtr<const PageNode> GetWeakPtr() const = 0;
};
// Observer interface for page nodes.
class PageNodeObserver : public base::CheckedObserver {
public:
PageNodeObserver();
PageNodeObserver(const PageNodeObserver&) = delete;
PageNodeObserver& operator=(const PageNodeObserver&) = delete;
~PageNodeObserver() override;
// Node lifetime notifications.
// Called before a `page_node` is added to the graph. OnPageNodeAdded() is
// better for most purposes, but this can be useful if an observer needs to
// check the state of the graph without including `page_node`, or to set
// initial properties on the node that should be visible to other observers in
// OnPageNodeAdded().
//
// 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 OnPageNodeAdded().
//
// Note that observers are notified in an arbitrary order, so property changes
// made here may or may not be visible to other observers in
// OnBeforePageNodeAdded().
virtual void OnBeforePageNodeAdded(const PageNode* page_node) {}
// Called after a `page_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 OnPageNodeAdded(const PageNode* page_node) {}
// Called before a `page_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 OnBeforePageNodeRemoved(const PageNode* page_node) {}
// Called after a `page_node` is removed from the graph.
// OnBeforePageNodeRemoved() is better for most purposes, but this can be
// useful if an observer needs to check the state of the graph without
// including `page_node`.
//
// 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 OnPageNodeRemoved(const PageNode* page_node) {}
// Notifications of property changes.
// Invoked when this page has been assigned an opener, had the opener
// change, or had the opener removed. This happens when a page is opened
// via window.open, or when that relationship is subsequently severed or
// reparented.
virtual void OnOpenerFrameNodeChanged(const PageNode* page_node,
const FrameNode* previous_opener) {}
// Invoked when this page has been assigned an embedder, had the embedder
// change, or had the embedder removed. This can happen if a page is opened
// via webviews, guestviews etc, or when that relationship is subsequently
// severed or reparented.
virtual void OnEmbedderFrameNodeChanged(const PageNode* page_node,
const FrameNode* previous_embedder) {}
// Invoked when the GetType property changes.
virtual void OnTypeChanged(const PageNode* page_node,
PageType previous_type) {}
// Invoked when the IsFocused property changes.
virtual void OnIsFocusedChanged(const PageNode* page_node) {}
// Invoked when the IsVisible property changes.
//
// GetLastVisibilityChangeTime() will return the time of the previous
// IsVisible change. After all observers have fired it will return the time of
// this property change.
virtual void OnIsVisibleChanged(const PageNode* page_node) {}
// Invoked when the IsAudible property changes.
//
// GetTimeSinceLastAudibleChange() will return the time since the previous
// IsAudible change. After all observers have fired it will return the time of
// this property change.
virtual void OnIsAudibleChanged(const PageNode* page_node) {}
// Invoked when the HasPictureInPicture property changes.
virtual void OnHasPictureInPictureChanged(const PageNode* page_node) {}
// Invoked when the HasFreezingOriginTrialOptOut() property changes.
virtual void OnPageHasFreezingOriginTrialOptOutChanged(
const PageNode* page_node) {}
// Invoked when the GetLoadingState property changes.
virtual void OnLoadingStateChanged(const PageNode* page_node,
PageNode::LoadingState previous_state) {}
// Invoked when the UkmSourceId property changes.
virtual void OnUkmSourceIdChanged(const PageNode* page_node) {}
// Invoked when the PageLifecycleState property changes.
virtual void OnPageLifecycleStateChanged(const PageNode* page_node) {}
// Invoked when the IsHoldingWebLock property changes.
virtual void OnPageIsHoldingWebLockChanged(const PageNode* page_node) {}
// Invoked when the IsHoldingBlockingIndexedDBLock property changes.
virtual void OnPageIsHoldingBlockingIndexedDBLockChanged(
const PageNode* page_node) {}
// Invoked when the UsesWebRTC property changes.
virtual void OnPageUsesWebRTCChanged(const PageNode* page_node) {}
// Invoked when the GetNotificationPermissionStatus property changes.
virtual void OnPageNotificationPermissionStatusChange(
const PageNode* page_node,
std::optional<blink::mojom::PermissionStatus> previous_status) {}
// Invoked when the MainFrameUrl property changes.
virtual void OnMainFrameUrlChanged(const PageNode* page_node) {}
// This is fired when a non-same document navigation commits in the main
// frame. It indicates that the the |NavigationId| property and possibly the
// |MainFrameUrl| properties have changed.
virtual void OnMainFrameDocumentChanged(const PageNode* page_node) {}
// Invoked when the HadFormInteraction property changes.
virtual void OnHadFormInteractionChanged(const PageNode* page_node) {}
// Invoked when the HadUserEdits property changes.
virtual void OnHadUserEditsChanged(const PageNode* page_node) {}
// Events with no property changes.
// Fired when the tab title associated with a page changes. This property is
// not directly reflected on the node.
virtual void OnTitleUpdated(const PageNode* page_node) {}
// Fired when the favicon associated with a page is updated. This property is
// not directly reflected on the node.
virtual void OnFaviconUpdated(const PageNode* page_node) {}
// Fired after `new_page_node` is created but before `page_node` is deleted
// from being discarded. See the equivalent function on `WebContentsObserver`
// for more detail.
virtual void OnAboutToBeDiscarded(const PageNode* page_node,
const PageNode* new_page_node) {}
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_