1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
// Copyright 2015 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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TIMING_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TIMING_H_
#include <memory>
#include "third_party/blink/public/web/web_performance.h"
#include "third_party/blink/public/web/web_swap_result.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
#include "third_party/blink/renderer/core/paint/paint_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace base {
class TickClock;
}
namespace blink {
class LocalFrame;
// PaintTiming is responsible for tracking paint-related timings for a given
// document.
class CORE_EXPORT PaintTiming final : public GarbageCollected<PaintTiming>,
public Supplement<Document> {
friend class FirstMeaningfulPaintDetector;
using ReportTimeCallback =
WTF::CrossThreadOnceFunction<void(WebSwapResult, base::TimeTicks)>;
using RequestAnimationFrameTimesAfterBackForwardCacheRestore = std::array<
base::TimeTicks,
WebPerformance::
kRequestAnimationFramesToRecordAfterBackForwardCacheRestore>;
public:
static const char kSupplementName[];
explicit PaintTiming(Document&);
PaintTiming(const PaintTiming&) = delete;
PaintTiming& operator=(const PaintTiming&) = delete;
virtual ~PaintTiming() = default;
static PaintTiming& From(Document&);
// Mark*() methods record the time for the given paint event and queue a
// presentation promise to record the |first_*_presentation_| timestamp. These
// methods do nothing (early return) if a time has already been recorded for
// the given paint event.
void MarkFirstPaint();
// MarkFirstImagePaint, and MarkFirstContentfulPaint
// will also record first paint if first paint hasn't been recorded yet.
void MarkFirstContentfulPaint();
// MarkFirstImagePaint will also record first contentful paint if first
// contentful paint hasn't been recorded yet.
void MarkFirstImagePaint();
// MarkFirstEligibleToPaint records the first time that the frame is not
// throttled and so is eligible to paint. A null value indicates throttling.
void MarkFirstEligibleToPaint();
// MarkIneligibleToPaint resets the paint eligibility timestamp to null.
// A null value indicates throttling. This call is ignored if a first
// contentful paint has already been recorded.
void MarkIneligibleToPaint();
void SetFirstMeaningfulPaintCandidate(base::TimeTicks timestamp);
void SetFirstMeaningfulPaint(
base::TimeTicks presentation_time,
FirstMeaningfulPaintDetector::HadUserInput had_input);
void NotifyPaint(bool is_first_paint, bool text_painted, bool image_painted);
// Notifies the PaintTiming that this Document received the onPortalActivate
// event.
void OnPortalActivate();
void SetPortalActivatedPaint(base::TimeTicks stamp);
// The getters below return monotonically-increasing seconds, or zero if the
// given paint event has not yet occurred. See the comments for
// monotonicallyIncreasingTime in wtf/Time.h for additional details.
// FirstPaint returns the first time that anything was painted for the
// current document.
base::TimeTicks FirstPaint() const { return first_paint_presentation_; }
// Times when the first paint happens after the page is restored from the
// back-forward cache. If the element value is zero time tick, the first paint
// event did not happen for that navigation.
WTF::Vector<base::TimeTicks> FirstPaintsAfterBackForwardCacheRestore() const {
return first_paints_after_back_forward_cache_restore_presentation_;
}
WTF::Vector<RequestAnimationFrameTimesAfterBackForwardCacheRestore>
RequestAnimationFramesAfterBackForwardCacheRestore() const {
return request_animation_frames_after_back_forward_cache_restore_;
}
// FirstContentfulPaint returns the first time that 'contentful' content was
// painted. For instance, the first time that text or image content was
// painted.
base::TimeTicks FirstContentfulPaint() const {
return first_contentful_paint_presentation_;
}
// FirstImagePaint returns the first time that image content was painted.
base::TimeTicks FirstImagePaint() const {
return first_image_paint_presentation_;
}
// FirstEligibleToPaint returns the first time that the frame is not
// throttled and is eligible to paint. A null value indicates throttling.
base::TimeTicks FirstEligibleToPaint() const {
return first_eligible_to_paint_;
}
// FirstMeaningfulPaint returns the first time that page's primary content
// was painted.
base::TimeTicks FirstMeaningfulPaint() const {
return first_meaningful_paint_presentation_;
}
// The time that the first paint happened after a portal activation.
base::TimeTicks LastPortalActivatedPaint() const {
return last_portal_activated_presentation_;
}
// FirstMeaningfulPaintCandidate indicates the first time we considered a
// paint to qualify as the potentially first meaningful paint. Unlike
// firstMeaningfulPaint, this signal is available in real time, but it may be
// an optimistic (i.e., too early) estimate.
base::TimeTicks FirstMeaningfulPaintCandidate() const {
return first_meaningful_paint_candidate_;
}
FirstMeaningfulPaintDetector& GetFirstMeaningfulPaintDetector() {
return *fmp_detector_;
}
void RegisterNotifyPresentationTime(ReportTimeCallback);
void ReportPresentationTime(PaintEvent,
WebSwapResult,
base::TimeTicks timestamp);
void ReportFirstPaintAfterBackForwardCacheRestorePresentationTime(
size_t index,
WebSwapResult,
base::TimeTicks timestamp);
void ReportSwapResultHistogram(WebSwapResult);
// The caller owns the |clock| which must outlive the PaintTiming.
void SetTickClockForTesting(const base::TickClock* clock);
void OnRestoredFromBackForwardCache();
void Trace(Visitor*) const override;
private:
friend class RecodingTimeAfterBackForwardCacheRestoreFrameCallback;
LocalFrame* GetFrame() const;
void NotifyPaintTimingChanged();
// Set*() set the timing for the given paint event to the given timestamp if
// the value is currently zero, and queue a presentation promise to record the
// |first_*_presentation_| timestamp. These methods can be invoked from other
// Mark*() or Set*() methods to make sure that first paint is marked as part
// of marking first contentful paint, or that first contentful paint is marked
// as part of marking first text/image paint, for example.
void SetFirstPaint(base::TimeTicks stamp);
// setFirstContentfulPaint will also set first paint time if first paint
// time has not yet been recorded.
void SetFirstContentfulPaint(base::TimeTicks stamp);
// Set*Presentation() are called when the presentation promise is fulfilled
// and the presentation timestamp is available. These methods will record
// trace events, update Web Perf API (FP and FCP only), and notify that paint
// timing has changed, which triggers UMAs and UKMS. |stamp| is the
// presentation timestamp used for tracing, UMA, UKM, and Web Perf API.
void SetFirstPaintPresentation(base::TimeTicks stamp);
void SetFirstContentfulPaintPresentation(base::TimeTicks stamp);
void SetFirstImagePaintPresentation(base::TimeTicks stamp);
// When quickly navigating back and forward between the pages in the cache
// paint events might race with navigations. Pass explicit bfcache restore
// index to avoid confusing the data from different navigations.
void SetFirstPaintAfterBackForwardCacheRestorePresentation(
base::TimeTicks stamp,
size_t index);
void SetRequestAnimationFrameAfterBackForwardCacheRestore(size_t index,
size_t count);
void RegisterNotifyPresentationTime(PaintEvent);
void RegisterNotifyFirstPaintAfterBackForwardCacheRestorePresentationTime(
size_t index);
base::TimeTicks FirstPaintRendered() const { return first_paint_; }
base::TimeTicks FirstContentfulPaintRendered() const {
return first_contentful_paint_;
}
// TODO(crbug/738235): Non first_*_presentation_ variables are only being
// tracked to compute deltas for reporting histograms and should be removed
// once we confirm the deltas and discrepancies look reasonable.
base::TimeTicks first_paint_;
base::TimeTicks first_paint_presentation_;
WTF::Vector<base::TimeTicks>
first_paints_after_back_forward_cache_restore_presentation_;
WTF::Vector<RequestAnimationFrameTimesAfterBackForwardCacheRestore>
request_animation_frames_after_back_forward_cache_restore_;
base::TimeTicks first_image_paint_;
base::TimeTicks first_image_paint_presentation_;
base::TimeTicks first_contentful_paint_;
base::TimeTicks first_contentful_paint_presentation_;
base::TimeTicks first_meaningful_paint_presentation_;
base::TimeTicks first_meaningful_paint_candidate_;
base::TimeTicks first_eligible_to_paint_;
base::TimeTicks last_portal_activated_presentation_;
Member<FirstMeaningfulPaintDetector> fmp_detector_;
// The callback ID for requestAnimationFrame to record its time after the page
// is restored from the back-forward cache.
int raf_after_bfcache_restore_measurement_callback_id_ = 0;
const base::TickClock* clock_;
FRIEND_TEST_ALL_PREFIXES(FirstMeaningfulPaintDetectorTest,
TwoLayoutsSignificantFirst);
};
} // namespace blink
#endif
|