OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" | 5 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" |
6 #include "base/files/scoped_temp_dir.h" | 6 #include "base/files/scoped_temp_dir.h" |
7 #include "chrome/browser/extensions/extension_service.h" | 7 #include "chrome/browser/extensions/extension_service.h" |
8 #include "chrome/browser/profiles/profile_manager.h" | 8 #include "chrome/browser/profiles/profile_manager.h" |
9 #include "chrome/browser/ui/app_list/app_list_test_util.h" | 9 #include "chrome/browser/ui/app_list/app_list_test_util.h" |
10 #include "chrome/test/base/testing_browser_process.h" | 10 #include "chrome/test/base/testing_browser_process.h" |
11 #include "chrome/test/base/testing_profile.h" | 11 #include "chrome/test/base/testing_profile.h" |
12 #include "components/crx_file/id_util.h" | 12 #include "components/crx_file/id_util.h" |
13 #include "components/sync/model/attachments/attachment_service_proxy_for_test.h" | |
14 #include "components/sync/model/fake_sync_change_processor.h" | |
15 #include "components/sync/model/sync_error_factory.h" | |
16 #include "components/sync/model/sync_error_factory_mock.h" | |
17 #include "components/sync/protocol/sync.pb.h" | |
13 #include "extensions/browser/extension_system.h" | 18 #include "extensions/browser/extension_system.h" |
14 #include "extensions/common/constants.h" | 19 #include "extensions/common/constants.h" |
15 #include "ui/app_list/app_list_item.h" | 20 #include "ui/app_list/app_list_item.h" |
16 #include "ui/app_list/app_list_model.h" | 21 #include "ui/app_list/app_list_model.h" |
17 | 22 |
23 using namespace crx_file::id_util; | |
24 | |
18 namespace { | 25 namespace { |
19 | 26 |
20 scoped_refptr<extensions::Extension> MakeApp( | 27 scoped_refptr<extensions::Extension> MakeApp( |
21 const std::string& name, | 28 const std::string& name, |
22 const std::string& id, | 29 const std::string& id, |
23 extensions::Extension::InitFromValueFlags flags) { | 30 extensions::Extension::InitFromValueFlags flags) { |
24 std::string err; | 31 std::string err; |
25 base::DictionaryValue value; | 32 base::DictionaryValue value; |
26 value.SetString("name", name); | 33 value.SetString("name", name); |
27 value.SetString("version", "0.0"); | 34 value.SetString("version", "0.0"); |
(...skipping 11 matching lines...) Expand all Loading... | |
39 std::string next_app_id = app_id; | 46 std::string next_app_id = app_id; |
40 size_t index = next_app_id.length() - 1; | 47 size_t index = next_app_id.length() - 1; |
41 while (index > 0 && next_app_id[index] == 'p') | 48 while (index > 0 && next_app_id[index] == 'p') |
42 next_app_id[index--] = 'a'; | 49 next_app_id[index--] = 'a'; |
43 DCHECK(next_app_id[index] != 'p'); | 50 DCHECK(next_app_id[index] != 'p'); |
44 next_app_id[index]++; | 51 next_app_id[index]++; |
45 DCHECK(crx_file::id_util::IdIsValid(next_app_id)); | 52 DCHECK(crx_file::id_util::IdIsValid(next_app_id)); |
46 return next_app_id; | 53 return next_app_id; |
47 } | 54 } |
48 | 55 |
56 constexpr char kUnset[] = "__unset__"; | |
57 constexpr char kDefault[] = "__default__"; | |
58 | |
59 // BAD STYLE ALERT: using const instead of constexpr in order to initialize | |
60 // with results of crx_file::id_util::GenerateId(). | |
61 const std::string kInvalidOrdinalsId = GenerateId("invalid_ordinals"); | |
xiyuan
2017/06/23 17:11:34
std::string is not allowed for global variable and
stevenjb
2017/06/23 19:46:05
e.g.. these could be members of a helper struct an
rcui
2017/06/23 21:28:08
How about this - defining the constants as functio
rcui
2017/06/23 21:28:41
This is done in the newest patchset.
| |
62 const std::string kEmptyItemNameId = GenerateId("empty_item_name"); | |
63 const std::string kEmptyItemNameUnsetId = GenerateId("empty_item_name_unset"); | |
64 const std::string kEmptyParentId = GenerateId("empty_parent_id"); | |
65 const std::string kEmptyParentUnsetId = GenerateId("empty_parent_id_unset"); | |
66 const std::string kEmptyOrdinalsId = GenerateId("empty_ordinals"); | |
67 const std::string kEmptyOrdinalsUnsetId = GenerateId("empty_ordinals_unset"); | |
68 const std::string kDupeItemId = GenerateId("dupe_item_id"); | |
69 const std::string kParentId = GenerateId("parent_id"); | |
70 | |
71 syncer::SyncData CreateAppRemoteData(const std::string& id, | |
72 const std::string& name, | |
73 const std::string& parent_id, | |
74 const std::string& item_ordinal, | |
75 const std::string& item_pin_ordinal) { | |
76 sync_pb::EntitySpecifics specifics; | |
77 sync_pb::AppListSpecifics* app_list = specifics.mutable_app_list(); | |
78 if (id != kUnset) | |
79 app_list->set_item_id(id); | |
80 app_list->set_item_type(sync_pb::AppListSpecifics_AppListItemType_TYPE_APP); | |
81 if (name != kUnset) | |
82 app_list->set_item_name(name); | |
83 if (parent_id != kUnset) | |
84 app_list->set_parent_id(parent_id); | |
85 if (item_ordinal != kUnset) | |
86 app_list->set_item_ordinal(item_ordinal); | |
87 if (item_pin_ordinal != kUnset) | |
88 app_list->set_item_pin_ordinal(item_pin_ordinal); | |
89 | |
90 return syncer::SyncData::CreateRemoteData( | |
91 std::hash<std::string>{}(id), specifics, base::Time(), | |
92 syncer::AttachmentIdList(), | |
93 syncer::AttachmentServiceProxyForTest::Create()); | |
94 } | |
95 | |
96 syncer::SyncDataList CreateBadAppRemoteData(const std::string& id) { | |
97 syncer::SyncDataList sync_list; | |
98 // Invalid item_ordinal and item_pin_ordinal. | |
99 sync_list.push_back(CreateAppRemoteData( | |
100 id == kDefault ? kInvalidOrdinalsId : id, "item_name", kParentId, | |
101 "$$invalid_ordinal$$", "$$invalid_ordinal$$")); | |
102 // Empty item name. | |
103 sync_list.push_back( | |
104 CreateAppRemoteData(id == kDefault ? kEmptyItemNameId : id, "", kParentId, | |
105 "ordinal", "pinordinal")); | |
106 sync_list.push_back( | |
107 CreateAppRemoteData(id == kDefault ? kEmptyItemNameUnsetId : id, kUnset, | |
108 kParentId, "ordinal", "pinordinal")); | |
109 // Empty parent ID. | |
110 sync_list.push_back(CreateAppRemoteData(id == kDefault ? kEmptyParentId : id, | |
111 "item_name", "", "ordinal", | |
112 "pinordinal")); | |
113 sync_list.push_back( | |
114 CreateAppRemoteData(id == kDefault ? kEmptyParentUnsetId : id, | |
115 "item_name", kUnset, "ordinal", "pinordinal")); | |
116 // Empty item_ordinal and item_pin_ordinal. | |
117 sync_list.push_back(CreateAppRemoteData( | |
118 id == kDefault ? kEmptyOrdinalsId : id, "item_name", kParentId, "", "")); | |
119 sync_list.push_back( | |
120 CreateAppRemoteData(id == kDefault ? kEmptyOrdinalsUnsetId : id, | |
121 "item_name", kParentId, kUnset, kUnset)); | |
122 // Duplicate item_id. | |
123 sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId : id, | |
124 "item_name", kParentId, "ordinal", | |
125 "pinordinal")); | |
126 sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId : id, | |
127 "item_name_dupe", kParentId, | |
128 "ordinal", "pinordinal")); | |
129 // Empty item_id. | |
130 sync_list.push_back( | |
131 CreateAppRemoteData("", "item_name", kParentId, "ordinal", "pinordinal")); | |
132 sync_list.push_back(CreateAppRemoteData(kUnset, "item_name", kParentId, | |
133 "ordinal", "pinordinal")); | |
134 // All fields empty. | |
135 sync_list.push_back(CreateAppRemoteData("", "", "", "", "")); | |
136 sync_list.push_back( | |
137 CreateAppRemoteData(kUnset, kUnset, kUnset, kUnset, kUnset)); | |
138 | |
139 return sync_list; | |
140 } | |
141 | |
49 } // namespace | 142 } // namespace |
50 | 143 |
51 class AppListSyncableServiceTest : public AppListTestBase { | 144 class AppListSyncableServiceTest : public AppListTestBase { |
52 public: | 145 public: |
53 AppListSyncableServiceTest() = default; | 146 AppListSyncableServiceTest() = default; |
54 ~AppListSyncableServiceTest() override = default; | 147 ~AppListSyncableServiceTest() override = default; |
55 | 148 |
56 void SetUp() override { | 149 void SetUp() override { |
57 AppListTestBase::SetUp(); | 150 AppListTestBase::SetUp(); |
58 | 151 |
59 // Make sure we have a Profile Manager. | 152 // Make sure we have a Profile Manager. |
60 DCHECK(temp_dir_.CreateUniqueTempDir()); | 153 DCHECK(temp_dir_.CreateUniqueTempDir()); |
61 TestingBrowserProcess::GetGlobal()->SetProfileManager( | 154 TestingBrowserProcess::GetGlobal()->SetProfileManager( |
62 new ProfileManagerWithoutInit(temp_dir_.GetPath())); | 155 new ProfileManagerWithoutInit(temp_dir_.GetPath())); |
63 | 156 |
64 extensions::ExtensionSystem* extension_system = | 157 extensions::ExtensionSystem* extension_system = |
65 extensions::ExtensionSystem::Get(profile_.get()); | 158 extensions::ExtensionSystem::Get(profile_.get()); |
66 DCHECK(extension_system); | 159 DCHECK(extension_system); |
67 app_list_syncable_service_.reset( | 160 app_list_syncable_service_.reset( |
68 new app_list::AppListSyncableService(profile_.get(), extension_system)); | 161 new app_list::AppListSyncableService(profile_.get(), extension_system)); |
69 } | 162 } |
70 | 163 |
71 void TearDown() override { app_list_syncable_service_.reset(); } | 164 void TearDown() override { app_list_syncable_service_.reset(); } |
72 | 165 |
73 app_list::AppListModel* model() { | 166 app_list::AppListModel* model() { |
74 return app_list_syncable_service_->GetModel(); | 167 return app_list_syncable_service_->GetModel(); |
75 } | 168 } |
76 | 169 |
170 const app_list::AppListSyncableService::SyncItem* GetSyncItem( | |
171 const std::string& id) const { | |
172 return app_list_syncable_service_->GetSyncItem(id); | |
173 } | |
174 | |
175 protected: | |
176 app_list::AppListSyncableService* app_list_syncable_service() { | |
177 return app_list_syncable_service_.get(); | |
178 } | |
179 | |
77 private: | 180 private: |
78 base::ScopedTempDir temp_dir_; | 181 base::ScopedTempDir temp_dir_; |
79 std::unique_ptr<app_list::AppListSyncableService> app_list_syncable_service_; | 182 std::unique_ptr<app_list::AppListSyncableService> app_list_syncable_service_; |
80 | 183 |
81 DISALLOW_COPY_AND_ASSIGN(AppListSyncableServiceTest); | 184 DISALLOW_COPY_AND_ASSIGN(AppListSyncableServiceTest); |
82 }; | 185 }; |
83 | 186 |
84 TEST_F(AppListSyncableServiceTest, OEMFolderForConflictingPos) { | 187 TEST_F(AppListSyncableServiceTest, OEMFolderForConflictingPos) { |
85 // Create a "web store" app. | 188 // Create a "web store" app. |
86 const std::string web_store_app_id(extensions::kWebStoreAppId); | 189 const std::string web_store_app_id(extensions::kWebStoreAppId); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
124 EXPECT_FALSE(model()->top_level_item_list()->FindItemIndex(oem_app_id, | 227 EXPECT_FALSE(model()->top_level_item_list()->FindItemIndex(oem_app_id, |
125 &oem_app_index)); | 228 &oem_app_index)); |
126 // But OEM folder is. | 229 // But OEM folder is. |
127 EXPECT_TRUE(model()->top_level_item_list()->FindItemIndex( | 230 EXPECT_TRUE(model()->top_level_item_list()->FindItemIndex( |
128 app_list::AppListSyncableService::kOemFolderId, &oem_folder_index)); | 231 app_list::AppListSyncableService::kOemFolderId, &oem_folder_index)); |
129 | 232 |
130 // Ensure right item sequence. | 233 // Ensure right item sequence. |
131 EXPECT_EQ(some_app_index, web_store_app_index + 1); | 234 EXPECT_EQ(some_app_index, web_store_app_index + 1); |
132 EXPECT_EQ(oem_folder_index, web_store_app_index + 2); | 235 EXPECT_EQ(oem_folder_index, web_store_app_index + 2); |
133 } | 236 } |
237 | |
238 TEST_F(AppListSyncableServiceTest, InitialMerge) { | |
239 const std::string kItemId1 = GenerateId("item_id1"); | |
240 const std::string kItemId2 = GenerateId("item_id2"); | |
241 | |
242 syncer::SyncDataList sync_list; | |
243 sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", | |
244 GenerateId("parent_id1"), "ordinal", | |
245 "pinordinal")); | |
246 sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", | |
247 GenerateId("parent_id2"), "ordinal", | |
248 "pinordinal")); | |
249 | |
250 app_list_syncable_service()->MergeDataAndStartSyncing( | |
251 syncer::APP_LIST, sync_list, | |
252 base::MakeUnique<syncer::FakeSyncChangeProcessor>(), | |
253 base::MakeUnique<syncer::SyncErrorFactoryMock>()); | |
254 content::RunAllBlockingPoolTasksUntilIdle(); | |
255 | |
256 ASSERT_TRUE(GetSyncItem(kItemId1)); | |
257 EXPECT_EQ("item_name1", GetSyncItem(kItemId1)->item_name); | |
258 EXPECT_EQ(GenerateId("parent_id1"), GetSyncItem(kItemId1)->parent_id); | |
259 EXPECT_EQ("ordinal", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); | |
260 EXPECT_EQ("pinordinal", | |
261 GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); | |
262 | |
263 ASSERT_TRUE(GetSyncItem(kItemId2)); | |
264 EXPECT_EQ("item_name2", GetSyncItem(kItemId2)->item_name); | |
265 EXPECT_EQ(GenerateId("parent_id2"), GetSyncItem(kItemId2)->parent_id); | |
266 EXPECT_EQ("ordinal", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); | |
267 EXPECT_EQ("pinordinal", | |
268 GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); | |
269 } | |
270 | |
271 TEST_F(AppListSyncableServiceTest, InitialMerge_BadData) { | |
272 syncer::SyncDataList sync_list = CreateBadAppRemoteData(kDefault); | |
273 | |
274 app_list_syncable_service()->MergeDataAndStartSyncing( | |
275 syncer::APP_LIST, sync_list, | |
276 base::MakeUnique<syncer::FakeSyncChangeProcessor>(), | |
277 base::MakeUnique<syncer::SyncErrorFactoryMock>()); | |
278 content::RunAllBlockingPoolTasksUntilIdle(); | |
279 | |
280 // Invalid item_ordinal and item_pin_ordinal. | |
281 ASSERT_TRUE(GetSyncItem(kInvalidOrdinalsId)); | |
282 EXPECT_EQ("n", GetSyncItem(kInvalidOrdinalsId)->item_ordinal.ToDebugString()); | |
283 EXPECT_EQ("INVALID[$$invalid_ordinal$$]", | |
284 GetSyncItem(kInvalidOrdinalsId)->item_pin_ordinal.ToDebugString()); | |
285 | |
286 // Empty item name. | |
287 ASSERT_TRUE(GetSyncItem(kEmptyItemNameId)); | |
288 EXPECT_EQ("", GetSyncItem(kEmptyItemNameId)->item_name); | |
289 EXPECT_TRUE(GetSyncItem(kEmptyItemNameUnsetId)); | |
290 EXPECT_EQ("", GetSyncItem(kEmptyItemNameUnsetId)->item_name); | |
291 | |
292 // Empty parent ID. | |
293 ASSERT_TRUE(GetSyncItem(kEmptyParentId)); | |
294 EXPECT_EQ("", GetSyncItem(kEmptyParentId)->parent_id); | |
295 EXPECT_TRUE(GetSyncItem(kEmptyParentUnsetId)); | |
296 EXPECT_EQ("", GetSyncItem(kEmptyParentUnsetId)->parent_id); | |
297 | |
298 // Empty item_ordinal and item_pin_ordinal. | |
299 ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsId)); | |
300 EXPECT_EQ("n", GetSyncItem(kEmptyOrdinalsId)->item_ordinal.ToDebugString()); | |
301 EXPECT_EQ("INVALID[]", | |
302 GetSyncItem(kEmptyOrdinalsId)->item_pin_ordinal.ToDebugString()); | |
303 ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsUnsetId)); | |
304 EXPECT_EQ("n", | |
305 GetSyncItem(kEmptyOrdinalsUnsetId)->item_ordinal.ToDebugString()); | |
306 EXPECT_EQ( | |
307 "INVALID[]", | |
308 GetSyncItem(kEmptyOrdinalsUnsetId)->item_pin_ordinal.ToDebugString()); | |
309 | |
310 // Duplicate item_id overrides previous. | |
311 ASSERT_TRUE(GetSyncItem(kDupeItemId)); | |
312 EXPECT_EQ("item_name_dupe", GetSyncItem(kDupeItemId)->item_name); | |
313 } | |
314 | |
315 TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate) { | |
316 const std::string kItemId1 = GenerateId("item_id1"); | |
317 const std::string kItemId2 = GenerateId("item_id2"); | |
318 | |
319 syncer::SyncDataList sync_list; | |
320 sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", kParentId, | |
321 "ordinal", "pinordinal")); | |
322 sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", kParentId, | |
323 "ordinal", "pinordinal")); | |
324 | |
325 app_list_syncable_service()->MergeDataAndStartSyncing( | |
326 syncer::APP_LIST, sync_list, | |
327 base::MakeUnique<syncer::FakeSyncChangeProcessor>(), | |
328 base::MakeUnique<syncer::SyncErrorFactoryMock>()); | |
329 content::RunAllBlockingPoolTasksUntilIdle(); | |
330 | |
331 ASSERT_TRUE(GetSyncItem(kItemId1)); | |
332 ASSERT_TRUE(GetSyncItem(kItemId2)); | |
333 | |
334 syncer::SyncChangeList change_list; | |
335 change_list.push_back(syncer::SyncChange( | |
336 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, | |
337 CreateAppRemoteData(kItemId1, "item_name1x", GenerateId("parent_id1x"), | |
338 "ordinalx", "pinordinalx"))); | |
339 change_list.push_back(syncer::SyncChange( | |
340 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, | |
341 CreateAppRemoteData(kItemId2, "item_name2x", GenerateId("parent_id2x"), | |
342 "ordinalx", "pinordinalx"))); | |
343 | |
344 app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), | |
345 change_list); | |
346 content::RunAllBlockingPoolTasksUntilIdle(); | |
347 | |
348 ASSERT_TRUE(GetSyncItem(kItemId1)); | |
349 EXPECT_EQ("item_name1x", GetSyncItem(kItemId1)->item_name); | |
350 EXPECT_EQ(GenerateId("parent_id1x"), GetSyncItem(kItemId1)->parent_id); | |
351 EXPECT_EQ("ordinalx", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); | |
352 EXPECT_EQ("pinordinalx", | |
353 GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); | |
354 | |
355 ASSERT_TRUE(GetSyncItem(kItemId2)); | |
356 EXPECT_EQ("item_name2x", GetSyncItem(kItemId2)->item_name); | |
357 EXPECT_EQ(GenerateId("parent_id2x"), GetSyncItem(kItemId2)->parent_id); | |
358 EXPECT_EQ("ordinalx", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); | |
359 EXPECT_EQ("pinordinalx", | |
360 GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); | |
361 } | |
362 | |
363 TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate_BadData) { | |
364 const std::string kItemId = GenerateId("item_id"); | |
365 | |
366 syncer::SyncDataList sync_list; | |
367 sync_list.push_back(CreateAppRemoteData(kItemId, "item_name", kParentId, | |
368 "ordinal", "pinordinal")); | |
369 | |
370 app_list_syncable_service()->MergeDataAndStartSyncing( | |
371 syncer::APP_LIST, sync_list, | |
372 base::MakeUnique<syncer::FakeSyncChangeProcessor>(), | |
373 base::MakeUnique<syncer::SyncErrorFactoryMock>()); | |
374 content::RunAllBlockingPoolTasksUntilIdle(); | |
375 | |
376 ASSERT_TRUE(GetSyncItem(kItemId)); | |
377 | |
378 syncer::SyncChangeList change_list; | |
379 syncer::SyncDataList update_list = CreateBadAppRemoteData(kItemId); | |
380 for (syncer::SyncDataList::const_iterator iter = update_list.begin(); | |
381 iter != update_list.end(); ++iter) { | |
382 change_list.push_back(syncer::SyncChange( | |
383 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, *iter)); | |
384 } | |
385 | |
386 // Validate items with bad data are processed without crashing. | |
387 app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), | |
388 change_list); | |
389 content::RunAllBlockingPoolTasksUntilIdle(); | |
390 | |
391 ASSERT_TRUE(GetSyncItem(kItemId)); | |
392 } | |
OLD | NEW |