Bug 1722322 - Implement LargestContentfulPaint r=emilio

Spec: https://w3c.github.io/largest-contentful-paint

Differential Revision: https://phabricator.services.mozilla.com/D151079
This commit is contained in:
Sean Feng
2023-11-02 20:53:36 +00:00
parent 8af9f7d663
commit 2d6e584e05
30 changed files with 1080 additions and 52 deletions

View File

@@ -89,6 +89,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/TimelineManager.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/PerformanceMainThread.h"
#include "mozilla/dom/PerformanceTiming.h"
#include "mozilla/dom/PerformancePaintTiming.h"
#include "mozilla/layers/APZThreadUtils.h"
@@ -2781,8 +2782,16 @@ void nsPresContext::NotifyNonBlankPaint() {
}
}
bool nsPresContext::HasStoppedGeneratingLCP() const {
if (auto* perf = GetPerformanceMainThread()) {
return perf->HasDispatchedInputEvent() || perf->HasDispatchedScrollEvent();
}
return true;
}
void nsPresContext::NotifyContentfulPaint() {
if (mHadFirstContentfulPaint) {
if (mHadFirstContentfulPaint && HasStoppedGeneratingLCP()) {
return;
}
nsRootPresContext* rootPresContext = GetRootPresContext();
@@ -2804,19 +2813,24 @@ void nsPresContext::NotifyContentfulPaint() {
}
return;
}
mHadFirstContentfulPaint = true;
mFirstContentfulPaintTransactionId =
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
if (nsPIDOMWindowInner* innerWindow = mDocument->GetInnerWindow()) {
if (Performance* perf = innerWindow->GetPerformance()) {
if (!mHadFirstContentfulPaint) {
mHadFirstContentfulPaint = true;
mFirstContentfulPaintTransactionId =
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
}
if (auto* perf = GetPerformanceMainThread()) {
mMarkPaintTimingStart = TimeStamp::Now();
MOZ_ASSERT(rootPresContext->RefreshDriver()->IsInRefresh(),
"We should only notify contentful paint during refresh "
"driver ticks");
if (!perf->HadFCPTimingEntry()) {
TimeStamp nowTime = rootPresContext->RefreshDriver()->MostRecentRefresh(
/* aEnsureTimerStarted */ false);
MOZ_ASSERT(!nowTime.IsNull(),
"Most recent refresh timestamp should exist since we are in "
"a refresh driver tick");
MOZ_ASSERT(rootPresContext->RefreshDriver()->IsInRefresh(),
"We should only notify contentful paint during refresh "
"driver ticks");
RefPtr<PerformancePaintTiming> paintTiming = new PerformancePaintTiming(
perf, u"first-contentful-paint"_ns, nowTime);
perf->SetFCPTimingEntry(paintTiming);
@@ -2833,12 +2847,15 @@ void nsPresContext::NotifyContentfulPaint() {
nsContentUtils::TruncatedURLForDisplay(docURI).get());
PROFILER_MARKER_TEXT(
"FirstContentfulPaint", DOM,
MarkerOptions(MarkerTiming::Interval(navigationStart, nowTime),
MarkerInnerWindowId(innerWindow->WindowID())),
MarkerOptions(
MarkerTiming::Interval(navigationStart, nowTime),
MarkerInnerWindowId(mDocument->GetInnerWindow()->WindowID())),
marker);
}
}
}
perf->ProcessElementTiming();
}
}
@@ -3050,6 +3067,16 @@ void nsPresContext::SetSafeAreaInsets(const ScreenIntMargin& aSafeAreaInsets) {
RestyleHint::RecascadeSubtree());
}
PerformanceMainThread* nsPresContext::GetPerformanceMainThread() const {
if (nsPIDOMWindowInner* innerWindow = mDocument->GetInnerWindow()) {
if (auto* perf = static_cast<PerformanceMainThread*>(
innerWindow->GetPerformance())) {
return perf;
}
}
return nullptr;
}
#ifdef DEBUG
void nsPresContext::ValidatePresShellAndDocumentReleation() const {