File: navigation_predictor_metrics_document_data.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (185 lines) | stat: -rw-r--r-- 8,132 bytes parent folder | download | duplicates (6)
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
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_METRICS_DOCUMENT_DATA_H_
#define CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_METRICS_DOCUMENT_DATA_H_

#include "base/time/time.h"
#include "content/public/browser/document_user_data.h"
#include "content/public/browser/render_frame_host.h"

class NavigationPredictorMetricsDocumentData
    : public content::DocumentUserData<NavigationPredictorMetricsDocumentData> {
 public:
  struct AnchorsData {
    AnchorsData();
    ~AnchorsData();

    int MedianLinkLocation();

    size_t number_of_anchors_same_host_ = 0;
    size_t number_of_anchors_contains_image_ = 0;
    size_t number_of_anchors_in_iframe_ = 0;
    size_t number_of_anchors_url_incremented_ = 0;
    size_t number_of_anchors_ = 0;
    int total_clickable_space_ = 0;
    int viewport_height_ = 0;
    int viewport_width_ = 0;
    std::vector<int> link_locations_;
  };
  struct PageLinkClickData {
    int anchor_element_index_;
    std::optional<bool> href_unchanged_;
    base::TimeDelta navigation_start_to_link_clicked_;
  };
  struct AnchorElementMetricsData {
    AnchorElementMetricsData();
    AnchorElementMetricsData(AnchorElementMetricsData&&);

    AnchorElementMetricsData& operator=(AnchorElementMetricsData&&);

    uint8_t font_size_bucket_;
    bool contains_image_ : 1;
    bool has_text_sibling_ : 1;
    bool is_bold_ : 1;
    bool is_in_iframe_ : 1;
    bool is_url_incremented_by_one_ : 1;
    bool is_same_host_ : 1;
    base::TimeDelta navigation_start_to_link_logged;
    uint8_t path_length_;
    uint8_t path_depth_;
    uint8_t bucketed_path_hash_;
    uint8_t percent_clickable_area_;
    int percent_vertical_distance_;
  };

  // This structure holds the user interactions with a given anchor element.
  // Whenever, the user clicks on a link, we iterate over all
  // |UserInteractions| data and check if the anchor element is still in
  // viewport or not. If it is still in viewport, we use
  // |last_navigation_start_to_entered_viewport| and
  // |navigation_start_to_click_| to update |max_time_in_viewport|. Similarly,
  // we also check if the pointer is still hovering over the anchor element,
  // and use |last_navigation_start_to_pointer_over| and
  // |navigation_start_to_click_| to update |max_hover_dwell_time|. We then
  // record |max_time_in_viewport|, and |max_hover_dwell_time| to UKM.
  struct UserInteractionsData {
    UserInteractionsData();
    UserInteractionsData(const UserInteractionsData&);
    UserInteractionsData& operator=(const UserInteractionsData&);

    // True if the anchor element is still in viewport, otherwise false.
    bool is_in_viewport = false;
    // True if the pointer is still hovering over the anchor element,
    // otherwise false;
    bool is_hovered = false;
    // Number of times the pointer was hovering over the anchor element.
    int pointer_hovering_over_count = 0;
    // Number of times the anchor element entered the viewport.
    int entered_viewport_count = 0;
    // If the anchor element is still in viewport, it is the TimeDelta between
    // the navigation start of the anchor element's root document and the last
    // time the anchor element entered the viewport, otherwise empty.
    std::optional<base::TimeDelta> last_navigation_start_to_entered_viewport;
    // The maximum duration that the anchor element was in the viewport.
    std::optional<base::TimeDelta> max_time_in_viewport;
    // TimeDelta between the navigation start of the anchor element's root
    // document and the last time the pointer started to hover over the anchor
    // element, otherwise empty.
    std::optional<base::TimeDelta> last_navigation_start_to_pointer_over;
    // TimeDelta between the navigation start of the anchor element's root
    // document and the last time the pointer down event happened over the
    // anchor element, otherwise empty.
    std::optional<base::TimeDelta> last_navigation_start_to_last_pointer_down;
    // The maximum the pointer hover dwell time over the anchor element.
    std::optional<base::TimeDelta> max_hover_dwell_time;
    // Mouse velocity when the on-hover event was triggered.
    std::optional<double> mouse_velocity;
    // Mouse acceleration when the on-hover event was triggered.
    std::optional<double> mouse_acceleration;
    // Vertical position of the anchor element's center in the viewport
    // (recorded as a percentage of the viewport's height).
    std::optional<int> percent_vertical_position;
    // Vertical distance of the anchor element from the most recently recorded
    // pointerdown that initiated a scroll. This is recorded as a _signed_
    // percentage of the screen height, so that the cases of the link being
    // above and below the pointer are distinguishable.
    std::optional<int> percent_distance_from_pointer_down;
  };

  struct PreloadOnHoverData {
    bool taken = false;
    std::optional<base::TimeDelta> hover_dwell_time;
    std::optional<base::TimeDelta> pointer_down_duration;
  };

  NavigationPredictorMetricsDocumentData(
      const NavigationPredictorMetricsDocumentData&) = delete;
  NavigationPredictorMetricsDocumentData& operator=(
      const NavigationPredictorMetricsDocumentData&) = delete;
  ~NavigationPredictorMetricsDocumentData() override;

  void SetUkmSourceId(ukm::SourceId ukm_source_id) {
    ukm_source_id_ = ukm_source_id;
  }
  void ResetUkmSourceId() { ukm_source_id_.reset(); }

  AnchorsData& GetAnchorsData() { return anchor_data_; }
  void RecordAnchorData(ukm::SourceId ukm_source_id);

  void AddPageLinkClickData(PageLinkClickData data);
  void ClearPageLinkClickData();
  void RecordPageLinkClickData(ukm::SourceId ukm_source_id);

  void AddAnchorElementMetricsData(int anchor_index,
                                   AnchorElementMetricsData data);
  void RecordAnchorElementMetricsData(ukm::SourceId ukm_source_id);

  void AddUserInteractionsData(int anchor_index, UserInteractionsData data);
  void SetNavigationStartToClick(
      const base::TimeDelta& navigation_start_to_click) {
    navigation_start_to_click_ = navigation_start_to_click;
  }
  void SetNavigationStartTime(const base::TimeTicks& navigation_start_time) {
    navigation_start_time_ = navigation_start_time;
  }
  void RecordUserInteractionsData(ukm::SourceId ukm_source_id);
  void ClearUserInteractionsData();
  std::unordered_map<int, UserInteractionsData>& GetUserInteractionsData() {
    return user_interactions_;
  }

  void AddPreloadOnHoverData(PreloadOnHoverData data);
  void RecordPreloadOnHoverData(ukm::SourceId ukm_source_id);

  void RecordDataToUkm(ukm::SourceId ukm_source_id);

 private:
  friend class content::DocumentUserData<
      NavigationPredictorMetricsDocumentData>;
  explicit NavigationPredictorMetricsDocumentData(
      content::RenderFrameHost* render_frame_host);

  void RecordAnchorElementMetricsData(int anchor_index,
                                      const AnchorElementMetricsData& data);

  // TODO(isaboori): Right now we keep track of UKM source ID here as a member
  // variable and we also receive it as an argument in Record.*() methods. It is
  // to make sure that `NavigationPredictorMetricsDocumentData` and
  // 'PageAnchorMetricsObserver` are not getting out of sync. In future, we
  // should remove the `ukm_source_id` from the methods' arguments.
  std::optional<ukm::SourceId> ukm_source_id_;
  AnchorsData anchor_data_;
  std::vector<PageLinkClickData> page_link_clicks_;
  std::map<int, AnchorElementMetricsData> anchor_element_metrics_;
  std::unordered_map<int, UserInteractionsData> user_interactions_;
  std::vector<PreloadOnHoverData> preload_on_hover_;
  // The time between navigation start and the last time user clicked on a
  // link.
  std::optional<base::TimeDelta> navigation_start_to_click_;
  base::TimeTicks navigation_start_time_;
  DOCUMENT_USER_DATA_KEY_DECL();
};

#endif  // CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_METRICS_DOCUMENT_DATA_H_