blob: 1df11d8d120c8ce29115b6501a2874f511af4d0d [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/types/strong_alias.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_download_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/metrics/autofill_metrics.h"
#include "components/autofill/core/common/dense_set.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/language_code.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/signatures.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/autofill_assistant/core/public/autofill_assistant_intent.h"
#include "components/translate/core/browser/translate_driver.h"
#include "components/version_info/channel.h"
namespace gfx {
class RectF;
}
namespace autofill {
class AutofillField;
class AutofillOfferManager;
class CreditCardAccessManager;
struct FormData;
struct FormFieldData;
class FormStructure;
class LogManager;
// This class defines the interface should be implemented by autofill
// implementation in browser side to interact with AutofillDriver.
//
// AutofillManager has two implementations:
// - AndroidAutofillManager for WebView and WebLayer,
// - BrowserAutofillManager for Chrome.
//
// It is owned by the AutofillDriver.
class AutofillManager
: public AutofillDownloadManager::Observer,
public translate::TranslateDriver::LanguageDetectionObserver {
public:
// Observer of AutofillManager events.
//
// OnAfterFoo() is called, perhaps asynchronously (but on the UI thread),
// after OnBeforeFoo(). The only exceptions where OnBeforeFoo() may be called
// without a corresponding OnAfterFoo() call are:
// - if the number of cached forms exceeds `kAutofillManagerMaxFormCacheSize`;
// - if this AutofillManager has been destroyed or reset in the meantime.
//
// The main purpose are unit tests. New pairs of events may be added as
// needed.
class Observer : public base::CheckedObserver {
public:
virtual void OnAutofillManagerDestroyed() {}
virtual void OnAutofillManagerReset() {}
virtual void OnBeforeLanguageDetermined() {}
virtual void OnAfterLanguageDetermined() {}
virtual void OnBeforeFormsSeen() {}
virtual void OnAfterFormsSeen() {}
virtual void OnBeforeTextFieldDidChange() {}
virtual void OnAfterTextFieldDidChange() {}
virtual void OnBeforeDidFillAutofillFormData() {}
virtual void OnAfterDidFillAutofillFormData() {}
virtual void OnBeforeAskForValuesToFill() {}
virtual void OnAfterAskForValuesToFill() {}
virtual void OnBeforeJavaScriptChangedAutofilledValue() {}
virtual void OnAfterJavaScriptChangedAutofilledValue() {}
// TODO(crbug.com/1330105): Clean up API: delete the events that don't
// follow the OnBeforeFoo() / OnAfterFoo() pattern.
virtual void OnFormParsed() {}
virtual void OnTextFieldDidChange() {}
virtual void OnTextFieldDidScroll() {}
virtual void OnSelectControlDidChange() {}
virtual void OnFormSubmitted() {}
};
using EnableDownloadManager =
base::StrongAlias<struct EnableDownloadManagerTag, bool>;
// Raw metadata uploading enabled iff this Chrome instance is on Canary or Dev
// channel.
static bool IsRawMetadataUploadingEnabled(version_info::Channel channel);
// TODO(crbug.com/1151542): Move to anonymous namespace once
// BrowserAutofillManager::OnLoadedServerPredictions() moves to
// AutofillManager.
static void LogAutofillTypePredictionsAvailable(
LogManager* log_manager,
const std::vector<FormStructure*>& forms);
AutofillManager(const AutofillManager&) = delete;
AutofillManager& operator=(const AutofillManager&) = delete;
~AutofillManager() override;
// The following will fail a DCHECK if called for a prerendered main frame.
AutofillClient* client() {
DCHECK(!driver()->IsPrerendering());
return client_;
}
const AutofillClient* client() const {
DCHECK(!driver()->IsPrerendering());
return client_;
}
// Returns a WeakPtr to the leaf class.
virtual base::WeakPtr<AutofillManager> GetWeakPtr() = 0;
// May return nullptr.
virtual AutofillOfferManager* GetOfferManager() = 0;
// May return nullptr.
virtual CreditCardAccessManager* GetCreditCardAccessManager() = 0;
// Events triggered by the renderer.
// Returns true only if the previewed form should be cleared.
virtual bool ShouldClearPreviewedForm() = 0;
// Invoked when the value of textfield is changed.
// |bounding_box| are viewport coordinates.
// Virtual for testing.
virtual void OnTextFieldDidChange(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp);
// Invoked when the textfield is scrolled.
// |bounding_box| are viewport coordinates.
void OnTextFieldDidScroll(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box);
// Invoked when the value of select is changed.
// |bounding_box| are viewport coordinates.
void OnSelectControlDidChange(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box);
// Invoked when the |form| needs to be autofilled, the |bounding_box| is
// a window relative value of |field|.
// |bounding_box| are viewport coordinates.
// |touch_to_fill_eligible| indicates if the Touch To Fill surface could be
// used for showing suggestion. Note that it doesn't guarantee the given form
// input field is eligible for autofilling.
// Virtual for testing.
virtual void OnAskForValuesToFill(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
int query_id,
bool autoselect_first_suggestion,
FormElementWasClicked form_element_was_clicked);
// Invoked when |form|'s |field| has focus.
// |bounding_box| are viewport coordinates.
void OnFocusOnFormField(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box);
// Invoked when |form| has been submitted.
// Processes the submitted |form|, saving any new Autofill data to the user's
// personal profile.
// Virtual for testing.
virtual void OnFormSubmitted(const FormData& form,
bool known_success,
mojom::SubmissionSource source);
void FillCreditCardForm(int query_id,
const FormData& form,
const FormFieldData& field,
const CreditCard& credit_card,
const std::u16string& cvc);
void FillProfileForm(const AutofillProfile& profile,
const FormData& form,
const FormFieldData& field);
// Invoked when |form| has been filled with the value given by
// FillOrPreviewForm.
// Virtual for testing.
virtual void OnDidFillAutofillFormData(const FormData& form,
const base::TimeTicks timestamp);
// Profile Autofill was triggered by assistant's |intent|. This only affects
// metrics logging.
virtual void SetProfileFillViaAutofillAssistantIntent(
const autofill_assistant::AutofillAssistantIntent intent) = 0;
// Credit Card Autofill was triggered by assistant's |intent|. This only
// affects metrics logging.
virtual void SetCreditCardFillViaAutofillAssistantIntent(
const autofill_assistant::AutofillAssistantIntent intent) = 0;
// Invoked when changes of the forms have been detected: the forms in
// |updated_forms| are either new or have changed, and the forms in
// |removed_forms| have been removed from the DOM (but may be re-added to the
// DOM later).
// Virtual for testing.
virtual void OnFormsSeen(const std::vector<FormData>& updated_forms,
const std::vector<FormGlobalId>& removed_forms);
// Invoked when focus is no longer on form. |had_interacted_form| indicates
// whether focus was previously on a form with which the user had interacted.
void OnFocusNoLongerOnForm(bool had_interacted_form);
// Invoked when preview autofill value has been shown.
void OnDidPreviewAutofillFormData();
// Invoked when textfeild editing ended
void OnDidEndTextFieldEditing();
// Invoked when popup window should be hidden.
void OnHidePopup();
// Invoked when the options of a select element in the |form| changed.
void OnSelectFieldOptionsDidChange(const FormData& form);
// Invoked after JavaScript set the value of |field| in |form|. Only called
// if |field| was in autofilled state. Note that from a renderer's
// perspective, modifying the value with JavaScript leads to a state where
// the field is not considered autofilled anymore. So this notification won't
// be sent again until the field gets autofilled again.
virtual void OnJavaScriptChangedAutofilledValue(
const FormData& form,
const FormFieldData& field,
const std::u16string& old_value);
// Other events.
// Invoked when the field type predictions are downloaded from the autofill
// server.
virtual void PropagateAutofillPredictions(
const std::vector<FormStructure*>& forms) = 0;
virtual void ReportAutofillWebOTPMetrics(bool used_web_otp) = 0;
// Resets cache.
virtual void Reset();
// translate::TranslateDriver::LanguageDetectionObserver:
void OnTranslateDriverDestroyed(
translate::TranslateDriver* translate_driver) override;
// Invoked when the language has been detected by the Translate component.
// As this usually happens after Autofill has parsed the forms for the first
// time, the heuristics need to be re-run by this function in order to use
// language-specific patterns.
void OnLanguageDetermined(
const translate::LanguageDetectionDetails& details) override;
// Fills |form_structure| and |autofill_field| with the cached elements
// corresponding to |form| and |field|. This might have the side-effect of
// updating the cache. Returns false if the |form| is not autofillable, or if
// it is not already present in the cache and the cache is full.
[[nodiscard]] bool GetCachedFormAndField(const FormData& form,
const FormFieldData& field,
FormStructure** form_structure,
AutofillField** autofill_field);
// Returns nullptr if no cached form structure is found with a matching
// |form_id|. Runs in logarithmic time.
FormStructure* FindCachedFormByRendererId(FormGlobalId form_id) const;
// Returns the number of forms this Autofill handler is aware of.
size_t NumFormsDetected() const { return form_structures_.size(); }
void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
void RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void NotifyObservers(void (Observer::*event)()) {
for (Observer& observer : observers_)
base::invoke(event, observer);
}
// Returns the present form structures seen by Autofill handler.
const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
form_structures() const {
return form_structures_;
}
AutofillDriver* driver() { return driver_; }
const AutofillDriver* driver() const { return driver_; }
AutofillDownloadManager* download_manager() {
return download_manager_.get();
}
// The return value shouldn't be cached, retrieve it as needed.
AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger() {
return form_interactions_ukm_logger_.get();
}
// A public wrapper that calls |OnLoadedServerPredictions| for testing
// purposes only, it is used by WebView integration test and unit test, so it
// can't be in #ifdef UNIT_TEST.
void OnLoadedServerPredictionsForTest(
std::string response,
const std::vector<FormSignature>& queried_form_signatures) {
OnLoadedServerPredictions(response, queried_form_signatures);
}
void OnServerRequestErrorForTest(
FormSignature form_signature,
AutofillDownloadManager::RequestType request_type,
int http_error) {
OnServerRequestError(form_signature, request_type, http_error);
}
#ifdef UNIT_TEST
// A public wrapper that calls |mutable_form_structures| for testing purposes
// only.
std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
mutable_form_structures_for_test() {
return mutable_form_structures();
}
// A public wrapper that calls |ParseForm| for testing purposes only.
FormStructure* ParseFormForTest(const FormData& form) {
return ParseForm(form, nullptr);
}
#endif // UNIT_TEST
protected:
AutofillManager(AutofillDriver* driver,
AutofillClient* client,
version_info::Channel channel,
EnableDownloadManager enable_download_manager);
LogManager* log_manager() { return log_manager_; }
// Retrieves the page language from |client_|
LanguageCode GetCurrentPageLanguage();
// The following do not check for prerendering. These should only used while
// constructing or resetting the manager.
// TODO(crbug.com/1239281): if we never intend to support multiple navigations
// while prerendering, these will be unnecessary (they're used during Reset
// which can be called during prerendering, but we could skip Reset for
// prerendering if we never have state to clear).
AutofillClient* unsafe_client() { return client_; }
const AutofillClient* unsafe_client() const { return client_; }
virtual void OnFormSubmittedImpl(const FormData& form,
bool known_success,
mojom::SubmissionSource source) = 0;
virtual void OnTextFieldDidChangeImpl(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp) = 0;
virtual void OnTextFieldDidScrollImpl(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
virtual void OnAskForValuesToFillImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
int query_id,
bool autoselect_first_suggestion,
FormElementWasClicked form_element_was_clicked) = 0;
virtual void OnFocusOnFormFieldImpl(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
virtual void OnSelectControlDidChangeImpl(const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
virtual void OnDidFillAutofillFormDataImpl(
const FormData& form,
const base::TimeTicks timestamp) = 0;
virtual void FillCreditCardFormImpl(const FormData& form,
const FormFieldData& field,
const CreditCard& credit_card,
const std::u16string& cvc,
int query_id) = 0;
virtual void FillProfileFormImpl(const FormData& form,
const FormFieldData& field,
const AutofillProfile& profile) = 0;
virtual void OnFocusNoLongerOnFormImpl(bool had_interacted_form) = 0;
virtual void OnDidPreviewAutofillFormDataImpl() = 0;
virtual void OnDidEndTextFieldEditingImpl() = 0;
virtual void OnHidePopupImpl() = 0;
virtual void OnSelectFieldOptionsDidChangeImpl(const FormData& form) = 0;
virtual void OnJavaScriptChangedAutofilledValueImpl(
const FormData& form,
const FormFieldData& field,
const std::u16string& old_value) = 0;
// Return whether the |forms| from OnFormSeen() should be parsed to
// form_structures.
virtual bool ShouldParseForms(const std::vector<FormData>& forms) = 0;
// Invoked before parsing the forms.
// TODO(crbug.com/1309848): Rename to some consistent scheme, e.g.,
// OnBeforeParsedForm().
virtual void OnBeforeProcessParsedForms() = 0;
// Invoked when the given |form| has been processed to the given
// |form_structure|.
virtual void OnFormProcessed(const FormData& form_data,
const FormStructure& form_structure) = 0;
// Invoked after all forms have been processed, |form_types| is a set of
// FormType found.
virtual void OnAfterProcessParsedForms(
const DenseSet<FormType>& form_types) = 0;
// Returns the number of FormStructures with the given |form_signature| and
// appends them to |form_structures|. Runs in linear time.
size_t FindCachedFormsBySignature(
FormSignature form_signature,
std::vector<FormStructure*>* form_structures) const;
// Parses multiple forms in one go. The function proceeds in three stages:
//
// 1. Turn (almost) every FormData into a FormStructure.
// 2. Run DetermineHeuristicTypes() on all FormStructures.
// 3. Update the cache member variable `form_structures_` and call `callback`.
//
// Step 1 runs synchronously on the main thread.
// Step 2 runs asynchronously on a worker task.
// Step 3 runs again on the main thread.
//
// There are two conditions under which a FormData is skipped in Step 1:
// - if the overall number exceeds `kAutofillManagerMaxFormCacheSize`;
// - if the form should not be parsed according to ShouldParseForms().
//
// TODO(crbug.com/1309848): Add unit tests.
// TODO(crbug.com/1345089): Eliminate either the ParseFormsAsync() or
// ParseFormAsync(). There are a few possible directions:
// - Let ParseFormAync() wrap the FormData in a vector, call
// ParseFormsAsync(), and then unwrap the vector again.
// - Let OnFormsSeen() take a single FormData. That simplifies also
// ContentAutofillDriver and ContentAutofillRouter a bit, but then the
// AutofillDownloadManager needs to collect forms to send a batch query.
// - Let all other events take a FormGlobalId instead of a FormData and fire
// OnFormsSeen() before these events if necessary.
void ParseFormsAsync(
const std::vector<FormData>& forms,
base::OnceCallback<void(AutofillManager&, const std::vector<FormData>&)>
callback);
// Parses a single form analogously to ParseFormsAsync().
void ParseFormAsync(
const FormData& form,
base::OnceCallback<void(AutofillManager&, const FormData&)> callback);
// Parses the |form| with the server data retrieved from the |cached_form|
// (if any). Returns nullptr if the form should not be parsed. Otherwise, adds
// the returned form structure to the |form_structures_|.
FormStructure* ParseForm(const FormData& form,
const FormStructure* cached_form);
bool value_from_dynamic_change_form_ = false;
std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
mutable_form_structures() {
return &form_structures_;
}
#ifdef UNIT_TEST
// Exposed for testing.
void set_download_manager_for_test(
std::unique_ptr<AutofillDownloadManager> manager) {
download_manager_ = std::move(manager);
}
#endif // UNIT_TEST
private:
// AutofillDownloadManager::Observer:
void OnLoadedServerPredictions(
std::string response,
const std::vector<FormSignature>& queried_form_signatures) override;
void OnServerRequestError(FormSignature form_signature,
AutofillDownloadManager::RequestType request_type,
int http_error) override;
// Invoked when forms from OnFormsSeen() have been parsed to
// |form_structures|.
void OnFormsParsed(const std::vector<FormData>& forms);
std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
CreateFormInteractionsUkmLogger();
// Provides driver-level context to the shared code of the component. Must
// outlive this object.
const raw_ptr<AutofillDriver> driver_;
// Do not access this directly. Instead, please use client() or
// unsafe_client(). These functions check (or explicitly don't check) that the
// client isn't accessed incorrectly.
const raw_ptr<AutofillClient> client_;
const raw_ptr<LogManager> log_manager_;
// Observer needed to re-run heuristics when the language has been detected.
base::ScopedObservation<
translate::TranslateDriver,
translate::TranslateDriver::LanguageDetectionObserver,
&translate::TranslateDriver::AddLanguageDetectionObserver,
&translate::TranslateDriver::RemoveLanguageDetectionObserver>
translate_observation_{this};
// Our copy of the form data.
std::map<FormGlobalId, std::unique_ptr<FormStructure>> form_structures_;
// Handles queries and uploads to Autofill servers. Will be nullptr if
// the download manager functionality is disabled.
std::unique_ptr<AutofillDownloadManager> download_manager_;
// Utility for logging URL keyed metrics.
std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
form_interactions_ukm_logger_;
// Observers that listen to updates of this instance.
base::ObserverList<Observer> observers_;
// DetermineHeuristicTypes() should only be run on the `parsing_task_runner_`.
// The reply will be called on the main thread and should be a no-op if this
// AutofillManager has been destroyed or reset; to detect this, the reply
// should take a WeakPtr from `parsing_weak_ptr_factory_`.
scoped_refptr<base::SequencedTaskRunner> parsing_task_runner_ =
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_VISIBLE});
base::WeakPtrFactory<AutofillManager> parsing_weak_ptr_factory_{this};
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_H_