1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/sync/profile_sync_service.h"
12 #include "chrome/browser/sync/test/integration/autofill_helper.h"
13 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
14 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
15 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
16 #include "chrome/browser/sync/test/integration/sync_test.h"
17 #include "chrome/browser/web_data_service_factory.h"
18 #include "components/autofill/core/browser/credit_card.h"
19 #include "components/autofill/core/browser/field_types.h"
20 #include "components/autofill/core/browser/personal_data_manager.h"
21 #include "components/autofill/core/common/autofill_pref_names.h"
22 #include "content/public/browser/notification_service.h"
23 #include "sync/internal_api/public/base/model_type.h"
24 #include "sync/test/fake_server/fake_server_entity.h"
25 #include "sync/test/fake_server/unique_client_entity.h"
27 using autofill_helper::GetPersonalDataManager
;
28 using sync_integration_test_util::AwaitCommitActivityCompletion
;
32 // Setting the Preferences files contents to this string (before Profile is
33 // created) will bypass the Sync experiment logic for enabling this feature.
34 const char kWalletSyncEnabledPreferencesContents
[] =
35 "{\"autofill\": { \"wallet_import_sync_experiment_enabled\": true } }";
37 const char kWalletSyncExperimentTag
[] = "wallet_sync";
39 const char kDefaultCardID
[] = "wallet entity ID";
40 const int kDefaultCardExpMonth
= 8;
41 const int kDefaultCardExpYear
= 2087;
42 const char kDefaultCardLastFour
[] = "1234";
43 const char kDefaultCardName
[] = "Patrick Valenzuela";
44 const sync_pb::WalletMaskedCreditCard_WalletCardType kDefaultCardType
=
45 sync_pb::WalletMaskedCreditCard::AMEX
;
47 void AddDefaultCard(fake_server::FakeServer
* server
) {
48 sync_pb::EntitySpecifics specifics
;
49 sync_pb::AutofillWalletSpecifics
* wallet_specifics
=
50 specifics
.mutable_autofill_wallet();
51 wallet_specifics
->set_type(
52 sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD
);
54 sync_pb::WalletMaskedCreditCard
* credit_card
=
55 wallet_specifics
->mutable_masked_card();
56 credit_card
->set_id(kDefaultCardID
);
57 credit_card
->set_exp_month(kDefaultCardExpMonth
);
58 credit_card
->set_exp_year(kDefaultCardExpYear
);
59 credit_card
->set_last_four(kDefaultCardLastFour
);
60 credit_card
->set_name_on_card(kDefaultCardName
);
61 credit_card
->set_status(sync_pb::WalletMaskedCreditCard::VALID
);
62 credit_card
->set_type(kDefaultCardType
);
64 server
->InjectEntity(fake_server::UniqueClientEntity::CreateForInjection(
71 class SingleClientWalletSyncTest
: public SyncTest
{
73 SingleClientWalletSyncTest() : SyncTest(SINGLE_CLIENT
) {}
74 ~SingleClientWalletSyncTest() override
{}
76 void TriggerSyncCycle() {
77 // Note: we use the experiments type here as we want to be able to trigger a
78 // sync cycle even when wallet is not enabled yet.
79 const syncer::ModelTypeSet
kExperimentsType(syncer::EXPERIMENTS
);
80 TriggerSyncForModelTypes(0, kExperimentsType
);
84 DISALLOW_COPY_AND_ASSIGN(SingleClientWalletSyncTest
);
87 // Checker that will wait until an asynchronous Wallet datatype enable event
88 // happens, or times out.
89 class WalletEnabledChecker
: public SingleClientStatusChangeChecker
{
91 WalletEnabledChecker()
92 : SingleClientStatusChangeChecker(
93 sync_datatype_helper::test()->GetSyncService(0)) {}
94 ~WalletEnabledChecker() override
{}
96 // SingleClientStatusChangeChecker overrides.
97 bool IsExitConditionSatisfied() override
{
98 return service()->GetActiveDataTypes().Has(syncer::AUTOFILL_WALLET_DATA
);
100 std::string
GetDebugMessage() const override
{
101 return "Waiting for wallet enable event.";
105 // Checker that will wait until an asynchronous Wallet datatype disable event
106 // happens, or times out
107 class WalletDisabledChecker
: public SingleClientStatusChangeChecker
{
109 WalletDisabledChecker()
110 : SingleClientStatusChangeChecker(
111 sync_datatype_helper::test()->GetSyncService(0)) {}
112 ~WalletDisabledChecker() override
{}
114 // SingleClientStatusChangeChecker overrides.
115 bool IsExitConditionSatisfied() override
{
116 return !service()->GetActiveDataTypes().Has(syncer::AUTOFILL_WALLET_DATA
);
118 std::string
GetDebugMessage() const override
{
119 return "Waiting for wallet disable event.";
123 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
, DisabledByDefault
) {
124 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
125 // The type should not be enabled without the experiment enabled.
126 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
127 syncer::AUTOFILL_WALLET_DATA
));
128 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
129 syncer::AUTOFILL_WALLET_METADATA
));
132 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
, EnabledViaPreference
) {
133 SetPreexistingPreferencesFileContents(kWalletSyncEnabledPreferencesContents
);
134 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
135 // The type should not be enabled without the experiment enabled.
136 ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
137 syncer::AUTOFILL_WALLET_DATA
));
138 // TODO(pvalenzuela): Assert that the local root node for AUTOFILL_WALLET_DATA
140 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
141 syncer::AUTOFILL_WALLET_METADATA
));
144 // Tests that an experiment received at sync startup time (during sign-in)
145 // enables the wallet datatype.
146 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
,
147 EnabledViaExperimentStartup
) {
148 sync_pb::EntitySpecifics experiment_entity
;
149 sync_pb::ExperimentsSpecifics
* experiment_specifics
=
150 experiment_entity
.mutable_experiments();
151 experiment_specifics
->mutable_wallet_sync()->set_enabled(true);
152 GetFakeServer()->InjectEntity(
153 fake_server::UniqueClientEntity::CreateForInjection(
154 kWalletSyncExperimentTag
,
157 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
158 ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
159 syncer::AUTOFILL_WALLET_DATA
));
160 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
161 syncer::AUTOFILL_WALLET_METADATA
));
164 // Tests receiving an enable experiment at runtime, followed by a disabled
165 // experiment, and verifies the datatype is enabled/disabled as necessary.
166 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
,
167 EnabledDisabledViaExperiment
) {
168 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
169 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().
170 Has(syncer::AUTOFILL_WALLET_DATA
));
172 sync_pb::EntitySpecifics experiment_entity
;
173 sync_pb::ExperimentsSpecifics
* experiment_specifics
=
174 experiment_entity
.mutable_experiments();
176 // First enable the experiment.
177 experiment_specifics
->mutable_wallet_sync()->set_enabled(true);
178 GetFakeServer()->InjectEntity(
179 fake_server::UniqueClientEntity::CreateForInjection(
180 kWalletSyncExperimentTag
, experiment_entity
));
183 WalletEnabledChecker enabled_checker
;
184 enabled_checker
.Wait();
185 ASSERT_FALSE(enabled_checker
.TimedOut());
186 ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
187 syncer::AUTOFILL_WALLET_DATA
));
188 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
189 syncer::AUTOFILL_WALLET_METADATA
));
191 // Then disable the experiment.
192 experiment_specifics
->mutable_wallet_sync()->set_enabled(false);
193 GetFakeServer()->InjectEntity(
194 fake_server::UniqueClientEntity::CreateForInjection(
195 kWalletSyncExperimentTag
, experiment_entity
));
198 WalletDisabledChecker disable_checker
;
199 disable_checker
.Wait();
200 ASSERT_FALSE(disable_checker
.TimedOut());
201 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().
202 Has(syncer::AUTOFILL_WALLET_DATA
));
203 ASSERT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
204 syncer::AUTOFILL_WALLET_METADATA
));
207 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
, Download
) {
208 SetPreexistingPreferencesFileContents(kWalletSyncEnabledPreferencesContents
);
209 AddDefaultCard(GetFakeServer());
210 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
212 autofill::PersonalDataManager
* pdm
= GetPersonalDataManager(0);
213 ASSERT_TRUE(pdm
!= nullptr);
214 std::vector
<autofill::CreditCard
*> cards
= pdm
->GetCreditCards();
215 ASSERT_EQ(1uL, cards
.size());
217 autofill::CreditCard
* card
= cards
[0];
218 ASSERT_EQ(autofill::CreditCard::MASKED_SERVER_CARD
, card
->record_type());
219 ASSERT_EQ(kDefaultCardID
, card
->server_id());
220 ASSERT_EQ(base::UTF8ToUTF16(kDefaultCardLastFour
), card
->LastFourDigits());
221 ASSERT_EQ(autofill::kAmericanExpressCard
, card
->type());
222 ASSERT_EQ(kDefaultCardExpMonth
, card
->expiration_month());
223 ASSERT_EQ(kDefaultCardExpYear
, card
->expiration_year());
224 ASSERT_EQ(base::UTF8ToUTF16(kDefaultCardName
),
225 card
->GetRawInfo(autofill::ServerFieldType::CREDIT_CARD_NAME
));
228 // Wallet data should get cleared from the database when sync is disabled.
229 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
, ClearOnDisableSync
) {
230 SetPreexistingPreferencesFileContents(kWalletSyncEnabledPreferencesContents
);
231 AddDefaultCard(GetFakeServer());
232 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
234 // Make sure the card is in the DB.
235 autofill::PersonalDataManager
* pdm
= GetPersonalDataManager(0);
236 ASSERT_TRUE(pdm
!= nullptr);
237 std::vector
<autofill::CreditCard
*> cards
= pdm
->GetCreditCards();
238 ASSERT_EQ(1uL, cards
.size());
240 // Turn off sync, the card should be gone.
241 ASSERT_TRUE(GetClient(0)->DisableSyncForAllDatatypes());
242 cards
= pdm
->GetCreditCards();
243 ASSERT_EQ(0uL, cards
.size());
246 // Wallet data should get cleared from the database when the wallet sync type
248 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
, ClearOnDisableWalletSync
) {
249 SetPreexistingPreferencesFileContents(kWalletSyncEnabledPreferencesContents
);
250 AddDefaultCard(GetFakeServer());
251 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
253 // Make sure the card is in the DB.
254 autofill::PersonalDataManager
* pdm
= GetPersonalDataManager(0);
255 ASSERT_TRUE(pdm
!= nullptr);
256 std::vector
<autofill::CreditCard
*> cards
= pdm
->GetCreditCards();
257 ASSERT_EQ(1uL, cards
.size());
259 // Turn off autofill sync, the card should be gone.
260 ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL
));
261 cards
= pdm
->GetCreditCards();
262 ASSERT_EQ(0uL, cards
.size());
265 // Wallet data should get cleared from the database when the wallet autofill
266 // integration flag is disabled.
267 IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest
,
268 ClearOnDisableWalletAutofill
) {
269 SetPreexistingPreferencesFileContents(kWalletSyncEnabledPreferencesContents
);
270 AddDefaultCard(GetFakeServer());
271 ASSERT_TRUE(SetupSync()) << "SetupSync() failed";
273 // Make sure the card is in the DB.
274 autofill::PersonalDataManager
* pdm
= GetPersonalDataManager(0);
275 ASSERT_TRUE(pdm
!= nullptr);
276 std::vector
<autofill::CreditCard
*> cards
= pdm
->GetCreditCards();
277 ASSERT_EQ(1uL, cards
.size());
279 // Turn off the wallet autofill pref, the card should be gone as a side
280 // effect of the wallet data type controller noticing.
281 GetProfile(0)->GetPrefs()->SetBoolean(
282 autofill::prefs::kAutofillWalletImportEnabled
, false);
283 cards
= pdm
->GetCreditCards();
284 ASSERT_EQ(0uL, cards
.size());