chromium/components/plus_addresses/plus_address_service_unittest.cc

// 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 "components/plus_addresses/plus_address_service.h"

#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/gmock_expected_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "components/affiliations/core/browser/affiliation_utils.h"
#include "components/affiliations/core/browser/mock_affiliation_service.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_test_helpers.h"
#include "components/autofill/core/common/aliases.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/plus_addresses/blocked_facets.pb.h"
#include "components/plus_addresses/features.h"
#include "components/plus_addresses/plus_address_blocklist_data.h"
#include "components/plus_addresses/plus_address_http_client_impl.h"
#include "components/plus_addresses/plus_address_preallocator.h"
#include "components/plus_addresses/plus_address_prefs.h"
#include "components/plus_addresses/plus_address_test_environment.h"
#include "components/plus_addresses/plus_address_test_utils.h"
#include "components/plus_addresses/plus_address_types.h"
#include "components/plus_addresses/settings/fake_plus_address_setting_service.h"
#include "components/plus_addresses/webdata/plus_address_sync_util.h"
#include "components/plus_addresses/webdata/plus_address_table.h"
#include "components/plus_addresses/webdata/plus_address_webdata_service.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/strings/grit/components_strings.h"
#include "components/webdata/common/web_database.h"
#include "components/webdata/common/web_database_backend.h"
#include "components/webdata/common/web_database_service.h"
#include "net/http/http_status_code.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace plus_addresses {

namespace {

PasswordFormClassification;
SuggestionEvent;
FacetURI;
AutofillSuggestionTriggerSource;
EqualsSuggestion;
FormFieldData;
Suggestion;
SuggestionType;
RunOnceCallback;
CreatePreallocatedPlusAddress;
AllOf;
ElementsAre;
Field;
IsEmpty;
NiceMock;
UnorderedElementsAre;

constexpr char kPlusAddress[] =;

auto IsSingleCreatePlusAddressSuggestion() {}

auto EqualsFillPlusAddressSuggestion(std::string_view address) {}

auto IsSingleFillPlusAddressSuggestion(std::string_view address) {}

MATCHER_P(IsPreallocatedPlusAddress, address, "") {}

url::Origin OriginFromFacet(const affiliations::FacetURI& facet) {}

}  // namespace

class MockPlusAddressServiceObserver : public PlusAddressService::Observer {};

class PlusAddressServiceTest : public ::testing::Test {};

TEST_F(PlusAddressServiceTest, BasicTest) {}

TEST_F(PlusAddressServiceTest, GetPlusProfileByFacet) {}

TEST_F(PlusAddressServiceTest, DefaultShouldShowManualFallbackState) {}

// Ensure `ShouldShowManualFallback` is false without a server URL.
TEST_F(PlusAddressServiceTest, ShouldShowManualFallbackNoServer) {}

TEST_F(PlusAddressServiceTest, NoAccountPlusAddressCreation) {}

TEST_F(PlusAddressServiceTest, AbortPlusAddressCreation) {}

// Tests that GetPlusProfiles returns all cached plus profiles.
TEST_F(PlusAddressServiceTest, GetPlusProfiles) {}

// Tests the PlusAddressService ability to make network requests.
class PlusAddressServiceRequestsTest : public PlusAddressServiceTest {};

TEST_F(PlusAddressServiceRequestsTest, ReservePlusAddress_ReturnsUnconfirmed) {}

TEST_F(PlusAddressServiceRequestsTest, ReservePlusAddress_ReturnsConfirmed) {}

TEST_F(PlusAddressServiceRequestsTest, ReservePlusAddress_Fails) {}

TEST_F(PlusAddressServiceRequestsTest, ConfirmPlusAddress_Successful) {}

TEST_F(PlusAddressServiceRequestsTest, ConfirmPlusAddress_Fails) {}

// Doesn't run on ChromeOS since ClearPrimaryAccount() doesn't exist for it.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PlusAddressServiceRequestsTest,
       PrimaryAccountCleared_TogglesPlusAddressCreationOff) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

// Tests that if an account error happens while a server request is ongoing,
// the request ends in an error and the eventual server response is ignored.
TEST_F(PlusAddressServiceRequestsTest,
       PrimaryRefreshTokenError_ResetsHttpRequests) {}

TEST_F(PlusAddressServiceRequestsTest,
       PrimaryRefreshTokenError_TogglesPlusAddressCreationOff) {}

