Commit facf49bd authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

[PM] Plumb FirstContentfulPaint to FrameNodes.

This will be used in upcoming page load prioritization logic.

BUG=1064763

Change-Id: I6290b4e500edc39759411f9a00f6f4255e1e0acd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2144312Reviewed-by: default avatarWill Harris <wfh@chromium.org>
Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758895}
parent d85ee3d9
...@@ -92,6 +92,10 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump, ...@@ -92,6 +92,10 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump,
// Ignored. // Ignored.
void OnHadFormInteractionChanged( void OnHadFormInteractionChanged(
const performance_manager::FrameNode* frame_node) override {} const performance_manager::FrameNode* frame_node) override {}
// Ignored.
void OnFirstContentfulPaint(
const performance_manager::FrameNode* frame_node,
base::TimeDelta time_since_navigation_start) override {}
// PageNodeObserver implementation: // PageNodeObserver implementation:
void OnPageNodeAdded(const performance_manager::PageNode* page_node) override; void OnPageNodeAdded(const performance_manager::PageNode* page_node) override;
......
...@@ -87,15 +87,22 @@ void FrameNodeImpl::SetIsAdFrame() { ...@@ -87,15 +87,22 @@ void FrameNodeImpl::SetIsAdFrame() {
is_ad_frame_.SetAndMaybeNotify(this, true); is_ad_frame_.SetAndMaybeNotify(this, true);
} }
void FrameNodeImpl::SetHadFormInteraction() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
document_.had_form_interaction.SetAndMaybeNotify(this, true);
}
void FrameNodeImpl::OnNonPersistentNotificationCreated() { void FrameNodeImpl::OnNonPersistentNotificationCreated() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (auto* observer : GetObservers()) for (auto* observer : GetObservers())
observer->OnNonPersistentNotificationCreated(this); observer->OnNonPersistentNotificationCreated(this);
} }
void FrameNodeImpl::SetHadFormInteraction() { void FrameNodeImpl::OnFirstContentfulPaint(
base::TimeDelta time_since_navigation_start) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
document_.had_form_interaction.SetAndMaybeNotify(this, true); for (auto* observer : GetObservers())
observer->OnFirstContentfulPaint(this, time_since_navigation_start);
} }
const RenderFrameHostProxy& FrameNodeImpl::GetRenderFrameHostProxy() const { const RenderFrameHostProxy& FrameNodeImpl::GetRenderFrameHostProxy() const {
......
...@@ -77,8 +77,10 @@ class FrameNodeImpl ...@@ -77,8 +77,10 @@ class FrameNodeImpl
void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override; void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override;
void SetOriginTrialFreezePolicy(mojom::InterventionPolicy policy) override; void SetOriginTrialFreezePolicy(mojom::InterventionPolicy policy) override;
void SetIsAdFrame() override; void SetIsAdFrame() override;
void OnNonPersistentNotificationCreated() override;
void SetHadFormInteraction() override; void SetHadFormInteraction() override;
void OnNonPersistentNotificationCreated() override;
void OnFirstContentfulPaint(
base::TimeDelta time_since_navigation_start) override;
const RenderFrameHostProxy& GetRenderFrameHostProxy() const override; const RenderFrameHostProxy& GetRenderFrameHostProxy() const override;
// Partial FrameNodbase::TimeDelta time_since_navigatione implementation: // Partial FrameNodbase::TimeDelta time_since_navigatione implementation:
......
...@@ -137,10 +137,11 @@ class LenientMockObserver : public FrameNodeImpl::Observer { ...@@ -137,10 +137,11 @@ class LenientMockObserver : public FrameNodeImpl::Observer {
MOCK_METHOD1(OnIsAdFrameChanged, void(const FrameNode*)); MOCK_METHOD1(OnIsAdFrameChanged, void(const FrameNode*));
MOCK_METHOD1(OnFrameIsHoldingWebLockChanged, void(const FrameNode*)); MOCK_METHOD1(OnFrameIsHoldingWebLockChanged, void(const FrameNode*));
MOCK_METHOD1(OnFrameIsHoldingIndexedDBLockChanged, void(const FrameNode*)); MOCK_METHOD1(OnFrameIsHoldingIndexedDBLockChanged, void(const FrameNode*));
MOCK_METHOD1(OnNonPersistentNotificationCreated, void(const FrameNode*));
MOCK_METHOD2(OnPriorityAndReasonChanged, MOCK_METHOD2(OnPriorityAndReasonChanged,
void(const FrameNode*, const PriorityAndReason& previous_value)); void(const FrameNode*, const PriorityAndReason& previous_value));
MOCK_METHOD1(OnHadFormInteractionChanged, void(const FrameNode*)); MOCK_METHOD1(OnHadFormInteractionChanged, void(const FrameNode*));
MOCK_METHOD1(OnNonPersistentNotificationCreated, void(const FrameNode*));
MOCK_METHOD2(OnFirstContentfulPaint, void(const FrameNode*, base::TimeDelta));
void SetCreatedFrameNode(const FrameNode* frame_node) { void SetCreatedFrameNode(const FrameNode* frame_node) {
created_frame_node_ = frame_node; created_frame_node_ = frame_node;
...@@ -340,6 +341,21 @@ TEST_F(FrameNodeImplTest, FormInteractions) { ...@@ -340,6 +341,21 @@ TEST_F(FrameNodeImplTest, FormInteractions) {
graph()->RemoveFrameNodeObserver(&obs); graph()->RemoveFrameNodeObserver(&obs);
} }
TEST_F(FrameNodeImplTest, FirstContentfulPaint) {
auto process = CreateNode<ProcessNodeImpl>();
auto page = CreateNode<PageNodeImpl>();
auto frame_node = CreateFrameNodeAutoId(process.get(), page.get());
MockObserver obs;
graph()->AddFrameNodeObserver(&obs);
base::TimeDelta fcp = base::TimeDelta::FromMilliseconds(1364);
EXPECT_CALL(obs, OnFirstContentfulPaint(frame_node.get(), fcp));
frame_node->OnFirstContentfulPaint(fcp);
graph()->RemoveFrameNodeObserver(&obs);
}
TEST_F(FrameNodeImplTest, PublicInterface) { TEST_F(FrameNodeImplTest, PublicInterface) {
auto process = CreateNode<ProcessNodeImpl>(); auto process = CreateNode<ProcessNodeImpl>();
auto page = CreateNode<PageNodeImpl>(); auto page = CreateNode<PageNodeImpl>();
......
...@@ -230,6 +230,15 @@ class FrameNodeObserver { ...@@ -230,6 +230,15 @@ class FrameNodeObserver {
virtual void OnNonPersistentNotificationCreated( virtual void OnNonPersistentNotificationCreated(
const FrameNode* frame_node) = 0; const FrameNode* frame_node) = 0;
// 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) = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(FrameNodeObserver); DISALLOW_COPY_AND_ASSIGN(FrameNodeObserver);
}; };
...@@ -263,6 +272,9 @@ class FrameNode::ObserverDefaultImpl : public FrameNodeObserver { ...@@ -263,6 +272,9 @@ class FrameNode::ObserverDefaultImpl : public FrameNodeObserver {
void OnHadFormInteractionChanged(const FrameNode* frame_node) override {} void OnHadFormInteractionChanged(const FrameNode* frame_node) override {}
void OnNonPersistentNotificationCreated( void OnNonPersistentNotificationCreated(
const FrameNode* frame_node) override {} const FrameNode* frame_node) override {}
void OnFirstContentfulPaint(
const FrameNode* frame_node,
base::TimeDelta time_since_navigation_start) override {}
private: private:
DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl); DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
......
...@@ -49,7 +49,18 @@ interface DocumentCoordinationUnit { ...@@ -49,7 +49,18 @@ interface DocumentCoordinationUnit {
SetIsAdFrame(); SetIsAdFrame();
// Event signals. // Event signals.
// Called when the associated frame has caused a non-persistent notification
// to be created.
OnNonPersistentNotificationCreated(); OnNonPersistentNotificationCreated();
// Invoked when the frame associated with this document 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.
OnFirstContentfulPaint(mojo_base.mojom.TimeDelta time_since_navigation_start);
}; };
interface ProcessCoordinationUnit { interface ProcessCoordinationUnit {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h" #include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
...@@ -245,6 +246,12 @@ void PaintTiming::SetFirstContentfulPaintSwap(base::TimeTicks stamp) { ...@@ -245,6 +246,12 @@ void PaintTiming::SetFirstContentfulPaintSwap(base::TimeTicks stamp) {
if (interactive_detector) { if (interactive_detector) {
interactive_detector->OnFirstContentfulPaint(first_contentful_paint_swap_); interactive_detector->OnFirstContentfulPaint(first_contentful_paint_swap_);
} }
auto* coordinator = GetSupplementable()->GetResourceCoordinator();
if (coordinator && GetFrame() && GetFrame()->IsMainFrame()) {
PerformanceTiming* timing = performance->timing();
base::TimeDelta fcp = stamp - timing->NavigationStartAsMonotonicTime();
coordinator->OnFirstContentfulPaint(fcp);
}
} }
void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) { void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) {
......
...@@ -72,4 +72,9 @@ void DocumentResourceCoordinator::SetHadFormInteraction() { ...@@ -72,4 +72,9 @@ void DocumentResourceCoordinator::SetHadFormInteraction() {
had_form_interaction_ = true; had_form_interaction_ = true;
} }
void DocumentResourceCoordinator::OnFirstContentfulPaint(
base::TimeDelta time_since_navigation_start) {
service_->OnFirstContentfulPaint(time_since_navigation_start);
}
} // namespace blink } // namespace blink
...@@ -35,6 +35,7 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final { ...@@ -35,6 +35,7 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
void SetIsAdFrame(); void SetIsAdFrame();
void OnNonPersistentNotificationCreated(); void OnNonPersistentNotificationCreated();
void SetHadFormInteraction(); void SetHadFormInteraction();
void OnFirstContentfulPaint(base::TimeDelta time_since_navigation_start);
private: private:
explicit DocumentResourceCoordinator(const BrowserInterfaceBrokerProxy&); explicit DocumentResourceCoordinator(const BrowserInterfaceBrokerProxy&);
......
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