1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_STICKY_FRAME_TRACKER_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_STICKY_FRAME_TRACKER_H_
7 
8 #include "third_party/blink/renderer/core/core_export.h"
9 #include "third_party/blink/renderer/platform/geometry/int_point.h"
10 #include "third_party/blink/renderer/platform/wtf/deque.h"
11 
12 namespace blink {
13 
14 // Keeps track of the viewport position of a frame.
15 //
16 // This is for catching ads that don't follow the Better Ads Standard --
17 // https://www.betterads.org/desktop-large-sticky-ad/.
18 //
19 // The heuristic for "sticky" is as follows:
20 //
21 // Given the latest two pairs of main frame scroll offset and frame's position
22 // wrt viewport (a.k.a. viewport offset), if the two main frame scroll offsets
23 // differ while the viewport offsets are the same, the frame is considered
24 // sticky.
25 //
26 // In addition, we store the latest 10 (|kNumScrollEvents|) main frame scroll
27 // offsets and viewport offsets, and keep comparing their range. For the latest
28 // 10 recordings, if the frame has a viewport offsets range smaller than 0.5
29 // (|kStickyFrameOffsetsRangeToScrollOffsetsRangeThreshold|) of the main frame
30 // scroll offsets range, then it's considered sticky as well.
31 //
32 // Right now we only consider offsets on the vertical dimension. The
33 // implementation can be extended to cover both dimensions if needed.
34 class CORE_EXPORT StickyFrameTracker {
35  public:
36   // Returns whether the |frame_size| is considered large compared to
37   // |main_frame_viewport_size|.
38   static bool IsLarge(const IntSize& main_frame_viewport_size,
39                       const IntSize& frame_size);
40 
41   StickyFrameTracker() = default;
42   StickyFrameTracker(const StickyFrameTracker&) = delete;
43   ~StickyFrameTracker() = default;
44 
45   // Called when the frame's position with respect to the viewport may have
46   // changed. Returns whether the frame is sticky. |main_frame_scroll_offset|
47   // is the scroll position in the main page. |viewport_offset| is the position
48   // of the top-left corner of this frame (every StickyFrameTracker will only be
49   // tracking one frame) relative to the browser viewport.
50   bool UpdateStickyStatus(const IntPoint& main_frame_scroll_offset,
51                           const IntPoint& viewport_offset);
52 
53  private:
54   void SetSticky();
55 
56   bool is_sticky_ = false;
57   Deque<int> viewport_offsets_;
58   Deque<int> main_frame_scroll_offsets_;
59 };
60 
61 }  // namespace blink
62 
63 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_STICKY_FRAME_TRACKER_H_
64