// Tests that ongoing network requests are cancelled on signout.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PlusAddressServiceRequestsTest, OngoingRequestsCancelledOnSignout) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

class PlusAddressServicePreAllocationTest
    : public PlusAddressServiceRequestsTest {};

// Tests that a successful plus address confirmation removes the pre-allocated
// email from the pre-allocated pool of addresses.
TEST_F(PlusAddressServicePreAllocationTest,
       ConfirmationRemovesAllocatedPlusAddress) {}

class PlusAddressHttpForbiddenResponseTest
    : public PlusAddressServiceRequestsTest {};

// Tests that two `HTTP_FORBIDDEN` responses and no successful network request
// lead to a disabled service.
TEST_F(PlusAddressHttpForbiddenResponseTest, RepeatedHttpForbiddenFromConfirm) {}

// Tests that two `HTTP_FORBIDDEN` responses and no successful network request
// do not lead to a disabled service unless the feature param is set.
TEST_F(PlusAddressHttpForbiddenResponseTest,
       RepeatedHttpForbiddenFromConfirmWithDisabledParam) {}

// Tests that two `HTTP_FORBIDDEN` responses and no successful network request
// lead to a disabled service and that other network errors do not have an
// impact.
TEST_F(PlusAddressHttpForbiddenResponseTest, OtherErrorsHaveNoEffect) {}

// Tests a single successful response prevents later `HTTP_FORBIDDEN` responses
// from disabling the service.
TEST_F(PlusAddressHttpForbiddenResponseTest, NoDisablingAfterSuccess) {}

// Tests that communication with `PlusAddressTable` works.
class PlusAddressServiceWebDataTest : public ::testing::Test {};

TEST_F(PlusAddressServiceWebDataTest, OnWebDataChangedBySync) {}

class PlusAddressServiceDisabledTest : public PlusAddressServiceTest {};

TEST_F(PlusAddressServiceDisabledTest, FeatureExplicitlyDisabled) {}

class PlusAddressServiceEnabledTest : public PlusAddressServiceTest {};

TEST_F(PlusAddressServiceEnabledTest, NoSignedInUser) {}

TEST_F(PlusAddressServiceEnabledTest, FullySupported) {}

// `ShouldShowManualFallback` returns false when `origin` is included on
// `kPlusAddressExcludedSites` and true otherwise.
TEST_F(PlusAddressServiceEnabledTest, ExcludedSitesAreNotSupported) {}

// Tests that the blocklist data is available and used to check for domain
// support in the plus address service.
TEST_F(PlusAddressServiceEnabledTest, BlocklistMechanism) {}

// `ShouldShowManualFallback` returns false when `origin` scheme is not http or
// https.
TEST_F(PlusAddressServiceEnabledTest, NonHTTPSchemesAreNotSupported) {}

// `ShouldShowManualFallback` returns false when `origin` is opaque.
TEST_F(PlusAddressServiceEnabledTest, OpaqueOriginIsNotSupported) {}

TEST_F(PlusAddressServiceEnabledTest, OTRWithNoExistingAddress) {}

TEST_F(PlusAddressServiceEnabledTest, OTRWithExistingAddress) {}

TEST_F(PlusAddressServiceEnabledTest, GlobalSettingsToggleOff) {}

TEST_F(PlusAddressServiceEnabledTest,
       GlobalSettingsToggleOffButTheUserHasPlusAddress) {}

TEST_F(PlusAddressServiceEnabledTest, SignedOutGetEmail) {}

TEST_F(PlusAddressServiceEnabledTest, SignedInGetEmail) {}

// Tests that PlusAddresses is "disabled" in the following states:
// - When a primary account is unset after login.
// - When a primary account's refresh token has an auth error.
//
// If PlusAddressService is "disabled" it should stop offering the feature,
// clear any local storage, and not issue network requests.
class PlusAddressServiceSignoutTest : public PlusAddressServiceTest {};

// Doesn't run on ChromeOS since ClearPrimaryAccount() doesn't exist for it.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(PlusAddressServiceSignoutTest, PrimaryAccountCleared_TogglesIsEnabled) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(PlusAddressServiceSignoutTest,
       PrimaryRefreshTokenError_TogglesIsEnabled) {}

// A test fixture with a `PlusAddressService` that is enabled to allow testing
// suggestion generation.
class PlusAddressSuggestionsTest : public PlusAddressServiceTest {};

