Commit 20d9207c authored by sunjian's avatar sunjian Committed by Commit bot

first-paint and first-contentful paint

BUG=657825
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2

Review-Url: https://codereview.chromium.org/2528513003
Cr-Commit-Position: refs/heads/master@{#443142}
parent e850e3f2
......@@ -79,6 +79,8 @@ Bug(none) webaudio/ [ Skip ]
Bug(none) webexposed/ [ Skip ]
Bug(none) webmidi/ [ Skip ]
Bug(none) xmlviewer/ [ Skip ]
crbug.com/657825 fast/performance/performance-first-paint-timing-observable.html [ Skip ]
crbug.com/657825 fast/performance/performance-paint-timing-observable.html [ Skip ]
Bug(none) broadcastchannel/blobs.html [ Pass Failure ]
Bug(none) compositing/3d-cube.html [ Failure ]
......
<!DOCTYPE html>
<head>
<title>Performance Paint Timing Test</title>
</head>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
async_test(function (t) {
var observer = new PerformanceObserver(
t.step_func(function (entryList) {
var entries = entryList.getEntries();
// Nothing contentful to be painted yet.
assert_equals(entries.length, 1,
"There should be only first paint timing instance.");
assert_equals(entries[0].entryType, "paint",
"Expected entryType to be: paint.");
assert_equals(entries[0].name, "first-paint",
"Expected name to be: first-paint.");
assert_equals(entries[0].duration, 0,
"Expected duration to be: 0.");
observer.disconnect();
t.done();
})
);
observer.observe({entryTypes: ["paint"]});
}, "Performance first paint timing entry is observable.");
</script>
<div style="background-color:black;color:white;padding:20px;"></div>
</body>
</html>
<!DOCTYPE html>
<head>
<title>Performance Paint Timing Test</title>
</head>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
async_test(function (t) {
var observer = new PerformanceObserver(
t.step_func(function (entryList) {
var entries = entryList.getEntries();
assert_equals(entries.length, 2,
"There should be two paint timing instances.");
assert_equals(entries[0].entryType, "paint",
"Expected entryType to be: paint.");
assert_equals(entries[0].duration, 0,
"Expected duration to be: 0.");
assert_equals(entries[1].entryType, "paint",
"Expected entryType to be: paint.");
assert_equals(entries[1].duration, 0,
"Expected duration to be: 0.");
observer.disconnect();
t.done();
})
);
observer.observe({entryTypes: ["paint"]});
}, "Both first-paint-timing and first-contentful-paint timing entry are observable.");
</script>
<div style="background-color:black;color:white;padding:20px;">...test...</div>
</body>
</html>
\ No newline at end of file
......@@ -10,7 +10,7 @@ FAIL [[GetOwnProperty]] - Property descriptors for cross-origin properties shoul
FAIL [[Delete]] Should throw on cross-origin objects assert_throws: Can't delete cross-origin indexed property function "function () { delete C[0]; }" did not throw
FAIL [[DefineOwnProperty]] Should throw for cross-origin objects assert_throws: Can't define cross-origin value property length function "function () { Object.defineProperty(obj, prop, valueDesc); }" did not throw
FAIL [[Enumerate]] should return an empty iterator assert_unreached: Shouldn't have been able to enumerate stop on cross-origin Window Reached unreachable code
FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 874 got 13
FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 875 got 13
PASS A and B jointly observe the same identity for cross-origin Window and Location
PASS Cross-origin functions get local Function.prototype
FAIL Cross-origin Window accessors get local Function.prototype Cannot read property 'name' of undefined
......
......@@ -4616,6 +4616,9 @@ interface PerformanceObserverEntryList
method getEntries
method getEntriesByName
method getEntriesByType
interface PerformancePaintTiming : PerformanceEntry
attribute @@toStringTag
method constructor
interface PerformanceResourceTiming : PerformanceEntry
attribute @@toStringTag
getter connectEnd
......
......@@ -400,6 +400,7 @@ core_idl_files = get_path_info([
"timing/PerformanceNavigationTiming.idl",
"timing/PerformanceObserver.idl",
"timing/PerformanceObserverEntryList.idl",
"timing/PerformancePaintTiming.idl",
"timing/PerformanceResourceTiming.idl",
"timing/PerformanceTiming.idl",
"timing/TaskAttributionTiming.idl",
......
......@@ -6,13 +6,28 @@
#include "core/dom/Document.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/loader/DocumentLoader.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "platform/WebFrameScheduler.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
namespace blink {
namespace {
Performance* getPerformanceInstance(LocalFrame* frame) {
Performance* performance = nullptr;
if (frame && frame->domWindow()) {
performance = DOMWindowPerformance::performance(*frame->domWindow());
}
return performance;
}
} // namespace
static const char kSupplementName[] = "PaintTiming";
PaintTiming& PaintTiming::from(Document& document) {
......@@ -120,6 +135,10 @@ void PaintTiming::setFirstPaint(double stamp) {
if (m_firstPaint != 0.0)
return;
m_firstPaint = stamp;
Performance* performance = getPerformanceInstance(frame());
if (performance)
performance->addFirstPaintTiming(m_firstPaint);
TRACE_EVENT_INSTANT1("blink.user_timing,rail", "firstPaint",
TRACE_EVENT_SCOPE_PROCESS, "frame", frame());
}
......@@ -129,6 +148,9 @@ void PaintTiming::setFirstContentfulPaint(double stamp) {
return;
setFirstPaint(stamp);
m_firstContentfulPaint = stamp;
Performance* performance = getPerformanceInstance(frame());
if (performance)
performance->addFirstContentfulPaintTiming(m_firstContentfulPaint);
TRACE_EVENT_INSTANT1("blink.user_timing,rail", "firstContentfulPaint",
TRACE_EVENT_SCOPE_PROCESS, "frame", frame());
}
......
......@@ -27,6 +27,8 @@ blink_core_sources("timing") {
"PerformanceObserver.h",
"PerformanceObserverEntryList.cpp",
"PerformanceObserverEntryList.h",
"PerformancePaintTiming.cpp",
"PerformancePaintTiming.h",
"PerformanceResourceTiming.cpp",
"PerformanceResourceTiming.h",
"PerformanceTiming.cpp",
......
......@@ -157,9 +157,11 @@ PerformanceEntryVector PerformanceBase::getEntriesByType(
if (m_userTiming)
entries.appendVector(m_userTiming->getMeasures());
break;
// Unsupported for LongTask, TaskAttribution.
// Unsupported for Paint, LongTask, TaskAttribution.
// Per the spec, these entries can only be accessed via
// Performance Observer. No separate buffer is maintained.
case PerformanceEntry::Paint:
break;
case PerformanceEntry::LongTask:
break;
case PerformanceEntry::TaskAttribution:
......@@ -400,6 +402,24 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
notifyObserversOfEntry(*m_navigationTiming);
}
void PerformanceBase::addFirstPaintTiming(double startTime) {
addPaintTiming(PerformancePaintTiming::PaintType::FirstPaint, startTime);
}
void PerformanceBase::addFirstContentfulPaintTiming(double startTime) {
addPaintTiming(PerformancePaintTiming::PaintType::FirstContentfulPaint,
startTime);
}
void PerformanceBase::addPaintTiming(PerformancePaintTiming::PaintType type,
double startTime) {
if (!RuntimeEnabledFeatures::performancePaintTimingEnabled())
return;
PerformanceEntry* entry = new PerformancePaintTiming(
type, monotonicTimeToDOMHighResTimeStamp(startTime));
notifyObserversOfEntry(*entry);
}
void PerformanceBase::addResourceTimingBuffer(PerformanceEntry& entry) {
m_resourceTimingBuffer.push_back(&entry);
......@@ -557,7 +577,8 @@ DOMHighResTimeStamp PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
return 0.0;
double timeInSeconds = monotonicTime - timeOrigin;
DCHECK_GE(timeInSeconds, 0);
if (timeInSeconds < 0)
return 0.0;
return convertSecondsToDOMHighResTimeStamp(
clampTimeResolution(timeInSeconds));
}
......
......@@ -38,6 +38,7 @@
#include "core/loader/FrameLoaderTypes.h"
#include "core/timing/PerformanceEntry.h"
#include "core/timing/PerformanceNavigationTiming.h"
#include "core/timing/PerformancePaintTiming.h"
#include "platform/Timer.h"
#include "platform/heap/Handle.h"
#include "wtf/Forward.h"
......@@ -113,6 +114,10 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData {
void addNavigationTiming(LocalFrame*);
void addFirstPaintTiming(double startTime);
void addFirstContentfulPaintTiming(double startTime);
void mark(const String& markName, ExceptionState&);
void clearMarks(const String& markName);
......@@ -145,6 +150,8 @@ class CORE_EXPORT PerformanceBase : public EventTargetWithInlineData {
const AtomicString&,
ExecutionContext*);
void addPaintTiming(PerformancePaintTiming::PaintType, double startTime);
protected:
explicit PerformanceBase(double timeOrigin);
......
......@@ -81,6 +81,8 @@ PerformanceEntry::EntryType PerformanceEntry::toEntryTypeEnum(
return Navigation;
if (entryType == "taskattribution")
return TaskAttribution;
if (entryType == "paint")
return Paint;
return Invalid;
}
......
......@@ -44,8 +44,8 @@ class ScriptState;
class ScriptValue;
class V8ObjectBuilder;
using PerformanceEntryType = unsigned char;
using PerformanceEntryTypeMask = unsigned char;
using PerformanceEntryType = unsigned;
using PerformanceEntryTypeMask = unsigned;
class CORE_EXPORT PerformanceEntry
: public GarbageCollectedFinalized<PerformanceEntry>,
......@@ -55,7 +55,7 @@ class CORE_EXPORT PerformanceEntry
public:
virtual ~PerformanceEntry();
enum EntryType {
enum EntryType : PerformanceEntryType {
Invalid = 0,
Navigation = 1 << 0,
Composite = 1 << 1,
......@@ -65,6 +65,7 @@ class CORE_EXPORT PerformanceEntry
Resource = 1 << 5,
LongTask = 1 << 6,
TaskAttribution = 1 << 7,
Paint = 1 << 8
};
String name() const;
......@@ -87,7 +88,7 @@ class CORE_EXPORT PerformanceEntry
return a->startTime() < b->startTime();
}
static EntryType toEntryTypeEnum(const String& entryType);
static PerformanceEntry::EntryType toEntryTypeEnum(const String& entryType);
DEFINE_INLINE_VIRTUAL_TRACE() {}
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/timing/PerformancePaintTiming.h"
#include "bindings/core/v8/V8ObjectBuilder.h"
namespace blink {
PerformancePaintTiming::PerformancePaintTiming(PaintType type, double startTime)
: PerformanceEntry(fromPaintTypeToString(type),
"paint",
startTime,
startTime) {}
PerformancePaintTiming::~PerformancePaintTiming() {}
String PerformancePaintTiming::fromPaintTypeToString(PaintType type) {
switch (type) {
case PaintType::FirstPaint:
return "first-paint";
case PaintType::FirstContentfulPaint:
return "first-contentful-paint";
}
NOTREACHED();
return "";
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PerformancePaintTiming_h
#define PerformancePaintTiming_h
#include "core/CoreExport.h"
#include "core/timing/PerformanceEntry.h"
namespace blink {
class CORE_EXPORT PerformancePaintTiming final : public PerformanceEntry {
DEFINE_WRAPPERTYPEINFO();
public:
enum class PaintType { FirstPaint, FirstContentfulPaint };
PerformancePaintTiming(PaintType, double startTime);
~PerformancePaintTiming() override;
static String fromPaintTypeToString(PaintType);
};
} // namespace blink
#endif // PerformancePaintTiming_h
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://github.com/WICG/paint-timing
[
RuntimeEnabled=PerformancePaintTiming,
] interface PerformancePaintTiming : PerformanceEntry {
};
......@@ -283,3 +283,4 @@ ParseHTMLOnMainThread status=test
SendBeaconThrowForBlobWithNonSimpleType status=experimental
PerformanceNavigationTiming2 status=experimental
BackgroundVideoTrackOptimization status=stable
PerformancePaintTiming status=test
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