910e62b5创建于 1月15日历史提交
// Copyright 2014 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_UI_AUTOFILL_CHROME_AUTOFILL_CLIENT_H_
#define CHROME_BROWSER_UI_AUTOFILL_CHROME_AUTOFILL_CLIENT_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/i18n/rtl.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autofill_suggestion_controller.h"
#include "chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h"
#include "components/autofill/content/browser/autofill_log_router_factory.h"
#include "components/autofill/content/browser/content_autofill_client.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_identity_credential_delegate.h"
#include "components/autofill/core/browser/country_type.h"
#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h"
#include "components/autofill/core/browser/crowdsourcing/votes_uploader.h"
#include "components/autofill/core/browser/data_model/autofill_ai/entity_type.h"
#include "components/autofill/core/browser/filling/filling_product.h"
#include "components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager.h"
#include "components/autofill/core/browser/integrators/identity_credential/identity_credential_delegate.h"
#include "components/autofill/core/browser/integrators/password_form_classification.h"
#include "components/autofill/core/browser/integrators/plus_addresses/autofill_plus_address_delegate.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/metrics/form_interactions_ukm_logger.h"
#include "components/autofill/core/browser/single_field_fillers/single_field_fill_router.h"
#include "components/autofill/core/browser/studies/autofill_ablation_study.h"
#include "components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "content/public/browser/visibility.h"
#include "content/public/browser/web_contents_observer.h"

#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/autofill/autofill_snackbar_controller_impl.h"
#include "components/autofill/core/browser/integrators/fast_checkout/fast_checkout_client.h"
#else  // BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/autofill/autofill_field_promo_controller.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace optimization_guide {
class RemoteModelExecutor;
}

namespace autofill {

#if BUILDFLAG(IS_ANDROID)
// TODO(crbug.com/364089352): When //c/b/ui/android/autofill gets modularized,
// //c/b/ui/autofill/ can depend directly on it. Now, forward declare the
// SaveUpdateAddressProfileFlowManager.
class SaveUpdateAddressProfileFlowManager;
#endif

class AutofillOptimizationGuideDecider;
class EmailVerifierDelegate;
class FormFieldData;
class OtpFieldDetector;
class ChromeOtpPhishGuardDelegate;
class LogRouter;
enum class SuggestionType;

// Chrome implementation of AutofillClient.
//
// ChromeAutofillClient is instantiated once per WebContents, and usages of
// main frame refer to the primary main frame because WebContents only has a
// primary main frame.
//
// Production code should not depend on ChromeAutofillClient but only on
// ContentAutofillClient. This ensures that tests can inject different
// implementations of ContentAutofillClient without causing invalid casts to
// ChromeAutofillClient.
//
// BEWARE OF SUBCLASSING in tests: virtual function calls during construction
// may lead to very surprising behavior. The class is not `final` because a few
// tests derive from it. Member functions should be final unless they need to be
// mocked or overridden in subclasses and you have verified that they are not
// called, directly or indirectly, from the constructor.
class ChromeAutofillClient : public ContentAutofillClient,
                             public content::WebContentsObserver {
 public:
  // Creates a new ChromeAutofillClient for the given `web_contents` if no
  // ContentAutofillClient is associated with the `web_contents` yet. Otherwise,
  // it's a no-op.
  static void CreateForWebContents(content::WebContents* web_contents);

  // Only tests that require ChromeAutofillClient's `*ForTesting()` functions
  // may use this function.
  //
  // Generally, code should use ContentAutofillClient::FromWebContents() if
  // possible. This is because many tests inject clients that do not inherit
  // from ChromeAutofillClient.
  static ChromeAutofillClient* FromWebContentsForTesting(
      content::WebContents* web_contents) {
    return static_cast<ChromeAutofillClient*>(FromWebContents(web_contents));
  }

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

  // AutofillClient:
  base::WeakPtr<AutofillClient> GetWeakPtr() final;
  const std::string& GetAppLocale() const final;
  version_info::Channel GetChannel() const final;
  bool IsOffTheRecord() const final;
  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() final;
  AutofillCrowdsourcingManager& GetCrowdsourcingManager() final;
  VotesUploader& GetVotesUploader() final;
  AutofillOptimizationGuideDecider* GetAutofillOptimizationGuideDecider()
      const final;
  FieldClassificationModelHandler* GetAutofillFieldClassificationModelHandler()
      final;
  FieldClassificationModelHandler*
  GetPasswordManagerFieldClassificationModelHandler() final;
  PersonalDataManager& GetPersonalDataManager() final;
  ValuablesDataManager* GetValuablesDataManager() final;
  EntityDataManager* GetEntityDataManager() final;
  SingleFieldFillRouter& GetSingleFieldFillRouter() final;
  AutocompleteHistoryManager* GetAutocompleteHistoryManager() final;
  AutofillComposeDelegate* GetComposeDelegate() final;
  AutofillPlusAddressDelegate* GetPlusAddressDelegate() final;
  PasswordManagerDelegate* GetPasswordManagerDelegate(
      const FieldGlobalId& field_id) final;
  void GetAiPageContent(GetAiPageContentCallback callback) final;
  AutofillAiManager* GetAutofillAiManager() final;
  AutofillAiModelCache* GetAutofillAiModelCache() final;
  AutofillAiModelExecutor* GetAutofillAiModelExecutor() final;
  optimization_guide::RemoteModelExecutor* GetRemoteModelExecutor() final;
  IdentityCredentialDelegate* GetIdentityCredentialDelegate() final;
  PrefService* GetPrefs() final;
  const PrefService* GetPrefs() const final;
  syncer::SyncService* GetSyncService() final;
  signin::IdentityManager* GetIdentityManager() final;
  const signin::IdentityManager* GetIdentityManager() const final;
  const GoogleGroupsManager* GetGoogleGroupsManager() const final;
  FormDataImporter* GetFormDataImporter() final;
  payments::ChromePaymentsAutofillClient* GetPaymentsAutofillClient() final;
  strike_database::StrikeDatabase* GetStrikeDatabase() final;
  ukm::UkmRecorder* GetUkmRecorder() final;
  AddressNormalizer* GetAddressNormalizer() final;
  const GURL& GetLastCommittedPrimaryMainFrameURL() const final;
  url::Origin GetLastCommittedPrimaryMainFrameOrigin() const final;
  security_state::SecurityLevel GetSecurityLevelForUmaHistograms() final;
  const translate::LanguageState* GetLanguageState() final;
  translate::TranslateDriver* GetTranslateDriver() final;
  GeoIpCountryCode GetVariationConfigCountryCode() const final;
  profile_metrics::BrowserProfileType GetProfileType() const final;
  FastCheckoutClient* GetFastCheckoutClient() final;
  void ShowAutofillSettings(SuggestionType suggestion_type) final;
  void ConfirmSaveAddressProfile(
      const AutofillProfile& profile,
      const AutofillProfile* original_profile,
      SaveAddressBubbleType save_address_bubble_type,
      AddressProfileSavePromptCallback callback) final;
  // Not called during construction -- safe to override in tests.
  SuggestionUiSessionId ShowAutofillSuggestions(
      const PopupOpenArgs& open_args,
      base::WeakPtr<AutofillSuggestionDelegate> delegate) override;
  void ShowPlusAddressEmailOverrideNotification(
      const std::string& original_email,
      EmailOverrideUndoCallback email_final) final;
  void UpdateAutofillDataListValues(
      base::span<const SelectOption> datalist) final;
  base::span<const Suggestion> GetAutofillSuggestions() const final;
  std::optional<PopupScreenLocation> GetPopupScreenLocation() const final;
  std::optional<SuggestionUiSessionId>
  GetSessionIdForCurrentAutofillSuggestions() const final;
  void UpdateAutofillSuggestions(
      const std::vector<Suggestion>& suggestions,
      FillingProduct main_filling_product,
      AutofillSuggestionTriggerSource trigger_source) final;
  void HideAutofillSuggestions(SuggestionHidingReason reason) final;
  void TriggerUserPerceptionOfAutofillSurvey(
      FillingProduct filling_product,
      const std::map<std::string, std::string>& field_filling_stats_data) final;
  void TriggerDeclinedSaveAddressReasonSurvey() final;
  void TriggerAutofillAiFillingJourneySurvey(
      bool suggestion_accepted,
      EntityType entity_type,
      const base::flat_set<EntityTypeName>& saved_entities,
      const FieldTypeSet& triggering_field_types) final;
  void TriggerAutofillAiSavePromptSurvey(
      bool prompt_accepted,
      EntityType entity_type,
      const base::flat_set<EntityTypeName>& saved_entities) final;
  bool IsActorTaskActive() const final;
  bool IsAutofillEnabled() const final;
  bool IsAutofillProfileEnabled() const final;
  bool IsAutocompleteEnabled() const final;
  bool IsWalletStorageEnabled() const final;
  bool IsPasswordManagerEnabled() const final;
  void DidFillForm(AutofillTriggerSource trigger_source, bool is_refill) final;
  bool IsContextSecure() const final;
  LogManager* GetCurrentLogManager() final;
  autofill_metrics::FormInteractionsUkmLogger& GetFormInteractionsUkmLogger()
      final;

  const AutofillAblationStudy& GetAblationStudy() const final;
#if BUILDFLAG(IS_ANDROID)
  // The AutofillSnackbarController is used to show a snackbar notification
  // on Android.
  AutofillSnackbarControllerImpl* GetAutofillSnackbarController() final;
#endif
  FormInteractionsFlowId GetCurrentFormInteractionsFlowId() final;
  std::unique_ptr<device_reauth::DeviceAuthenticator> GetDeviceAuthenticator()
      final;
  bool ShowAutofillFieldIphForFeature(const FormFieldData& field,
                                      AutofillClient::IphFeature feature) final;
  void HideAutofillFieldIph() final;
  void NotifyIphFeatureUsed(AutofillClient::IphFeature feature) final;
  void set_test_addresses(std::vector<AutofillProfile> test_addresses) final;
  base::span<const AutofillProfile> GetTestAddresses() const final;
  PasswordFormClassification ClassifyAsPasswordForm(
      AutofillManager& manager,
      FormGlobalId form_id,
      FieldGlobalId field_id) const final;
  void TriggerPlusAddressUserPerceptionSurvey(
      plus_addresses::hats::SurveyType survey_type) final;
  optimization_guide::ModelQualityLogsUploaderService* GetMqlsUploadService()
      override;
  void ShowEntityImportBubble(
      EntityInstance new_entity,
      std::optional<EntityInstance> old_entity,
      EntityImportPromptResultCallback prompt_closed_callback) override;
  void ShowEmailVerifiedToast() final;

  // TODO(crbug.com/407666146): Create a test API.
  base::WeakPtr<AutofillSuggestionController>
  suggestion_controller_for_testing() {
    return suggestion_controller_;
  }
#if defined(UNIT_TEST)
  void SetKeepPopupOpenForTesting(bool keep_popup_open_for_testing) {
    keep_popup_open_for_testing_ = keep_popup_open_for_testing;
    if (suggestion_controller_) {
      suggestion_controller_->SetKeepPopupOpenForTesting(
          keep_popup_open_for_testing);
    }
  }
#if !BUILDFLAG(IS_ANDROID)
  void SetAutofillFieldPromoTesting(
      std::unique_ptr<AutofillFieldPromoController> test_controller) {
    autofill_field_promo_controller_ = std::move(test_controller);
  }
#endif  // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID)
  void SetAutofillSnackbarControllerImplForTesting(
      std::unique_ptr<AutofillSnackbarControllerImpl>
          autofill_snackbar_controller_impl) {
    autofill_snackbar_controller_impl_ =
        std::move(autofill_snackbar_controller_impl);
  }
#endif
#endif  // defined(UNIT_TEST)

  // ContentAutofillClient:
  std::unique_ptr<AutofillManager> CreateManager(
      base::PassKey<ContentAutofillDriver> pass_key,
      ContentAutofillDriver& driver) final;

  // ContentAutofillClient:
  credential_management::ContentCredentialManager* GetContentCredentialManager()
      override;

  OtpFieldDetector* GetOtpFieldDetector() override;
  OtpPhishGuardDelegate* GetOtpPhishGuardDelegate() override;

  one_time_tokens::OneTimeTokenService* GetOneTimeTokenService() const final;

 protected:
  explicit ChromeAutofillClient(content::WebContents* web_contents);

 private:
  Profile* GetProfile() const;
  bool SupportsConsentlessExecution(const url::Origin& origin);
  void ShowAutofillSuggestionsImpl(
      SuggestionUiSessionId session_id,
      const PopupOpenArgs& open_args,
      base::WeakPtr<AutofillSuggestionDelegate> delegate);

  const raw_ptr<LogRouter> log_router_ =
      AutofillLogRouterFactory::GetForBrowserContext(
          GetWebContents().GetBrowserContext());
  std::unique_ptr<LogManager> log_manager_;
  autofill_metrics::FormInteractionsUkmLogger form_interactions_ukm_logger_{
      this};

  std::unique_ptr<AutofillAiManager> autofill_ai_manager_;

  // These members are initialized lazily in their respective getters.
  // Therefore, do not access the members directly.
  std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_;
  VotesUploader votes_uploader_{this};
  std::unique_ptr<FormDataImporter> form_data_importer_;

  payments::ChromePaymentsAutofillClient payments_autofill_client_{this};
  SingleFieldFillRouter single_field_fill_router_{
      // This call is during construction, so GetAutocompleteHistoryManager()
      // does not dispatch to more-derived classes, should there be any.
      GetAutocompleteHistoryManager(),
      payments_autofill_client_.GetIbanManager(),
      payments_autofill_client_.GetMerchantPromoCodeManager()};

  base::WeakPtr<AutofillSuggestionController> suggestion_controller_;
  FormInteractionsFlowId flow_id_;
  base::Time flow_id_date_;
  // If set to true, the popup will stay open regardless of external changes on
  // the test machine, that may normally cause the popup to be hidden
  bool keep_popup_open_for_testing_ = false;
#if BUILDFLAG(IS_ANDROID)
  std::unique_ptr<SaveUpdateAddressProfileFlowManager>
      save_update_address_profile_flow_manager_;
  std::unique_ptr<FastCheckoutClient> fast_checkout_client_;
  std::unique_ptr<AutofillSnackbarControllerImpl>
      autofill_snackbar_controller_impl_;
#else   // BUILDFLAG(IS_ANDROID)
  std::unique_ptr<AutofillFieldPromoController>
      autofill_field_promo_controller_;
#endif  // BUILDFLAG(IS_ANDROID)
  // Test addresses used to allow developers to test their forms.
  std::vector<AutofillProfile> test_addresses_;
  const AutofillAblationStudy ablation_study_;

  ContentIdentityCredentialDelegate identity_credential_delegate_;
  std::unique_ptr<OtpFieldDetector> otp_field_detector_;
  std::unique_ptr<EmailVerifierDelegate> email_verifier_delegate_;
  std::unique_ptr<ChromeOtpPhishGuardDelegate> otp_phish_guard_delegate_;

  base::WeakPtrFactory<ChromeAutofillClient> weak_ptr_factory_{this};
};

}  // namespace autofill

#endif  // CHROME_BROWSER_UI_AUTOFILL_CHROME_AUTOFILL_CLIENT_H_