// Tests that fill plus address suggestions are offered iff the value in the
// focused field matches the prefix of an existing plus address.
TEST_F(PlusAddressSuggestionsTest, SuggestionsForExistingPlusAddress) {}

// Tests that fill plus address suggestions regardless of whether there is
// already text in the field if the trigger source was manual fallback.
TEST_F(PlusAddressSuggestionsTest,
       SuggestionsForExistingPlusAddressWithManualFallback) {}

// Tests that a create plus address suggestion is offered if there is no
// existing plus address for the domain and the field value is empty.
TEST_F(PlusAddressSuggestionsTest, SuggestionsForCreateNewPlusAddress) {}

// Tests that a create plus address suggestion is offered regardless of the
// field's value if there is no existing plus address for the domain and the
// trigger source is a manual fallback.
TEST_F(PlusAddressSuggestionsTest,
       SuggestionsForCreateNewPlusAddressWithManualFallback) {}

// Tests that no suggestions are returned when plus address are disabled.
TEST_F(PlusAddressSuggestionsTest, NoSuggestionsWhenDisabled) {}

// Tests that the only password form on which create suggestions are offered on
// click is a signup form if the username field is the focused field, but that
// filling suggestions are always offered.
TEST_F(PlusAddressSuggestionsTest, SuggestionsOnPasswordFormsUsernameField) {}

// Tests that creation is offered on all password forms if the focused field is
// not the username field.
TEST_F(PlusAddressSuggestionsTest, SuggestionsOnPasswordFormsNonUsernameField) {}

// Tests that plus address creation is offered on signup forms and single
// username forms even if the focused field is the username field if
// `kPlusAddressOfferCreationOnSingleUsernameForms` is enabled.
TEST_F(PlusAddressSuggestionsTest,
       SuggestionsOnPasswordFormWithSingleUsernameCreationEnabled) {}

// Tests that create suggestions are offered regardless of form type if the
// trigger source is a manual fallback.
TEST_F(PlusAddressSuggestionsTest,
       SuggestionsOnPasswordFormsWithManualFallbacks) {}

// Tests the content of the "Manage plus addresses..." suggestion.
TEST_F(PlusAddressSuggestionsTest, GetManagePlusAddressSuggestion) {}

TEST_F(PlusAddressSuggestionsTest, OnClickedRefreshInlineSuggestion) {}

class PlusAddressAffiliationsTest : public PlusAddressServiceTest {};

// Verifies that affiliated PSL suggestions are returned. It also validates that
// entries in the PSL extensions list are respected.
TEST_F(PlusAddressAffiliationsTest, GetAffiliatedPSLSuggestions) {}

// Verifies that affiliated group suggestions are returned.
TEST_F(PlusAddressAffiliationsTest, GetAffiliatedGroupSuggestions) {}

// Tests that filling suggestions are returned even if they are affiliated
// matches and the profile is off the record.
TEST_F(PlusAddressAffiliationsTest,
       GetSuggestionsIsAffiliationAwareWhenOffTheRecord) {}

// Tests that no creation suggestion is offered when the profile is off the
// record.
TEST_F(PlusAddressAffiliationsTest,
       GetSuggestionsDoesNotOfferCreationWhenOffTheRecord) {}

// Tests that no creation suggestion is offered when the global toggle is off.
TEST_F(PlusAddressAffiliationsTest,
       GetSuggestionsDoesNotOfferCreationWhenToggleIsOff) {}

// Tests that filling suggestions are returned even if they are affiliated
// matches and the global settings toggle is off.
TEST_F(PlusAddressAffiliationsTest,
       FillingSuggestionsAreOfferedWhenGlobalToggleIsOff) {}

// Verifies that no affiliated suggestions are returned when there are no
// matches. Instead, the creation chip is offered.
TEST_F(PlusAddressAffiliationsTest, GetEmptyAffiliatedSuggestionMatches) {}

// Verifies that affiliated plus profiles are returned.
TEST_F(PlusAddressAffiliationsTest, GetAffiliatedPSLProfiles) {}

// Verifies that the service returns profiles from affiliated domains even if
// the requested domain doesn't have an affiliated plus address.
TEST_F(PlusAddressAffiliationsTest,
       AffiliatedProfilesForDomainWithNoPlusAddresses) {}

}  // namespace plus_addresses