File: fenced_frame_viewport_observer.h

package info (click to toggle)
chromium 140.0.7339.185-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,193,740 kB
  • sloc: cpp: 35,093,945; ansic: 7,161,670; javascript: 4,199,694; python: 1,441,797; asm: 949,904; xml: 747,515; pascal: 187,748; perl: 88,691; sh: 88,248; objc: 79,953; sql: 52,714; cs: 44,599; fortran: 24,137; makefile: 22,114; tcl: 15,277; php: 13,980; yacc: 9,000; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (125 lines) | stat: -rw-r--r-- 5,773 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
// 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_BROWSER_FENCED_FRAME_FENCED_FRAME_VIEWPORT_OBSERVER_H_
#define CONTENT_BROWSER_FENCED_FRAME_FENCED_FRAME_VIEWPORT_OBSERVER_H_

#include <map>
#include <unordered_set>

#include "base/types/optional_ref.h"
#include "content/browser/fenced_frame/fenced_frame_config.h"
#include "content/public/browser/commit_deferring_condition.h"
#include "content/public/browser/frame_tree_node_id.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/page_user_data.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/base/schemeful_site.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"

namespace content {

// This class tracks how many same-site fenced frames are visible in the
// viewport at once per primary main frame by updating the relevant metrics in
// the primary Page's FencedFrameViewportMonitor. Bound to the lifetime of the
// WebContents. Intended to monitor cases where multiple same-site fenced frames
// may collude to exfiltrate information via mouse click; for more info, see
// https://github.com/WICG/fenced-frame/blob/master/explainer/fenced_frames_with_local_unpartitioned_data_access.md#click-privacy-considerations
class FencedFrameViewportObserver : public WebContentsObserver {
 public:
  explicit FencedFrameViewportObserver(WebContents* web_contents);
  ~FencedFrameViewportObserver() override;

  FencedFrameViewportObserver(const FencedFrameViewportObserver&) = delete;
  FencedFrameViewportObserver(FencedFrameViewportObserver&&) = delete;
  FencedFrameViewportObserver& operator=(const FencedFrameViewportObserver&) =
      delete;
  FencedFrameViewportObserver& operator=(FencedFrameViewportObserver&&) =
      delete;

  // WebContentsObserver implementation.
  void FrameDeleted(FrameTreeNodeId frame_tree_node_id) override;
  void DidFinishNavigation(NavigationHandle* navigation_handle) override;
  void OnFrameVisibilityChanged(
      RenderFrameHost* rfh,
      blink::mojom::FrameVisibility visibility) override;
};

// Monitors the number of same-site fenced frames that are rendered in the
// viewport, and logs relevant UMA metrics. Scoped to the lifetime of the
// primary Page. Metrics will be logged when the primary Page enters
// BackForwardCache or is destroyed (destroying this object as well).
class FencedFrameViewportMonitor
    : public PageUserData<FencedFrameViewportMonitor> {
 public:
  // Helper to hold visibility info for each fenced frame in the
  // `visibility_infos_` map below.
  struct FencedFrameVisibilityInfo {
    net::SchemefulSite site;
    blink::mojom::FrameVisibility current_visibility =
        blink::mojom::FrameVisibility::kNotRendered;
  };

  ~FencedFrameViewportMonitor() override;

  // These methods correspond to the `WebContentsObserver` methods of the same
  // name, but are called only by `FencedFrameViewportObserver` when the
  // corresponding method is invoked for a fenced frame root.
  void FrameDeleted(FrameTreeNodeId frame_tree_node_id);
  void DidFinishNavigation(NavigationHandle* navigation_handle);
  void OnFrameVisibilityChanged(FrameTreeNodeId frame_tree_node_id,
                                blink::mojom::FrameVisibility visibility);

  // Called immediately before sending a commit for the primary main frame, or
  // when the frame tree is being torn down. Either of these actions will cause
  // fenced frames to leave the viewport, so we need to compute a snapshot of
  // how many same-site fenced frames were in the viewport beforehand, which
  // will ensure accurate UMA metrics.
  void ComputeSameSiteFencedFrameMaximumBeforePrimaryPageChange();

  // Logs UMA metrics and resets this object's local state before entering
  // BackForwardCache, which ensures that it's restored into the proper state
  // after being activated again.
  void OnPrimaryPageEnteringBFCache();

 private:
  explicit FencedFrameViewportMonitor(Page& page);

  friend PageUserData<FencedFrameViewportMonitor>;
  PAGE_USER_DATA_KEY_DECL();

  // Called when this object is destroyed or enters BackForwardCache.
  void LogUmaMetrics();

  // Increments or decrements the count of fenced frames navigated to `site`
  // that are visible in the viewport.
  void IncrementFencedFrameViewportCountForSite(const net::SchemefulSite& site);
  void DecrementFencedFrameViewportCountForSite(const net::SchemefulSite& site);

  // Relevant site + visibility info for each fenced frame, identified by its
  // FrameTreeNode.
  std::map<FrameTreeNodeId, FencedFrameVisibilityInfo> visibility_infos_;

  // Total count of fenced frames in the viewport, for each site.
  std::map<net::SchemefulSite, int> fenced_frames_in_viewport_per_site_;

  // Tracks the maximum number of same-site fenced frames that were rendered in
  // the viewport over the lifetime of this page load. Logged via UMA when this
  // object is destroyed or enters BackForwardCache.
  int max_same_site_fenced_frames_in_viewport_count_ = 0;

  // Tracks the maximum number of same-site fenced frames that were rendered in
  // the viewport at the moment the primary main frame unloads.
  int max_same_site_fenced_frames_in_viewport_at_unload_count_ = 0;

  // There are multiple code paths that may try to unload all the fenced frames
  // on the page, and they may or may not overlap. This flag ensures there's
  // only one computation per primary Page, done as early as possible.
  bool has_computed_unload_count_ = false;
};

}  // namespace content

#endif  // CONTENT_BROWSER_FENCED_FRAME_FENCED_FRAME_VIEWPORT_OBSERVER_H_