blob: 953fb245cc565a888e78841af082f2a95619dfae [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_mock_time_message_loop_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_service.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace password_manager {
namespace {
using StrategyOnCacheMiss = AffiliationService::StrategyOnCacheMiss;
class MockAffiliationService : public testing::StrictMock<AffiliationService> {
public:
MockAffiliationService() : testing::StrictMock<AffiliationService>(nullptr) {
testing::DefaultValue<AffiliatedFacets>::Set(AffiliatedFacets());
}
~MockAffiliationService() override {}
MOCK_METHOD2(OnGetAffiliationsAndBrandingCalled,
AffiliatedFacets(const FacetURI&, StrategyOnCacheMiss));
MOCK_METHOD2(Prefetch, void(const FacetURI&, const base::Time&));
MOCK_METHOD2(CancelPrefetch, void(const FacetURI&, const base::Time&));
MOCK_METHOD1(TrimCacheForFacetURI, void(const FacetURI&));
void GetAffiliationsAndBranding(
const FacetURI& facet_uri,
StrategyOnCacheMiss cache_miss_strategy,
const ResultCallback& result_callback) override {
AffiliatedFacets affiliation =
OnGetAffiliationsAndBrandingCalled(facet_uri, cache_miss_strategy);
result_callback.Run(affiliation, !affiliation.empty());
}
void ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
const FacetURI& expected_facet_uri,
StrategyOnCacheMiss expected_cache_miss_strategy,
const AffiliatedFacets& affiliations_to_return) {
EXPECT_CALL(*this, OnGetAffiliationsAndBrandingCalled(
expected_facet_uri, expected_cache_miss_strategy))
.WillOnce(testing::Return(affiliations_to_return));
}
void ExpectCallToGetAffiliationsAndBrandingAndEmulateFailure(
const FacetURI& expected_facet_uri,
StrategyOnCacheMiss expected_cache_miss_strategy) {
EXPECT_CALL(*this, OnGetAffiliationsAndBrandingCalled(
expected_facet_uri, expected_cache_miss_strategy))
.WillOnce(testing::Return(AffiliatedFacets()));
}
void ExpectCallToPrefetch(const char* expected_facet_uri_spec) {
EXPECT_CALL(*this,
Prefetch(FacetURI::FromCanonicalSpec(expected_facet_uri_spec),
base::Time::Max()))
.RetiresOnSaturation();
}
void ExpectCallToCancelPrefetch(const char* expected_facet_uri_spec) {
EXPECT_CALL(*this, CancelPrefetch(
FacetURI::FromCanonicalSpec(expected_facet_uri_spec),
base::Time::Max()))
.RetiresOnSaturation();
}
void ExpectCallToTrimCacheForFacetURI(const char* expected_facet_uri_spec) {
EXPECT_CALL(*this, TrimCacheForFacetURI(FacetURI::FromCanonicalSpec(
expected_facet_uri_spec)))
.RetiresOnSaturation();
}
private:
DISALLOW_ASSIGN(MockAffiliationService);
};
const char kTestWebFacetURIAlpha1[] = "https://one.alpha.example.com";
const char kTestWebFacetURIAlpha2[] = "https://two.alpha.example.com";
const char kTestAndroidFacetURIAlpha3[] =
"android://hash@com.example.alpha.android";
const char kTestAndroidFacetNameAlpha3[] = "Facet Name Alpha 3";
const char kTestAndroidFacetIconURLAlpha3[] = "https://example.com/alpha_3.png";
const char kTestWebRealmAlpha1[] = "https://one.alpha.example.com/";
const char kTestWebRealmAlpha2[] = "https://two.alpha.example.com/";
const char kTestAndroidRealmAlpha3[] =
"android://hash@com.example.alpha.android/";
const char kTestWebFacetURIBeta1[] = "https://one.beta.example.com";
const char kTestAndroidFacetURIBeta2[] =
"android://hash@com.example.beta.android";
const char kTestAndroidFacetNameBeta2[] = "Facet Name Beta 2";
const char kTestAndroidFacetIconURLBeta2[] = "https://example.com/beta_2.png";
const char kTestAndroidFacetURIBeta3[] =
"android://hash@com.yetanother.beta.android";
const char kTestAndroidFacetNameBeta3[] = "Facet Name Beta 3";
const char kTestAndroidFacetIconURLBeta3[] = "https://example.com/beta_3.png";
const char kTestWebRealmBeta1[] = "https://one.beta.example.com/";
const char kTestAndroidRealmBeta2[] =
"android://hash@com.example.beta.android/";
const char kTestAndroidRealmBeta3[] =
"android://hash@com.yetanother.beta.android/";
const char kTestAndroidFacetURIGamma[] =
"android://hash@com.example.gamma.android";
const char kTestAndroidRealmGamma[] =
"android://hash@com.example.gamma.android";
const char kTestUsername[] = "JohnDoe";
const char kTestPassword[] = "secret";
AffiliatedFacets GetTestEquivalenceClassAlpha() {
return {
{FacetURI::FromCanonicalSpec(kTestWebFacetURIAlpha1)},
{FacetURI::FromCanonicalSpec(kTestWebFacetURIAlpha2)},
{FacetURI::FromCanonicalSpec(kTestAndroidFacetURIAlpha3),
FacetBrandingInfo{kTestAndroidFacetNameAlpha3,
GURL(kTestAndroidFacetIconURLAlpha3)}},
};
}
AffiliatedFacets GetTestEquivalenceClassBeta() {
return {
{FacetURI::FromCanonicalSpec(kTestWebFacetURIBeta1)},
{FacetURI::FromCanonicalSpec(kTestAndroidFacetURIBeta2),
FacetBrandingInfo{kTestAndroidFacetNameBeta2,
GURL(kTestAndroidFacetIconURLBeta2)}},
{FacetURI::FromCanonicalSpec(kTestAndroidFacetURIBeta3),
FacetBrandingInfo{kTestAndroidFacetNameBeta3,
GURL(kTestAndroidFacetIconURLBeta3)}},
};
}
autofill::PasswordForm GetTestAndroidCredentials(const char* signon_realm) {
autofill::PasswordForm form;
form.scheme = autofill::PasswordForm::SCHEME_HTML;
form.signon_realm = signon_realm;
form.username_value = base::ASCIIToUTF16(kTestUsername);
form.password_value = base::ASCIIToUTF16(kTestPassword);
return form;
}
autofill::PasswordForm GetTestBlacklistedAndroidCredentials(
const char* signon_realm) {
autofill::PasswordForm form = GetTestAndroidCredentials(signon_realm);
form.blacklisted_by_user = true;
return form;
}
PasswordStore::FormDigest GetTestObservedWebForm(const char* signon_realm,
const char* origin) {
return {autofill::PasswordForm::SCHEME_HTML, signon_realm,
origin ? GURL(origin) : GURL()};
}
} // namespace
class AffiliatedMatchHelperTest : public testing::Test {
public:
AffiliatedMatchHelperTest()
: expecting_result_callback_(false), mock_affiliation_service_(nullptr) {}
~AffiliatedMatchHelperTest() override {}
protected:
void RunDeferredInitialization() {
mock_time_task_runner_->RunUntilIdle();
ASSERT_EQ(AffiliatedMatchHelper::kInitializationDelayOnStartup,
mock_time_task_runner_->NextPendingTaskDelay());
mock_time_task_runner_->FastForwardBy(
AffiliatedMatchHelper::kInitializationDelayOnStartup);
}
void ExpectNoDeferredTasks() {
mock_time_task_runner_->RunUntilIdle();
ASSERT_FALSE(mock_time_task_runner_->HasPendingTask());
}
void RunUntilIdle() {
// TODO(gab): Add support for base::RunLoop().RunUntilIdle() in scope of
// ScopedMockTimeMessageLoopTaskRunner and use it instead of this helper
// method.
mock_time_task_runner_->RunUntilIdle();
}
void AddLogin(const autofill::PasswordForm& form) {
password_store_->AddLogin(form);
RunUntilIdle();
}
void UpdateLoginWithPrimaryKey(
const autofill::PasswordForm& new_form,
const autofill::PasswordForm& old_primary_key) {
password_store_->UpdateLoginWithPrimaryKey(new_form, old_primary_key);
RunUntilIdle();
}
void RemoveLogin(const autofill::PasswordForm& form) {
password_store_->RemoveLogin(form);
RunUntilIdle();
}
void AddAndroidAndNonAndroidTestLogins() {
AddLogin(GetTestAndroidCredentials(kTestAndroidRealmAlpha3));
AddLogin(GetTestAndroidCredentials(kTestAndroidRealmBeta2));
AddLogin(GetTestBlacklistedAndroidCredentials(kTestAndroidRealmBeta3));
AddLogin(GetTestAndroidCredentials(kTestAndroidRealmGamma));
AddLogin(GetTestAndroidCredentials(kTestWebRealmAlpha1));
AddLogin(GetTestAndroidCredentials(kTestWebRealmAlpha2));
}
void RemoveAndroidAndNonAndroidTestLogins() {
RemoveLogin(GetTestAndroidCredentials(kTestAndroidRealmAlpha3));
RemoveLogin(GetTestAndroidCredentials(kTestAndroidRealmBeta2));
RemoveLogin(GetTestBlacklistedAndroidCredentials(kTestAndroidRealmBeta3));
RemoveLogin(GetTestAndroidCredentials(kTestAndroidRealmGamma));
RemoveLogin(GetTestAndroidCredentials(kTestWebRealmAlpha1));
RemoveLogin(GetTestAndroidCredentials(kTestWebRealmAlpha2));
}
void ExpectPrefetchForAndroidTestLogins() {
mock_affiliation_service()->ExpectCallToPrefetch(
kTestAndroidFacetURIAlpha3);
mock_affiliation_service()->ExpectCallToPrefetch(kTestAndroidFacetURIBeta2);
mock_affiliation_service()->ExpectCallToPrefetch(kTestAndroidFacetURIBeta3);
mock_affiliation_service()->ExpectCallToPrefetch(kTestAndroidFacetURIGamma);
}
void ExpectCancelPrefetchForAndroidTestLogins() {
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIAlpha3);
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIBeta2);
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIBeta3);
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIGamma);
}
void ExpectTrimCacheForAndroidTestLogins() {
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIAlpha3);
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIBeta2);
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIBeta3);
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIGamma);
}
std::vector<std::string> GetAffiliatedAndroidRealms(
const PasswordStore::FormDigest& observed_form) {
expecting_result_callback_ = true;
match_helper()->GetAffiliatedAndroidRealms(
observed_form,
base::Bind(&AffiliatedMatchHelperTest::OnAffiliatedRealmsCallback,
base::Unretained(this)));
RunUntilIdle();
EXPECT_FALSE(expecting_result_callback_);
return last_result_realms_;
}
std::vector<std::string> GetAffiliatedWebRealms(
const PasswordStore::FormDigest& android_form) {
expecting_result_callback_ = true;
match_helper()->GetAffiliatedWebRealms(
android_form,
base::Bind(&AffiliatedMatchHelperTest::OnAffiliatedRealmsCallback,
base::Unretained(this)));
RunUntilIdle();
EXPECT_FALSE(expecting_result_callback_);
return last_result_realms_;
}
std::vector<std::unique_ptr<autofill::PasswordForm>>
InjectAffiliationAndBrandingInformation(
std::vector<std::unique_ptr<autofill::PasswordForm>> forms) {
expecting_result_callback_ = true;
match_helper()->InjectAffiliationAndBrandingInformation(
std::move(forms),
base::Bind(&AffiliatedMatchHelperTest::OnFormsCallback,
base::Unretained(this)));
RunUntilIdle();
EXPECT_FALSE(expecting_result_callback_);
return std::move(last_result_forms_);
}
void DestroyMatchHelper() { match_helper_.reset(); }
TestPasswordStore* password_store() { return password_store_.get(); }
MockAffiliationService* mock_affiliation_service() {
return mock_affiliation_service_;
}
AffiliatedMatchHelper* match_helper() { return match_helper_.get(); }
private:
void OnAffiliatedRealmsCallback(
const std::vector<std::string>& affiliated_realms) {
EXPECT_TRUE(expecting_result_callback_);
expecting_result_callback_ = false;
last_result_realms_ = affiliated_realms;
}
void OnFormsCallback(
std::vector<std::unique_ptr<autofill::PasswordForm>> forms) {
EXPECT_TRUE(expecting_result_callback_);
expecting_result_callback_ = false;
last_result_forms_.swap(forms);
}
// testing::Test:
void SetUp() override {
std::unique_ptr<MockAffiliationService> service(
new MockAffiliationService());
mock_affiliation_service_ = service.get();
password_store_ = new TestPasswordStore;
password_store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
match_helper_.reset(
new AffiliatedMatchHelper(password_store_.get(), std::move(service)));
}
void TearDown() override {
match_helper_.reset();
password_store_->ShutdownOnUIThread();
password_store_ = nullptr;
// Clean up on the background thread.
RunUntilIdle();
}
base::test::ScopedTaskEnvironment task_environment_;
base::ScopedMockTimeMessageLoopTaskRunner mock_time_task_runner_;
std::vector<std::string> last_result_realms_;
std::vector<std::unique_ptr<autofill::PasswordForm>> last_result_forms_;
bool expecting_result_callback_;
scoped_refptr<TestPasswordStore> password_store_;
std::unique_ptr<AffiliatedMatchHelper> match_helper_;
// Owned by |match_helper_|.
MockAffiliationService* mock_affiliation_service_;
DISALLOW_COPY_AND_ASSIGN(AffiliatedMatchHelperTest);
};
// GetAffiliatedAndroidRealm* tests verify that GetAffiliatedAndroidRealms()
// returns the realms of affiliated Android applications, but only Android
// applications, and only if the observed form is a secure HTML login form.
TEST_F(AffiliatedMatchHelperTest, GetAffiliatedAndroidRealmsYieldsResults) {
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestWebFacetURIBeta1),
StrategyOnCacheMiss::FAIL, GetTestEquivalenceClassBeta());
EXPECT_THAT(GetAffiliatedAndroidRealms(
GetTestObservedWebForm(kTestWebRealmBeta1, nullptr)),
testing::UnorderedElementsAre(kTestAndroidRealmBeta2,
kTestAndroidRealmBeta3));
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedAndroidRealmsYieldsOnlyAndroidApps) {
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestWebFacetURIAlpha1),
StrategyOnCacheMiss::FAIL, GetTestEquivalenceClassAlpha());
// This verifies that |kTestWebRealmAlpha2| is not returned.
EXPECT_THAT(GetAffiliatedAndroidRealms(
GetTestObservedWebForm(kTestWebRealmAlpha1, nullptr)),
testing::UnorderedElementsAre(kTestAndroidRealmAlpha3));
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedAndroidRealmsYieldsEmptyResultsForHTTPBasicAuthForms) {
PasswordStore::FormDigest http_auth_observed_form(
GetTestObservedWebForm(kTestWebRealmAlpha1, nullptr));
http_auth_observed_form.scheme = autofill::PasswordForm::SCHEME_BASIC;
EXPECT_THAT(GetAffiliatedAndroidRealms(http_auth_observed_form),
testing::IsEmpty());
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedAndroidRealmsYieldsEmptyResultsForHTTPDigestAuthForms) {
PasswordStore::FormDigest http_auth_observed_form(
GetTestObservedWebForm(kTestWebRealmAlpha1, nullptr));
http_auth_observed_form.scheme = autofill::PasswordForm::SCHEME_DIGEST;
EXPECT_THAT(GetAffiliatedAndroidRealms(http_auth_observed_form),
testing::IsEmpty());
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedAndroidRealmsYieldsEmptyResultsForAndroidKeyedForms) {
PasswordStore::FormDigest android_observed_form(
GetTestAndroidCredentials(kTestAndroidRealmBeta2));
EXPECT_THAT(GetAffiliatedAndroidRealms(android_observed_form),
testing::IsEmpty());
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedAndroidRealmsYieldsEmptyResultsWhenNoPrefetch) {
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndEmulateFailure(
FacetURI::FromCanonicalSpec(kTestWebFacetURIAlpha1),
StrategyOnCacheMiss::FAIL);
EXPECT_THAT(GetAffiliatedAndroidRealms(
GetTestObservedWebForm(kTestWebRealmAlpha1, nullptr)),
testing::IsEmpty());
}
// GetAffiliatedWebRealms* tests verify that GetAffiliatedWebRealms() returns
// the realms of web sites affiliated with the given Android application, but
// only web sites, and only if an Android application is queried.
TEST_F(AffiliatedMatchHelperTest, GetAffiliatedWebRealmsYieldsResults) {
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIAlpha3),
StrategyOnCacheMiss::FETCH_OVER_NETWORK,
GetTestEquivalenceClassAlpha());
PasswordStore::FormDigest android_form(
GetTestAndroidCredentials(kTestAndroidRealmAlpha3));
EXPECT_THAT(
GetAffiliatedWebRealms(android_form),
testing::UnorderedElementsAre(kTestWebRealmAlpha1, kTestWebRealmAlpha2));
}
TEST_F(AffiliatedMatchHelperTest, GetAffiliatedWebRealmsYieldsOnlyWebsites) {
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIBeta2),
StrategyOnCacheMiss::FETCH_OVER_NETWORK,
GetTestEquivalenceClassBeta());
PasswordStore::FormDigest android_form(
GetTestAndroidCredentials(kTestAndroidRealmBeta2));
// This verifies that |kTestAndroidRealmBeta3| is not returned.
EXPECT_THAT(GetAffiliatedWebRealms(android_form),
testing::UnorderedElementsAre(kTestWebRealmBeta1));
}
TEST_F(AffiliatedMatchHelperTest,
GetAffiliatedWebRealmsYieldsEmptyResultsForWebKeyedForms) {
EXPECT_THAT(GetAffiliatedWebRealms(
GetTestObservedWebForm(kTestWebRealmBeta1, nullptr)),
testing::IsEmpty());
}
// Verifies that InjectAffiliationAndBrandingInformation() injects the realms of
// web sites affiliated with the given Android application into the password
// forms, as well as branding information corresponding to the application, if
// any.
TEST_F(AffiliatedMatchHelperTest, InjectAffiliationAndBrandingInformation) {
std::vector<std::unique_ptr<autofill::PasswordForm>> forms;
forms.push_back(std::make_unique<autofill::PasswordForm>(
GetTestAndroidCredentials(kTestAndroidRealmAlpha3)));
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIAlpha3),
StrategyOnCacheMiss::FAIL, GetTestEquivalenceClassAlpha());
forms.push_back(std::make_unique<autofill::PasswordForm>(
GetTestAndroidCredentials(kTestAndroidRealmBeta2)));
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIBeta2),
StrategyOnCacheMiss::FAIL, GetTestEquivalenceClassBeta());
forms.push_back(std::make_unique<autofill::PasswordForm>(
GetTestAndroidCredentials(kTestAndroidRealmBeta3)));
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndSucceedWithResult(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIBeta3),
StrategyOnCacheMiss::FAIL, GetTestEquivalenceClassBeta());
forms.push_back(std::make_unique<autofill::PasswordForm>(
GetTestAndroidCredentials(kTestAndroidRealmGamma)));
mock_affiliation_service()
->ExpectCallToGetAffiliationsAndBrandingAndEmulateFailure(
FacetURI::FromCanonicalSpec(kTestAndroidFacetURIGamma),
StrategyOnCacheMiss::FAIL);
PasswordStore::FormDigest digest =
GetTestObservedWebForm(kTestWebRealmBeta1, nullptr);
autofill::PasswordForm web_form;
web_form.scheme = digest.scheme;
web_form.signon_realm = digest.signon_realm;
web_form.origin = digest.origin;
forms.push_back(std::make_unique<autofill::PasswordForm>(web_form));
size_t expected_form_count = forms.size();
std::vector<std::unique_ptr<autofill::PasswordForm>> results(
InjectAffiliationAndBrandingInformation(std::move(forms)));
ASSERT_EQ(expected_form_count, results.size());
EXPECT_THAT(results[0]->affiliated_web_realm,
testing::AnyOf(kTestWebRealmAlpha1, kTestWebRealmAlpha2));
EXPECT_EQ(kTestAndroidFacetNameAlpha3, results[0]->app_display_name);
EXPECT_EQ(kTestAndroidFacetIconURLAlpha3,
results[0]->app_icon_url.possibly_invalid_spec());
EXPECT_THAT(results[1]->affiliated_web_realm,
testing::Eq(kTestWebRealmBeta1));
EXPECT_EQ(kTestAndroidFacetNameBeta2, results[1]->app_display_name);
EXPECT_EQ(kTestAndroidFacetIconURLBeta2,
results[1]->app_icon_url.possibly_invalid_spec());
EXPECT_THAT(results[2]->affiliated_web_realm,
testing::Eq(kTestWebRealmBeta1));
EXPECT_EQ(kTestAndroidFacetNameBeta3, results[2]->app_display_name);
EXPECT_EQ(kTestAndroidFacetIconURLBeta3,
results[2]->app_icon_url.possibly_invalid_spec());
EXPECT_THAT(results[3]->affiliated_web_realm, testing::IsEmpty());
EXPECT_THAT(results[4]->affiliated_web_realm, testing::IsEmpty());
}
// Note: IsValidWebCredential() is tested as part of GetAffiliatedAndroidRealms
// tests above.
TEST_F(AffiliatedMatchHelperTest, IsValidAndroidCredential) {
EXPECT_FALSE(AffiliatedMatchHelper::IsValidAndroidCredential(
GetTestObservedWebForm(kTestWebRealmBeta1, nullptr)));
PasswordStore::FormDigest android_credential(
GetTestAndroidCredentials(kTestAndroidRealmBeta2));
EXPECT_TRUE(
AffiliatedMatchHelper::IsValidAndroidCredential(android_credential));
}
// Verifies that affiliations for Android applications with pre-existing
// credentials on start-up are prefetched.
TEST_F(
AffiliatedMatchHelperTest,
PrefetchAffiliationsAndBrandingForPreexistingAndroidCredentialsOnStartup) {
AddAndroidAndNonAndroidTestLogins();
match_helper()->Initialize();
RunUntilIdle();
ExpectPrefetchForAndroidTestLogins();
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
}
// Stores credentials for Android applications between Initialize() and
// DoDeferredInitialization(). Verifies that corresponding affiliation
// information gets prefetched.
TEST_F(AffiliatedMatchHelperTest,
PrefetchAffiliationsForAndroidCredentialsAddedInInitializationDelay) {
match_helper()->Initialize();
RunUntilIdle();
AddAndroidAndNonAndroidTestLogins();
ExpectPrefetchForAndroidTestLogins();
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
}
// Stores credentials for Android applications after DoDeferredInitialization().
// Verifies that corresponding affiliation information gets prefetched.
TEST_F(AffiliatedMatchHelperTest,
PrefetchAffiliationsForAndroidCredentialsAddedAfterInitialization) {
match_helper()->Initialize();
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
ExpectPrefetchForAndroidTestLogins();
AddAndroidAndNonAndroidTestLogins();
}
TEST_F(AffiliatedMatchHelperTest,
CancelPrefetchingAffiliationsAndBrandingForRemovedAndroidCredentials) {
AddAndroidAndNonAndroidTestLogins();
match_helper()->Initialize();
ExpectPrefetchForAndroidTestLogins();
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
ExpectCancelPrefetchForAndroidTestLogins();
ExpectTrimCacheForAndroidTestLogins();
RemoveAndroidAndNonAndroidTestLogins();
}
// Verify that whenever the primary key is updated for a credential (in which
// case both REMOVE and ADD change notifications are sent out), then Prefetch()
// is called in response to the addition before the call to
// TrimCacheForFacetURI() in response to the removal, so that cached data is not
// deleted and then immediately re-fetched.
TEST_F(AffiliatedMatchHelperTest, PrefetchBeforeTrimForPrimaryKeyUpdates) {
AddAndroidAndNonAndroidTestLogins();
match_helper()->Initialize();
ExpectPrefetchForAndroidTestLogins();
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIAlpha3);
{
testing::InSequence in_sequence;
mock_affiliation_service()->ExpectCallToPrefetch(
kTestAndroidFacetURIAlpha3);
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIAlpha3);
}
autofill::PasswordForm old_form(
GetTestAndroidCredentials(kTestAndroidRealmAlpha3));
autofill::PasswordForm new_form(old_form);
new_form.username_value = base::ASCIIToUTF16("NewUserName");
UpdateLoginWithPrimaryKey(new_form, old_form);
}
// Stores and removes four credentials for the same an Android application, and
// expects that Prefetch() and CancelPrefetch() will each be called four times.
TEST_F(AffiliatedMatchHelperTest,
DuplicateCredentialsArePrefetchWithMultiplicity) {
EXPECT_CALL(*mock_affiliation_service(),
Prefetch(FacetURI::FromCanonicalSpec(kTestAndroidFacetURIAlpha3),
base::Time::Max()))
.Times(4);
autofill::PasswordForm android_form(
GetTestAndroidCredentials(kTestAndroidRealmAlpha3));
AddLogin(android_form);
// Store two credentials before initialization.
autofill::PasswordForm android_form2(android_form);
android_form2.username_value = base::ASCIIToUTF16("JohnDoe2");
AddLogin(android_form2);
match_helper()->Initialize();
RunUntilIdle();
// Store one credential between initialization and deferred initialization.
autofill::PasswordForm android_form3(android_form);
android_form3.username_value = base::ASCIIToUTF16("JohnDoe3");
AddLogin(android_form3);
ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
// Store one credential after deferred initialization.
autofill::PasswordForm android_form4(android_form);
android_form4.username_value = base::ASCIIToUTF16("JohnDoe4");
AddLogin(android_form4);
for (size_t i = 0; i < 4; ++i) {
mock_affiliation_service()->ExpectCallToCancelPrefetch(
kTestAndroidFacetURIAlpha3);
mock_affiliation_service()->ExpectCallToTrimCacheForFacetURI(
kTestAndroidFacetURIAlpha3);
}
RemoveLogin(android_form);
RemoveLogin(android_form2);
RemoveLogin(android_form3);
RemoveLogin(android_form4);
}
TEST_F(AffiliatedMatchHelperTest, DestroyBeforeDeferredInitialization) {
match_helper()->Initialize();
RunUntilIdle();
DestroyMatchHelper();
ASSERT_NO_FATAL_FAILURE(ExpectNoDeferredTasks());
}
} // namespace password_manager