summaryrefslogtreecommitdiff
path: root/chromium/components/performance_manager/public
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/performance_manager/public
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/performance_manager/public')
-rw-r--r--chromium/components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h2
-rw-r--r--chromium/components/performance_manager/public/decorators/v8_per_frame_memory_decorator.h198
-rw-r--r--chromium/components/performance_manager/public/features.h5
-rw-r--r--chromium/components/performance_manager/public/graph/frame_node.h30
-rw-r--r--chromium/components/performance_manager/public/graph/graph.h4
-rw-r--r--chromium/components/performance_manager/public/graph/node_attached_data.h2
-rw-r--r--chromium/components/performance_manager/public/graph/page_node.h42
-rw-r--r--chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h29
-rw-r--r--chromium/components/performance_manager/public/mechanisms/tab_loading_frame_navigation_scheduler.h1
-rw-r--r--chromium/components/performance_manager/public/performance_manager.h67
-rw-r--r--chromium/components/performance_manager/public/performance_manager_main_thread_observer.h18
-rw-r--r--chromium/components/performance_manager/public/performance_manager_owned.h51
-rw-r--r--chromium/components/performance_manager/public/performance_manager_registered.h83
-rw-r--r--chromium/components/performance_manager/public/web_contents_proxy.h6
14 files changed, 524 insertions, 14 deletions
diff --git a/chromium/components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h b/chromium/components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h
index 5ebe065fb5e..e4fa05d4960 100644
--- a/chromium/components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h
+++ b/chromium/components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h
@@ -12,7 +12,7 @@ namespace performance_manager {
// This class must be instantiated on the UI thread in order to maintain the
// PageLoadTracker decorator of PageNodes.
class PageLoadTrackerDecoratorHelper
- : public PerformanceManagerMainThreadObserver {
+ : public PerformanceManagerMainThreadObserverDefaultImpl {
public:
PageLoadTrackerDecoratorHelper();
~PageLoadTrackerDecoratorHelper() override;
diff --git a/chromium/components/performance_manager/public/decorators/v8_per_frame_memory_decorator.h b/chromium/components/performance_manager/public/decorators/v8_per_frame_memory_decorator.h
new file mode 100644
index 00000000000..2d3b2c59b40
--- /dev/null
+++ b/chromium/components/performance_manager/public/decorators/v8_per_frame_memory_decorator.h
@@ -0,0 +1,198 @@
+// 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.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_V8_PER_FRAME_MEMORY_DECORATOR_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_V8_PER_FRAME_MEMORY_DECORATOR_H_
+
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "components/performance_manager/public/graph/graph.h"
+#include "components/performance_manager/public/graph/graph_registered.h"
+#include "components/performance_manager/public/graph/node_data_describer.h"
+#include "components/performance_manager/public/graph/process_node.h"
+#include "content/public/common/performance_manager/v8_per_frame_memory.mojom.h"
+
+namespace performance_manager {
+
+namespace internal {
+
+// A callback that will bind a V8PerFrameMemoryReporter interface to
+// communicate with the given process. Exposed so that it can be overridden to
+// implement the interface with a test fake.
+using BindV8PerFrameMemoryReporterCallback = base::RepeatingCallback<void(
+ mojo::PendingReceiver<performance_manager::mojom::V8PerFrameMemoryReporter>,
+ RenderProcessHostProxy)>;
+
+// Sets a callback that will be used to bind the V8PerFrameMemoryReporter
+// interface. The callback is owned by the caller and must live until this
+// function is called again with nullptr.
+void SetBindV8PerFrameMemoryReporterCallbackForTesting(
+ BindV8PerFrameMemoryReporterCallback* callback);
+
+} // namespace internal
+
+// A decorator that queries each renderer process for the amount of memory used
+// by V8 in each frame.
+//
+// To start sampling create a MeasurementRequest object that specifies how
+// often to request a memory measurement. Delete the object when you no longer
+// need measurements. Measurement involves some overhead so choose the lowest
+// sampling frequency your use case needs. The decorator will use the highest
+// sampling frequency that any caller requests, and stop measurements entirely
+// when no more MeasurementRequest objects exist.
+//
+// When measurements are available the decorator attaches them to FrameData and
+// ProcessData objects that can be retrieved with FrameData::ForFrameNode and
+// ProcessData::ForProcessNode. ProcessData objects can be cleaned up when
+// MeasurementRequest objects are deleted so callers must save the measurements
+// they are interested in before releasing their MeasurementRequest.
+//
+// MeasurementRequest, FrameData and ProcessData must all be accessed on the
+// graph sequence.
+class V8PerFrameMemoryDecorator
+ : public GraphOwned,
+ public GraphRegisteredImpl<V8PerFrameMemoryDecorator>,
+ public ProcessNode::ObserverDefaultImpl,
+ public NodeDataDescriberDefaultImpl {
+ public:
+ class MeasurementRequest;
+ class FrameData;
+ class ProcessData;
+
+ V8PerFrameMemoryDecorator();
+ ~V8PerFrameMemoryDecorator() override;
+
+ V8PerFrameMemoryDecorator(const V8PerFrameMemoryDecorator&) = delete;
+ V8PerFrameMemoryDecorator& operator=(const V8PerFrameMemoryDecorator&) =
+ delete;
+
+ // GraphOwned implementation.
+ void OnPassedToGraph(Graph* graph) override;
+ void OnTakenFromGraph(Graph* graph) override;
+
+ // ProcessNodeObserver overrides.
+ void OnProcessNodeAdded(const ProcessNode* process_node) override;
+
+ // NodeDataDescriber overrides.
+ base::Value DescribeFrameNodeData(const FrameNode* node) const override;
+ base::Value DescribeProcessNodeData(const ProcessNode* node) const override;
+
+ // Returns the amount of time to wait between requests for each process.
+ // Returns a zero TimeDelta if no requests should be made.
+ base::TimeDelta GetMinTimeBetweenRequestsPerProcess() const;
+
+ private:
+ friend class MeasurementRequest;
+
+ void AddMeasurementRequest(MeasurementRequest* request);
+ void RemoveMeasurementRequest(MeasurementRequest* request);
+ void UpdateProcessMeasurementSchedules() const;
+
+ Graph* graph_ = nullptr;
+
+ // List of requests sorted by sample_frequency (lowest first).
+ std::vector<MeasurementRequest*> measurement_requests_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+class V8PerFrameMemoryDecorator::MeasurementRequest {
+ public:
+ // Creates a MeasurementRequest but does not start the measurements. Call
+ // StartMeasurement to add it to the request list.
+ explicit MeasurementRequest(const base::TimeDelta& sample_frequency);
+
+ // Creates a MeasurementRequest and calls StartMeasurement. This will request
+ // measurements for all ProcessNode's in |graph| with frequency
+ // |sample_frequency|.
+ MeasurementRequest(const base::TimeDelta& sample_frequency, Graph* graph);
+ ~MeasurementRequest();
+
+ MeasurementRequest(const MeasurementRequest&) = delete;
+ MeasurementRequest& operator=(const MeasurementRequest&) = delete;
+
+ const base::TimeDelta& sample_frequency() const { return sample_frequency_; }
+
+ // Requests measurements for all ProcessNode's in |graph| with this object's
+ // sample frequency. This must only be called once for each
+ // MeasurementRequest.
+ void StartMeasurement(Graph* graph);
+
+ private:
+ friend class V8PerFrameMemoryDecorator;
+ void OnDecoratorUnregistered();
+
+ base::TimeDelta sample_frequency_;
+ V8PerFrameMemoryDecorator* decorator_ = nullptr;
+};
+
+class V8PerFrameMemoryDecorator::FrameData {
+ public:
+ FrameData() = default;
+ virtual ~FrameData() = default;
+
+ FrameData(const FrameData&) = delete;
+ FrameData& operator=(const FrameData&) = delete;
+
+ // Returns the number of bytes used by V8 for this frame at the last
+ // measurement.
+ uint64_t v8_bytes_used() const { return v8_bytes_used_; }
+
+ void set_v8_bytes_used(uint64_t v8_bytes_used) {
+ v8_bytes_used_ = v8_bytes_used;
+ }
+
+ // Returns FrameData for the given node, or nullptr if no measurement has
+ // been taken. The returned pointer must only be accessed on the graph
+ // sequence and may go invalid at any time after leaving the calling scope.
+ static const FrameData* ForFrameNode(const FrameNode* node);
+
+ private:
+ uint64_t v8_bytes_used_ = 0;
+};
+
+class V8PerFrameMemoryDecorator::ProcessData {
+ public:
+ ProcessData() = default;
+ virtual ~ProcessData() = default;
+
+ ProcessData(const ProcessData&) = delete;
+ ProcessData& operator=(const ProcessData&) = delete;
+
+ // Returns the number of bytes used by V8 at the last measurement in this
+ // process that could not be attributed to a frame.
+ uint64_t unassociated_v8_bytes_used() const {
+ return unassociated_v8_bytes_used_;
+ }
+
+ void set_unassociated_v8_bytes_used(uint64_t unassociated_v8_bytes_used) {
+ unassociated_v8_bytes_used_ = unassociated_v8_bytes_used;
+ }
+
+ // Returns FrameData for the given node, or nullptr if no measurement has
+ // been taken. The returned pointer must only be accessed on the graph
+ // sequence and may go invalid at any time after leaving the calling scope.
+ static const ProcessData* ForProcessNode(const ProcessNode* node);
+
+ private:
+ uint64_t unassociated_v8_bytes_used_ = 0;
+};
+
+// Wrapper that can instantiate a V8PerFrameMemoryDecorator::MeasurementRequest
+// from any sequence.
+class V8PerFrameMemoryRequest {
+ public:
+ explicit V8PerFrameMemoryRequest(const base::TimeDelta& sample_frequency);
+ ~V8PerFrameMemoryRequest();
+
+ V8PerFrameMemoryRequest(const V8PerFrameMemoryRequest&) = delete;
+ V8PerFrameMemoryRequest& operator=(const V8PerFrameMemoryRequest&) = delete;
+
+ private:
+ std::unique_ptr<V8PerFrameMemoryDecorator::MeasurementRequest> request_;
+};
+
+} // namespace performance_manager
+
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_V8_PER_FRAME_MEMORY_DECORATOR_H_
diff --git a/chromium/components/performance_manager/public/features.h b/chromium/components/performance_manager/public/features.h
index 0c4e76f7333..2f22e6d5118 100644
--- a/chromium/components/performance_manager/public/features.h
+++ b/chromium/components/performance_manager/public/features.h
@@ -29,6 +29,11 @@ struct TabLoadingFrameNavigationThrottlesParams {
// non-primary content frames.
base::TimeDelta minimum_throttle_timeout;
base::TimeDelta maximum_throttle_timeout;
+
+ // The multiple of elapsed time from navigation start until
+ // FirstContentfulPaint (FCP) that is used in calculating the timeout to apply
+ // to the throttles.
+ double fcp_multiple;
};
} // namespace features
diff --git a/chromium/components/performance_manager/public/graph/frame_node.h b/chromium/components/performance_manager/public/graph/frame_node.h
index bf74cc4fd8c..1adfefadedb 100644
--- a/chromium/components/performance_manager/public/graph/frame_node.h
+++ b/chromium/components/performance_manager/public/graph/frame_node.h
@@ -7,6 +7,7 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/util/type_safety/strong_alias.h"
#include "components/performance_manager/public/frame_priority/frame_priority.h"
#include "components/performance_manager/public/graph/node.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
@@ -26,6 +27,10 @@ class ProcessNode;
class RenderFrameHostProxy;
class WorkerNode;
+// A strongly typed unguessable token for the frame tokens.
+using FrameToken =
+ util::StrongAlias<class FrameTokenTag, base::UnguessableToken>;
+
// Frame nodes form a tree structure, each FrameNode at most has one parent that
// is a FrameNode. Conceptually, a frame corresponds to a
// content::RenderFrameHost in the browser, and a content::RenderFrameImpl /
@@ -57,6 +62,7 @@ class FrameNode : public Node {
using InterventionPolicy = mojom::InterventionPolicy;
using LifecycleState = mojom::LifecycleState;
using Observer = FrameNodeObserver;
+ using PageNodeVisitor = base::RepeatingCallback<bool(const PageNode*)>;
using PriorityAndReason = frame_priority::PriorityAndReason;
class ObserverDefaultImpl;
@@ -84,9 +90,9 @@ class FrameNode : public Node {
// be current at a time. This is a constant over the lifetime of the frame.
virtual int GetFrameTreeNodeId() const = 0;
- // Gets the devtools token associated with this frame. This is a constant over
- // the lifetime of the frame.
- virtual const base::UnguessableToken& GetDevToolsToken() 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 FrameToken& 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.
@@ -110,6 +116,17 @@ class FrameNode : public Node {
// VisitChildFrameNodes when that makes sense.
virtual const base::flat_set<const FrameNode*> GetChildFrameNodes() const = 0;
+ // Visits the page nodes that have been opened by this frame. The iteration
+ // is halted if the visitor returns false. Returns true if every call to the
+ // visitor returned true, false otherwise.
+ virtual bool VisitOpenedPageNodes(const PageNodeVisitor& visitor) const = 0;
+
+ // Returns the set of opened pages associatted with this frame. Note that
+ // this incurs a full container copy all the opened nodes. Please use
+ // VisitOpenedPageNodes when that makes sense. This can change over the
+ // lifetime of the frame.
+ virtual const base::flat_set<const PageNode*> GetOpenedPageNodes() const = 0;
+
// Returns the current lifecycle state of this frame. See
// FrameNodeObserver::OnFrameLifecycleStateChanged.
virtual LifecycleState GetLifecycleState() const = 0;
@@ -160,6 +177,9 @@ class FrameNode : public Node {
// Returns true if at least one form of the frame has been interacted with.
virtual bool HadFormInteraction() const = 0;
+ // Returns true if the frame is audible, false otherwise.
+ virtual bool IsAudible() 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;
@@ -224,6 +244,9 @@ class FrameNodeObserver {
// Called when the frame receives a form interaction.
virtual void OnHadFormInteractionChanged(const FrameNode* frame_node) = 0;
+ // Invoked when the IsAudible property changes.
+ virtual void OnIsAudibleChanged(const FrameNode* frame_node) = 0;
+
// Events with no property changes.
// Invoked when a non-persistent notification has been issued by the frame.
@@ -270,6 +293,7 @@ class FrameNode::ObserverDefaultImpl : public FrameNodeObserver {
const FrameNode* frame_node,
const PriorityAndReason& previous_value) override {}
void OnHadFormInteractionChanged(const FrameNode* frame_node) override {}
+ void OnIsAudibleChanged(const FrameNode* frame_node) override {}
void OnNonPersistentNotificationCreated(
const FrameNode* frame_node) override {}
void OnFirstContentfulPaint(
diff --git a/chromium/components/performance_manager/public/graph/graph.h b/chromium/components/performance_manager/public/graph/graph.h
index 74e1ae56bb6..f00a3212388 100644
--- a/chromium/components/performance_manager/public/graph/graph.h
+++ b/chromium/components/performance_manager/public/graph/graph.h
@@ -92,8 +92,8 @@ class Graph {
// registered.
template <typename DerivedType>
DerivedType* GetRegisteredObjectAs() {
- // Be sure to access the TypeId provided GraphRegisteredImpl, in case this
- // class has other TypeId implementations.
+ // Be sure to access the TypeId provided by GraphRegisteredImpl, in case
+ // this class has other TypeId implementations.
GraphRegistered* object =
GetRegisteredObject(GraphRegisteredImpl<DerivedType>::TypeId());
return static_cast<DerivedType*>(object);
diff --git a/chromium/components/performance_manager/public/graph/node_attached_data.h b/chromium/components/performance_manager/public/graph/node_attached_data.h
index 88e9561351a..51fab9fdd12 100644
--- a/chromium/components/performance_manager/public/graph/node_attached_data.h
+++ b/chromium/components/performance_manager/public/graph/node_attached_data.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/macros.h"
namespace performance_manager {
diff --git a/chromium/components/performance_manager/public/graph/page_node.h b/chromium/components/performance_manager/public/graph/page_node.h
index d02c6ed6b8b..422c043ff72 100644
--- a/chromium/components/performance_manager/public/graph/page_node.h
+++ b/chromium/components/performance_manager/public/graph/page_node.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
+#include <ostream>
#include <string>
#include "base/containers/flat_set.h"
@@ -33,12 +34,36 @@ class PageNode : public Node {
using Observer = PageNodeObserver;
class ObserverDefaultImpl;
+ // Reasons for which a frame can become the opener of a page.
+ enum class OpenedType {
+ // Returned if this node doesn't have an opener.
+ kInvalid,
+ // This page is a popup (the opener created it via window.open).
+ kPopup,
+ // This page is a guest view. This can be many things (<webview>, <appview>,
+ // etc) but is backed by the same inner/outer WebContents mechanism.
+ kGuestView,
+ // This page is a portal.
+ kPortal,
+ };
+
+ // Returns a string for a PageNode::OpenedType enumeration.
+ static const char* ToString(PageNode::OpenedType opened_type);
+
PageNode();
~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 type of relationship this node has with its opener, if it has
+ // an opener.
+ virtual OpenedType GetOpenedType() const = 0;
+
// Returns true if this page is currently visible, false otherwise.
// See PageNodeObserver::OnIsVisibleChanged.
virtual bool IsVisible() const = 0;
@@ -132,6 +157,8 @@ class PageNode : public Node {
// implement the entire interface.
class PageNodeObserver {
public:
+ using OpenedType = PageNode::OpenedType;
+
PageNodeObserver();
virtual ~PageNodeObserver();
@@ -145,6 +172,14 @@ class PageNodeObserver {
// Notifications of property changes.
+ // Invoked when this page has been assigned an opener, had the opener change,
+ // or had the opener removed. This can happen if a page is opened via
+ // window.open, webviews, portals, etc, or when that relationship is
+ // subsequently severed or reparented.
+ virtual void OnOpenerFrameNodeChanged(const PageNode* page_node,
+ const FrameNode* previous_opener,
+ OpenedType previous_opened_type) = 0;
+
// Invoked when the IsVisible property changes.
virtual void OnIsVisibleChanged(const PageNode* page_node) = 0;
@@ -207,6 +242,9 @@ class PageNode::ObserverDefaultImpl : public PageNodeObserver {
// PageNodeObserver implementation:
void OnPageNodeAdded(const PageNode* page_node) override {}
void OnBeforePageNodeRemoved(const PageNode* page_node) override {}
+ void OnOpenerFrameNodeChanged(const PageNode* page_node,
+ const FrameNode* previous_opener,
+ OpenedType previous_opened_type) override {}
void OnIsVisibleChanged(const PageNode* page_node) override {}
void OnIsAudibleChanged(const PageNode* page_node) override {}
void OnIsLoadingChanged(const PageNode* page_node) override {}
@@ -229,4 +267,8 @@ class PageNode::ObserverDefaultImpl : public PageNodeObserver {
} // namespace performance_manager
+// std::ostream support for PageNode::OpenedType.
+std::ostream& operator<<(std::ostream& os,
+ performance_manager::PageNode::OpenedType opened_type);
+
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_PAGE_NODE_H_
diff --git a/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h b/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
index d49831a404c..5c37649835c 100644
--- a/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
+++ b/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
@@ -39,10 +39,11 @@ namespace policies {
// - Main frames are never throttled.
// - Child frames with the same eTLD+1 as the main frame are not throttled.
// - All other frames are throttled.
-// - Throttling continues until the main frame hits hits LargestContentfulPaint.
+// - Throttling continues until the main frame hits LargestContentfulPaint.
// Unfortunately, we can't know LCP in real time, so we use
-// 2 x FirstContentfulPaint as an estimate, with an upper bound of the UMA
-// measures 95th %ile of LCP.
+// 3 x FirstContentfulPaint as an estimate, with an upper bound of
+// the UMA measures 95th %ile of LCP (both the multiple and the upper bound
+// are configurable via Finch).
//
// See design document:
//
@@ -73,11 +74,16 @@ class TabLoadingFrameNavigationPolicy
// Exposed for testing. Only safe to call on the PM thread.
size_t GetThrottledPageCountForTesting() const { return timeouts_.size(); }
bool IsTimerRunningForTesting() const { return timeout_timer_.IsRunning(); }
+ base::TimeTicks GetPageTimeoutForTesting(const PageNode* page_node) const;
- // Exposed for testing. Can be called on any sequence, as this is initialized
- // at construction and stays constant afterwards.
+ // Exposed for testing. Can be called on any sequence, as these are
+ // initialized at construction and stays constant afterwards.
base::TimeDelta GetMinTimeoutForTesting() const { return timeout_min_; }
base::TimeDelta GetMaxTimeoutForTesting() const { return timeout_max_; }
+ double GetFCPMultipleForTesting() const { return fcp_multiple_; }
+ base::TimeDelta CalculateTimeoutFromFCPForTesting(base::TimeDelta fcp) const {
+ return CalculateTimeoutFromFCP(fcp);
+ }
// Exposed for testing. Allows setting a MechanismDelegate. This should be
// done immediately after construction and *before* passing to the PM graph.
@@ -91,7 +97,16 @@ class TabLoadingFrameNavigationPolicy
mechanism_ = mechanism;
}
+ // Exposed for testing. Can only be called on PM sequence.
+ void OnFirstContentfulPaintForTesting(
+ const FrameNode* frame_node,
+ base::TimeDelta time_since_navigation_start) {
+ OnFirstContentfulPaint(frame_node, time_since_navigation_start);
+ }
+
private:
+ base::TimeDelta CalculateTimeoutFromFCP(base::TimeDelta fcp) const;
+
// PageNodeObserver:
void OnBeforePageNodeRemoved(const PageNode* page_node) override;
@@ -161,6 +176,10 @@ class TabLoadingFrameNavigationPolicy
base::TimeDelta timeout_min_;
base::TimeDelta timeout_max_;
+ // The multiple applied to FCP to calculate the throttle timeout.
+ // Configured via Finch. See features.cc.
+ double fcp_multiple_;
+
// A one shot timer that is used to timeout existing throttles. This will be
// running whenever |timeouts_| is not empty.
base::OneShotTimer timeout_timer_;
diff --git a/chromium/components/performance_manager/public/mechanisms/tab_loading_frame_navigation_scheduler.h b/chromium/components/performance_manager/public/mechanisms/tab_loading_frame_navigation_scheduler.h
index 520031b0d34..fb6e8671706 100644
--- a/chromium/components/performance_manager/public/mechanisms/tab_loading_frame_navigation_scheduler.h
+++ b/chromium/components/performance_manager/public/mechanisms/tab_loading_frame_navigation_scheduler.h
@@ -64,6 +64,7 @@ class TabLoadingFrameNavigationScheduler
static bool IsMechanismRegisteredForTesting();
void StopThrottlingForTesting() { StopThrottlingImpl(); }
size_t GetThrottleCountForTesting() const { return throttles_.size(); }
+ int64_t GetNavigationIdForTesting() const { return navigation_id_; }
private:
friend class content::WebContentsUserData<TabLoadingFrameNavigationScheduler>;
diff --git a/chromium/components/performance_manager/public/performance_manager.h b/chromium/components/performance_manager/public/performance_manager.h
index 4616099f63c..0ea87f8c671 100644
--- a/chromium/components/performance_manager/public/performance_manager.h
+++ b/chromium/components/performance_manager/public/performance_manager.h
@@ -9,7 +9,9 @@
#include "base/callback.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
namespace content {
class RenderFrameHost;
@@ -24,6 +26,11 @@ class GraphOwned;
class PageNode;
class PerformanceManagerMainThreadMechanism;
class PerformanceManagerMainThreadObserver;
+class PerformanceManagerOwned;
+class PerformanceManagerRegistered;
+
+template <typename DerivedType>
+class PerformanceManagerRegisteredImpl;
// The performance manager is a rendezvous point for communicating with the
// performance manager graph on its dedicated sequence.
@@ -31,6 +38,9 @@ class PerformanceManager {
public:
virtual ~PerformanceManager();
+ PerformanceManager(const PerformanceManager&) = delete;
+ PerformanceManager& operator=(const PerformanceManager&) = delete;
+
// Returns true if the performance manager is initialized. Valid to call from
// the main thread only.
static bool IsAvailable();
@@ -84,11 +94,64 @@ class PerformanceManager {
static void RemoveMechanism(PerformanceManagerMainThreadMechanism* mechanism);
static bool HasMechanism(PerformanceManagerMainThreadMechanism* mechanism);
+ // For convenience, allows you to pass ownership of an object that lives on
+ // the main thread to the performance manager. Useful for attaching observers
+ // or mechanisms that will live with the PM until it dies. If you can name the
+ // object you can also take it back via "TakeFromPM". The objects will be
+ // torn down gracefully (and their "OnTakenFromPM" functions invoked) as the
+ // PM itself is torn down.
+ static void PassToPM(std::unique_ptr<PerformanceManagerOwned> pm_owned);
+ static std::unique_ptr<PerformanceManagerOwned> TakeFromPM(
+ PerformanceManagerOwned* pm_owned);
+
+ // A TakeFromPM helper for taking back the ownership of a
+ // PerformanceManagerOwned object via its DerivedType.
+ template <typename DerivedType>
+ static std::unique_ptr<DerivedType> TakeFromPMAs(DerivedType* pm_owned) {
+ return base::WrapUnique(
+ static_cast<DerivedType*>(TakeFromPM(pm_owned).release()));
+ }
+
+ // Registers an object with the PM. It is expected that no more than one
+ // object of a given type is registered at a given moment, and that all
+ // registered objects are unregistered before PM tear-down. This allows the
+ // PM to act as a rendez-vous point for objects that live on the main thread.
+ // Combined with PerformanceManagerOwned this offers an alternative to
+ // using singletons, and brings clear ownerships and lifetime semantics.
+ static void RegisterObject(PerformanceManagerRegistered* pm_object);
+
+ // Unregisters the provided |object|, which must previously have been
+ // registered with "RegisterObject". It is expected that all registered
+ // objects are unregistered before graph tear-down.
+ static void UnregisterObject(PerformanceManagerRegistered* object);
+
+ // Returns the registered object of the given type, nullptr if none has been
+ // registered.
+ template <typename DerivedType>
+ static DerivedType* GetRegisteredObjectAs() {
+ // Be sure to access the TypeId provided by PerformanceManagerRegisteredImpl
+ // in case this class has other TypeId implementations.
+ PerformanceManagerRegistered* object = GetRegisteredObject(
+ PerformanceManagerRegisteredImpl<DerivedType>::TypeId());
+ return static_cast<DerivedType*>(object);
+ }
+
+ // Returns the performance manager graph task runner. This is safe to call
+ // from any thread at any time between the creation of the thread pool and its
+ // destruction.
+ //
+ // NOTE: Tasks posted to this sequence from any thread but the UI thread, or
+ // on the UI thread after IsAvailable() returns false, cannot safely access
+ // the graph, graphowned objects or other performance manager related objects.
+ // In practice it's preferable to use CallOnGraph() whenever possible.
+ static scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();
+
protected:
PerformanceManager();
- private:
- DISALLOW_COPY_AND_ASSIGN(PerformanceManager);
+ // Retrieves the object with the given |type_id|, returning nullptr if none
+ // exists. Clients must use the GetRegisteredObjectAs wrapper instead.
+ static PerformanceManagerRegistered* GetRegisteredObject(uintptr_t type_id);
};
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/public/performance_manager_main_thread_observer.h b/chromium/components/performance_manager/public/performance_manager_main_thread_observer.h
index 6ec1c58a981..d0f85a7bd92 100644
--- a/chromium/components/performance_manager/public/performance_manager_main_thread_observer.h
+++ b/chromium/components/performance_manager/public/performance_manager_main_thread_observer.h
@@ -26,10 +26,28 @@ class PerformanceManagerMainThreadObserver : public base::CheckedObserver {
virtual void OnPageNodeCreatedForWebContents(
content::WebContents* web_contents) = 0;
+ // Invoked before the PM is torn down on the main thread.
+ virtual void OnBeforePerformanceManagerDestroyed() = 0;
+
protected:
PerformanceManagerMainThreadObserver() = default;
};
+// A default implementation of the observer, with all methods stubbed out.
+class PerformanceManagerMainThreadObserverDefaultImpl
+ : public PerformanceManagerMainThreadObserver {
+ public:
+ ~PerformanceManagerMainThreadObserverDefaultImpl() override = default;
+
+ // PerformanceManagerMainThreadObserver implementation:
+ void OnPageNodeCreatedForWebContents(
+ content::WebContents* web_contents) override {}
+ void OnBeforePerformanceManagerDestroyed() override {}
+
+ protected:
+ PerformanceManagerMainThreadObserverDefaultImpl() = default;
+};
+
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_MAIN_THREAD_OBSERVER_H_
diff --git a/chromium/components/performance_manager/public/performance_manager_owned.h b/chromium/components/performance_manager/public/performance_manager_owned.h
new file mode 100644
index 00000000000..f33e8d9a56b
--- /dev/null
+++ b/chromium/components/performance_manager/public/performance_manager_owned.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_OWNED_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_OWNED_H_
+
+namespace performance_manager {
+
+// Helper class for passing ownership of objects to the PerformanceManager.
+// The object is expected to live on the main thread.
+class PerformanceManagerOwned {
+ public:
+ virtual ~PerformanceManagerOwned() = default;
+
+ PerformanceManagerOwned(const PerformanceManagerOwned&) = delete;
+ PerformanceManagerOwned& operator=(const PerformanceManagerOwned&) = delete;
+
+ // Called when the object is passed into the PerformanceManager.
+ virtual void OnPassedToPM() = 0;
+
+ // Called when the object is removed from the PerformanceManager, either via
+ // an explicit call to TakeFromPM, or prior to the PerformanceManager being
+ // destroyed.
+ virtual void OnTakenFromPM() = 0;
+
+ protected:
+ PerformanceManagerOwned() = default;
+};
+
+// A default implementation of PerformanceManagerOwned.
+class PerformanceManagerOwnedDefaultImpl : public PerformanceManagerOwned {
+ public:
+ ~PerformanceManagerOwnedDefaultImpl() override = default;
+
+ PerformanceManagerOwnedDefaultImpl(
+ const PerformanceManagerOwnedDefaultImpl&) = delete;
+ PerformanceManagerOwnedDefaultImpl& operator=(
+ const PerformanceManagerOwnedDefaultImpl*) = delete;
+
+ // PerformanceManagerOwned implementation:
+ void OnPassedToPM() override {}
+ void OnTakenFromPM() override {}
+
+ protected:
+ PerformanceManagerOwnedDefaultImpl() = default;
+};
+
+} // namespace performance_manager
+
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_OWNED_H_
diff --git a/chromium/components/performance_manager/public/performance_manager_registered.h b/chromium/components/performance_manager/public/performance_manager_registered.h
new file mode 100644
index 00000000000..df64ec21c25
--- /dev/null
+++ b/chromium/components/performance_manager/public/performance_manager_registered.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_REGISTERED_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_REGISTERED_H_
+
+#include "components/performance_manager/public/performance_manager.h"
+
+namespace performance_manager {
+
+// This provides functionality that allows an instance of a PM-associated
+// object to be looked up by type, allowing the PM to act as a rendezvous
+// point for main thread objects. It enforces singleton semantics, so there may
+// be no more than one instance of an object of a given type registered with the
+// PM at the same time. All registration and unregistration must happen on the
+// main thread. It is illegal to register more than one object of the same class
+// at a time, and all registered objects must be unregistered prior to PM tear-
+// down.
+
+template <typename SelfType>
+class PerformanceManagerRegisteredImpl;
+
+// Interface that PerformanceManager registered objects must implement. Should
+// only be implemented via PerformanceManagerRegisteredImpl.
+class PerformanceManagerRegistered {
+ public:
+ PerformanceManagerRegistered(const PerformanceManagerRegistered&) = delete;
+ PerformanceManagerRegistered& operator=(const PerformanceManagerRegistered&) =
+ delete;
+ virtual ~PerformanceManagerRegistered() = default;
+
+ // Returns the unique type of the object. Implemented by
+ // PerformanceManagerRegisteredImpl.
+ virtual uintptr_t GetTypeId() const = 0;
+
+ protected:
+ template <typename SelfType>
+ friend class PerformanceManagerRegisteredImpl;
+
+ PerformanceManagerRegistered() = default;
+};
+
+// Fully implements PerformanceManagerRegistered. Clients should derive from
+// this class.
+template <typename SelfType>
+class PerformanceManagerRegisteredImpl : public PerformanceManagerRegistered {
+ public:
+ PerformanceManagerRegisteredImpl() = default;
+ ~PerformanceManagerRegisteredImpl() override = default;
+
+ // The static TypeId associated with this class.
+ static uintptr_t TypeId() {
+ // The pointer to this object acts as a unique key that identifies the type
+ // at runtime. Note that the address of this should be taken only from a
+ // single library, as a different address will be returned from each library
+ // into which a given data type is linked. Note that if base/type_id ever
+ // becomes a thing, this should use that!
+ static constexpr int kTypeId = 0;
+ return reinterpret_cast<uintptr_t>(&kTypeId);
+ }
+
+ // PerformanceManagerRegistered implementation:
+ uintptr_t GetTypeId() const override { return TypeId(); }
+
+ // Helper function for looking up the registered object of this type from the
+ // PM. Syntactic sugar for "PerformanceManager::GetRegisteredObjectAs".
+ static SelfType* GetFromPM() {
+ return PerformanceManager::GetRegisteredObjectAs<SelfType>();
+ }
+
+ // Returns true if this object is the registered object in the PM, false
+ // otherwise. Useful for DCHECKing contract conditions.
+ bool IsRegisteredInPM() const { return GetFromPM() == this; }
+
+ // Returns true if no object of this type is registered in the PM, false
+ // otherwise. Useful for DCHECKing contract conditions.
+ static bool NothingRegisteredInPM() { return GetFromPM() == nullptr; }
+};
+
+} // namespace performance_manager
+
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_REGISTERED_H_ \ No newline at end of file
diff --git a/chromium/components/performance_manager/public/web_contents_proxy.h b/chromium/components/performance_manager/public/web_contents_proxy.h
index 45cf541a6fd..80bc2738a25 100644
--- a/chromium/components/performance_manager/public/web_contents_proxy.h
+++ b/chromium/components/performance_manager/public/web_contents_proxy.h
@@ -42,6 +42,12 @@ class WebContentsProxy {
// on the UI thread.
int64_t LastNavigationId() const;
+ // Similar to the above, but for the last non same-document navigation
+ // associated with this WebContents. This is always for a navigation that is
+ // older or equal to "LastNavigationId". This must only be called on the UI
+ // thread.
+ int64_t LastNewDocNavigationId() const;
+
protected:
friend class PerformanceManagerTabHelper;