chromium/components/autofill/content/renderer/password_autofill_agent.cc

// 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.

#include "components/autofill/content/renderer/password_autofill_agent.h"

#include <stddef.h>

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

#include "base/check.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/i18n/case_conversion.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/content/renderer/password_generation_agent.h"
#include "components/autofill/content/renderer/prefilled_values_detector.h"
#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
#include "components/autofill/content/renderer/suggestion_properties.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.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/signatures.h"
#include "components/password_manager/core/common/password_manager_constants.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_util.h"
#include "components/safe_browsing/buildflags.h"
#include "content/public/renderer/render_frame.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_form_element.h"
#include "third_party/blink/public/web/web_input_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_view.h"
#include "ui/base/page_transition_types.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "url/gurl.h"

WebAutofillState;
WebDocument;
WebDocumentLoader;
WebElement;
WebElementCollection;
WebFormControlElement;
WebFormElement;
WebFrame;
WebInputElement;
WebLocalFrame;
WebNode;
WebSecurityOrigin;
WebString;
WebURL;
WebVector;
WebView;

IsRendererRecognizedCredentialForm;

namespace autofill {

namespace {

ExtractOption;
GetFieldRendererId;
GetFormByRendererId;
GetFormControlByRendererId;
GetFormRendererId;
IsElementEditable;
IsWebElementFocusableForAutofill;

SubmissionIndicatorEvent;
SubmissionSource;

constexpr auto kInputPassword =;

// The size above which we stop triggering autocomplete.
const size_t kMaximumTextSizeForAutocomplete =;

// Names of HTML attributes to show form and field signatures for debugging.
const char kDebugAttributeForFormSignature[] =;
const char kDebugAttributeForAlternativeFormSignature[] =;
const char kDebugAttributeForFieldSignature[] =;
const char kDebugAttributeForParserAnnotations[] =;
const char kDebugAttributeForVisibility[] =;
// Name of HTML attribute that stores the copy of autofill tooltip for
// debugging.
constexpr char kDebugAttributeForAutofill[] =;

// HTML attribute that is used as a tooltip if
// `kAutofillShowTypePredictions` is on.
constexpr char kHtmlAttributeForAutofillTooltip[] =;

// Maps element names to the actual elements to simplify form filling.
FormInputElementMap;

// Use the shorter name when referencing SavePasswordProgressLogger::StringID
// values to spare line breaks. The code provides enough context for that
// already.
Logger;

FormElementsList;

bool DoUsernamesMatch(const std::u16string& potential_suggestion,
                      const std::u16string& current_username,
                      bool exact_match) {}

// Returns whether the `username_element` is allowed to be autofilled.
//
// Note that if the user interacts with the `password_field` and the
// `username_element` is user-defined (i.e., non-empty and non-autofilled), then
// this function returns false. This is a precaution, to not override the field
// if it has been classified as username by accident.
bool IsUsernameAmendable(const WebInputElement& username_element,
                         bool is_password_field_selected) {}

// Log `message` if `logger` is not null.
void LogMessage(Logger* logger, Logger::StringID message) {}

// Log `message` and `value` if `logger` is not null.
void LogBoolean(Logger* logger, Logger::StringID message, bool value) {}

// Log a message including the name, method and action of |form|.
void LogHTMLForm(Logger* logger,
                 Logger::StringID message_id,
                 const WebFormElement& form) {}

// Returns true if there are any suggestions to be derived from `fill_data`.
// Only considers suggestions with usernames having `typed_username` as prefix.
bool CanShowUsernameSuggestion(const PasswordFormFillData& fill_data,
                               const std::u16string& typed_username) {}

// This function attempts to find the matching credentials for the
// `current_username` by scanning `fill_data`. The result is written in
// `username` and `password` parameters.
void FindMatchesByUsername(const PasswordFormFillData& fill_data,
                           const std::u16string& current_username,
                           bool exact_username_match,
                           RendererSavePasswordProgressLogger* logger,
                           std::u16string* username,
                           std::u16string* password) {}

// TODO(crbug.com/40447274): This duplicates code from
// components/password_manager/core/browser/password_store/psl_matching_helper.h.
// The logic using this code should ultimately end up in
// components/password_manager/core/browser, at which point it can use the
// original code directly.
std::string GetRegistryControlledDomain(const GURL& signon_realm) {}

// TODO(crbug.com/40447274): This duplicates code from
// components/password_manager/core/browser/password_store/psl_matching_helper.h.
// The logic using this code should ultimately end up in
// components/password_manager/core/browser, at which point it can use the
// original code directly.
bool IsPublicSuffixDomainMatch(const std::string& url1,
                               const std::string& url2) {}

// Helper function that calculates form signature for `form_data` and returns it
// as a string.
std::string GetFormSignatureAsString(const FormData& form_data) {}
// Similar to `GetFormSignatureAsString` but returns alternative form signature
// as a string.
std::string GetAlternativeFormSignatureAsString(const FormData& form_data) {}

// Sets the specified attribute of `target` to the given value. This must not
// happen while ScriptForbiddenScope is active (e.g. during
// blink::FrameLoader::FinishedParsing(), see crbug.com/1219852). Therefore,
// this function should be called asynchronously via SetAttributeAsync.
void SetAttributeInternal(WebElement target,
                          const std::string& attribute_utf8,
                          const std::string& value_utf8) {}

// Posts an async task to call SetAttributeInternal.
void SetAttributeAsync(WebElement target,
                       const std::string& attribute_utf8,
                       const std::string& value_utf8) {}

// Annotate `fields` with field signatures, form signature and visibility state
// as HTML attributes.
void AnnotateFieldsWithSignatures(
    base::span<const WebFormControlElement> fields,
    const std::string& form_signature,
    const std::string& alternative_form_signature) {}

// Returns true iff there is a password field in `frame`.
// We don't have to iterate through the whole DOM to find password fields.
// Instead, we can iterate through the fields of the forms and the unowned
// fields, both of which are cached in the Document.
bool HasPasswordField(const WebLocalFrame& frame) {}

// Returns the closest visible autocompletable non-password text element
// preceding the `password_element` either in a form, if it belongs to one, or
// in the `frame`.
WebInputElement FindUsernameElementPrecedingPasswordElement(
    WebLocalFrame* frame,
    const WebInputElement& password_element) {}

// Returns true if `element`'s frame origin is not PSL matched with the origin
// of any parent frame.
bool IsInCrossOriginIframeOrEmbeddedFrame(const WebInputElement& element) {}

void AnnotateFieldWithParsingResult(
    FieldRendererId renderer_id,
    const std::string& password_managers_annotation) {}

bool HasDocumentWithValidFrame(const WebInputElement& element) {}

// This method tries to fix `fields` with empty typed or filled properties by
// matching them against previously filled or typed in fields with the same
// value and copying their filled or typed mask.
//
// This helps against websites where submitted fields differ from fields that
// had previously been autofilled or typed into.
[[nodiscard]] std::vector<FormFieldData> FillNonTypedOrFilledPropertiesMasks(
    std::vector<FormFieldData> fields,
    const FieldDataManager& manager) {}

size_t GetIndexOfElement(const FormData& form_data,
                         const WebInputElement& element) {}

bool HasTextInputs(const FormData& form_data) {}

#if BUILDFLAG(IS_ANDROID)
bool IsWebAuthnForm(base::optional_ref<const FormData> form_data) {
  auto has_webauthn_attribute = [](const FormFieldData& field) {
    return field.parsed_autocomplete() && field.parsed_autocomplete()->webauthn;
  };
  return form_data &&
         base::ranges::any_of(form_data->fields(), has_webauthn_attribute);
}

// Returns a prediction whether the form that contains `username_element` and
// `password_element` will be ready for submission after filling these two
// elements.
// TODO(crbug.com/40248146): Consider to reduce `SubmissionReadinessState` to a
// boolean value (ready or not). The non-binary state is not needed for
// auto-submission (crbug.com/1283004), but showing TTF proactively
// (crbug.com/1393043) may need to check whether or not a given form comprises
// only two fields.
mojom::SubmissionReadinessState CalculateSubmissionReadiness(
    const FormData& form_data,
    const WebInputElement& username_element,
    WebInputElement password_element) {
  if (!password_element) {
    return mojom::SubmissionReadinessState::kNoPasswordField;
  }

  if (!username_element) {
    return mojom::SubmissionReadinessState::kNoUsernameField;
  }

  size_t username_index = GetIndexOfElement(form_data, username_element);
  size_t password_index = GetIndexOfElement(form_data, password_element);
  size_t number_of_elements = form_data.fields().size();
  if (username_index == number_of_elements ||
      password_index == number_of_elements) {
    // This is unexpected. `form_data` is supposed to contain username and
    // password elements.
    return mojom::SubmissionReadinessState::kError;
  }

  auto ShouldIgnoreField = [](const FormFieldData& field) {
    if (!field.IsFocusable())
      return true;
    // Don't treat a checkbox (e.g. "remember me") as an input field that may
    // block a form submission. Note: Don't use `check_status !=
    // kNotCheckable`, a radio button is considered a "checkable" element too,
    // but it should block a submission.
    return field.form_control_type() == mojom::FormControlType::kInputCheckbox;
  };

  for (size_t i = username_index + 1; i < password_index; ++i) {
    if (ShouldIgnoreField(form_data.fields()[i])) {
      continue;
    }
    return mojom::SubmissionReadinessState::kFieldBetweenUsernameAndPassword;
  }

  if (!password_element.IsLastInputElementInForm())
    return mojom::SubmissionReadinessState::kFieldAfterPasswordField;

  size_t number_of_visible_elements = 0;
  for (size_t i = 0; i < number_of_elements; ++i) {
    if (ShouldIgnoreField(form_data.fields()[i])) {
      continue;
    }

    if (username_index != i && password_index != i &&
        form_data.fields()[i].value().empty()) {
      return mojom::SubmissionReadinessState::kEmptyFields;
    }
    number_of_visible_elements++;
  }

  if (number_of_visible_elements > 2)
    return mojom::SubmissionReadinessState::kMoreThanTwoFields;

  return mojom::SubmissionReadinessState::kTwoFields;
}
#endif  // BUILDFLAG(IS_ANDROID)

}  // namespace

// During prerendering, we do not want the renderer to send messages to the
// corresponding driver. Since we use a channel associated interface, we still
// need to set up the mojo connection as before (i.e., we can't defer binding
// the interface). Instead, we enqueue our messages here as post-activation
// tasks. See post-prerendering activation steps here:
// https://wicg.github.io/nav-speculation/prerendering.html#prerendering-bcs-subsection
class PasswordAutofillAgent::DeferringPasswordManagerDriver
    : public mojom::PasswordManagerDriver {};

////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillAgent, public:

PasswordAutofillAgent::PasswordAutofillAgent(
    content::RenderFrame* render_frame,
    blink::AssociatedInterfaceRegistry* registry,
    EnableHeavyFormDataScraping enable_heavy_form_data_scraping)
    :{}

PasswordAutofillAgent::~PasswordAutofillAgent() = default;

void PasswordAutofillAgent::Init(AutofillAgent* autofill_agent) {}

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

void PasswordAutofillAgent::SetPasswordGenerationAgent(
    PasswordGenerationAgent* generation_agent) {}

PasswordAutofillAgent::FormStructureInfo::FormStructureInfo() = default;

PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
    const FormStructureInfo& other) = default;

