File: renderer_navigation_metrics_manager.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 (198 lines) | stat: -rw-r--r-- 9,619 bytes parent folder | download | duplicates (3)
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
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_RENDERER_NAVIGATION_METRICS_MANAGER_H_
#define CONTENT_RENDERER_RENDERER_NAVIGATION_METRICS_MANAGER_H_

#include <map>

#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "url/gurl.h"

namespace content {

// This class collects start and end times of different events pertaining to
// navigations in the renderer process. These events include RenderView/WebView
// creation, proxy creation, (possibly provisional) frame creation, and
// navigation commit. The main goal is to output a trace with the renderer's
// view of navigation events, as well as to record metrics for durations of
// those events. This is done by calling `RecordTraceEventsAndMetrics()` when a
// navigation finishes committing. The
// RendererNavigationMetricsManager::Timeline struct below keeps all the
// necessary timestamps for a single navigation.
//
// Multiple navigations may be in progress in the same renderer process, so this
// class keeps a map of Timelines keyed by "navigation metrics tokens", which
// are passed in by the browser process in IPCs related to navigations. Each
// navigation has a unique navigation metrics token, with the source of truth
// stored in the NavigationRequest.
//
// If a navigation starts creating view/frame/proxy objects but ends up not
// committing in this process, such as after a cross-process redirect or if the
// navigation is explicitly canceled by the user or another navigation, its
// timeline data is cleaned up lazily. In particular, a navigation's timestamps
// are cleaned up if the navigation hasn't committed after a 5-minute timeout -
// see note in RendererNavigationMetricsManager::GetOrCreateTimeline() about how
// this works, and why using explicit cancellation signals is hard. The goal is
// to change this into explicit cleanup in the future by improving signals for
// navigation cancellations and making them aware of navigation metrics tokens.
//
// There is one global RendererNavigationMetricsManager object in each renderer
// process, accessible via the `Instance()` method below.
class CONTENT_EXPORT RendererNavigationMetricsManager {
 public:
  RendererNavigationMetricsManager();

  static RendererNavigationMetricsManager& Instance();

  // This struct keeps a set of timestamps for performing a particular
  // navigation in the renderer process. It is created when the very first IPC
  // associated with this navigation is processed, which is typically
  // CreateView or CreateFrame.
  struct Timeline {
    Timeline();
    ~Timeline();

    // The time at which this navigation was started, without any beforeunload
    // adjustments. Note that navigation start might have happened in another
    // process (e.g., browser process or another renderer process).
    base::TimeTicks navigation_start;

    // Helper struct that holds a start/end time for a particular event.
    struct TimelineEvent {
      base::TimeTicks start;
      base::TimeTicks end;
    };

    // A set of <start, end> timestamps for processing all CreateView IPCs for
    // this navigation. These IPCs set up the blink::WebView and main frame
    // frame or proxy for the navigating frame and its opener Pages/FrameTrees,
    // if any.
    std::vector<TimelineEvent> create_view_events;

    // A set of <start, end> timestamps for processing all CreateRemoteChildren
    // IPCs that create all necessary subframe proxies for this navigation.
    // There is one pair  of timestamps for each Page/FrameTree that needed
    // subframe proxies, including the navigating frame's page as well as
    // its opener chain.
    std::vector<TimelineEvent> create_remote_children_events;

    // Start and end times for the CreateFrame IPC. This should exist for most
    // navigations, but could end up nullopt when a navigation stays in the same
    // RenderFrame, such as for same-document navigations or navigations out of
    // an initial blank document.
    std::optional<TimelineEvent> create_frame_event;

    // The time at which this navigation started processing the CommitNavigation
    // IPC.
    base::TimeTicks commit_start;

    // The time at which this navigation finished processing the
    // CommitNavigation IPC.
    base::TimeTicks commit_end;

    // A timer that's set at the time this Timeline object is created (i.e.,
    // when the very first IPC for this navigation is processed), to clean up
    // the Timeline if this navigation ends up never committing. See a note
    // about this in RendererNavigationMetricsManager::GetOrCreateTimeline().
    base::OneShotTimer lazy_cleanup_timer_;

