// Copyright 2013 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_CONTENT_RENDERER_PASSWORD_AUTOFILL_AGENT_H_
#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_AUTOFILL_AGENT_H_

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/containers/flat_set.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/types/strong_alias.h"
#include "build/build_config.h"
#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
#include "components/autofill/content/renderer/synchronous_form_cache.h"
#include "components/autofill/core/common/field_data_manager.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "content/public/renderer/render_frame_observer.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_input_element.h"

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
#include "components/autofill/content/renderer/page_passwords_analyser.h"
#endif

namespace blink {
class WebInputElement;
}

namespace autofill {
// Used in UMA histogram, please do NOT reorder.
// Metric: "PasswordManager.FirstRendererFillingResult".
// This metric records whether the PasswordAutofillAgent succeeded in filling
// credentials after being instructed to do so by the browser process.
enum class FillingResult {
  kSuccess = 0,
  // The password element to be filled has not been found.
  kNoPasswordElement = 1,
  // Filling only happens in iframes, if all parent frames PSL match the
  // security origin of the iframe containing the password field.
  kBlockedByFrameHierarchy = 2,
  // Passwords are not filled into fields that are not editable.
  kPasswordElementIsNotAutocompleteable = 3,
  // The username field contains a string that does not match the username of
  // any available credential.
  kUsernamePrefilledWithIncompatibleValue = 4,
  // No credential was filled due to mismatches with the username. This can
  // happen in a number of cases: In case the username field is empty and
  // readonly. In case of a username-first-flow where a user's credentials do
  // contain a username but the form contains only a password field and no
  // username field. In case of change password forms that contain no username
  // field. In case the user name is given on a page but only PSL matched
  // credentials exist for this username. There may be further cases.
  kFoundNoPasswordForUsername = 5,
  // Renderer was instructed to wait until user has manually picked a
  // credential. This happens for example if the session is an incognito
  // session, the credendial's URL matches the mainframe only via the PSL, the
  // site is on HTTP, or the form has no current password field.
  // PasswordManager.FirstWaitForUsernameReason records the root causes.
  kWaitForUsername = 6,
  // No fillable elements were found, only possible for old form parser.
  kNoFillableElementsFound = 7,
  kMaxValue = kNoFillableElementsFound,
};

class FieldDataManager;
class RendererSavePasswordProgressLogger;
class PasswordGenerationAgent;

// This class is responsible for filling password forms.
class PasswordAutofillAgent : public content::RenderFrameObserver,
                              public mojom::PasswordAutofillAgent {
 public:
  using UseFallbackData = base::StrongAlias<class UseFallbackDataTag, bool>;

  PasswordAutofillAgent(content::RenderFrame* render_frame,
                        blink::AssociatedInterfaceRegistry* registry);

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

  ~PasswordAutofillAgent() override;

  // Must be called prior to calling other methods.
  void Init(AutofillAgent* autofill_agent);

  void BindPendingReceiver(
      mojo::PendingAssociatedReceiver<mojom::PasswordAutofillAgent>
          pending_receiver);

  void SetPasswordGenerationAgent(PasswordGenerationAgent* generation_agent);

  // Callers should not store the returned value longer than a function scope.
  mojom::PasswordManagerDriver* unsafe_driver();

  // mojom::PasswordAutofillAgent:
  void ApplyFillDataOnParsingCompletion(
      const PasswordFormFillData& form_data) override;
  void FillPasswordSuggestion(const std::u16string& username,
                              const std::u16string& password,
                              base::OnceCallback<void(bool)> callback) override;
  void FillPasswordSuggestionById(
      FieldRendererId username_element_id,
      FieldRendererId password_element_id,
      const std::u16string& username,
      const std::u16string& password,
      AutofillSuggestionTriggerSource suggestion_source) override;
  void PreviewPasswordSuggestionById(FieldRendererId username_element_id,
                                     FieldRendererId password_element_id,
                                     const std::u16string& username,
                                     const std::u16string& password) override;
  void InformNoSavedCredentials(
      bool should_show_popup_without_passwords) override;
  void FillIntoFocusedField(bool is_password,
                            const std::u16string& credential) override;
  void PreviewField(FieldRendererId field_id,
                    const std::u16string& value) override;
  void FillField(FieldRendererId field_id,
                 const std::u16string& value,
                 FieldPropertiesMask field_properties,
                 base::OnceCallback<void(bool)> success_callback) override;
  void FillChangePasswordForm(FieldRendererId password_element_id,
                              FieldRendererId new_password_element_id,
                              FieldRendererId confirm_password_element_id,
                              const std::u16string& old_password,
                              const std::u16string& new_password,
                              FillChangePasswordFormCallback callback) override;
  void SetLoggingState(bool active) override;
  void AnnotateFieldsWithParsingResult(
      const ParsingResult& parsing_result) override;
  void CheckViewAreaVisible(FieldRendererId field_id,
                            CheckViewAreaVisibleCallback callback) override;
#if BUILDFLAG(IS_ANDROID)
  void TriggerFormSubmission() override;
#endif

  // An editing-related call of WebLocalFrameClient forwarded by AutofillAgent.
  // It returns a request that the agent should use to consume the event.
  // `form_cache` can be used to optimize form extractions occurring
  // synchronously after this function call.
  [[nodiscard]] std::optional<PasswordSuggestionRequest>
  CreateRequestForChangeInTextField(const blink::WebInputElement& element,
                                    const SynchronousFormCache& form_cache);

  // Called from AutofillAgent::UpdateStateForTextChange() to do
  // password-manager specific work. `form_cache` can be used to optimize form
  // extractions occurring synchronously after this function call.
  void UpdatePasswordStateForTextChange(const blink::WebInputElement& element,
                                        const SynchronousFormCache& form_cache);

  // Instructs `autofill_agent_` to track the autofilled `element`.
  void TrackAutofilledElement(const blink::WebFormControlElement& element);

  // Previews the username and password fields of this form with the given
  // values.
  void PreviewSuggestion(const blink::WebFormControlElement& node,
                         const std::u16string& username,
                         const std::u16string& password);

  // Clears all the previously previewed fields.
  void ClearPreviewedForm();

  // Sends a reputation check request in case if `element` has type password and
  // no check request were sent from this frame load.
  void MaybeCheckSafeBrowsingReputation(const blink::WebInputElement& element);

  // Performs necessary feasibility checks to trigger password suggestions
  // for the current domain on the `element`. `trigger_source` is used to
  // distinguish between the ways of how Autofill was triggered.
  // Returns a request if any suggestions can be shown, `nullopt` otherwise.
  // `form_cache` can be used to optimize form extractions occurring
  // synchronously after this function call.
  std::optional<PasswordSuggestionRequest> CreateRequestForDomain(
      const blink::WebInputElement& element,
      AutofillSuggestionTriggerSource trigger_source,
      const SynchronousFormCache& form_cache);

  // Performs necessary feasibility checks to trigger manual fallback
  // suggestion on the provided `element`. Returns a request if any suggestions
  // can be shown, `nullopt` otherwise.`form_cache` can be used to optimize
  // form extractions occurring synchronously after this function call.
  std::optional<PasswordSuggestionRequest> CreateManualFallbackRequest(
      const blink::WebInputElement& element,
      const SynchronousFormCache& form_cache);

  // Returns true if the password information for given `element` indicates the
  // user has already accepted a password suggestion on another password field.
  // This is useful to suppress a popups for already filled forms.
  bool HasAcceptedSuggestionOnOtherField(const blink::WebInputElement& element);

  // Called when new form controls are inserted. `form_cache` can be used to
  // optimize form extractions occurring synchronously after this function call.
  void OnDynamicFormsSeen(const SynchronousFormCache& form_cache);

  // Called when the user interacts with the page after a load. This is a
  // signal to make autofilled values of password input elements accessible to
  // JavaScript.
  void UserGestureObserved();

  std::optional<FormData> GetFormDataFromWebForm(
      const blink::WebFormElement& web_form,
      const SynchronousFormCache& form_cache);

  std::optional<FormData> GetFormDataFromUnownedInputElements(
      const SynchronousFormCache& form_cache);

  // Notification that form element was cleared by HTMLFormElement::reset()
  // method. This can be used as a signal of a successful submission for change
  // password forms.
  void InformAboutFormClearing(const blink::WebFormElement& form);

  // Notification that input element was cleared by HTMLInputValue::SetValue()
  // method by setting an empty value. This can be used as a signal of a
  // successful submission for change password forms.
  void InformAboutFieldClearing(const blink::WebInputElement& element);

  bool logging_state_active() const { return logging_state_active_; }

  // TODO(crbug.com/40281981): Replace `form_id` with non-optional
  // `submitted_form`.
  void FireHostSubmitEvent(FormRendererId form_id,
                           base::optional_ref<const FormData> submitted_form,
                           mojom::SubmissionSource source);

  // `form` and `input` are the elements user has just been interacting with
  // before the form save. `form` or `input` can be null but not both at the
  // same time. For example: if the form is unowned, `form` will be null; if the
  // user has submitted the form, `input` will be null. `form_cache` can be used
  // to optimize form extractions occurring synchronously after this function
  // call.
  void InformBrowserAboutUserInput(const blink::WebFormElement& form,
                                   const blink::WebInputElement& input,
                                   const SynchronousFormCache& form_cache);

  // Determine whether the current frame is allowed to access the password
  // manager. For example, frames with about:blank documents or documents with
  // unique origins aren't allowed access.
  virtual bool FrameCanAccessPasswordManager();

  // Called by `AutofillAgent::DidDispatchDOMContentLoadedEvent()`. `form_cache`
  // can be used to optimize form extractions occurring synchronously after this
  // function call.
  void DispatchedDOMContentLoadedEvent(const SynchronousFormCache& form_cache);

  // RenderFrameObserver:
  void DidFinishLoad() override;
  void ReadyToCommitNavigation(
      blink::WebDocumentLoader* document_loader) override;
  void DidCommitProvisionalLoad(ui::PageTransition transition) override;
  void OnDestruct() override;

  bool IsPrerendering() const;

  // Check if the given element is a username input field.
  bool IsUsernameInputField(const blink::WebInputElement& input_element) const;

  blink::WebFormControlElement last_queried_element() const {
    CHECK(autofill_agent_);
    return autofill_agent_->last_queried_element();
  }

  AutofillAgent& autofill_agent() { return *autofill_agent_; }

  // Notifies the driver about focusing the node.
  //
  // If `element` is null, notifies the password manager driver about removing
  // the focus from the currently focused node (with no setting it to a new
  // one).
  //
  // TODO: crbug.com/370301890 - Fire this in
  // RenderFrameObserver::FocusedElementChanged() and remove the plumbing from
  // AutofillAgent?
  void FocusedElementChangedWithCustomSemantics(
      const blink::WebElement& element,
      base::PassKey<AutofillAgent> pass_key) {
    focus_state_notifier_.FocusedElementChanged(element);
  }

 private:
  class DeferringPasswordManagerDriver;

  // This class ensures that the driver will only receive notifications only
  // when a focused field or its type (FocusedFieldType) change.
  class FocusStateNotifier {
   public:
    // Creates a new notifier that uses the agent which owns it to access the
    // real driver implementation.
    explicit FocusStateNotifier(PasswordAutofillAgent* agent);

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

    ~FocusStateNotifier();

    // Notifies the driver about focusing the node.
    void FocusedElementChanged(const blink::WebElement& element);

    // Notifies the password manager driver about removing the focus from the
    // currently focused node (with no setting it to a new one).
    void ResetFocus();

    mojom::FocusedFieldType GetFieldType(
        const blink::WebFormControlElement& node);
    void NotifyIfChanged(mojom::FocusedFieldType new_focused_field_type,
                         FieldRendererId new_focused_field_id);
    std::pair<mojom::FocusedFieldType, FieldRendererId> GetFocusedFieldInfo(
        const blink::WebElement& element);

    FieldRendererId focused_field_id_;
    mojom::FocusedFieldType focused_field_type_ =
        mojom::FocusedFieldType::kUnknown;
    const raw_ref<PasswordAutofillAgent> agent_;
  };

  // Various ways of how user can modify the field value.
  enum class FieldModificationType {
    // The field was typed in.
    kManualTyping = 0,
    // The field was filled by Chrome on explicit user trigger.
    kFillingOnUserTrigger = 1,
  };

  struct PasswordInfo {
    FieldRendererId password_field_id;
    PasswordFormFillData fill_data;
    // The user accepted a suggestion from a dropdown on a password field.
    bool password_field_suggestion_was_accepted = false;
  };

  // Stores information about form field structure.
  struct FormFieldInfo {
    FieldRendererId renderer_id;
    FormControlType form_control_type;
    std::string autocomplete_attribute;
    bool is_focusable = false;
  };

  // Stores information about form structure.
  struct FormStructureInfo {
    FormStructureInfo();
    FormStructureInfo(const FormStructureInfo& other);
    FormStructureInfo& operator=(const FormStructureInfo& other);
    FormStructureInfo(FormStructureInfo&& other);
    FormStructureInfo& operator=(FormStructureInfo&& other);
    ~FormStructureInfo();

    FormRendererId renderer_id;
    std::vector<FormFieldInfo> fields;
  };

  // Stores information about fields previewed by this agent.
  struct PreviewInfo {
    FieldRendererId field_id;
    blink::WebAutofillState autofill_state =
        blink::WebAutofillState::kNotFilled;
    bool is_password = false;
  };

  // This class keeps track of autofilled username and password input elements
  // and ensures that the autofilled values are not accessible to JavaScript
  // code until the user interacts with the page. This restriction improves
  // privacy (crbug.com/798492) and reduces attack surface (crbug.com/777272).
  class PasswordValueGatekeeper {
   public:
    PasswordValueGatekeeper();

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

    ~PasswordValueGatekeeper();

    // Call this for every autofilled username and password field, so that
    // the gatekeeper protects the value accordingly.
    void RegisterElement(blink::WebInputElement element);

    // Call this to notify the gatekeeper that the user interacted with the
    // page.
    void OnUserGesture();

    // Call this to reset the gatekeeper on a new page navigation.
    void Reset();

   private:
    // Make the value of `element` accessible to JavaScript code.
    void ShowValue(blink::WebInputElement element);

    bool was_user_gesture_seen_;
    std::vector<FieldRendererId> element_ids_;
  };

  // The RenderFrame* is nullptr while the PasswordAutofillAgent is pending
  // deletion, between AutofillAgent::OnDestruct() and ~PasswordAutofillAgent().
  content::RenderFrame* unsafe_render_frame() const {
    return content::RenderFrameObserver::render_frame();
  }

  // Use unsafe_render_frame() instead.
  template <typename T = int>
  content::RenderFrame* render_frame(T* = 0) const {
    static_assert(
        std::is_void_v<T>,
        "Beware that the RenderFrame may become nullptr by OnDestruct() "
        "because the owner of PasswordAutofillAgent destructs itself "
        "asynchronously. Use unsafe_render_frame() instead and test that it is "
        "non-nullptr.");
  }

  void OnFormSubmitted(const FormData& submitted_form);

  // Annotate `forms` and all fields in the current frame with form and field
  // signatures as HTML attributes. Used by
  // chrome://flags/#enable-show-autofill-signatures only.
  void AnnotateFormsAndFieldsWithSignatures(
      std::vector<blink::WebFormElement>& forms,
      const SynchronousFormCache& form_cache);

  // Scans the given frame for password forms and sends them up to the browser.
  // If `only_visible` is true, only forms visible in the layout are sent.
  // `form_cache` can be used to optimize form extractions occurring
  // synchronously after this function call.
  void SendPasswordForms(bool only_visible,
                         const SynchronousFormCache& form_cache);

  // Provides a request to show a pop-up suggesting which credentials could
  // be filled. If the username exists, it should be passed as `user_input`. If
  // there is no username, pass the password field in `user_input`. `form_cache`
  // can be used to optimize form extractions occurring synchronously after this
  // function call.
  std::optional<PasswordSuggestionRequest> CreateSuggestionRequest(
      const std::u16string& typed_username,
      const blink::WebInputElement& user_input,
      AutofillSuggestionTriggerSource trigger_source,
      const SynchronousFormCache& form_cache);

  // Finds the PasswordInfo, username and password fields corresponding to the
  // passed in `element`, which can refer to either a username or a password
  // element. If a PasswordInfo was found, returns `true` and assigns the
  // corresponding username, password elements and PasswordInfo into
  // `username_element`, `password_element` and `pasword_info`, respectively.
  // Note, that `username_element->IsNull()` can be true if `element` is a
  // password. Callers have the chance to restrict the usage of fallback data
  // by setting `use_fallback_data` to false. In that case data provided via
  // MaybeStoreFallbackData will be ignored and the function returns early.
  bool FindPasswordInfoForElement(const blink::WebInputElement& element,
                                  UseFallbackData use_fallback_data,
                                  blink::WebInputElement* username_element,
                                  blink::WebInputElement* password_element,
                                  PasswordInfo** password_info);

  // Returns true if at least one of the found username or password field is
  // fillable.
  bool IsUsernameOrPasswordFillable(
      const blink::WebInputElement& username_element,
      const blink::WebInputElement& password_element,
      PasswordInfo* password_info);

  // Finds the PasswordInfo, username and password fields corresponding to the
  // passed in `element` and returns true if there is at least one field that
  // can be filled by a password suggestion.
  bool HasElementsToFill(const blink::WebInputElement& trigger_element,
                         UseFallbackData use_fallback_data,
                         blink::WebInputElement* username_element,
                         blink::WebInputElement* password_element,
                         PasswordInfo** password_info);

  // Cleans up the state when document is shut down, e.g. when committing a new
  // document or closing the frame.
  void CleanupOnDocumentShutdown();

  // Sets suggested value of the `input` to `credential`. Persists the
  // information about `input` to clear the previewed value in the future.
  void DoPreviewField(blink::WebInputElement input,
                      const std::u16string& credential,
                      bool is_password);

  // Checks that a given input field is valid before filling the given `input`
  // with the given `credential` and marking the field as auto-filled.
  // `field_properties` will be set for a filled field.
  void DoFillField(blink::WebInputElement input,
                   const std::u16string& credential,
                   FieldPropertiesMask field_properties);

  // Given `username_element` and `password_element`, previews `username` and
  // `password` respectively into them.
  void PreviewUsernameAndPasswordElements(
      blink::WebInputElement username_element,
      blink::WebInputElement password_element,
      const std::u16string& username,
      const std::u16string& password);

  // Given `username_element` and `password_element`, fills `username` and
  // `password` respectively into them.
  // Uses `suggestion_source` to update the `FieldPropertiesMask` of filled
  // fields.
  // Returns whether the fields were filled with the requested values
  // successfully.
  bool FillUsernameAndPasswordElements(
      blink::WebInputElement username_element,
      blink::WebInputElement password_element,
      const std::u16string& username,
      const std::u16string& password,
      AutofillSuggestionTriggerSource suggestion_source);

  // Uses `FillField` to fill the given `credential` into the `password_input`.
  // Saves the password for its associated form.
  // Uses `suggestion_source` to update the `FieldPropertiesMask` of filled
  // fields.
  void FillPasswordFieldAndSave(
      blink::WebInputElement password_input,
      const std::u16string& credential,
      AutofillSuggestionTriggerSource suggestion_source);

  // This function attempts to fill `username_element` and `password_element`
  // with values from `fill_data` when the page is loaded. The
  // `username_element` and `password_element` will only have the suggestedValue
  // set. Returns true if filling was successful.
  bool FillCredentialsAutomatically(blink::WebInputElement username_element,
                                    blink::WebInputElement password_element,
                                    const PasswordFormFillData& fill_data,
                                    RendererSavePasswordProgressLogger* logger);

  void HidePopup();

  // Returns pair(username_element, password_element) based on renderer ids from
  // `username_field` and `password_field` from `form_data`.
  std::pair<blink::WebInputElement, blink::WebInputElement>
  FindUsernamePasswordElements(const PasswordFormFillData& form_data);

  // Populates `web_input_to_password_info_` and `password_to_username_` in
  // order to provide fill on account select on `username_element` and
  // `password_element` with credentials from `form_data`.
  void StoreDataForFillOnAccountSelect(const PasswordFormFillData& form_data,
                                       blink::WebInputElement username_element,
                                       blink::WebInputElement password_element);

  // In case when `web_input_to_password_info_` is empty (i.e. no fill on
  // account select data yet) this function populates
  // `web_input_to_password_info_` in order to provide fill on account select on
  // any password field (aka filling fallback) with credentials from
  // `form_data`.
  void MaybeStoreFallbackData(const PasswordFormFillData& form_data);

  // Records whether filling succeeded for the first attempt to fill on a site.
  // The logging is a bit conservative: It is possible that user-perceived
  // navigations (via dynamic HTML sites) not trigger any actual navigations
  // and therefore, the `recorded_first_filling_result_` never gets reset.
  void LogFirstFillingResult(const PasswordFormFillData& form_data,
                             FillingResult result);

  // Extracts information about form structure.
  static FormStructureInfo ExtractFormStructureInfo(const FormData& form_data);
  // Checks whether the form structure (amount of elements, element types etc)
  // was changed.
  bool WasFormStructureChanged(const FormStructureInfo& form_data) const;
  // Tries to restore `control_elements` values with cached values.
  void TryFixAutofilledForm(
      std::vector<blink::WebFormControlElement>& control_elements) const;

  // Fills `field` with `value` and updates `gatekeeper_` after the form is
  // loaded and parsed, automatically (=without explicit user action).
  // `field_data_manager_`, `autofilled_elements_cache_`. `field` should be
  // non-null.
  void FillFieldAutomatically(const std::u16string& value,
                              blink::WebInputElement field);

  void SetLastUpdatedFormAndField(const blink::WebFormElement& form,
                                  const blink::WebFormControlElement& input);

  bool CanShowPopupWithoutPasswords(
      const blink::WebInputElement& password_element) const;

  // Returns true if the element is of type 'password' and has either user typed
  // input or input autofilled on user trigger.
  bool IsPasswordFieldFilledByUser(
      const blink::WebFormControlElement& element) const;

  // Extracts and sends the form data of `cleared_form` to PasswordManager.
  void NotifyPasswordManagerAboutClearedForm(
      const blink::WebFormElement& cleared_form);

  // Notifies the PasswordManager about a field modification.
  void NotifyPasswordManagerAboutUserFieldModification(
      const blink::WebInputElement& element,
      FieldModificationType modification_type);

  // Shows suggestions on the focused element if it was focused before the form
  // was processed by the password manager.
  void MaybeTriggerSuggestionsOnFocusedElement(
      const blink::WebInputElement& username_element,
      const blink::WebInputElement& password_element);

  FieldDataManager& field_data_manager() const {
    return autofill_agent_->field_data_manager();
  }

  // A map from WebInput elements to `PasswordInfo` for all elements that
  // password manager has fill information for.
  //
  // After any mutation, `last_supplied_password_info_iter_` must be updated.
  std::map<FieldRendererId, PasswordInfo> web_input_to_password_info_;

  // A (sort-of) reverse map to `web_input_to_password_info_`.
  std::map<FieldRendererId, FieldRendererId> password_to_username_;

  // The chronologically last insertion into `web_input_to_password_info_`.
  // This iterator always points to `web_input_to_password_info_`.
  std::map<FieldRendererId, PasswordInfo>::iterator
      last_supplied_password_info_iter_ = web_input_to_password_info_.end();

  // Set of fields that are reliably identified as non-credential fields.
  base::flat_set<FieldRendererId> suggestion_banned_fields_;

#if BUILDFLAG(ENABLE_DICE_SUPPORT)
  // The Password Manager normally shows passwords if there are passwords to
  // fill, there are cases, when PWM might show other suggestions (e.g. promos)
  // on password fields.
  bool should_show_popup_without_passwords_ = false;
#endif

  PasswordValueGatekeeper gatekeeper_;

  // True indicates that user debug information should be logged.
  bool logging_state_active_ = false;

  std::vector<PreviewInfo> previewed_elements_;

  // True indicates that a request for credentials has been sent to the store.
  bool sent_request_to_store_ = false;

  // True indicates that a safe browsing reputation check has been triggered.
  bool checked_safe_browsing_reputation_ = false;

  raw_ptr<AutofillAgent> autofill_agent_ = nullptr;

  raw_ptr<PasswordGenerationAgent> password_generation_agent_ = nullptr;

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
  PagePasswordsAnalyser page_passwords_analyser_;
#endif

  mojo::AssociatedRemote<mojom::PasswordManagerDriver> password_manager_driver_;

  // Used for deferring messages while prerendering.
  std::unique_ptr<DeferringPasswordManagerDriver>
      deferring_password_manager_driver_;

  mojo::AssociatedReceiver<mojom::PasswordAutofillAgent> receiver_{this};

  // Keeps autofilled values for the form elements until a user gesture
  // is observed. At that point, the map is cleared.
  std::map<FieldRendererId, blink::WebString> autofilled_elements_cache_;
  base::flat_set<FieldRendererId> all_autofilled_elements_;
  // Keeps forms structure (amount of elements, element types etc).
  // TODO(crbug.com/41422255): It's too expensive to keep the whole FormData
  // structure. Replace FormData with a smaller structure.
  std::map<FormRendererId, FormStructureInfo> forms_structure_cache_;

  // The HTML based username detector's cache which maps form elements to
  // username predictions.
  UsernameDetectorCache username_detector_cache_;

  // Flag to prevent that multiple PasswordManager.FirstRendererFillingResult
  // UMA metrics are recorded per page load. This is reset on
  // DidCommitProvisionalLoad() but only for non-same-document-navigations.
  bool recorded_first_filling_result_ = false;

  // Contains render id of the field where a form submission should be
  // triggered.
  FieldRendererId field_renderer_id_to_submit_;

  // Tracks how many times PasswordFormFillData was received from the browser
  // for every form.
  // Can be used to estimate how many times forms are actually reparsed
  // during their lifetime.
  std::map<FormRendererId, size_t> times_received_fill_data_;

  // This notifier is used to avoid sending redundant messages to the password
  // manager driver mojo interface.
  FocusStateNotifier focus_state_notifier_{this};
};

}  // namespace autofill

#endif  // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_AUTOFILL_AGENT_H_
