зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1518999 - Implement PerformancePaintTiming for FirstContentfulPaint r=smaug,mstange
Spec: https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming We only support FirstContentfulPaint at the moment. Differential Revision: https://phabricator.services.mozilla.com/D66463
This commit is contained in:
Родитель
d54712b964
Коммит
61ec0bd3c3
|
@ -22,6 +22,7 @@ namespace dom {
|
|||
|
||||
class PerformanceEntry;
|
||||
class PerformanceNavigation;
|
||||
class PerformancePaintTiming;
|
||||
class PerformanceObserver;
|
||||
class PerformanceService;
|
||||
class PerformanceStorage;
|
||||
|
@ -85,6 +86,8 @@ class Performance : public DOMEventTargetHelper {
|
|||
|
||||
virtual PerformanceNavigation* Navigation() = 0;
|
||||
|
||||
virtual void SetFCPTimingEntry(PerformancePaintTiming* aEntry) = 0;
|
||||
|
||||
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
|
||||
|
||||
virtual void GetMozMemory(JSContext* aCx,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "PerformanceMainThread.h"
|
||||
#include "PerformanceNavigation.h"
|
||||
#include "PerformancePaintTiming.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_privacy.h"
|
||||
|
||||
|
@ -43,14 +44,14 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming, mNavigation, mDocEntry)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming, mNavigation, mDocEntry, mFCPTiming)
|
||||
tmp->mMozMemory = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
|
||||
Performance)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming, mNavigation, mDocEntry)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming, mNavigation, mDocEntry, mFCPTiming)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMainThread,
|
||||
|
@ -161,6 +162,14 @@ void PerformanceMainThread::AddRawEntry(UniquePtr<PerformanceTimingData> aData,
|
|||
InsertResourceEntry(entry);
|
||||
}
|
||||
|
||||
void PerformanceMainThread::SetFCPTimingEntry(PerformancePaintTiming* aEntry) {
|
||||
MOZ_ASSERT(aEntry);
|
||||
if (!mFCPTiming) {
|
||||
mFCPTiming = aEntry;
|
||||
QueueEntry(aEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// To be removed once bug 1124165 lands
|
||||
bool PerformanceMainThread::IsPerformanceTimingAttribute(
|
||||
const nsAString& aName) {
|
||||
|
@ -376,6 +385,9 @@ void PerformanceMainThread::GetEntries(
|
|||
aRetval.AppendElement(mDocEntry);
|
||||
}
|
||||
|
||||
if (mFCPTiming) {
|
||||
aRetval.AppendElement(mFCPTiming);
|
||||
}
|
||||
aRetval.Sort(PerformanceEntryComparator());
|
||||
}
|
||||
|
||||
|
@ -396,6 +408,13 @@ void PerformanceMainThread::GetEntriesByType(
|
|||
return;
|
||||
}
|
||||
|
||||
if (aEntryType.EqualsLiteral("paint")) {
|
||||
if (mFCPTiming) {
|
||||
aRetval.AppendElement(mFCPTiming);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Performance::GetEntriesByType(aEntryType, aRetval);
|
||||
}
|
||||
|
||||
|
@ -410,6 +429,13 @@ void PerformanceMainThread::GetEntriesByName(
|
|||
|
||||
Performance::GetEntriesByName(aName, aEntryType, aRetval);
|
||||
|
||||
if (mFCPTiming && mFCPTiming->GetName().Equals(aName) &&
|
||||
(!aEntryType.WasPassed() ||
|
||||
mFCPTiming->GetEntryType().Equals(aEntryType.Value()))) {
|
||||
aRetval.AppendElement(mFCPTiming);
|
||||
return;
|
||||
}
|
||||
|
||||
// The navigation entry is the first one. If it exists and the name matches,
|
||||
// let put it in front.
|
||||
if (mDocEntry && mDocEntry->GetName().Equals(aName)) {
|
||||
|
|
|
@ -38,6 +38,7 @@ class PerformanceMainThread final : public Performance,
|
|||
void AddRawEntry(UniquePtr<PerformanceTimingData>,
|
||||
const nsAString& aInitiatorType,
|
||||
const nsAString& aEntryName);
|
||||
virtual void SetFCPTimingEntry(PerformancePaintTiming* aEntry) override;
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
|
@ -90,6 +91,7 @@ class PerformanceMainThread final : public Performance,
|
|||
nsCOMPtr<nsITimedChannel> mChannel;
|
||||
RefPtr<PerformanceTiming> mTiming;
|
||||
RefPtr<PerformanceNavigation> mNavigation;
|
||||
RefPtr<PerformancePaintTiming> mFCPTiming;
|
||||
JS::Heap<JSObject*> mMozMemory;
|
||||
|
||||
const bool mCrossOriginIsolated;
|
||||
|
|
|
@ -132,11 +132,8 @@ void PerformanceObserver::QueueEntry(PerformanceEntry* aEntry) {
|
|||
* Keep this list in alphabetical order.
|
||||
* https://w3c.github.io/performance-timeline/#supportedentrytypes-attribute
|
||||
*/
|
||||
static const char16_t* const sValidTypeNames[4] = {
|
||||
u"mark",
|
||||
u"measure",
|
||||
u"navigation",
|
||||
u"resource",
|
||||
static const char16_t* const sValidTypeNames[5] = {
|
||||
u"mark", u"measure", u"navigation", u"paint", u"resource",
|
||||
};
|
||||
|
||||
void PerformanceObserver::ReportUnsupportedTypesErrorToConsole(
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PerformancePaintTiming.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/dom/PerformanceMeasureBinding.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformancePaintTiming, PerformanceEntry,
|
||||
mPerformance)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformancePaintTiming)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(PerformancePaintTiming, PerformanceEntry)
|
||||
NS_IMPL_RELEASE_INHERITED(PerformancePaintTiming, PerformanceEntry)
|
||||
|
||||
PerformancePaintTiming::PerformancePaintTiming(Performance* aPerformance,
|
||||
const nsAString& aName,
|
||||
const TimeStamp& aStartTime)
|
||||
: PerformanceEntry(aPerformance->GetParentObject(), aName, u"paint"_ns),
|
||||
mPerformance(aPerformance),
|
||||
mStartTime(aStartTime) {}
|
||||
|
||||
PerformancePaintTiming::~PerformancePaintTiming() = default;
|
||||
|
||||
JSObject* PerformancePaintTiming::WrapObject(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
||||
return PerformancePaintTiming_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp PerformancePaintTiming::StartTime() const {
|
||||
DOMHighResTimeStamp rawValue =
|
||||
mPerformance->GetDOMTiming()->TimeStampToDOMHighRes(mStartTime);
|
||||
return nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||
rawValue, mPerformance->GetRandomTimelineSeed(),
|
||||
mPerformance->IsSystemPrincipal(), mPerformance->CrossOriginIsolated());
|
||||
}
|
||||
|
||||
size_t PerformancePaintTiming::SizeOfIncludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PerformancePaintTiming_h___
|
||||
#define mozilla_dom_PerformancePaintTiming_h___
|
||||
|
||||
#include "mozilla/dom/PerformanceEntry.h"
|
||||
#include "mozilla/dom/PerformancePaintTimingBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
|
||||
// Unlike timeToContentfulPaint, this timing is generated during
|
||||
// displaylist building, when a frame is contentful, we collect
|
||||
// the timestamp. Whereas, timeToContentfulPaint uses a compositor-side
|
||||
// timestamp.
|
||||
class PerformancePaintTiming final : public PerformanceEntry {
|
||||
public:
|
||||
PerformancePaintTiming(Performance* aPerformance, const nsAString& aName,
|
||||
const TimeStamp& aStartTime);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PerformancePaintTiming,
|
||||
PerformanceEntry)
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
DOMHighResTimeStamp StartTime() const override;
|
||||
|
||||
size_t SizeOfIncludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
private:
|
||||
~PerformancePaintTiming();
|
||||
RefPtr<Performance> mPerformance;
|
||||
const TimeStamp mStartTime;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_PerformanacePaintTiming_h___ */
|
|
@ -33,6 +33,10 @@ class PerformanceWorker final : public Performance {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void SetFCPTimingEntry(PerformancePaintTiming* aEntry) override {
|
||||
MOZ_CRASH("This should not be called on workers.");
|
||||
}
|
||||
|
||||
TimeStamp CreationTimeStamp() const override;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const override;
|
||||
|
|
|
@ -17,6 +17,7 @@ EXPORTS.mozilla.dom += [
|
|||
'PerformanceNavigationTiming.h',
|
||||
'PerformanceObserver.h',
|
||||
'PerformanceObserverEntryList.h',
|
||||
'PerformancePaintTiming.h',
|
||||
'PerformanceResourceTiming.h',
|
||||
'PerformanceServerTiming.h',
|
||||
'PerformanceService.h',
|
||||
|
@ -35,6 +36,7 @@ UNIFIED_SOURCES += [
|
|||
'PerformanceNavigationTiming.cpp',
|
||||
'PerformanceObserver.cpp',
|
||||
'PerformanceObserverEntryList.cpp',
|
||||
'PerformancePaintTiming.cpp',
|
||||
'PerformanceResourceTiming.cpp',
|
||||
'PerformanceServerTiming.cpp',
|
||||
'PerformanceService.cpp',
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 21 KiB |
|
@ -14,6 +14,14 @@ support-files =
|
|||
[test_performance_observer.html]
|
||||
[test_performance_user_timing.html]
|
||||
[test_performance_navigation_timing.html]
|
||||
[test_performance_paint_timing.html]
|
||||
support-files =
|
||||
test_performance_paint_timing_helper.html
|
||||
logo.png
|
||||
[test_performance_paint_observer.html]
|
||||
support-files =
|
||||
test_performance_paint_observer_helper.html
|
||||
logo.png
|
||||
[test_worker_user_timing.html]
|
||||
[test_worker_observer.html]
|
||||
[test_sharedWorker_performance_user_timing.html]
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1518999
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1518999 (Observer API) </title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1518999">Mozilla
|
||||
Bug 1518999 - Paint Timing API For Observers</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
let tab;
|
||||
function runTest() {
|
||||
tab = window.open("test_performance_paint_observer_helper.html");
|
||||
}
|
||||
|
||||
function done() {
|
||||
tab.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
</body>
|
||||
<script>
|
||||
var promise = new Promise(resolve => {
|
||||
var observer = new PerformanceObserver(list => resolve(list));
|
||||
observer.observe({entryTypes: ["paint"]});
|
||||
});
|
||||
|
||||
promise.then(list => {
|
||||
var perfEntries = list.getEntries();
|
||||
opener.is(list.getEntries().length, 1);
|
||||
opener.isDeeply(list.getEntries(),
|
||||
performance.getEntriesByType("paint"),
|
||||
"Observed 'paint' entries should equal to entries obtained by getEntriesByType.");
|
||||
opener.isDeeply(list.getEntries({name: "paint"}),
|
||||
performance.getEntriesByName("paint"),
|
||||
"getEntries with name filter should return correct results.");
|
||||
opener.isDeeply(list.getEntries({entryType: "paint"}),
|
||||
performance.getEntriesByType("paint"),
|
||||
"getEntries with entryType filter should return correct results.");
|
||||
opener.done();
|
||||
});
|
||||
|
||||
const img = document.createElement("IMG");
|
||||
img.src = "http://example.org/tests/dom/performance/tests/logo.png";
|
||||
document.body.appendChild(img);
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,38 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1518999
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1518999</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1518999">Mozilla
|
||||
Bug 1518999 - Paint Timing API</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
let tab;
|
||||
function runTest() {
|
||||
tab = window.open("test_performance_paint_timing_helper.html");
|
||||
}
|
||||
function done() {
|
||||
tab.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,65 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1518999
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1518999</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="main"></div>
|
||||
<div id="image"></div>
|
||||
<div id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
async function runTest() {
|
||||
const paintEntries = performance.getEntriesByType('paint');
|
||||
opener.is(paintEntries.length, 0, "No paint entries yet");
|
||||
|
||||
const img = document.createElement("img");
|
||||
img.src = "http://example.org/tests/dom/performance/tests/logo.png";
|
||||
|
||||
img.onload = function() {
|
||||
function getAndTestEntries(runCount) {
|
||||
function testEntries(entries) {
|
||||
opener.is(entries.length, 1, "FCP Only returns");
|
||||
opener.is(entries[0].entryType, "paint", "entryType is paint");
|
||||
opener.is(entries[0].name, "first-contentful-paint",
|
||||
"Returned entry should be first-contentful-paint" );
|
||||
const fcpEntriesGotByName =
|
||||
performance.getEntriesByName('first-contentful-paint');
|
||||
opener.is(fcpEntriesGotByName.length, 1, "entries length should match");
|
||||
opener.is(entries[0], fcpEntriesGotByName[0], "should be the same entry");
|
||||
opener.done();
|
||||
}
|
||||
const entries = performance.getEntriesByType('paint');
|
||||
if (entries.length < 1) {
|
||||
if (runCount < 4) {
|
||||
opener.SimpleTest.requestFlakyTimeout("FCP is being registered asynchronously, so wait a bit of time");
|
||||
setTimeout(function() {
|
||||
getAndTestEntries(runCount + 1);
|
||||
}, 20);
|
||||
} else {
|
||||
opener.ok(false, "Unable to find paint entries within a reasonable amount of time");
|
||||
opener.done();
|
||||
}
|
||||
} else {
|
||||
testEntries(entries);
|
||||
}
|
||||
}
|
||||
getAndTestEntries(1);
|
||||
}
|
||||
document.body.appendChild(img);
|
||||
}
|
||||
window.onload = function() {
|
||||
runTest();
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -858,6 +858,8 @@ var interfaceNamesInGlobalScope = [
|
|||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformanceObserverEntryList", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformancePaintTiming", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformanceResourceTiming", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "PerformanceServerTiming", insecureContext: false },
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Exposed=(Window)]
|
||||
interface PerformancePaintTiming : PerformanceEntry
|
||||
{
|
||||
};
|
|
@ -750,6 +750,7 @@ WEBIDL_FILES = [
|
|||
'PerformanceNavigationTiming.webidl',
|
||||
'PerformanceObserver.webidl',
|
||||
'PerformanceObserverEntryList.webidl',
|
||||
'PerformancePaintTiming.webidl',
|
||||
'PerformanceResourceTiming.webidl',
|
||||
'PerformanceServerTiming.webidl',
|
||||
'PerformanceTiming.webidl',
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PerformanceTiming.h"
|
||||
#include "mozilla/dom/PerformancePaintTiming.h"
|
||||
#include "mozilla/layers/APZThreadUtils.h"
|
||||
#include "MobileViewportManager.h"
|
||||
#include "mozilla/dom/ImageTracker.h"
|
||||
|
@ -189,6 +190,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
|
|||
mInflationDisabledForShrinkWrap(false),
|
||||
mInteractionTimeEnabled(true),
|
||||
mHasPendingInterrupt(false),
|
||||
mHasEverBuiltInvisibleText(false),
|
||||
mPendingInterruptFromTest(false),
|
||||
mInterruptsEnabled(false),
|
||||
mSendAfterPaintToContent(false),
|
||||
|
@ -2367,7 +2369,8 @@ void nsPresContext::NotifyNonBlankPaint() {
|
|||
}
|
||||
}
|
||||
|
||||
void nsPresContext::NotifyContentfulPaint() {
|
||||
void nsPresContext::NotifyContentfulPaint(
|
||||
const mozilla::TimeStamp& aTimeStamp) {
|
||||
if (!mHadContentfulPaint) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
(new AsyncEventDispatcher(mDocument, u"MozFirstContentfulPaint"_ns,
|
||||
|
@ -2375,10 +2378,18 @@ void nsPresContext::NotifyContentfulPaint() {
|
|||
->PostDOMEvent();
|
||||
#endif
|
||||
mHadContentfulPaint = true;
|
||||
if (IsRootContentDocument()) {
|
||||
if (nsRootPresContext* rootPresContext = GetRootPresContext()) {
|
||||
mFirstContentfulPaintTransactionId =
|
||||
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
|
||||
if (nsRootPresContext* rootPresContext = GetRootPresContext()) {
|
||||
mFirstContentfulPaintTransactionId =
|
||||
Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
|
||||
nsPIDOMWindowInner* innerWindow = mDocument->GetInnerWindow();
|
||||
if (innerWindow) {
|
||||
mozilla::dom::Performance* perf = innerWindow->GetPerformance();
|
||||
if (perf) {
|
||||
RefPtr<PerformancePaintTiming> paintTiming =
|
||||
new PerformancePaintTiming(perf, u"first-contentful-paint"_ns,
|
||||
aTimeStamp);
|
||||
perf->SetFCPTimingEntry(paintTiming);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1031,10 +1031,13 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
bool HadNonBlankPaint() const { return mHadNonBlankPaint; }
|
||||
bool HadContentfulPaint() const { return mHadContentfulPaint; }
|
||||
void NotifyNonBlankPaint();
|
||||
void NotifyContentfulPaint();
|
||||
void NotifyContentfulPaint(const mozilla::TimeStamp& aTimeStamp);
|
||||
void NotifyPaintStatusReset();
|
||||
void NotifyDOMContentFlushed();
|
||||
|
||||
bool HasEverBuiltInvisibleText() const { return mHasEverBuiltInvisibleText; }
|
||||
void SetBuiltInvisibleText() { mHasEverBuiltInvisibleText = true; }
|
||||
|
||||
bool UsesExChUnits() const { return mUsesExChUnits; }
|
||||
|
||||
void SetUsesExChUnits(bool aValue) { mUsesExChUnits = aValue; }
|
||||
|
@ -1277,6 +1280,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
protected:
|
||||
unsigned mInteractionTimeEnabled : 1;
|
||||
unsigned mHasPendingInterrupt : 1;
|
||||
unsigned mHasEverBuiltInvisibleText : 1;
|
||||
unsigned mPendingInterruptFromTest : 1;
|
||||
unsigned mInterruptsEnabled : 1;
|
||||
unsigned mSendAfterPaintToContent : 1;
|
||||
|
|
|
@ -4881,6 +4881,9 @@ void nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
TextDecorations textDecs;
|
||||
GetTextDecorations(PresContext(), eResolvedColors, textDecs);
|
||||
if (!textDecs.HasDecorationLines()) {
|
||||
if (auto* currentPresContext = aBuilder->CurrentPresContext()) {
|
||||
currentPresContext->SetBuiltInvisibleText();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -507,6 +507,13 @@ class nsDisplayVideo : public nsPaintedDisplayItem {
|
|||
return elem->IsPotentiallyPlaying() ? LayerState::LAYER_ACTIVE_FORCE
|
||||
: LayerState::LAYER_INACTIVE;
|
||||
}
|
||||
|
||||
// Only report FirstContentfulPaint when the video is set
|
||||
bool IsContentful() const override {
|
||||
nsVideoFrame* f = static_cast<nsVideoFrame*>(Frame());
|
||||
HTMLVideoElement* video = HTMLVideoElement::FromNode(f->GetContent());
|
||||
return video->VideoWidth() > 0;
|
||||
}
|
||||
};
|
||||
|
||||
void nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -1065,7 +1065,8 @@ static bool DisplayListIsNonBlank(nsDisplayList* aList) {
|
|||
// 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) {
|
||||
static bool DisplayListIsContentful(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList) {
|
||||
for (nsDisplayItem* i : *aList) {
|
||||
DisplayItemType type = i->GetType();
|
||||
nsDisplayList* children = i->GetChildren();
|
||||
|
@ -1077,10 +1078,14 @@ static bool DisplayListIsContentful(nsDisplayList* aList) {
|
|||
// actually tracking all modifications)
|
||||
default:
|
||||
if (i->IsContentful()) {
|
||||
return true;
|
||||
bool dummy;
|
||||
nsRect bound = i->GetBounds(aBuilder, &dummy);
|
||||
if (!bound.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (children) {
|
||||
if (DisplayListIsContentful(children)) {
|
||||
if (DisplayListIsContentful(aBuilder, children)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1105,9 +1110,11 @@ void nsDisplayListBuilder::LeavePresShell(const nsIFrame* aReferenceFrame,
|
|||
}
|
||||
}
|
||||
if (!pc->HadContentfulPaint()) {
|
||||
if (!CurrentPresShellState()->mIsBackgroundOnly &&
|
||||
DisplayListIsContentful(aPaintedContents)) {
|
||||
pc->NotifyContentfulPaint();
|
||||
if (!CurrentPresShellState()->mIsBackgroundOnly) {
|
||||
if (pc->HasEverBuiltInvisibleText() ||
|
||||
DisplayListIsContentful(this, aPaintedContents)) {
|
||||
pc->NotifyContentfulPaint(TimeStamp::Now());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4678,6 +4678,14 @@ class nsDisplayBackgroundImage : public nsDisplayImageContainer {
|
|||
nsDisplayImageContainer::RemoveFrame(aFrame);
|
||||
}
|
||||
|
||||
// Match https://w3c.github.io/paint-timing/#contentful-image
|
||||
bool IsContentful() const override {
|
||||
const auto& styleImage =
|
||||
mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mImage;
|
||||
|
||||
return styleImage.IsSizeAvailable() && styleImage.IsUrl();
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef class mozilla::layers::ImageContainer ImageContainer;
|
||||
typedef class mozilla::layers::ImageLayer ImageLayer;
|
||||
|
|
Загрузка…
Ссылка в новой задаче