blob: 7f03844a6096edd9763a9c8b0395dea428ddd11b [file] [log] [blame]
// 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