blob: 8efc7812daefbf6f4444b5fb7a446b758465c64d [file] [log] [blame]
// Copyright 2015 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/core/common/autofill_util.h"
#include <string>
#include <string_view>
#include <vector>
#include "base/command_line.h"
#include "base/containers/to_vector.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/i18n/string_search.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_switches.h"
namespace autofill {
using mojom::FocusedFieldType;
using mojom::SubmissionIndicatorEvent;
using mojom::SubmissionSource;
bool IsShowAutofillSignaturesEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kShowAutofillSignatures);
}
bool IsPrefixOfEmailEndingWithAtSign(std::u16string_view full_string,
std::u16string_view prefix) {
return full_string.size() > prefix.size() &&
full_string.starts_with(prefix) && full_string[prefix.size()] == u'@';
}
bool IsCheckable(const FormFieldData::CheckStatus& check_status) {
return check_status != FormFieldData::CheckStatus::kNotCheckable;
}
bool IsChecked(const FormFieldData::CheckStatus& check_status) {
return check_status == FormFieldData::CheckStatus::kChecked;
}
void SetCheckStatus(FormFieldData* form_field_data,
bool is_checkable,
bool is_checked) {
using enum FormFieldData::CheckStatus;
form_field_data->set_check_status(!is_checkable ? kNotCheckable
: is_checked ? kChecked
: kCheckableButUnchecked);
}
std::optional<size_t> FindShortestSubstringMatchInSelect(
const std::u16string& value,
bool ignore_whitespace,
base::span<const SelectOption> field_options) {
std::optional<size_t> best_match;
std::u16string value_stripped =
ignore_whitespace ? RemoveWhitespace(value) : value;
base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents searcher(
value_stripped);
for (size_t i = 0; i < field_options.size(); ++i) {
const SelectOption& option = field_options[i];
std::u16string option_value =
ignore_whitespace ? RemoveWhitespace(option.value) : option.value;
std::u16string option_text =
ignore_whitespace ? RemoveWhitespace(option.text) : option.text;
if (searcher.Search(option_value, nullptr, nullptr) ||
searcher.Search(option_text, nullptr, nullptr)) {
if (!best_match.has_value() ||
field_options[best_match.value()].value.size() >
option.value.size()) {
best_match = i;
}
}
}
return best_match;
}
std::vector<std::string> LowercaseAndTokenizeAttributeString(
std::string_view attribute) {
return base::SplitString(base::ToLowerASCII(attribute),
base::kWhitespaceASCII, base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
}
std::u16string RemoveWhitespace(std::u16string_view value) {
std::u16string stripped_value;
base::RemoveChars(value, base::kWhitespaceUTF16, &stripped_value);
return stripped_value;
}
std::u16string SanitizeCreditCardFieldValue(std::u16string_view value) {
std::u16string sanitized;
// We remove whitespace as well as some invisible unicode characters.
base::TrimWhitespace(value, base::TRIM_ALL, &sanitized);
base::TrimString(sanitized,
std::u16string({base::i18n::kRightToLeftMark,
base::i18n::kLeftToRightMark}),
&sanitized);
// Some sites have ____-____-____-____ in their credit card number fields, for
// example.
base::RemoveChars(sanitized, u"-_", &sanitized);
return sanitized;
}
bool SanitizedFieldIsEmpty(std::u16string_view value) {
// Some sites enter values such as ____-____-____-____ or (___)-___-____ in
// their fields. Check if the field value is empty after the removal of the
// formatting characters.
static const base::NoDestructor<std::u16string> formatting(
base::StrCat({u"-_()/",
{&base::i18n::kRightToLeftMark, 1},
{&base::i18n::kLeftToRightMark, 1},
base::kWhitespaceUTF16}));
return base::ContainsOnlyChars(value, *formatting);
}
bool IsFillable(FocusedFieldType focused_field_type) {
switch (focused_field_type) {
case FocusedFieldType::kFillableTextArea:
case FocusedFieldType::kFillableSearchField:
case FocusedFieldType::kFillableNonSearchField:
case FocusedFieldType::kFillableUsernameField:
case FocusedFieldType::kFillablePasswordField:
case FocusedFieldType::kFillableWebauthnTaggedField:
return true;
case FocusedFieldType::kUnfillableElement:
case FocusedFieldType::kUnknown:
return false;
}
NOTREACHED();
}
SubmissionIndicatorEvent ToSubmissionIndicatorEvent(SubmissionSource source) {
switch (source) {
case SubmissionSource::NONE:
return SubmissionIndicatorEvent::NONE;
case SubmissionSource::SAME_DOCUMENT_NAVIGATION:
return SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
case SubmissionSource::XHR_SUCCEEDED:
return SubmissionIndicatorEvent::XHR_SUCCEEDED;
case SubmissionSource::FRAME_DETACHED:
return SubmissionIndicatorEvent::FRAME_DETACHED;
case SubmissionSource::PROBABLY_FORM_SUBMITTED:
return SubmissionIndicatorEvent::PROBABLE_FORM_SUBMISSION;
case SubmissionSource::FORM_SUBMISSION:
return SubmissionIndicatorEvent::HTML_FORM_SUBMISSION;
case SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL:
return SubmissionIndicatorEvent::DOM_MUTATION_AFTER_AUTOFILL;
}
NOTREACHED();
}
GURL StripAuth(const GURL& gurl) {
GURL::Replacements rep;
rep.ClearUsername();
rep.ClearPassword();
return gurl.ReplaceComponents(rep);
}
GURL StripAuthAndParams(const GURL& gurl) {
GURL::Replacements rep;
rep.ClearUsername();
rep.ClearPassword();
rep.ClearQuery();
rep.ClearRef();
return gurl.ReplaceComponents(rep);
}
IsPasswordRequestManuallyTriggered IsPasswordsAutofillManuallyTriggered(
AutofillSuggestionTriggerSource trigger_source) {
return IsPasswordRequestManuallyTriggered(
trigger_source ==
AutofillSuggestionTriggerSource::kManualFallbackPasswords);
}
bool IsPlusAddressesManuallyTriggered(
AutofillSuggestionTriggerSource trigger_source) {
return trigger_source ==
AutofillSuggestionTriggerSource::kManualFallbackPlusAddresses;
}
bool IsPaymentsFieldSwappingEnabled() {
return base::FeatureList::IsEnabled(features::kAutofillPaymentsFieldSwapping);
}
std::u16string GetButtonTitlesString(const ButtonTitleList& titles_list) {
std::vector<std::u16string> titles = base::ToVector(
titles_list, [](const auto& list_item) { return list_item.first; });
return base::JoinString(titles, u",");
}
bool IsFormPerfectlyFilled(const FormData& form) {
return std::none_of(form.fields().begin(), form.fields().end(),
[](const FormFieldData& field) {
return field.is_user_edited() && !field.is_autofilled();
});
}
} // namespace autofill