File: fast_checkout_trigger_validator_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (162 lines) | stat: -rw-r--r-- 6,575 bytes parent folder | download | duplicates (3)
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;
}