Skip to content

Commit

Permalink
Query AutofillOptimizationGuide before showing VCN suggestions
Browse files Browse the repository at this point in the history
This CL adds the logic in AutofillOptimizationGuide to query the
Optimization Guide Decider associated with the
`VCN_MERCHANT_OPT_OUT_VISA` optimization type when we have a virtual
card that there is a merchant opt-out blocklist for. It blocks
displaying VCN suggestions if the Optimization Guide Decider associated
with this blocklist denotes that the URL origin we are on is blocked.

Bug: 1411881
Change-Id: I6360a650c6d49d7bf6a8aaad1e56d377684e00a7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4303536
Reviewed-by: Siyu An <siyua@chromium.org>
Commit-Queue: Vinny Persky <vinnypersky@google.com>
Reviewed-by: Dominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1115615}
  • Loading branch information
Vinny Persky authored and Chromium LUCI CQ committed Mar 10, 2023
1 parent b11c4ed commit e79028d
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 39 deletions.
47 changes: 39 additions & 8 deletions components/autofill/core/browser/autofill_optimization_guide.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void AutofillOptimizationGuide::OnDidParseForm(

if (base::FeatureList::IsEnabled(
features::kAutofillEnableIbanClientSideUrlFiltering)) {
auto has_iban_field =
bool has_iban_field =
base::ranges::any_of(form_structure, [](const auto& field) {
return field->Type().GetStorableType() == IBAN_VALUE;
});
Expand All @@ -75,7 +75,7 @@ void AutofillOptimizationGuide::OnDidParseForm(
if (base::FeatureList::IsEnabled(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering) &&
personal_data_manager) {
auto has_credit_card_field =
bool has_credit_card_field =
base::ranges::any_of(form_structure, [](const auto& field) {
return field->Type().group() == FieldTypeGroup::kCreditCard;
});
Expand Down Expand Up @@ -115,12 +115,13 @@ bool AutofillOptimizationGuide::ShouldBlockSingleFieldSuggestions(
url, optimization_guide::proto::IBAN_AUTOFILL_BLOCKED,
/*optimization_metadata=*/nullptr);
// Since the optimization guide decider integration corresponding to
// `optimization_guide::proto::IBAN_AUTOFILL_BLOCKED` is a blocklist,
// `optimization_guide::OptimizationGuideDecision::kFalse` indicates that
// `url` is blocked from displaying IBAN suggestions. If the optimization
// type was not registered in time when we queried it, it will be
// `kUnknown`, so the default functionality in this case will be to not
// block the suggestions from being shown.
// `IBAN_AUTOFILL_BLOCKED` lists are blocklists for the question "Can this
// site be optimized?" a match on the blocklist answers the question with
// "no". Therefore, ...::kFalse indicates that `url` is blocked from
// displaying IBAN suggestions. If the optimization type was not registered
// in time when we queried it, it will be `kUnknown`, so the default
// functionality in this case will be to not block the suggestions from
// being shown.
return decision == optimization_guide::OptimizationGuideDecision::kFalse;
}

Expand All @@ -129,4 +130,34 @@ bool AutofillOptimizationGuide::ShouldBlockSingleFieldSuggestions(
return false;
}

bool AutofillOptimizationGuide::ShouldBlockFormFieldSuggestion(
const GURL& url,
const CreditCard* card) const {
if (!base::FeatureList::IsEnabled(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering)) {
return false;
}

if (auto optimization_type =
GetVcnMerchantOptOutOptimizationTypeForCard(card);
optimization_type != optimization_guide::proto::TYPE_UNSPECIFIED) {
optimization_guide::OptimizationGuideDecision decision =
decider_->CanApplyOptimization(url, optimization_type,
/*optimization_metadata=*/nullptr);
// Since the optimization guide decider integration corresponding to VCN
// merchant opt-out lists are blocklists for the question "Can this site be
// optimized?" a match on the blocklist answers the question with "no".
// Therefore, ...::kFalse indicates that `url` is blocked from displaying
// this suggestion. If the optimization type was not registered
// in time when we queried it, it will be `kUnknown`, so the default
// functionality in this case will be to not block the suggestion from being
// shown.
return decision == optimization_guide::OptimizationGuideDecision::kFalse;
}

// No conditions to block displaying this virtual card suggestion were met, so
// return that we should not block displaying this suggestion.
return false;
}

} // namespace autofill
10 changes: 9 additions & 1 deletion components/autofill/core/browser/autofill_optimization_guide.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class NewOptimizationGuideDecider;
namespace autofill {

class AutofillField;
class CreditCard;
class FormStructure;
class PersonalDataManager;

Expand Down Expand Up @@ -44,7 +45,8 @@ class AutofillOptimizationGuide : public KeyedService {

// Returns whether the URL origin contained in `url` is blocked from
// displaying suggestions for `field` by querying the optimization guide
// decider corresponding to `field`'s storable type.
// decider corresponding to `field`'s storable type. If the function returns
// true, no suggestions should be displayed for `field`.
virtual bool ShouldBlockSingleFieldSuggestions(const GURL& url,
AutofillField* field) const;

Expand All @@ -53,6 +55,12 @@ class AutofillOptimizationGuide : public KeyedService {
return decider_;
}

// Returns whether autofill suggestions for `card` should be blocked on `url`.
// This function relies on the optimization guide decider that corresponds to
// the network of `card`.
virtual bool ShouldBlockFormFieldSuggestion(const GURL& url,
const CreditCard* card) const;

private:
// Raw pointer to a decider which is owned by the decider's factory.
// The factory dependencies ensure that the `decider_` outlives this object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/data_model/credit_card_test_api.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/form_structure_test_api.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
Expand Down Expand Up @@ -424,4 +423,132 @@ TEST_F(
url, form_structure.field(0)));
}

// Test that blocking a virtual card suggestion works correctly in the VCN
// merchant opt-out use-case.
TEST_F(AutofillOptimizationGuideTest,
ShouldBlockFormFieldSuggestion_VcnMerchantOptOut) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering);
GURL url("https://example.com/");
CreditCard virtual_card = test::GetVirtualCard();
virtual_card.set_virtual_card_enrollment_type(CreditCard::NETWORK);
CreditCardTestApi(&virtual_card).set_network_for_virtual_card(kVisaCard);

ON_CALL(*decider_,
CanApplyOptimization(
testing::Eq(url),
testing::Eq(optimization_guide::proto::VCN_MERCHANT_OPT_OUT_VISA),
testing::Matcher<optimization_guide::OptimizationMetadata*>(
testing::Eq(nullptr))))
.WillByDefault(testing::Return(
optimization_guide::OptimizationGuideDecision::kFalse));

EXPECT_TRUE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion(
url, &virtual_card));
}

// Test that if the URL is not blocklisted, we do not block a virtual card
// suggestion in the VCN merchant opt-out use-case.
TEST_F(AutofillOptimizationGuideTest,
ShouldNotBlockFormFieldSuggestion_VcnMerchantOptOut_UrlNotBlocked) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering);
GURL url("https://example.com/");
CreditCard virtual_card = test::GetVirtualCard();
virtual_card.set_virtual_card_enrollment_type(CreditCard::NETWORK);
CreditCardTestApi(&virtual_card).set_network_for_virtual_card(kVisaCard);

ON_CALL(*decider_,
CanApplyOptimization(
testing::Eq(url),
testing::Eq(optimization_guide::proto::VCN_MERCHANT_OPT_OUT_VISA),
testing::Matcher<optimization_guide::OptimizationMetadata*>(
testing::Eq(nullptr))))
.WillByDefault(testing::Return(
optimization_guide::OptimizationGuideDecision::kTrue));

EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion(
url, &virtual_card));
}

// Test that if all of the prerequisites are met to block a virtual card
// suggestion for the VCN merchant opt-out use-case, but the flag is off, that
// we do not block the virtual card suggestion from being displayed.
TEST_F(AutofillOptimizationGuideTest,
ShouldNotBlockFormFieldSuggestion_VcnMerchantOptOut_FlagOff) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering);
GURL url("https://example.com/");
CreditCard virtual_card = test::GetVirtualCard();
virtual_card.set_virtual_card_enrollment_type(CreditCard::NETWORK);
CreditCardTestApi(&virtual_card).set_network_for_virtual_card(kVisaCard);

EXPECT_CALL(
*decider_,
CanApplyOptimization(
testing::Eq(url),
testing::Eq(optimization_guide::proto::VCN_MERCHANT_OPT_OUT_VISA),
testing::Matcher<optimization_guide::OptimizationMetadata*>(
testing::Eq(nullptr))))
.Times(0);

EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion(
url, &virtual_card));
}

// Test that we do not block virtual card suggestions in the VCN merchant
// opt-out use-case if the card is an issuer-level enrollment.
TEST_F(AutofillOptimizationGuideTest,
ShouldNotBlockFormFieldSuggestion_VcnMerchantOptOut_IssuerEnrollment) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering);
GURL url("https://example.com/");
CreditCard virtual_card = test::GetVirtualCard();
virtual_card.set_virtual_card_enrollment_type(CreditCard::ISSUER);
CreditCardTestApi(&virtual_card).set_network_for_virtual_card(kVisaCard);

EXPECT_CALL(
*decider_,
CanApplyOptimization(
testing::Eq(url),
testing::Eq(optimization_guide::proto::VCN_MERCHANT_OPT_OUT_VISA),
testing::Matcher<optimization_guide::OptimizationMetadata*>(
testing::Eq(nullptr))))
.Times(0);

EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion(
url, &virtual_card));
}

// Test that we do not block the virtual card suggestion from being shown in the
// VCN merchant opt-out use-case if the network does not have a VCN merchant
// opt-out blocklist.
TEST_F(
AutofillOptimizationGuideTest,
ShouldNotBlockFormFieldSuggestion_VcnMerchantOptOut_NetworkDoesNotHaveBlocklist) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
features::kAutofillEnableMerchantOptOutClientSideUrlFiltering);
GURL url("https://example.com/");
CreditCard virtual_card = test::GetVirtualCard();
virtual_card.set_virtual_card_enrollment_type(CreditCard::NETWORK);
CreditCardTestApi(&virtual_card).set_network_for_virtual_card(kMasterCard);

EXPECT_CALL(
*decider_,
CanApplyOptimization(
testing::Eq(url),
testing::Eq(optimization_guide::proto::VCN_MERCHANT_OPT_OUT_VISA),
testing::Matcher<optimization_guide::OptimizationMetadata*>(
testing::Eq(nullptr))))
.Times(0);

EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion(
url, &virtual_card));
}

} // namespace autofill
44 changes: 35 additions & 9 deletions components/autofill/core/browser/autofill_suggestion_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "components/autofill/core/browser/autofill_browser_util.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_optimization_guide.h"
#include "components/autofill/core/browser/data_model/autofill_offer_data.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/data_model/iban.h"
Expand Down Expand Up @@ -397,16 +398,16 @@ Suggestion::BackendId AutofillSuggestionGenerator::GetBackendIdFromFrontendId(
bool AutofillSuggestionGenerator::ShouldShowVirtualCardOption(
const CreditCard* candidate_card) const {
switch (candidate_card->record_type()) {
case CreditCard::LOCAL_CARD:
candidate_card = GetServerCardForLocalCard(candidate_card);

// If we could not find a matching server duplicate, return false.
if (!candidate_card) {
return false;
}
ABSL_FALLTHROUGH_INTENDED;
case CreditCard::MASKED_SERVER_CARD:
return candidate_card->virtual_card_enrollment_state() ==
CreditCard::ENROLLED;
case CreditCard::LOCAL_CARD: {
const CreditCard* server_duplicate =
GetServerCardForLocalCard(candidate_card);
return server_duplicate &&
server_duplicate->virtual_card_enrollment_state() ==
CreditCard::ENROLLED;
}
return ShouldShowVirtualCardOptionForServerCard(candidate_card);
case CreditCard::FULL_SERVER_CARD:
return false;
case CreditCard::VIRTUAL_CARD:
Expand Down Expand Up @@ -707,4 +708,29 @@ void AutofillSuggestionGenerator::SetCardArtURL(
#endif
}

bool AutofillSuggestionGenerator::ShouldShowVirtualCardOptionForServerCard(
const CreditCard* card) const {
CHECK(card);

// If the card is not enrolled into virtual cards, we should not show a
// virtual card suggestion for it.
if (card->virtual_card_enrollment_state() != CreditCard::ENROLLED) {
return false;
}

// We should not show a suggestion for this card if the autofill
// optimization guide returns that this suggestion should be blocked.
if (auto* autofill_optimization_guide =
autofill_client_->GetAutofillOptimizationGuide()) {
bool blocked = autofill_optimization_guide->ShouldBlockFormFieldSuggestion(
autofill_client_->GetLastCommittedPrimaryMainFrameOrigin().GetURL(),
card);
return !blocked;
}

// No conditions to prevent displaying a virtual card suggestion were
// found, so return true.
return true;
}

} // namespace autofill
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ class AutofillSuggestionGenerator {
const CreditCard& credit_card,
bool virtual_card_option) const;

// Returns true if we should show a virtual card option for the server card
// `card`, false otherwise.
bool ShouldShowVirtualCardOptionForServerCard(const CreditCard* card) const;

// Suggestion backend ID to frontend ID mapping. We keep two maps to convert
// back and forth.
std::map<Suggestion::BackendId, int> backend_to_frontend_map_;
Expand Down

0 comments on commit e79028d

Please sign in to comment.