Bug 1298381: Implement TimeToFirstContentfulPaint behind a pref r=mattwoodrow,smaug

This commit is contained in:
Randell Jesup 2018-10-18 16:16:45 -04:00
Родитель 6183e66d60
Коммит a37d80eed4
14 изменённых файлов: 179 добавлений и 41 удалений

Просмотреть файл

@ -52,6 +52,8 @@ nsDOMNavigationTiming::Clear()
mDOMContentLoadedEventStart = TimeStamp();
mDOMContentLoadedEventEnd = TimeStamp();
mDOMComplete = TimeStamp();
mContentfulPaint = TimeStamp();
mNonBlankPaint = TimeStamp();
mDocShellHasBeenActiveSinceNavigationStart = false;
}
@ -308,7 +310,7 @@ nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer)
{
// Check TTI: see if it's been 5 seconds since the last Long Task
TimeStamp now = TimeStamp::Now();
MOZ_RELEASE_ASSERT(!mNonBlankPaint.IsNull(), "TTI timeout with no non-blank-paint?");
MOZ_RELEASE_ASSERT(!mContentfulPaint.IsNull(), "TTI timeout with no contentful-paint?");
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
TimeStamp lastLongTaskEnded;
@ -323,11 +325,10 @@ nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer)
return;
}
}
// To correctly implement TTI/TTFI as proposed, we'd need to use
// FirstContentfulPaint (FCP, which we have not yet implemented) instead
// of FirstNonBlankPaing (FNBP) to start at, and not fire it until there
// are no more than 2 network loads. By the proposed definition, without
// that we're closer to TimeToFirstInteractive.
// To correctly implement TTI/TTFI as proposed, we'd need to not
// fire it until there are no more than 2 network loads. By the
// proposed definition, without that we're closer to
// TimeToFirstInteractive.
// XXX check number of network loads, and if > 2 mark to check if loads
// decreases to 2 (or record that point and let the normal timer here
@ -341,7 +342,7 @@ nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer)
mTTFI = MaxWithinWindowBeginningAtMin(lastLongTaskEnded, mDOMContentLoadedEventEnd,
TimeDuration::FromMilliseconds(TTI_WINDOW_SIZE_MS));
if (mTTFI.IsNull()) {
mTTFI = mNonBlankPaint;
mTTFI = mContentfulPaint;
}
}
// XXX Implement TTI via check number of network loads, and if > 2 mark
@ -399,15 +400,6 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
}
#endif
if (!mTTITimer) {
mTTITimer = NS_NewTimer();
}
// TTI is first checked 5 seconds after the FCP (non-blank-paint is very close to FCP).
mTTITimer->InitWithNamedFuncCallback(TTITimeoutCallback, this, TTI_WINDOW_SIZE_MS,
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"nsDOMNavigationTiming::TTITimeout");
if (mDocShellHasBeenActiveSinceNavigationStart) {
if (net::nsHttp::IsBeforeLastActiveTabLoadOptimization(mNavigationStart)) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_NETOPT_MS,
@ -425,6 +417,42 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
}
}
void
nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mNavigationStart.IsNull());
if (!mContentfulPaint.IsNull()) {
return;
}
mContentfulPaint = TimeStamp::Now();
#ifdef MOZ_GECKO_PROFILER
if (profiler_is_active()) {
TimeDuration elapsed = mContentfulPaint - mNavigationStart;
nsAutoCString spec;
if (mLoadedURI) {
mLoadedURI->GetSpec(spec);
}
nsPrintfCString marker("Contentful paint after %dms for URL %s, %s",
int(elapsed.ToMilliseconds()), spec.get(),
mDocShellHasBeenActiveSinceNavigationStart ? "foreground tab" : "this tab was inactive some of the time between navigation start and first non-blank paint");
profiler_add_marker(marker.get());
}
#endif
if (!mTTITimer) {
mTTITimer = NS_NewTimer();
}
// TTI is first checked 5 seconds after the FCP (non-blank-paint is very close to FCP).
mTTITimer->InitWithNamedFuncCallback(TTITimeoutCallback, this, TTI_WINDOW_SIZE_MS,
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"nsDOMNavigationTiming::TTITimeout");
}
void
nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument()
{

Просмотреть файл

@ -97,6 +97,10 @@ public:
{
return TimeStampToDOM(mNonBlankPaint);
}
DOMTimeMilliSec GetTimeToContentfulPaint() const
{
return TimeStampToDOM(mContentfulPaint);
}
DOMTimeMilliSec GetTimeToTTFI() const
{
return TimeStampToDOM(mTTFI);
@ -174,6 +178,7 @@ public:
void NotifyLongTask(mozilla::TimeStamp aWhen);
void NotifyNonBlankPaintForRootContentDocument();
void NotifyContentfulPaintForRootContentDocument();
void NotifyDOMContentFlushedForRootContentDocument();
void NotifyDocShellStateChanged(DocShellState aDocShellState);
@ -209,6 +214,7 @@ private:
DOMHighResTimeStamp mNavigationStartHighRes;
mozilla::TimeStamp mNavigationStart;
mozilla::TimeStamp mNonBlankPaint;
mozilla::TimeStamp mContentfulPaint;
mozilla::TimeStamp mDOMContentFlushed;
mozilla::TimeStamp mBeforeUnloadStart;

Просмотреть файл

@ -396,6 +396,7 @@ NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver)
HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsGenericHTMLElement(std::move(aNodeInfo)),
mResetLayer(true) ,
mMaybeModified(false) ,
mWriteOnly(false)
{}
@ -1010,6 +1011,7 @@ HTMLCanvasElement::GetContext(const nsAString& aContextId,
nsISupports** aContext)
{
ErrorResult rv;
mMaybeModified = true; // For FirstContentfulPaint
*aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take();
return rv.StealNSResult();
}
@ -1024,6 +1026,7 @@ HTMLCanvasElement::GetContext(JSContext* aCx,
return nullptr;
}
mMaybeModified = true; // For FirstContentfulPaint
return CanvasRenderingContextHelper::GetContext(aCx, aContextId,
aContextOptions.isObject() ? aContextOptions : JS::NullHandleValue,
aRv);

Просмотреть файл

@ -349,6 +349,8 @@ public:
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
bool MaybeModified() const { return mMaybeModified; };
protected:
virtual ~HTMLCanvasElement();
@ -387,6 +389,7 @@ protected:
AsyncCanvasRenderer* GetAsyncCanvasRenderer();
bool mResetLayer;
bool mMaybeModified; // we fetched the context, so we may have written to the canvas
RefPtr<HTMLCanvasElement> mOriginalCanvas;
RefPtr<PrintCallback> mPrintCallback;
RefPtr<HTMLCanvasPrintState> mPrintState;

Просмотреть файл

@ -440,6 +440,20 @@ public:
mPerformance->GetRandomTimelineSeed());
}
DOMTimeMilliSec TimeToContentfulPaint() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
nsContentUtils::ShouldResistFingerprinting()) {
return 0;
}
if (mPerformance->IsSystemPrincipal()) {
return GetDOMTiming()->GetTimeToContentfulPaint();
}
return nsRFPService::ReduceTimePrecisionAsMSecs(
GetDOMTiming()->GetTimeToContentfulPaint(),
mPerformance->GetRandomTimelineSeed());
}
DOMTimeMilliSec TimeToDOMContentFlushed() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||

Просмотреть файл

@ -39,6 +39,10 @@ interface PerformanceTiming {
[Pref="dom.performance.time_to_non_blank_paint.enabled"]
readonly attribute unsigned long long timeToNonBlankPaint;
// Returns 0 if a contentful paint has not happened.
[Pref="dom.performance.time_to_contentful_paint.enabled"]
readonly attribute unsigned long long timeToContentfulPaint;
// This is a Mozilla proprietary extension and not part of the
// performance/navigation timing specification. It marks the
// completion of the first presentation flush after DOMContentLoaded.

Просмотреть файл

@ -251,7 +251,8 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
mQuirkSheetAdded(false),
mNeedsPrefUpdate(false),
mHadNonBlankPaint(false)
mHadNonBlankPaint(false),
mHadContentfulPaint(false)
#ifdef DEBUG
, mInitialized(false)
#endif
@ -2892,6 +2893,22 @@ nsPresContext::NotifyNonBlankPaint()
}
}
void
nsPresContext::NotifyContentfulPaint()
{
if (!mHadContentfulPaint) {
mHadContentfulPaint = true;
if (IsRootContentDocument()) {
RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (timing) {
timing->NotifyContentfulPaintForRootContentDocument();
}
mFirstContentfulPaintTime = TimeStamp::Now();
}
}
}
void
nsPresContext::NotifyDOMContentFlushed()
{

Просмотреть файл

@ -1120,8 +1120,11 @@ public:
bool HadNonBlankPaint() const {
return mHadNonBlankPaint;
}
bool HadContentfulPaint() const {
return mHadContentfulPaint;
}
void NotifyNonBlankPaint();
void NotifyContentfulPaint();
void NotifyDOMContentFlushed();
bool UsesRootEMUnits() const {
@ -1398,6 +1401,7 @@ protected:
// Time of various first interaction types, used to report time from
// first paint of the top level content pres shell to first interaction.
mozilla::TimeStamp mFirstNonBlankPaintTime;
mozilla::TimeStamp mFirstContentfulPaintTime;
mozilla::TimeStamp mFirstClickTime;
mozilla::TimeStamp mFirstKeyTime;
mozilla::TimeStamp mFirstMouseMoveTime;
@ -1474,6 +1478,8 @@ protected:
// Has NotifyNonBlankPaint been called on this PresContext?
unsigned mHadNonBlankPaint : 1;
// Has NotifyContentfulPaint been called on this PresContext?
unsigned mHadContentfulPaint : 1;
#ifdef DEBUG
unsigned mInitialized : 1;

Просмотреть файл

@ -221,6 +221,16 @@ public:
return LAYER_INACTIVE;
}
// FirstContentfulPaint is supposed to ignore "white" canvases. We use MaybeModified (if
// GetContext() was called on the canvas) as a standin for "white"
virtual bool IsContentful() const override
{
nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(Frame());
HTMLCanvasElement* canvas =
HTMLCanvasElement::FromNode(f->GetContent());
return canvas->MaybeModified();
}
};

