summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
blob: e3a2bb379a2998d839e5a4b9faa84ed7f885730a (plain)
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
// Copyright 2020 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_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_

#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"

namespace blink {

class LocalFrame;

// Detects overlay interstitials and record a use counter when an instance is
// found. The current scope is to consider only pop-ups, which appear after
// content on the page begins to load.
//
// Better Ads Standards definition:
// https://www.betterads.org/desktop-pop-up-ad/
// https://www.betterads.org/mobile-pop-up-ad/
//
// Heuristic:
// We do hit testing at the center of the browser viewport at regular intervals.
// The top element is an interstitial pop-up candidate if the following
// conditions are met:
// 1) It's immobile to scrolling (e.g. position:fixed).
// 2) The size is large.
// 3) It's created without user gesture.
// 4) It's created after the main content has loaded.
//
// The candidate will be actually counted as an overlay pop-up instance after we
// have checked some status at its dismissal time. On dismissal, if the main
// frame scrolling offset hasn't changed since the candidate's appearance, we
// count it as an overlay pop-up; otherwise, we skip that candidate because it
// could be a parallax/scroller ad.
//
// We could potentially miss some true positive cases: the user could click at
// an empty space which activates the user gesture, and coincidentally the
// pop-up automatically shows up; the user could make some scrolling
// before closing the pop-up; etc. However, we accept the trade-off exchanging a
// lower rate of false positive for an increase in the rate of false negatives.
class CORE_EXPORT OverlayInterstitialAdDetector {
 public:
  OverlayInterstitialAdDetector() = default;
  ~OverlayInterstitialAdDetector() = default;

  void MaybeFireDetection(LocalFrame* main_frame);
  void OnPopupAdDetected(LocalFrame* main_frame);

 private:
  bool started_detection_ = false;
  bool main_content_has_loaded_ = false;

  // The following members are valid only when |started_detection_| is true.
  base::Time last_detection_time_;
  IntSize last_detection_main_frame_size_;

  DOMNodeId candidate_id_;

  // The following members are valid only when |candidate_| is not nullptr.
  int candidate_start_main_frame_scroll_offset_ = 0;

  // The node id of the last element that was detected as unqualified to be an
  // overlay pop-up. We compare any potential candidate with the last
  // unqualified element and skip it if they are equal.
  //
  // It allows us to exclude some false positive cases. e.g. an
  // overlay was excluded from the initial consideration because it was created
  // with a gesture. After 5 seconds the gesture would be gone, but we still
  // want to exclude it as it was originally created with a gesture.
  //
  // Another advantage is this saves some computation cost. e.g. if an ad was
  // unqualified because it didn't have a viewport constraint position, then we
  // can skip it on its next occurrence without computing the style again.
  DOMNodeId last_unqualified_element_id_;

  bool done_detection_ = false;

  DISALLOW_COPY_AND_ASSIGN(OverlayInterstitialAdDetector);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_