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_
|