1 // Copyright 2020 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.
4
5 #include "base/test/scoped_feature_list.h"
6 #include "chrome/browser/sync/sync_invalidations_service_factory.h"
7 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
8 #include "chrome/browser/sync/test/integration/device_info_helper.h"
9 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
10 #include "chrome/browser/sync/test/integration/sync_test.h"
11 #include "components/bookmarks/browser/bookmark_model.h"
12 #include "components/sync/base/model_type.h"
13 #include "components/sync/invalidations/switches.h"
14 #include "components/sync/invalidations/sync_invalidations_service.h"
15 #include "components/sync/protocol/sync.pb.h"
16 #include "components/sync/test/fake_server/bookmark_entity_builder.h"
17 #include "components/sync/test/fake_server/entity_builder_factory.h"
18 #include "content/public/test/browser_test.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace {
23
24 using testing::AllOf;
25 using testing::ElementsAre;
26 using testing::Not;
27 using testing::NotNull;
28 using testing::UnorderedElementsAre;
29
30 const char kSyncedBookmarkURL[] = "http://www.mybookmark.com";
31
32 MATCHER_P(InterestedDataTypesAre, expected_data_types, "") {
33 syncer::ModelTypeSet data_types;
34 for (const int field_number : arg.specifics()
35 .device_info()
36 .invalidation_fields()
37 .interested_data_type_ids()) {
38 syncer::ModelType data_type =
39 syncer::GetModelTypeFromSpecificsFieldNumber(field_number);
40 if (!syncer::IsRealDataType(data_type)) {
41 return false;
42 }
43 data_types.Put(data_type);
44 }
45 return data_types == expected_data_types;
46 }
47
48 MATCHER_P(InterestedDataTypesContain, expected_data_types, "") {
49 syncer::ModelTypeSet data_types;
50 for (const int field_number : arg.specifics()
51 .device_info()
52 .invalidation_fields()
53 .interested_data_type_ids()) {
54 syncer::ModelType data_type =
55 syncer::GetModelTypeFromSpecificsFieldNumber(field_number);
56 if (!syncer::IsRealDataType(data_type)) {
57 return false;
58 }
59 data_types.Put(data_type);
60 }
61 return data_types.HasAll(expected_data_types);
62 }
63
64 MATCHER(HasInstanceIdToken, "") {
65 return arg.specifics()
66 .device_info()
67 .invalidation_fields()
68 .has_instance_id_token();
69 }
70
71 MATCHER_P(HasInstanceIdToken, expected_token, "") {
72 return arg.specifics()
73 .device_info()
74 .invalidation_fields()
75 .instance_id_token() == expected_token;
76 }
77
78 class SingleClientWithSyncSendInterestedDataTypesTest : public SyncTest {
79 public:
SingleClientWithSyncSendInterestedDataTypesTest()80 SingleClientWithSyncSendInterestedDataTypesTest() : SyncTest(SINGLE_CLIENT) {
81 override_features_.InitWithFeatures(
82 /*enabled_features=*/{switches::kSyncSendInterestedDataTypes},
83 /*disabled_features=*/{
84 switches::kUseSyncInvalidations,
85 switches::kUseSyncInvalidationsForWalletAndOffer});
86 }
87 ~SingleClientWithSyncSendInterestedDataTypesTest() override = default;
88
89 private:
90 base::test::ScopedFeatureList override_features_;
91
92 DISALLOW_COPY_AND_ASSIGN(SingleClientWithSyncSendInterestedDataTypesTest);
93 };
94
IN_PROC_BROWSER_TEST_F(SingleClientWithSyncSendInterestedDataTypesTest,SendInterestedDataTypesAsPartOfDeviceInfo)95 IN_PROC_BROWSER_TEST_F(SingleClientWithSyncSendInterestedDataTypesTest,
96 SendInterestedDataTypesAsPartOfDeviceInfo) {
97 ASSERT_TRUE(SetupSync());
98
99 syncer::SyncInvalidationsService* sync_invalidations_service =
100 SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0));
101 ASSERT_THAT(sync_invalidations_service, NotNull());
102 syncer::ModelTypeSet interested_data_types =
103 sync_invalidations_service->GetInterestedDataTypes();
104
105 // Check that some "standard" data types are included.
106 EXPECT_TRUE(
107 interested_data_types.HasAll({syncer::NIGORI, syncer::BOOKMARKS}));
108 // Wallet and Offer data types are excluded unless
109 // kUseSyncInvalidationsForWalletAndOffer is also enabled.
110 EXPECT_FALSE(interested_data_types.Has(syncer::AUTOFILL_WALLET_DATA));
111 EXPECT_FALSE(interested_data_types.Has(syncer::AUTOFILL_WALLET_OFFER));
112
113 // The local device should eventually be committed to the server.
114 // The InstanceID token should only be uploaded if kUseSyncInvalidations is
115 // also enabled.
116 EXPECT_TRUE(
117 ServerDeviceInfoMatchChecker(
118 GetFakeServer(),
119 ElementsAre(AllOf(InterestedDataTypesAre(interested_data_types),
120 Not(HasInstanceIdToken()))))
121 .Wait());
122 }
123
124 class SingleClientWithUseSyncInvalidationsTest : public SyncTest {
125 public:
SingleClientWithUseSyncInvalidationsTest()126 SingleClientWithUseSyncInvalidationsTest() : SyncTest(SINGLE_CLIENT) {
127 override_features_.InitWithFeatures(
128 /*enabled_features=*/{switches::kSyncSendInterestedDataTypes,
129 switches::kUseSyncInvalidations},
130 /*disabled_features=*/{
131 switches::kUseSyncInvalidationsForWalletAndOffer});
132 }
133 ~SingleClientWithUseSyncInvalidationsTest() override = default;
134
135 private:
136 base::test::ScopedFeatureList override_features_;
137
138 DISALLOW_COPY_AND_ASSIGN(SingleClientWithUseSyncInvalidationsTest);
139 };
140
IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsTest,SendInterestedDataTypesAndFCMTokenAsPartOfDeviceInfo)141 IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsTest,
142 SendInterestedDataTypesAndFCMTokenAsPartOfDeviceInfo) {
143 ASSERT_TRUE(SetupSync());
144
145 syncer::SyncInvalidationsService* sync_invalidations_service =
146 SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0));
147 ASSERT_THAT(sync_invalidations_service, NotNull());
148 syncer::ModelTypeSet interested_data_types =
149 sync_invalidations_service->GetInterestedDataTypes();
150 std::string fcm_token = sync_invalidations_service->GetFCMRegistrationToken();
151
152 // Check that some "standard" data types are included.
153 EXPECT_TRUE(
154 interested_data_types.HasAll({syncer::NIGORI, syncer::BOOKMARKS}));
155 // Wallet and Offer data types are excluded unless
156 // kUseSyncInvalidationsForWalletAndOffer is also enabled.
157 EXPECT_FALSE(interested_data_types.Has(syncer::AUTOFILL_WALLET_DATA));
158 EXPECT_FALSE(interested_data_types.Has(syncer::AUTOFILL_WALLET_OFFER));
159 EXPECT_FALSE(fcm_token.empty());
160
161 // The local device should eventually be committed to the server.
162 EXPECT_TRUE(
163 ServerDeviceInfoMatchChecker(
164 GetFakeServer(),
165 ElementsAre(AllOf(InterestedDataTypesAre(interested_data_types),
166 HasInstanceIdToken(fcm_token))))
167 .Wait());
168 }
169
170 class SingleClientWithUseSyncInvalidationsForWalletAndOfferTest
171 : public SyncTest {
172 public:
SingleClientWithUseSyncInvalidationsForWalletAndOfferTest()173 SingleClientWithUseSyncInvalidationsForWalletAndOfferTest()
174 : SyncTest(SINGLE_CLIENT) {
175 override_features_.InitWithFeatures(
176 /*enabled_features=*/{switches::kSyncSendInterestedDataTypes,
177 switches::kUseSyncInvalidations,
178 switches::kUseSyncInvalidationsForWalletAndOffer},
179 /*disabled_features=*/{});
180 }
181 ~SingleClientWithUseSyncInvalidationsForWalletAndOfferTest() override =
182 default;
183
InjectSyncedBookmark()184 void InjectSyncedBookmark() {
185 fake_server::BookmarkEntityBuilder bookmark_builder =
186 entity_builder_factory_.NewBookmarkEntityBuilder("My Bookmark");
187 GetFakeServer()->InjectEntity(
188 bookmark_builder.BuildBookmark(GURL(kSyncedBookmarkURL)));
189 }
190
191 private:
192 base::test::ScopedFeatureList override_features_;
193 fake_server::EntityBuilderFactory entity_builder_factory_;
194
195 DISALLOW_COPY_AND_ASSIGN(
196 SingleClientWithUseSyncInvalidationsForWalletAndOfferTest);
197 };
198
IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,SendInterestedDataTypesAndFCMTokenAsPartOfDeviceInfo)199 IN_PROC_BROWSER_TEST_F(
200 SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,
201 SendInterestedDataTypesAndFCMTokenAsPartOfDeviceInfo) {
202 ASSERT_TRUE(SetupSync());
203
204 syncer::SyncInvalidationsService* sync_invalidations_service =
205 SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0));
206 ASSERT_THAT(sync_invalidations_service, NotNull());
207 syncer::ModelTypeSet interested_data_types =
208 sync_invalidations_service->GetInterestedDataTypes();
209 std::string fcm_token = sync_invalidations_service->GetFCMRegistrationToken();
210
211 // Check that some "standard" data types are included.
212 EXPECT_TRUE(
213 interested_data_types.HasAll({syncer::NIGORI, syncer::BOOKMARKS}));
214 // Wallet data type should be included by default if
215 // kUseSyncInvalidationsForWalletAndOffer is enabled.
216 EXPECT_TRUE(interested_data_types.Has(syncer::AUTOFILL_WALLET_DATA));
217 EXPECT_FALSE(fcm_token.empty());
218
219 // The local device should eventually be committed to the server.
220 EXPECT_TRUE(
221 ServerDeviceInfoMatchChecker(
222 GetFakeServer(),
223 ElementsAre(AllOf(InterestedDataTypesAre(interested_data_types),
224 HasInstanceIdToken(fcm_token))))
225 .Wait());
226 }
227
IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,EnableAndDisableADataType)228 IN_PROC_BROWSER_TEST_F(
229 SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,
230 EnableAndDisableADataType) {
231 ASSERT_TRUE(SetupSync());
232
233 // The local device should eventually be committed to the server. BOOKMARKS
234 // should be included in interested types, since it's enabled by default.
235 EXPECT_TRUE(ServerDeviceInfoMatchChecker(
236 GetFakeServer(),
237 ElementsAre(InterestedDataTypesContain(syncer::BOOKMARKS)))
238 .Wait());
239
240 // Disable BOOKMARKS.
241 ASSERT_TRUE(
242 GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kBookmarks));
243 // The local device should eventually be committed to the server. BOOKMARKS
244 // should not be included in interested types, as it was disabled.
245 EXPECT_TRUE(
246 ServerDeviceInfoMatchChecker(
247 GetFakeServer(),
248 ElementsAre(Not(InterestedDataTypesContain(syncer::BOOKMARKS))))
249 .Wait());
250
251 // Create a bookmark on the server.
252 InjectSyncedBookmark();
253 // Enable BOOKMARKS again.
254 ASSERT_TRUE(
255 GetClient(0)->EnableSyncForType(syncer::UserSelectableType::kBookmarks));
256 // The local device should eventually be committed to the server. BOOKMARKS
257 // should now be included in interested types.
258 EXPECT_TRUE(ServerDeviceInfoMatchChecker(
259 GetFakeServer(),
260 ElementsAre(InterestedDataTypesContain(syncer::BOOKMARKS)))
261 .Wait());
262 // The bookmark should get synced now.
263 EXPECT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
264 GURL(kSyncedBookmarkURL)));
265 }
266
267 // ChromeOS doesn't have the concept of sign-out.
268 #if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,SignoutAndSignin)269 IN_PROC_BROWSER_TEST_F(
270 SingleClientWithUseSyncInvalidationsForWalletAndOfferTest,
271 SignoutAndSignin) {
272 ASSERT_TRUE(SetupSync());
273
274 // The local device should eventually be committed to the server. The FCM
275 // token should be present in device info.
276 std::string old_token =
277 SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0))
278 ->GetFCMRegistrationToken();
279 EXPECT_TRUE(ServerDeviceInfoMatchChecker(
280 GetFakeServer(), ElementsAre(HasInstanceIdToken(old_token)))
281 .Wait());
282
283 // Sign out. The FCM token should be cleared.
284 GetClient(0)->SignOutPrimaryAccount();
285 EXPECT_TRUE(SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0))
286 ->GetFCMRegistrationToken()
287 .empty());
288
289 // Sign in again.
290 ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
291 std::string new_token =
292 SyncInvalidationsServiceFactory::GetForProfile(GetProfile(0))
293 ->GetFCMRegistrationToken();
294 EXPECT_NE(new_token, old_token);
295 EXPECT_FALSE(new_token.empty());
296 // New device info should eventually be committed to the server (but the old
297 // device info will remain on the server). The FCM token should be present.
298 EXPECT_TRUE(ServerDeviceInfoMatchChecker(
299 GetFakeServer(), UnorderedElementsAre(HasInstanceIdToken(old_token),
300 HasInstanceIdToken(new_token)))
301 .Wait());
302 }
303 #endif // !OS_CHROMEOS
304
305 } // namespace
306