PasswordAutofillAgent::FormStructureInfo&
PasswordAutofillAgent::FormStructureInfo::operator=(
    const PasswordAutofillAgent::FormStructureInfo& other) = default;

PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
    FormStructureInfo&& other) = default;

PasswordAutofillAgent::FormStructureInfo&
PasswordAutofillAgent::FormStructureInfo::operator=(
    PasswordAutofillAgent::FormStructureInfo&& other) = default;

PasswordAutofillAgent::FormStructureInfo::~FormStructureInfo() = default;

PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
    :{}

PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() =
    default;

void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement(
    WebInputElement element) {}

void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {}

void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {}

void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
    WebInputElement element) {}

bool PasswordAutofillAgent::TextDidChangeInTextField(
    const WebInputElement& element) {}

// LINT.IfChange

void PasswordAutofillAgent::NotifyPasswordManagerAboutFieldModification(
    const WebInputElement& element) {}

void PasswordAutofillAgent::UpdatePasswordStateForTextChange(
    const WebInputElement& element) {}

// LINT.ThenChange(//components/password_manager/core/browser/password_manager.cc:update_password_state_for_text_change)

void PasswordAutofillAgent::TrackAutofilledElement(
    const WebFormControlElement& element) {}

void PasswordAutofillAgent::FillPasswordSuggestion(
    const std::u16string& username,
    const std::u16string& password) {}

void PasswordAutofillAgent::FillIntoFocusedField(
    bool is_password,
    const std::u16string& credential) {}

void PasswordAutofillAgent::PreviewField(FieldRendererId field_id,
                                         const std::u16string& value) {}

void PasswordAutofillAgent::FillField(FieldRendererId field_id,
                                      const std::u16string& value) {}

void PasswordAutofillAgent::DoPreviewField(WebInputElement input,
                                           const std::u16string& credential,
                                           bool is_password) {}

void PasswordAutofillAgent::DoFillField(WebInputElement input,
                                        const std::u16string& credential) {}

void PasswordAutofillAgent::FillPasswordFieldAndSave(
    WebInputElement password_input,
    const std::u16string& credential) {}

void PasswordAutofillAgent::PreviewSuggestion(
    const WebFormControlElement& control_element,
    const std::u16string& username,
    const std::u16string& password) {}

void PasswordAutofillAgent::ClearPreviewedForm() {}

bool PasswordAutofillAgent::FindPasswordInfoForElement(
    const WebInputElement& element,
    UseFallbackData use_fallback_data,
    WebInputElement* username_element,
    WebInputElement* password_element,
    PasswordInfo** password_info) {}

bool PasswordAutofillAgent::IsUsernameOrPasswordFillable(
    const WebInputElement& username_element,
    const WebInputElement& password_element,
    PasswordInfo* password_info) {}

bool PasswordAutofillAgent::HasElementsToFill(
    const WebInputElement& trigger_element,
    UseFallbackData use_fallback_data,
    WebInputElement* username_element,
    WebInputElement* password_element,
    PasswordInfo** password_info) {}

void PasswordAutofillAgent::MaybeCheckSafeBrowsingReputation(
    const WebInputElement& element) {}

#if BUILDFLAG(IS_ANDROID)
bool PasswordAutofillAgent::ShouldSuppressKeyboard() {
  // The keyboard should be suppressed if a keyboard replacing surface is
  // displayed (e.g. TouchToFill).
  return keyboard_replacing_surface_state_ ==
         KeyboardReplacingSurfaceState::kIsShowing;
}

bool PasswordAutofillAgent::TryToShowKeyboardReplacingSurface(
    const WebFormControlElement& control_element) {
  if (keyboard_replacing_surface_state_ !=
      KeyboardReplacingSurfaceState::kShouldShow) {
    return false;
  }

  const WebInputElement input_element =
      control_element.DynamicTo<WebInputElement>();
  WebInputElement username_element;
  WebInputElement password_element;
  PasswordInfo* password_info = nullptr;
  if (!input_element || !IsElementEditable(input_element) ||
      !FindPasswordInfoForElement(input_element, UseFallbackData(false),
                                  &username_element, &password_element,
                                  &password_info)) {
    return false;
  }

  bool has_amendable_username_element = IsUsernameAmendable(
      username_element,
      input_element.FormControlTypeForAutofill() == kInputPassword);
  bool has_editable_password_element =
      password_element && IsElementEditable(password_element);
  CHECK(has_amendable_username_element || has_editable_password_element);

  WebFormElement form = password_element
                            ? form_util::GetOwningForm(password_element)
                            : form_util::GetOwningForm(username_element);
  std::optional<FormData> form_data =
      form ? GetFormDataFromWebForm(form)
           : GetFormDataFromUnownedInputElements();

  GetPasswordManagerDriver().ShowKeyboardReplacingSurface(
      form_data ? CalculateSubmissionReadiness(*form_data, username_element,
                                               password_element)
                : mojom::SubmissionReadinessState::kNoInformation,
      IsWebAuthnForm(form_data));

  keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kIsShowing;
  return true;
}
#endif

bool PasswordAutofillAgent::ShowSuggestions(
    const WebInputElement& element,
    AutofillSuggestionTriggerSource trigger_source) {}

bool PasswordAutofillAgent::FrameCanAccessPasswordManager() {}

void PasswordAutofillAgent::OnDynamicFormsSeen() {}

void PasswordAutofillAgent::UserGestureObserved() {}

void PasswordAutofillAgent::AnnotateFormsAndFieldsWithSignatures(
    WebVector<WebFormElement>& forms) {}

void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {}

void PasswordAutofillAgent::DidDispatchDOMContentLoadedEvent() {}

void PasswordAutofillAgent::DidFinishLoad() {}

void PasswordAutofillAgent::DidCommitProvisionalLoad(
    ui::PageTransition transition) {}

void PasswordAutofillAgent::OnDestruct() {}

bool PasswordAutofillAgent::IsPrerendering() const {}

bool PasswordAutofillAgent::IsUsernameInputField(
    const WebInputElement& input_element) const {}

void PasswordAutofillAgent::ReadyToCommitNavigation(
    WebDocumentLoader* document_loader) {}

void PasswordAutofillAgent::OnProbablyFormSubmitted() {}

// mojom::PasswordAutofillAgent:
void PasswordAutofillAgent::SetPasswordFillData(
    const PasswordFormFillData& form_data) {}

void PasswordAutofillAgent::SetLoggingState(bool active) {}

void PasswordAutofillAgent::AnnotateFieldsWithParsingResult(
    const ParsingResult& parsing_result) {}

void PasswordAutofillAgent::InformNoSavedCredentials(
    bool should_show_popup_without_passwords) {}

#if BUILDFLAG(IS_ANDROID)
void PasswordAutofillAgent::KeyboardReplacingSurfaceClosed(
    bool show_virtual_keyboard) {
  keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kWasShown;

  auto focused_input_element = focused_element().DynamicTo<WebInputElement>();
  if (!focused_input_element || focused_element().IsReadOnly()) {
    return;
  }

  if (show_virtual_keyboard) {
    render_frame()->ShowVirtualKeyboard();

    // Since a keyboard replacing surface suppresses the Autofill popup,
    // re-trigger the suggestions in case the virtual keyboard should be shown.
    // This is limited to the keyboard accessory, as otherwise it would result
    // in a flickering of the popup, due to showing the keyboard at the same
    // time.
    ShowSuggestions(
        focused_input_element,
        autofill::AutofillSuggestionTriggerSource::kFormControlElementClicked);
  }
}

void PasswordAutofillAgent::TriggerFormSubmission() {
  // Find the last interacted element to simulate an enter keystroke at.
  WebFormControlElement form_control =
      GetFormControlByRendererId(field_renderer_id_to_submit_);
  if (!form_control) {
    // The target field doesn't exist anymore. Don't try to submit it.
    return;
  }

  // `form_control` can only be `WebInputElement`, not `WebSelectElement`.
  WebInputElement input = form_control.To<WebInputElement>();
  input.DispatchSimulatedEnter();
  field_renderer_id_to_submit_ = FieldRendererId();
}
#endif

std::optional<FormData> PasswordAutofillAgent::GetFormDataFromWebForm(
    const WebFormElement& web_form) {}

std::optional<FormData>
PasswordAutofillAgent::GetFormDataFromUnownedInputElements() {}

void PasswordAutofillAgent::InformAboutFormClearing(
    const WebFormElement& form) {}

void PasswordAutofillAgent::InformAboutFieldClearing(
    const WebInputElement& cleared_element) {}

////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillAgent, private:

bool PasswordAutofillAgent::ShowSuggestionsForDomain(
    const WebInputElement& element,
    AutofillSuggestionTriggerSource trigger_source) {}

bool PasswordAutofillAgent::ShowManualFallbackSuggestions(
    const WebInputElement& element) {}

void PasswordAutofillAgent::ShowSuggestionPopup(
    const std::u16string& typed_username,
    const WebInputElement& user_input,
    AutofillSuggestionTriggerSource trigger_source) {}

void PasswordAutofillAgent::CleanupOnDocumentShutdown() {}

void PasswordAutofillAgent::InformBrowserAboutUserInput(
    const WebFormElement& form,
    const WebInputElement& element) {}

bool PasswordAutofillAgent::FillUserNameAndPassword(
    WebInputElement username_element,
    WebInputElement password_element,
    const PasswordFormFillData& fill_data,
    RendererSavePasswordProgressLogger* logger) {}

void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
    PrefilledUsernameFillOutcome outcome) {}

void PasswordAutofillAgent::OnProvisionallySaveForm(
    const WebFormElement& form,
    const WebFormControlElement& element,
    SaveFormReason source) {}

void PasswordAutofillAgent::FireHostSubmitEvent(
    FormRendererId form_id,
    mojom::SubmissionSource source) {}

void PasswordAutofillAgent::OnFormSubmitted(const WebFormElement& form) {}

void PasswordAutofillAgent::OnInferredFormSubmission(SubmissionSource source) {}

void PasswordAutofillAgent::HidePopup() {}

mojom::PasswordManagerDriver&
PasswordAutofillAgent::GetPasswordManagerDriver() {}

std::pair<WebInputElement, WebInputElement>
PasswordAutofillAgent::FindUsernamePasswordElements(
    const PasswordFormFillData& form_data) {}

void PasswordAutofillAgent::StoreDataForFillOnAccountSelect(
    const PasswordFormFillData& form_data,
    WebInputElement username_element,
    WebInputElement password_element) {}

void PasswordAutofillAgent::MaybeStoreFallbackData(
    const PasswordFormFillData& form_data) {}

void PasswordAutofillAgent::LogFirstFillingResult(
    const PasswordFormFillData& form_data,
    FillingResult result) {}

PasswordAutofillAgent::FormStructureInfo
PasswordAutofillAgent::ExtractFormStructureInfo(const FormData& form_data) {}

bool PasswordAutofillAgent::WasFormStructureChanged(
    const FormStructureInfo& form_info) const {}

void PasswordAutofillAgent::TryFixAutofilledForm(
    std::vector<WebFormControlElement>& control_elements) const {}

void PasswordAutofillAgent::AutofillField(const std::u16string& value,
                                          WebInputElement field) {}

bool PasswordAutofillAgent::CanShowPopupWithoutPasswords(
    const WebInputElement& password_element) const {}

bool PasswordAutofillAgent::IsPasswordFieldFilledByUser(
    const WebFormControlElement& element) const {}

void PasswordAutofillAgent::NotifyPasswordManagerAboutClearedForm(
    const WebFormElement& cleared_form) {}

void PasswordAutofillAgent::MaybeTriggerSuggestionsOnFocusedElement(
    const WebInputElement& username_element,
    const WebInputElement& password_element) {}

}  // namespace autofill