Commit ff4559a4 authored by Clemens Arbesser's avatar Clemens Arbesser Committed by Commit Bot

[Autofill Assistant] Refactor field formatter

This CL refactors the field formatter such that non-integer keys are
also supported. This is in preparation for an upcoming CL where this
will be required.

Bug: b/145043394
Change-Id: I603ea66b2ef338d43c263cfa00031eb11dda565d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2235615
Commit-Queue: Clemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarSandro Maggi <sandromaggi@google.com>
Cr-Commit-Position: refs/heads/master@{#777327}
parent 30705dd5
...@@ -84,8 +84,6 @@ jumbo_static_library("browser") { ...@@ -84,8 +84,6 @@ jumbo_static_library("browser") {
"actions/wait_for_dom_action.h", "actions/wait_for_dom_action.h",
"actions/wait_for_navigation_action.cc", "actions/wait_for_navigation_action.cc",
"actions/wait_for_navigation_action.h", "actions/wait_for_navigation_action.h",
"autofill_field_formatter.cc",
"autofill_field_formatter.h",
"basic_interactions.cc", "basic_interactions.cc",
"basic_interactions.h", "basic_interactions.h",
"batch_element_checker.cc", "batch_element_checker.cc",
...@@ -115,6 +113,8 @@ jumbo_static_library("browser") { ...@@ -115,6 +113,8 @@ jumbo_static_library("browser") {
"event_handler.h", "event_handler.h",
"features.cc", "features.cc",
"features.h", "features.h",
"field_formatter.cc",
"field_formatter.h",
"generic_ui_java_generated_enums.h", "generic_ui_java_generated_enums.h",
"info_box.cc", "info_box.cc",
"info_box.h", "info_box.h",
...@@ -254,7 +254,6 @@ source_set("unit_tests") { ...@@ -254,7 +254,6 @@ source_set("unit_tests") {
"actions/use_credit_card_action_unittest.cc", "actions/use_credit_card_action_unittest.cc",
"actions/wait_for_document_action_unittest.cc", "actions/wait_for_document_action_unittest.cc",
"actions/wait_for_dom_action_unittest.cc", "actions/wait_for_dom_action_unittest.cc",
"autofill_field_formatter_unittest.cc",
"basic_interactions_unittest.cc", "basic_interactions_unittest.cc",
"batch_element_checker_unittest.cc", "batch_element_checker_unittest.cc",
"controller_unittest.cc", "controller_unittest.cc",
...@@ -262,6 +261,7 @@ source_set("unit_tests") { ...@@ -262,6 +261,7 @@ source_set("unit_tests") {
"element_area_unittest.cc", "element_area_unittest.cc",
"element_precondition_unittest.cc", "element_precondition_unittest.cc",
"event_handler_unittest.cc", "event_handler_unittest.cc",
"field_formatter_unittest.cc",
"protocol_utils_unittest.cc", "protocol_utils_unittest.cc",
"retry_timer_unittest.cc", "retry_timer_unittest.cc",
"script_executor_unittest.cc", "script_executor_unittest.cc",
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/optional.h" #include "base/optional.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h" #include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/autofill_field_formatter.h"
#include "components/autofill_assistant/browser/batch_element_checker.h" #include "components/autofill_assistant/browser/batch_element_checker.h"
#include "components/autofill_assistant/browser/client_status.h" #include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/field_formatter.h"
namespace autofill_assistant { namespace autofill_assistant {
namespace { namespace {
...@@ -51,7 +51,7 @@ RequiredFieldsFallbackHandler::~RequiredFieldsFallbackHandler() = default; ...@@ -51,7 +51,7 @@ RequiredFieldsFallbackHandler::~RequiredFieldsFallbackHandler() = default;
RequiredFieldsFallbackHandler::RequiredFieldsFallbackHandler( RequiredFieldsFallbackHandler::RequiredFieldsFallbackHandler(
const std::vector<RequiredField>& required_fields, const std::vector<RequiredField>& required_fields,
const std::map<int, std::string>& fallback_values, const std::map<std::string, std::string>& fallback_values,
ActionDelegate* delegate) ActionDelegate* delegate)
: required_fields_(required_fields), : required_fields_(required_fields),
fallback_values_(fallback_values), fallback_values_(fallback_values),
...@@ -154,8 +154,8 @@ void RequiredFieldsFallbackHandler::OnCheckRequiredFieldsDone( ...@@ -154,8 +154,8 @@ void RequiredFieldsFallbackHandler::OnCheckRequiredFieldsDone(
continue; continue;
} }
if (autofill_field_formatter::FormatString(required_field.value_expression, if (field_formatter::FormatAutofillString(required_field.value_expression,
fallback_values_) fallback_values_)
.has_value()) { .has_value()) {
has_fallbacks = true; has_fallbacks = true;
} else { } else {
...@@ -192,7 +192,7 @@ void RequiredFieldsFallbackHandler::SetFallbackFieldValuesSequentially( ...@@ -192,7 +192,7 @@ void RequiredFieldsFallbackHandler::SetFallbackFieldValuesSequentially(
// Set the next field to its fallback value. // Set the next field to its fallback value.
const RequiredField& required_field = required_fields_[required_fields_index]; const RequiredField& required_field = required_fields_[required_fields_index];
auto fallback_value = autofill_field_formatter::FormatString( auto fallback_value = field_formatter::FormatAutofillString(
required_field.value_expression, fallback_values_); required_field.value_expression, fallback_values_);
if (!fallback_value.has_value()) { if (!fallback_value.has_value()) {
VLOG(3) << "No fallback for " << required_field.selector; VLOG(3) << "No fallback for " << required_field.selector;
......
...@@ -28,7 +28,7 @@ class RequiredFieldsFallbackHandler { ...@@ -28,7 +28,7 @@ class RequiredFieldsFallbackHandler {
public: public:
explicit RequiredFieldsFallbackHandler( explicit RequiredFieldsFallbackHandler(
const std::vector<RequiredField>& required_fields, const std::vector<RequiredField>& required_fields,
const std::map<int, std::string>& fallback_values, const std::map<std::string, std::string>& fallback_values,
ActionDelegate* delegate); ActionDelegate* delegate);
~RequiredFieldsFallbackHandler(); ~RequiredFieldsFallbackHandler();
...@@ -87,7 +87,7 @@ class RequiredFieldsFallbackHandler { ...@@ -87,7 +87,7 @@ class RequiredFieldsFallbackHandler {
ClientStatus client_status_; ClientStatus client_status_;
std::vector<RequiredField> required_fields_; std::vector<RequiredField> required_fields_;
std::map<int, std::string> fallback_values_; std::map<std::string, std::string> fallback_values_;
base::OnceCallback<void(const ClientStatus&, base::OnceCallback<void(const ClientStatus&,
const base::Optional<ClientStatus>&)> const base::Optional<ClientStatus>&)>
status_update_callback_; status_update_callback_;
......
...@@ -84,12 +84,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ...@@ -84,12 +84,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
CreateRequiredField("52", {"#card_number"}), CreateRequiredField("52", {"#card_number"}),
CreateRequiredField("-3", {"#card_network"})}; CreateRequiredField("-3", {"#card_network"})};
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL), base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
"John Doe"); "John Doe");
fallback_values.emplace( fallback_values.emplace(base::NumberToString(static_cast<int>(
static_cast<int>(AutofillFormatProto::CREDIT_CARD_NETWORK), ""); AutofillFormatProto::CREDIT_CARD_NETWORK)),
"");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_); required_fields, fallback_values, &mock_action_delegate_);
...@@ -144,13 +146,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, AddsFirstFieldFillingError) { ...@@ -144,13 +146,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, AddsFirstFieldFillingError) {
CreateRequiredField("51", {"#card_name"}), CreateRequiredField("51", {"#card_name"}),
CreateRequiredField("52", {"#card_number"})}; CreateRequiredField("52", {"#card_number"})};
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL), base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
"John Doe"); "John Doe");
fallback_values.emplace( fallback_values.emplace(base::NumberToString(static_cast<int>(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NUMBER), autofill::ServerFieldType::CREDIT_CARD_NUMBER)),
"4111111111111111"); "4111111111111111");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_); required_fields, fallback_values, &mock_action_delegate_);
...@@ -222,9 +225,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsEmptyRequiredField) { ...@@ -222,9 +225,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsEmptyRequiredField) {
std::vector<RequiredField> required_fields = { std::vector<RequiredField> required_fields = {
CreateRequiredField("51", {"#card_name"})}; CreateRequiredField("51", {"#card_name"})};
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL), base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
"John Doe"); "John Doe");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
...@@ -253,9 +257,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FallsBackForForcedFilledField) { ...@@ -253,9 +257,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FallsBackForForcedFilledField) {
CreateRequiredField("51", {"#card_name"})}; CreateRequiredField("51", {"#card_name"})};
required_fields[0].forced = true; required_fields[0].forced = true;
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL), base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
"John Doe"); "John Doe");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
...@@ -328,11 +333,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsFieldWithPattern) { ...@@ -328,11 +333,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsFieldWithPattern) {
std::vector<RequiredField> required_fields = { std::vector<RequiredField> required_fields = {
CreateRequiredField("${53}/${55}", {"#card_expiry"})}; CreateRequiredField("${53}/${55}", {"#card_expiry"})};
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH), "08"); base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
"08");
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR), base::NumberToString(static_cast<int>(
autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR)),
"2050"); "2050");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
...@@ -361,9 +369,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ...@@ -361,9 +369,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
CreateRequiredField("53", {"#card_expiry"}), CreateRequiredField("53", {"#card_expiry"}),
CreateRequiredField("-3", {"#card_network"})}; CreateRequiredField("-3", {"#card_network"})};
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(base::NumberToString(static_cast<int>(
static_cast<int>(AutofillFormatProto::CREDIT_CARD_NETWORK), ""); AutofillFormatProto::CREDIT_CARD_NETWORK)),
"");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_); required_fields, fallback_values, &mock_action_delegate_);
...@@ -408,35 +417,6 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ...@@ -408,35 +417,6 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
std::move(callback)); std::move(callback));
} }
TEST_F(RequiredFieldsFallbackHandlerTest, IgnoresNonIntegerKeys) {
EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
Expectation set_value =
EXPECT_CALL(mock_action_delegate_,
OnSetFieldValue(Eq(Selector({"#card_expiry"})), "${KEY}", _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
.After(set_value)
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
std::vector<RequiredField> required_fields = {
CreateRequiredField("${KEY}", {"#card_expiry"})};
RequiredFieldsFallbackHandler fallback_handler(required_fields, {},
&mock_action_delegate_);
base::OnceCallback<void(const ClientStatus&,
const base::Optional<ClientStatus>&)>
callback =
base::BindOnce([](const ClientStatus& status,
const base::Optional<ClientStatus>& detail_status) {
EXPECT_EQ(status.proto_status(), ACTION_APPLIED);
});
fallback_handler.CheckAndFallbackRequiredFields(OkClientStatus(),
std::move(callback));
}
TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) { TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) {
EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0); EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
EXPECT_CALL(mock_action_delegate_, OnSetFieldValue(_, _, _)).Times(0); EXPECT_CALL(mock_action_delegate_, OnSetFieldValue(_, _, _)).Times(0);
...@@ -458,9 +438,11 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) { ...@@ -458,9 +438,11 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) {
CreateRequiredField("53", {"#card_expiry"})}; CreateRequiredField("53", {"#card_expiry"})};
required_fields[0].fallback_click_element = Selector({".option"}); required_fields[0].fallback_click_element = Selector({".option"});
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH), "08"); base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
"08");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_); required_fields, fallback_values, &mock_action_delegate_);
...@@ -498,9 +480,11 @@ TEST_F(RequiredFieldsFallbackHandlerTest, CustomDropdownClicksStopOnError) { ...@@ -498,9 +480,11 @@ TEST_F(RequiredFieldsFallbackHandlerTest, CustomDropdownClicksStopOnError) {
CreateRequiredField("53", {"#card_expiry"})}; CreateRequiredField("53", {"#card_expiry"})};
required_fields[0].fallback_click_element = Selector({".option"}); required_fields[0].fallback_click_element = Selector({".option"});
std::map<int, std::string> fallback_values; std::map<std::string, std::string> fallback_values;
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH), "08"); base::NumberToString(
static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
"08");
RequiredFieldsFallbackHandler fallback_handler( RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_); required_fields, fallback_values, &mock_action_delegate_);
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
#include "components/autofill_assistant/browser/actions/action_delegate.h" #include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/actions/fallback_handler/required_field.h" #include "components/autofill_assistant/browser/actions/fallback_handler/required_field.h"
#include "components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h" #include "components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h"
#include "components/autofill_assistant/browser/autofill_field_formatter.h"
#include "components/autofill_assistant/browser/client_status.h" #include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/field_formatter.h"
#include "components/autofill_assistant/browser/user_model.h" #include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/value_util.h" #include "components/autofill_assistant/browser/value_util.h"
...@@ -173,8 +173,8 @@ void UseAddressAction::ExecuteFallback(const ClientStatus& status) { ...@@ -173,8 +173,8 @@ void UseAddressAction::ExecuteFallback(const ClientStatus& status) {
DCHECK(fallback_handler_ == nullptr); DCHECK(fallback_handler_ == nullptr);
fallback_handler_ = std::make_unique<RequiredFieldsFallbackHandler>( fallback_handler_ = std::make_unique<RequiredFieldsFallbackHandler>(
required_fields, required_fields,
autofill_field_formatter::CreateAutofillMappings(*profile_, field_formatter::CreateAutofillMappings(*profile_,
/* locale = */ "en-US"), /* locale = */ "en-US"),
delegate_); delegate_);
fallback_handler_->CheckAndFallbackRequiredFields( fallback_handler_->CheckAndFallbackRequiredFields(
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -20,8 +21,8 @@ ...@@ -20,8 +21,8 @@
#include "components/autofill_assistant/browser/actions/action_delegate.h" #include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/actions/fallback_handler/required_field.h" #include "components/autofill_assistant/browser/actions/fallback_handler/required_field.h"
#include "components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h" #include "components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h"
#include "components/autofill_assistant/browser/autofill_field_formatter.h"
#include "components/autofill_assistant/browser/client_status.h" #include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/field_formatter.h"
#include "components/autofill_assistant/browser/user_model.h" #include "components/autofill_assistant/browser/user_model.h"
namespace autofill_assistant { namespace autofill_assistant {
...@@ -150,14 +151,16 @@ void UseCreditCardAction::OnGetFullCard( ...@@ -150,14 +151,16 @@ void UseCreditCardAction::OnGetFullCard(
required_fields.emplace_back(required_field); required_fields.emplace_back(required_field);
} }
std::map<int, std::string> fallback_values = std::map<std::string, std::string> fallback_values =
autofill_field_formatter::CreateAutofillMappings(*card, field_formatter::CreateAutofillMappings(*card,
/* locale = */ "en-US"); /* locale = */ "en-US");
fallback_values.emplace( fallback_values.emplace(
static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE), base::NumberToString(
static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
base::UTF16ToUTF8(cvc)); base::UTF16ToUTF8(cvc));
fallback_values.emplace( fallback_values.emplace(
(int)AutofillFormatProto::CREDIT_CARD_RAW_NUMBER, base::NumberToString(
static_cast<int>(AutofillFormatProto::CREDIT_CARD_RAW_NUMBER)),
base::UTF16ToUTF8(card->GetRawInfo(autofill::CREDIT_CARD_NUMBER))); base::UTF16ToUTF8(card->GetRawInfo(autofill::CREDIT_CARD_NUMBER)));
DCHECK(fallback_handler_ == nullptr); DCHECK(fallback_handler_ == nullptr);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill_assistant/browser/autofill_field_formatter.h" #include "components/autofill_assistant/browser/field_formatter.h"
#include "components/autofill_assistant/browser/script_executor_delegate.h" #include "components/autofill_assistant/browser/script_executor_delegate.h"
#include "components/autofill_assistant/browser/trigger_context.h" #include "components/autofill_assistant/browser/trigger_context.h"
#include "components/autofill_assistant/browser/user_model.h" #include "components/autofill_assistant/browser/user_model.h"
...@@ -167,9 +167,9 @@ bool ValueToString(UserModel* user_model, ...@@ -167,9 +167,9 @@ bool ValueToString(UserModel* user_model,
<< ": credit card not found"; << ": credit card not found";
return false; return false;
} }
auto formatted_string = autofill_field_formatter::FormatString( auto formatted_string = field_formatter::FormatAutofillString(
proto.autofill_format().pattern(), proto.autofill_format().pattern(),
autofill_field_formatter::CreateAutofillMappings( field_formatter::CreateAutofillMappings(
*credit_card, proto.autofill_format().locale())); *credit_card, proto.autofill_format().locale()));
if (!formatted_string.has_value()) { if (!formatted_string.has_value()) {
DVLOG(2) << "Error evaluating " << __func__ DVLOG(2) << "Error evaluating " << __func__
...@@ -191,9 +191,9 @@ bool ValueToString(UserModel* user_model, ...@@ -191,9 +191,9 @@ bool ValueToString(UserModel* user_model,
DVLOG(2) << "Error evaluating " << __func__ << ": profile not found"; DVLOG(2) << "Error evaluating " << __func__ << ": profile not found";
return false; return false;
} }
auto formatted_string = autofill_field_formatter::FormatString( auto formatted_string = field_formatter::FormatAutofillString(
proto.autofill_format().pattern(), proto.autofill_format().pattern(),
autofill_field_formatter::CreateAutofillMappings( field_formatter::CreateAutofillMappings(
*profile, proto.autofill_format().locale())); *profile, proto.autofill_format().locale()));
if (!formatted_string.has_value()) { if (!formatted_string.has_value()) {
DVLOG(2) << "Error evaluating " << __func__ DVLOG(2) << "Error evaluating " << __func__
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "components/autofill_assistant/browser/autofill_field_formatter.h" #include "components/autofill_assistant/browser/field_formatter.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_data_util.h"
...@@ -13,28 +13,28 @@ ...@@ -13,28 +13,28 @@
#include "third_party/re2/src/re2/stringpiece.h" #include "third_party/re2/src/re2/stringpiece.h"
namespace { namespace {
// Regex to find placeholders of the form ${N}, where N is an integer (possibly // Regex to find placeholders of the form ${key}, where key is an arbitrary
// negative). // string that does not contain curly braces.
const char kPlaceholderExtractor[] = R"re(\$\{(-?\d+)\})re"; const char kPlaceholderExtractor[] = R"re(\$\{([^{}]+)\})re";
base::Optional<std::string> GetFieldValue( base::Optional<std::string> GetFieldValue(
const std::map<int, std::string>& mappings, const std::map<std::string, std::string>& mappings,
int i) { const std::string& key) {
auto it = mappings.find(i); auto it = mappings.find(key);
if (it == mappings.end()) { if (it == mappings.end()) {
return base::nullopt; return base::nullopt;
} }
return it->second; return it->second;
} }
std::map<int, std::string> CreateFormGroupMappings( std::map<std::string, std::string> CreateFormGroupMappings(
const autofill::FormGroup& form_group, const autofill::FormGroup& form_group,
const std::string& locale) { const std::string& locale) {
std::map<int, std::string> mappings; std::map<std::string, std::string> mappings;
autofill::ServerFieldTypeSet available_fields; autofill::ServerFieldTypeSet available_fields;
form_group.GetNonEmptyTypes(locale, &available_fields); form_group.GetNonEmptyTypes(locale, &available_fields);
for (const auto& field : available_fields) { for (const auto& field : available_fields) {
mappings.emplace(static_cast<int>(field), mappings.emplace(base::NumberToString(static_cast<int>(field)),
base::UTF16ToUTF8(form_group.GetInfo( base::UTF16ToUTF8(form_group.GetInfo(
autofill::AutofillType(field), locale))); autofill::AutofillType(field), locale)));
} }
...@@ -44,11 +44,11 @@ std::map<int, std::string> CreateFormGroupMappings( ...@@ -44,11 +44,11 @@ std::map<int, std::string> CreateFormGroupMappings(
} // namespace } // namespace
namespace autofill_assistant { namespace autofill_assistant {
namespace autofill_field_formatter { namespace field_formatter {
base::Optional<std::string> FormatString( base::Optional<std::string> FormatAutofillString(
const std::string& pattern, const std::string& pattern,
const std::map<int, std::string> mappings) { const std::map<std::string, std::string>& mappings) {
if (pattern.empty()) { if (pattern.empty()) {
return std::string(); return std::string();
} }
...@@ -56,15 +56,26 @@ base::Optional<std::string> FormatString( ...@@ -56,15 +56,26 @@ base::Optional<std::string> FormatString(
// Special case: if the input is a single number, interpret as ${N}. // Special case: if the input is a single number, interpret as ${N}.
int field_type; int field_type;
if (base::StringToInt(pattern, &field_type)) { if (base::StringToInt(pattern, &field_type)) {
return GetFieldValue(mappings, field_type); return GetFieldValue(mappings, pattern);
}
return FormatString(pattern, mappings);
}
base::Optional<std::string> FormatString(
const std::string& pattern,
const std::map<std::string, std::string>& mappings) {
if (pattern.empty()) {
return std::string();
} }
std::string key;
std::string out = pattern; std::string out = pattern;
re2::StringPiece input(pattern); re2::StringPiece input(pattern);
while (re2::RE2::FindAndConsume(&input, kPlaceholderExtractor, &field_type)) { while (re2::RE2::FindAndConsume(&input, kPlaceholderExtractor, &key)) {
auto rewrite_value = GetFieldValue(mappings, field_type); auto rewrite_value = GetFieldValue(mappings, key);
if (!rewrite_value.has_value()) { if (!rewrite_value.has_value()) {
VLOG(2) << "No value for " << field_type << " in " << pattern; VLOG(2) << "No value for " << key << " in " << pattern;
return base::nullopt; return base::nullopt;
} }
...@@ -76,14 +87,15 @@ base::Optional<std::string> FormatString( ...@@ -76,14 +87,15 @@ base::Optional<std::string> FormatString(
} }
template <> template <>
std::map<int, std::string> CreateAutofillMappings<autofill::AutofillProfile>( std::map<std::string, std::string>
CreateAutofillMappings<autofill::AutofillProfile>(
const autofill::AutofillProfile& profile, const autofill::AutofillProfile& profile,
const std::string& locale) { const std::string& locale) {
return CreateFormGroupMappings(profile, locale); return CreateFormGroupMappings(profile, locale);
} }
template <> template <>
std::map<int, std::string> CreateAutofillMappings<autofill::CreditCard>( std::map<std::string, std::string> CreateAutofillMappings<autofill::CreditCard>(
const autofill::CreditCard& credit_card, const autofill::CreditCard& credit_card,
const std::string& locale) { const std::string& locale) {
auto mappings = CreateFormGroupMappings(credit_card, locale); auto mappings = CreateFormGroupMappings(credit_card, locale);
...@@ -92,24 +104,24 @@ std::map<int, std::string> CreateAutofillMappings<autofill::CreditCard>( ...@@ -92,24 +104,24 @@ std::map<int, std::string> CreateAutofillMappings<autofill::CreditCard>(
autofill::data_util::GetPaymentRequestData(credit_card.network()) autofill::data_util::GetPaymentRequestData(credit_card.network())
.basic_card_issuer_network); .basic_card_issuer_network);
if (!network.empty()) { if (!network.empty()) {
mappings[static_cast<int>(AutofillFormatProto::CREDIT_CARD_NETWORK)] = mappings[base::NumberToString(
network; static_cast<int>(AutofillFormatProto::CREDIT_CARD_NETWORK))] = network;
} }
auto network_for_display = base::UTF16ToUTF8(credit_card.NetworkForDisplay()); auto network_for_display = base::UTF16ToUTF8(credit_card.NetworkForDisplay());
if (!network_for_display.empty()) { if (!network_for_display.empty()) {
mappings[static_cast<int>( mappings[base::NumberToString(static_cast<int>(
AutofillFormatProto::CREDIT_CARD_NETWORK_FOR_DISPLAY)] = AutofillFormatProto::CREDIT_CARD_NETWORK_FOR_DISPLAY))] =
network_for_display; network_for_display;
} }
auto last_four_digits = base::UTF16ToUTF8(credit_card.LastFourDigits()); auto last_four_digits = base::UTF16ToUTF8(credit_card.LastFourDigits());
if (!last_four_digits.empty()) { if (!last_four_digits.empty()) {
mappings[static_cast<int>( mappings[base::NumberToString(static_cast<int>(
AutofillFormatProto::CREDIT_CARD_NUMBER_LAST_FOUR_DIGITS)] = AutofillFormatProto::CREDIT_CARD_NUMBER_LAST_FOUR_DIGITS))] =
last_four_digits; last_four_digits;
} }
return mappings; return mappings;
} }
} // namespace autofill_field_formatter } // namespace field_formatter
} // namespace autofill_assistant } // namespace autofill_assistant
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_AUTOFILL_FIELD_FORMATTER_H_ #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FIELD_FORMATTER_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_AUTOFILL_FIELD_FORMATTER_H_ #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FIELD_FORMATTER_H_
#include <map> #include <map>
#include <string> #include <string>
...@@ -12,26 +12,33 @@ ...@@ -12,26 +12,33 @@
#include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card.h"
namespace autofill_assistant { namespace autofill_assistant {
namespace autofill_field_formatter { namespace field_formatter {
// Replaces all placeholder occurrences of the form ${N} in |pattern| with the // Replaces all placeholder occurrences of the form ${key} in |input| with the
// corresponding value in |mappings|. Returns the result or nullopt if any // corresponding value in |mappings|, where |key| is an arbitrary string that
// of the requested fields was not available. As a special case, input patterns // does not contain curly braces. Fails if any of the found placeholders is not
// in |mappings|.
base::Optional<std::string> FormatString(
const std::string& input,
const std::map<std::string, std::string>& mappings);
// Same as |FormatString|, but also supports a special case: input patterns
// containing a single integer are also allowed and implicitly interpreted as // containing a single integer are also allowed and implicitly interpreted as
// ${N}. // ${N}.
base::Optional<std::string> FormatString( base::Optional<std::string> FormatAutofillString(
const std::string& pattern, const std::string& pattern,
const std::map<int, std::string> mappings); const std::map<std::string, std::string>& mappings);
// Creates a lookup map for all non-empty autofill and custom // Creates a lookup map for all non-empty autofill and custom
// AutofillFormatProto::AutofillAssistantCustomField field types in // AutofillFormatProto::AutofillAssistantCustomField field types in
// |autofill_data_model|. // |autofill_data_model|.
// |locale| should be a locale string such as "en-US". // |locale| should be a locale string such as "en-US".
template <typename T> template <typename T>
std::map<int, std::string> CreateAutofillMappings(const T& autofill_data_model, std::map<std::string, std::string> CreateAutofillMappings(
const std::string& locale); const T& autofill_data_model,
const std::string& locale);
} // namespace autofill_field_formatter } // namespace field_formatter
} // namespace autofill_assistant } // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_AUTOFILL_FIELD_FORMATTER_H_ #endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FIELD_FORMATTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment