blob: 79185e29907639f0094f80b8494671212b2f834b [file] [log] [blame]
// Copyright 2018 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_LAYOUT_LAYOUT_SHIFT_TRACKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SHIFT_TRACKER_H_
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_shift_region.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
class IntRect;
class LayoutObject;
class LocalFrameView;
class PropertyTreeState;
class TracedValue;
class WebInputEvent;
// Tracks "layout shifts" from layout objects changing their visual location
// between animation frames. See https://github.com/WICG/layout-instability.
class CORE_EXPORT LayoutShiftTracker {
USING_FAST_MALLOC(LayoutShiftTracker);
public:
LayoutShiftTracker(LocalFrameView*);
~LayoutShiftTracker() {}
// |paint_offset_diff| is an additional amount by which the paint offset
// shifted that is not tracked in visual rects. Visual rects are in the
// local transform space of the LayoutObject. Any time the transform space is
// changed, the offset of that rect to the "origin" is reset. This offset
// is also known as the paint offset.
// In cases where we can communicate paint offset diffs across transform
// space change boundaries, |paint_offset_diff| is how to do it. In
// particular, many transform spaces are artificial and are used as an
// implementation detail of compositing to make it easier to isolate state for
// composited layers. We can easily pass the paint offset diff across such
// boundaries.
void NotifyObjectPrePaint(const LayoutObject& object,
const PropertyTreeState& property_tree_state,
const IntRect& old_visual_rect,
const IntRect& new_visual_rect,
FloatSize paint_offset_delta);
void NotifyPrePaintFinished();
void NotifyInput(const WebInputEvent&);
void NotifyScroll(ScrollType, ScrollOffset delta);
void NotifyViewportSizeChanged();
bool IsActive();
double Score() const { return score_; }
double WeightedScore() const { return weighted_score_; }
float OverallMaxDistance() const { return overall_max_distance_; }
bool ObservedInputOrScroll() const { return observed_input_or_scroll_; }
void Dispose() { timer_.Stop(); }
base::TimeTicks MostRecentInputTimestamp() {
return most_recent_input_timestamp_;
}
private:
void ObjectShifted(const LayoutObject&,
const PropertyTreeState&,
FloatRect old_rect,
FloatRect new_rect,
FloatSize paint_offset_diff);
void ReportShift(double score_delta, double weighted_score_delta);
void TimerFired(TimerBase*) {}
std::unique_ptr<TracedValue> PerFrameTraceData(double score_delta,
bool input_detected) const;
double SubframeWeightingFactor() const;
void SetLayoutShiftRects(const Vector<IntRect>& int_rects);
void UpdateInputTimestamp(base::TimeTicks timestamp);
// This owns us.
UntracedMember<LocalFrameView> frame_view_;
// The document cumulative layout shift (DCLS) score for this LocalFrame,
// unweighted, with move distance applied.
double score_;
// The cumulative layout shift score for this LocalFrame, with each increase
// weighted by the extent to which the LocalFrame visibly occupied the main
// frame at the time the shift occurred, e.g. x0.5 if the subframe occupied
// half of the main frame's reported size; see SubframeWeightingFactor().
double weighted_score_;
// Stores information related to buffering layout shifts after pointerdown.
// We accumulate score deltas in this object until we know whether the
// pointerdown should be treated as a tap (triggering layout shift exclusion)
// or a scroll (not triggering layout shift exclusion). Once the correct
// treatment is known, the pending layout shifts are reported appropriately
// and the PointerdownPendingData object is reset.
struct PointerdownPendingData {
PointerdownPendingData()
: saw_pointerdown(false), score_delta(0), weighted_score_delta(0) {}
bool saw_pointerdown;
double score_delta;
double weighted_score_delta;
};
PointerdownPendingData pointerdown_pending_data_;
// The per-animation-frame impact region.
LayoutShiftRegion region_;
// Tracks the short period after an input event during which we ignore shifts
// for the purpose of cumulative scoring, and report them to the web perf API
// with hadRecentInput == true.
TaskRunnerTimer<LayoutShiftTracker> timer_;
// The maximum distance any layout object has moved in the current animation
// frame.
float frame_max_distance_;
// The maximum distance any layout object has moved, across all animation
// frames.
float overall_max_distance_;
// Sum of all scroll deltas that occurred in the current animation frame.
ScrollOffset frame_scroll_delta_;
// Whether either a user input or document scroll have been observed during
// the session. (This is only tracked so UkmPageLoadMetricsObserver to report
// LayoutInstability.CumulativeShiftScore.MainFrame.BeforeInputOrScroll. It's
// not related to input exclusion or the LayoutShift::had_recent_input_ bit.)
bool observed_input_or_scroll_;
// Most recent timestamp of a user input event that has been observed.
// User input includes window resizing but not scrolling.
base::TimeTicks most_recent_input_timestamp_;
bool most_recent_input_timestamp_initialized_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SHIFT_TRACKER_H_