Просмотреть файл

@ -34,7 +34,8 @@ enum
enum DisplayItemFlags
{
TYPE_RENDERS_NO_IMAGES = 1 << 0
TYPE_RENDERS_NO_IMAGES = 1 << 0,
TYPE_IS_CONTENTFUL = 1 << 1
};
inline const char*

Просмотреть файл

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// IWYU pragma: private, include "nsDisplayList.h"
DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK, 0)
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND, 0)
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER, TYPE_RENDERS_NO_IMAGES)
@ -15,18 +15,18 @@ DECLARE_DISPLAY_ITEM_TYPE(TABLE_BLEND_MODE, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BORDER, 0)
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BULLET, 0)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND, 0)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND, 0)
DECLARE_DISPLAY_ITEM_TYPE(BULLET, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_IMAGE, 0)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_IMAGE, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CARET, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CARET, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(CLEAR_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS, TYPE_RENDERS_NO_IMAGES)
@ -38,7 +38,7 @@ DECLARE_DISPLAY_ITEM_TYPE(STICKY_POSITION, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BORDER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BLANK, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(HEADER_FOOTER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(IMAGE, 0)
DECLARE_DISPLAY_ITEM_TYPE(IMAGE, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(LIST_FOCUS, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(OPACITY, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(OPTION_EVENT_GRABBER, TYPE_RENDERS_NO_IMAGES)
@ -58,23 +58,23 @@ DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(MASK, 0)
DECLARE_DISPLAY_ITEM_TYPE(FILTER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY, 0)
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT, 0)
DECLARE_DISPLAY_ITEM_TYPE(SVG_CHAR_CLIP, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(SVG_CHAR_CLIP, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(SVG_WRAPPER, 0)
DECLARE_DISPLAY_ITEM_TYPE(FOREIGN_OBJECT, 0)
DECLARE_DISPLAY_ITEM_TYPE(FOREIGN_OBJECT, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND, 0)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE, 0)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_IMAGE, 0)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_THEMED_BACKGROUND_IMAGE, 0)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_IMAGE, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_THEMED_BACKGROUND_IMAGE, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_FIXED_POSITION, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(TEXT, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(TEXT, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(TRANSFORM, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(PERSPECTIVE, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(VIDEO, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(VIDEO, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(WRAP_LIST, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(ZOOM, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(GENERIC, TYPE_RENDERS_NO_IMAGES)

Просмотреть файл

@ -19,6 +19,7 @@
#include "gfxContext.h"
#include "gfxUtils.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/KeyframeEffect.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/gfx/2D.h"
@ -1447,6 +1448,40 @@ DisplayListIsNonBlank(nsDisplayList* aList)
return false;
}
// A contentful paint is a paint that does contains DOM content (text,
// images, non-blank canvases, SVG): "First Contentful Paint entry
// contains a DOMHighResTimeStamp reporting the time when the browser
// first rendered any text, image (including background images),
// non-white canvas or SVG. This excludes any content of iframes, but
// includes text with pending webfonts. This is the first time users
// could start consuming page content."
static bool
DisplayListIsContentful(nsDisplayList* aList)
{
for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
DisplayItemType type = i->GetType();
nsDisplayList* children = i->GetChildren();
switch (type) {
case DisplayItemType::TYPE_SUBDOCUMENT: // iframes are ignored
break;
// CANVASes check if they may have been modified (as a stand-in
// actually tracking all modifications)
default:
if (i->IsContentful()) {
return true;
}
if (children) {
if (DisplayListIsContentful(children)) {
return true;
}
}
break;
}
}
return false;
}
void
nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
nsDisplayList* aPaintedContents)
@ -1455,7 +1490,7 @@ nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
aReferenceFrame->PresShell(),
"Presshell mismatch");
if (mIsPaintingToWindow) {
if (mIsPaintingToWindow && aPaintedContents) {
nsPresContext* pc = aReferenceFrame->PresContext();
if (!pc->HadNonBlankPaint()) {
if (!CurrentPresShellState()->mIsBackgroundOnly &&
@ -1463,6 +1498,12 @@ nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
pc->NotifyNonBlankPaint();
}
}
if (!pc->HadContentfulPaint()) {
if (!CurrentPresShellState()->mIsBackgroundOnly &&
DisplayListIsContentful(aPaintedContents)) {
pc->NotifyContentfulPaint();
}
}
}
ResetMarkedFramesForDisplayList(aReferenceFrame);

Просмотреть файл

@ -2411,7 +2411,9 @@ public:
*/
virtual uint32_t GetPerFrameKey() const { return uint32_t(GetType()); }
uint8_t GetFlags() { return GetDisplayItemFlagsForType(GetType()); }
uint8_t GetFlags() const { return GetDisplayItemFlagsForType(GetType()); }
virtual bool IsContentful() const { return GetFlags() & TYPE_IS_CONTENTFUL; }
/**
* This is called after we've constructed a display list for event handling.

Просмотреть файл

@ -179,6 +179,9 @@ pref("dom.permissions.revoke.enable", false);
// Enable exposing timeToNonBlankPaint
pref("dom.performance.time_to_non_blank_paint.enabled", false);
// Enable exposing timeToContentfulPaint
pref("dom.performance.time_to_contentful_paint.enabled", false);
// Enable exposing timeToDOMContentFlushed
pref("dom.performance.time_to_dom_content_flushed.enabled", false);