    // Whether this Timeline is for the first navigation in this renderer
    // process. This is needed to report a single zero-sized
    // WaitingForProcessReady event in cases that the renderer is ready before
    // the first navigation begins, to give a sense of how often a process
    // is ready to go when it's needed for a navigation.
    bool is_first_navigation_in_this_process;
  };

  // The following methods are called to add timestamps for processing the
  // CreateView, CreateRemoteChildren, and CreateFrame IPCs, for a navigation
  // identified by `navigation_metrics_token`. Note that there might be multiple
  // CreateView and CreateRemoteChildren IPCs per navigation, since one is sent
  // for each page/FrameTree, and there could be multiple pages involved with
  // opener chains. In this case, AddCreateViewEvent and
  // AddCreateRemoteChildrenEvent might be called multiple times and will record
  // a list of <start,end> timestamps.
  //
  // The normal expected sequence of these events is:
  // - each page (if any) on the opener chain will generate a CreateView event
  //   followed by a CreateRemoteChildren event for any subframe proxies on that
  //   page.
  // - the page with the navigating frame will generate an optional CreateView
  //   event (if a main frame/proxy needs to be created), followed by an
  //   optional CreateRemoteChildren event (if any subframe proxies need to be
  //   created).
  // - the navigating frame will generate an optional CreateFrame event (when it
  //   navigates in a new RenderFrame).
  //
  // Note that a navigation could involve no CreateView IPCs at all (e.g., in
  // same-origin navigations). It could also involve no CreateFrame IPCs if the
  // navigation is staying in a previous RenderFrame, such as when performing a
  // same-document navigation, or navigating out of an initial blank document
  // where RenderDocument is not used.
  void AddCreateViewEvent(
      const std::optional<base::UnguessableToken>& navigation_metrics_token,
      const base::TimeTicks& start_time,
      const base::TimeDelta& elapsed_time);
  void AddCreateRemoteChildrenEvent(
      const std::optional<base::UnguessableToken>& navigation_metrics_token,
      const base::TimeTicks& start_time,
      const base::TimeDelta& elapsed_time);
  void AddCreateFrameEvent(
      const std::optional<base::UnguessableToken>& navigation_metrics_token,
      const base::TimeTicks& start_time,
      const base::TimeDelta& elapsed_time);

  // Set the time at which the renderer process started processing the
  // CommitNavigation IPC for the navigation identified by
  // `navigation_metrics_token`. This is not guaranteed to happen for all
  // navigations - in particular, renderer-initiated same-document navigations
  // and synchronous about:blank navigations do not involve a commit IPC from
  // the browser process.
  //
  // TODO(crbug.com/415821826): Consider still calling this at the start of
  // commit for those cases and recording a timeline for them as well.
  void MarkCommitStart(const base::UnguessableToken& navigation_metrics_token);

  // This is called when a navigation to `url` and identified by
  // `navigation_metrics_token` has finished committing in the renderer process.
  // This is a signal for this class to generate trace events and metrics using
  // all the timestamps collected so far for it. `navigation_start_time`
  // identifies the time at which this navigation was started, possibly in
  // another process.
  void ProcessNavigationCommit(
      const base::UnguessableToken& navigation_metrics_token,
      const GURL& url,
      const base::TimeTicks& navigation_start_time);

 private:
  ~RendererNavigationMetricsManager();

  Timeline& GetOrCreateTimeline(
      const base::UnguessableToken& navigation_metrics_token);

  // Records trace events and metrics for a particular navigation, using
  // timestamps in the provided `timeline`. `url` is used to log a trace event
  // that contains the navigation's final URL for convenience.
  void RecordTraceEventsAndMetrics(
      const RendererNavigationMetricsManager::Timeline& timeline,
      const GURL& url);

  // A map of navigation metrics tokens to corresponding Timeline objects.
  std::map<base::UnguessableToken, Timeline> timelines_;

  // Whether or not a first navigation in this renderer process has started.
  // This is used to report a single zero-sized WaitingForProcessReady per
  // process in any cases that the process was ready before the first
  // navigation, which indicates how often the process is ready to go when it's
  // needed for a navigation.
  bool has_first_navigation_started_ = false;
};

}  // namespace content

#endif  // CONTENT_RENDERER_RENDERER_NAVIGATION_METRICS_MANAGER_H_