зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689156 - Don't generate first-contentful-paint if the paint doesn't come from Tick r=smaug
When a contentful paint occurs which doesn't come from Tick, we should not generate a first-contentful-paint entry for it because 1) It violates the spec 2) It usually means some magical paints which we should not expose to the web. So this patches stop generating a contentful paint entry for that, instead asking the next tick to generate the entry. Depends on D107858 Differential Revision: https://phabricator.services.mozilla.com/D107859
This commit is contained in:
Родитель
706997d444
Коммит
2d171637c1
|
@ -220,6 +220,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
|
|||
mQuirkSheetAdded(false),
|
||||
mHadNonBlankPaint(false),
|
||||
mHadContentfulPaint(false),
|
||||
mHadNonTickContentfulPaint(false),
|
||||
mHadContentfulPaintComposite(false)
|
||||
#ifdef DEBUG
|
||||
,
|
||||
|
@ -2422,33 +2423,42 @@ void nsPresContext::NotifyNonBlankPaint() {
|
|||
}
|
||||
|
||||
void nsPresContext::NotifyContentfulPaint() {
|
||||
nsRootPresContext* rootPresContext = GetRootPresContext();
|
||||
if (!rootPresContext) {
|
||||
return;
|
||||
}
|
||||
if (!mHadContentfulPaint) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
(new AsyncEventDispatcher(mDocument, u"MozFirstContentfulPaint"_ns,
|
||||
CanBubble::eYes, ChromeOnlyDispatch::eYes))
|
||||
->PostDOMEvent();
|
||||
if (!mHadNonTickContentfulPaint) {
|
||||
(new AsyncEventDispatcher(mDocument, u"MozFirstContentfulPaint"_ns,
|
||||
CanBubble::eYes, ChromeOnlyDispatch::eYes))
|
||||
->PostDOMEvent();
|
||||
}
|
||||
#endif
|
||||
if (!rootPresContext->RefreshDriver()->IsInRefresh()) {
|
||||
if (!mHadNonTickContentfulPaint) {
|
||||
rootPresContext->RefreshDriver()
|
||||
->AddForceNotifyContentfulPaintPresContext(this);
|
||||
mHadNonTickContentfulPaint = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
mHadContentfulPaint = true;
|
||||
if (nsRootPresContext* rootPresContext = GetRootPresContext()) {
|
||||
mFirstContentfulPaintTransactionId =
|
||||
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
|
||||
if (nsPIDOMWindowInner* innerWindow = mDocument->GetInnerWindow()) {
|
||||
if (Performance* perf = innerWindow->GetPerformance()) {
|
||||
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);
|
||||
}
|
||||
mFirstContentfulPaintTransactionId =
|
||||
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
|
||||
if (nsPIDOMWindowInner* innerWindow = mDocument->GetInnerWindow()) {
|
||||
if (Performance* perf = innerWindow->GetPerformance()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2462,6 +2472,7 @@ void nsPresContext::NotifyPaintStatusReset() {
|
|||
CanBubble::eYes, ChromeOnlyDispatch::eYes))
|
||||
->PostDOMEvent();
|
||||
#endif
|
||||
mHadNonTickContentfulPaint = false;
|
||||
}
|
||||
|
||||
void nsPresContext::NotifyDOMContentFlushed() {
|
||||
|
|
|
@ -1331,6 +1331,11 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
unsigned mHadNonBlankPaint : 1;
|
||||
// Has NotifyContentfulPaint been called on this PresContext?
|
||||
unsigned mHadContentfulPaint : 1;
|
||||
// True when a contentful paint has happened and this paint doesn't
|
||||
// come from the regular tick process. Usually this means a
|
||||
// contentful paint was triggered manually.
|
||||
unsigned mHadNonTickContentfulPaint : 1;
|
||||
|
||||
// Has NotifyDidPaintForSubtree been called for a contentful paint?
|
||||
unsigned mHadContentfulPaintComposite : 1;
|
||||
|
||||
|
|
|
@ -1355,6 +1355,21 @@ void nsRefreshDriver::RegisterCompositionPayload(
|
|||
mCompositionPayloads.AppendElement(aPayload);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::AddForceNotifyContentfulPaintPresContext(
|
||||
nsPresContext* aPresContext) {
|
||||
mForceNotifyContentfulPaintPresContexts.AppendElement(aPresContext);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::FlushForceNotifyContentfulPaintPresContext() {
|
||||
while (!mForceNotifyContentfulPaintPresContexts.IsEmpty()) {
|
||||
WeakPtr<nsPresContext> presContext =
|
||||
mForceNotifyContentfulPaintPresContexts.PopLastElement();
|
||||
if (presContext) {
|
||||
presContext->NotifyContentfulPaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsRefreshDriver::RunDelayedEventsSoon() {
|
||||
// Place entries for delayed events into their corresponding normal list,
|
||||
// and schedule a refresh. When these delayed events run, if their document
|
||||
|
@ -2033,6 +2048,8 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
|
|||
DisplayPortUtils::UpdateDisplayPortMarginsFromPendingMessages();
|
||||
}
|
||||
|
||||
FlushForceNotifyContentfulPaintPresContext();
|
||||
|
||||
AutoTArray<nsCOMPtr<nsIRunnable>, 16> earlyRunners = std::move(mEarlyRunners);
|
||||
for (auto& runner : earlyRunners) {
|
||||
runner->Run();
|
||||
|
|
|
@ -407,6 +407,9 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
|||
eHasVisualViewportScrollEvents = 1 << 5,
|
||||
};
|
||||
|
||||
void AddForceNotifyContentfulPaintPresContext(nsPresContext* aPresContext);
|
||||
void FlushForceNotifyContentfulPaintPresContext();
|
||||
|
||||
private:
|
||||
typedef nsTArray<RefPtr<VVPResizeEvent>> VisualViewportResizeEventArray;
|
||||
typedef nsTArray<RefPtr<mozilla::Runnable>> ScrollEventArray;
|
||||
|
@ -588,6 +591,17 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
|||
AutoTArray<mozilla::AnimationEventDispatcher*, 16>
|
||||
mAnimationEventFlushObservers;
|
||||
|
||||
// nsPresContexts which `NotifyContentfulPaint` have been called,
|
||||
// however the corresponding paint doesn't come from a regular
|
||||
// rendering steps(aka tick).
|
||||
//
|
||||
// For these nsPresContexts, we invoke
|
||||
// `FlushForceNotifyContentfulPaintPresContext` in the next tick
|
||||
// to force notify contentful paint, regardless whether the tick paints
|
||||
// or not.
|
||||
nsTArray<mozilla::WeakPtr<nsPresContext>>
|
||||
mForceNotifyContentfulPaintPresContexts;
|
||||
|
||||
void BeginRefreshingImages(RequestTable& aEntries,
|
||||
mozilla::TimeStamp aDesired);
|
||||
|
||||
|
|
|
@ -1178,8 +1178,7 @@ void nsDisplayListBuilder::LeavePresShell(const nsIFrame* aReferenceFrame,
|
|||
}
|
||||
}
|
||||
nsRootPresContext* rootPresContext = pc->GetRootPresContext();
|
||||
if (!pc->HadContentfulPaint() && rootPresContext &&
|
||||
rootPresContext->RefreshDriver()->IsInRefresh()) {
|
||||
if (!pc->HadContentfulPaint() && rootPresContext) {
|
||||
if (!CurrentPresShellState()->mIsBackgroundOnly) {
|
||||
if (pc->HasEverBuiltInvisibleText() ||
|
||||
DisplayListIsContentful(this, aPaintedContents)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче