1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/fast_checkout/fast_checkout_trigger_validator_impl.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/fast_checkout/fast_checkout_capabilities_fetcher.h"
#include "components/autofill/core/browser/data_manager/personal_data_manager.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/autofill_internals/log_message.h"
#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/logging/log_macros.h"
using ::autofill::FastCheckoutTriggerOutcome;
using ::autofill::FastCheckoutUIState;
FastCheckoutTriggerValidatorImpl::FastCheckoutTriggerValidatorImpl(
autofill::AutofillClient* autofill_client,
FastCheckoutCapabilitiesFetcher* capabilities_fetcher,
FastCheckoutPersonalDataHelper* personal_data_helper)
: autofill_client_(autofill_client),
capabilities_fetcher_(capabilities_fetcher),
personal_data_helper_(personal_data_helper) {}
FastCheckoutTriggerOutcome FastCheckoutTriggerValidatorImpl::ShouldRun(
const autofill::FormData& form,
const autofill::FormFieldData& field,
const FastCheckoutUIState ui_state,
const bool is_running,
const autofill::AutofillManager& autofill_manager) const {
LogAutofillInternals(
"Start of checking whether a Fast Checkout run should be permitted.");
// Trigger only if there is no ongoing run.
if (is_running) {
LogAutofillInternals(
"not triggered because Fast Checkout is already running.");
return FastCheckoutTriggerOutcome::kUnsupportedFieldType;
}
// Trigger only if the URL scheme is cryptographic and security level is not
// dangerous.
if (!autofill_client_->IsContextSecure()) {
LogAutofillInternals(
"not triggered because context is not secure, e.g. not https or "
"dangerous security level.");
return FastCheckoutTriggerOutcome::kUnsupportedFieldType;
}
// Trigger only if the form is a trigger form for Fast Checkout.
if (!IsTriggerForm(form, field)) {
return FastCheckoutTriggerOutcome::kUnsupportedFieldType;
}
if (autofill_client_->GetVariationConfigCountryCode() !=
GeoIpCountryCode("US")) {
return FastCheckoutTriggerOutcome::kUnsupportedCountry;
}
// UMA drop out metrics are recorded after this point only to avoid collecting
// unnecessary metrics that would dominate the other data points.
// Trigger only if not shown before.
if (ui_state != FastCheckoutUIState::kNotShownYet) {
LogAutofillInternals("not triggered because it was shown before.");
return FastCheckoutTriggerOutcome::kFailureShownBefore;
}
// Trigger only on focusable fields.
if (!field.is_focusable()) {
LogAutofillInternals("not triggered because field was not focusable.");
return FastCheckoutTriggerOutcome::kFailureFieldNotFocusable;
}
// Trigger only on empty fields.
if (!field.value().empty()) {
LogAutofillInternals("not triggered because field was not empty.");
return FastCheckoutTriggerOutcome::kFailureFieldNotEmpty;
}
// Trigger only if the UI is available.
if (!autofill_manager.CanShowAutofillUi()) {
LogAutofillInternals("not triggered because Autofill UI cannot be shown.");
return FastCheckoutTriggerOutcome::kFailureCannotShowAutofillUi;
}
FastCheckoutTriggerOutcome result = HasValidPersonalData();
if (result != FastCheckoutTriggerOutcome::kSuccess) {
return result;
}
LogAutofillInternals("was triggered successfully.");
return FastCheckoutTriggerOutcome::kSuccess;
}
bool FastCheckoutTriggerValidatorImpl::IsTriggerForm(
const autofill::FormData& form,
const autofill::FormFieldData& field) const {
if (!capabilities_fetcher_) {
return false;
}
// TODO(crbug.com/40236321): Stop calculating the signature once the form
// signature has been moved to `form_data`.
// Check browser form's signature and renderer form's signature.
autofill::FormSignature form_signature =
autofill::CalculateFormSignature(form);
bool is_trigger_form =
capabilities_fetcher_->IsTriggerFormSupported(form.main_frame_origin(),
form_signature) ||
capabilities_fetcher_->IsTriggerFormSupported(
form.main_frame_origin(), field.host_form_signature());
if (!is_trigger_form) {
LogAutofillInternals(
"not triggered because there is no Fast Checkout support for form "
"signatures {" +
base::NumberToString(form_signature.value()) + ", " +
base::NumberToString(field.host_form_signature().value()) +
"} on origin " + form.main_frame_origin().Serialize() + ".");
}
return is_trigger_form;
}
FastCheckoutTriggerOutcome
FastCheckoutTriggerValidatorImpl::HasValidPersonalData() const {
autofill::PersonalDataManager* pdm =
personal_data_helper_->GetPersonalDataManager();
if (!pdm->address_data_manager().IsAutofillProfileEnabled()) {
LogAutofillInternals("not triggered because Autofill profile is disabled.");
return FastCheckoutTriggerOutcome::kFailureAutofillProfileDisabled;
}
if (!pdm->payments_data_manager().IsAutofillPaymentMethodsEnabled()) {
LogAutofillInternals(
"not triggered because Autofill credit card is disabled.");
return FastCheckoutTriggerOutcome::kFailureAutofillCreditCardDisabled;
}
// Trigger only if there is at least 1 valid Autofill profile on file.
if (personal_data_helper_->GetValidAddressProfiles().empty()) {
LogAutofillInternals(
"not triggered because the client does not have at least one valid "
"Autofill profile stored.");
return FastCheckoutTriggerOutcome::kFailureNoValidAutofillProfile;
}
// Trigger only if there is at least 1 complete valid credit card on file.
if (personal_data_helper_->GetValidCreditCards().empty()) {
LogAutofillInternals(
"not triggered because the client does not have at least one "
"valid Autofill credit card stored.");
return FastCheckoutTriggerOutcome::kFailureNoValidCreditCard;
}
return FastCheckoutTriggerOutcome::kSuccess;
}
void FastCheckoutTriggerValidatorImpl::LogAutofillInternals(
std::string message) const {
LOG_AF(autofill_client_->GetCurrentLogManager())
<< autofill::LoggingScope::kFastCheckout
<< autofill::LogMessage::kFastCheckout << message;
}
|