File: tab_interaction_recorder_android.h

package info (click to toggle)
chromium 135.0.7049.95-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,959,392 kB
  • sloc: cpp: 34,198,526; ansic: 7,100,035; javascript: 3,985,800; python: 1,395,489; asm: 896,754; xml: 722,891; pascal: 180,504; sh: 94,909; perl: 88,388; objc: 79,739; sql: 53,020; cs: 41,358; fortran: 24,137; makefile: 22,501; php: 13,699; tcl: 10,142; yacc: 8,822; ruby: 7,350; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; awk: 197; sed: 36
file content (163 lines) | stat: -rw-r--r-- 6,659 bytes parent folder | download
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
// Copyright 2022 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_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_
#define CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_

#include "base/android/jni_android.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill/core/browser/foundations/autofill_manager.h"
#include "content/public/browser/document_user_data.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "url/gurl.h"

namespace customtabs {

// Autofill observer impl for the TabInteractionRecorderAndroid to use.
class AutofillObserverImpl : public autofill::AutofillManager::Observer {
 public:
  using OnFormInteractionCallback =
      base::OnceCallback<void(content::GlobalRenderFrameHostId)>;

  explicit AutofillObserverImpl(
      content::GlobalRenderFrameHostId id,
      autofill::AutofillManager* autofill_manager,
      OnFormInteractionCallback form_interaction_callback);

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

  // AutofillManager::Observer:
  void OnFormSubmitted(autofill::AutofillManager&,
                       const autofill::FormData&) override;
  void OnAfterSelectControlSelectionChanged(autofill::AutofillManager&,
                                            autofill::FormGlobalId,
                                            autofill::FieldGlobalId) override;
  void OnAfterTextFieldValueChanged(autofill::AutofillManager&,
                                    autofill::FormGlobalId,
                                    autofill::FieldGlobalId,
                                    const std::u16string&) override;
  void OnAfterTextFieldDidScroll(autofill::AutofillManager&,
                                 autofill::FormGlobalId,
                                 autofill::FieldGlobalId) override;
  void OnAfterFormsSeen(autofill::AutofillManager&,
                        base::span<const autofill::FormGlobalId>,
                        base::span<const autofill::FormGlobalId>) override;

 private:
  void OnFormInteraction();
  void Invalidate();

  const content::GlobalRenderFrameHostId global_id_;
  raw_ptr<autofill::AutofillManager, DanglingUntriaged> autofill_manager_;
  OnFormInteractionCallback form_interaction_callback_;
};

// DocumentUserData stored inside each RenderFrameHost indicating whether
// the hosting RFH experienced a form interaction.
class FormInteractionData
    : public content::DocumentUserData<FormInteractionData> {
 public:
  explicit FormInteractionData(content::RenderFrameHost* rfh);

  ~FormInteractionData() override;
  void SetHasFormInteractionData();
  bool GetHasFormInteractionData();

 private:
  bool had_form_interaction_data_;

  friend DocumentUserData;
  DOCUMENT_USER_DATA_KEY_DECL();
};

// Class that record interaction from the web contents. The definition
// of an "interaction" includes user's engagement with text inputs or selection
// inputs, or changes in navigation stacks.
//
// To attach this class to the web contents correctly, it has to be setup
// before the first navigation finishes in order to attach observers to
// corresponding autofill managers; otherwise the interaction with first frame
// would be missing.
class TabInteractionRecorderAndroid
    : public content::WebContentsObserver,
      public content::WebContentsUserData<TabInteractionRecorderAndroid> {
 public:
  ~TabInteractionRecorderAndroid() override;

  // Return whether the |web_contents()| has navigated away from the first page.
  bool HasNavigatedFromFirstPage() const;

  // Return whether there is an active render frame host which has incurred a
  // form interaction.
  bool HasActiveFormInteraction() const;

  // Return whether the |web_contents()| has seen any form interactions.
  bool has_form_interactions_in_session() const {
    return has_form_interactions_in_session_;
  }
  bool did_get_user_interaction() const { return did_get_user_interaction_; }

  // content::WebContentsObserver:

  // Dispatch an AutofillManagerObserver when a frame becomes active, or remove
  // the old AutofillManagerObserver when a frame becomes inactive.
  void RenderFrameHostStateChanged(
      content::RenderFrameHost* render_frame_host,
      content::RenderFrameHost::LifecycleState old_state,
      content::RenderFrameHost::LifecycleState new_state) override;
  // When a new frame is created, |RenderFrameHostStateChanged| happen earlier
  // than a AutofillManager initialized in such frame, which happened at
  // |DidFinishNavigation|. Observing |DidFinishNavigation| ensure this class
  // to dispatch the AutofillManagerObserver for newly created AutofillManager.
  void DidFinishNavigation(
      content::NavigationHandle* navigation_handle) override;
  void DidGetUserInteraction(const blink::WebInputEvent& event) override;

  // JNI methods
  jboolean DidGetUserInteraction(JNIEnv* env) const;
  jboolean HadFormInteractionInSession(JNIEnv* env) const;
  jboolean HadFormInteractionInActivePage(JNIEnv* env) const;
  jboolean HadNavigationInteraction(JNIEnv* env) const;
  void Reset(JNIEnv* env);

#ifdef UNIT_TEST
  void SetAutofillManagerForTest(
      autofill::AutofillManager* test_autofill_manager) {
    test_autofill_manager_ = test_autofill_manager;
  }
#endif

 private:
  explicit TabInteractionRecorderAndroid(content::WebContents* web_contents);

  friend class AutofillObserverImpl;
  void StartObservingFrame(content::RenderFrameHost* render_frame_host);
  void SetHasFormInteractions(content::GlobalRenderFrameHostId id);

  void ResetImpl();

  bool did_get_user_interaction_ = false;
  bool has_form_interactions_in_session_ = false;
  std::unordered_map<content::GlobalRenderFrameHostId,
                     std::unique_ptr<AutofillObserverImpl>,
                     content::GlobalRenderFrameHostIdHasher>
      rfh_observer_map_;
  raw_ptr<autofill::AutofillManager> test_autofill_manager_ = nullptr;

  // content::WebContentsUserData<TabInteractionRecorderAndroid>
  friend class content::WebContentsUserData<TabInteractionRecorderAndroid>;
  WEB_CONTENTS_USER_DATA_KEY_DECL();

  base::WeakPtrFactory<TabInteractionRecorderAndroid> weak_factory_{this};
};

}  // namespace customtabs

#endif  // CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_