1 // Copyright 2014 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.
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service.h"
13 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service_factory.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "sync/api/attachments/attachment_id.h"
18 #include "sync/api/sync_change.h"
19 #include "sync/api/sync_error_factory_mock.h"
20 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
21 #include "sync/protocol/sync.pb.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 #if defined(OS_CHROMEOS)
25 #include "components/user_manager/user_image/default_user_images.h"
28 using sync_pb::ManagedUserSpecifics
;
29 using syncer::SUPERVISED_USERS
;
30 using syncer::SyncChange
;
31 using syncer::SyncChangeList
;
32 using syncer::SyncChangeProcessor
;
33 using syncer::SyncData
;
34 using syncer::SyncDataList
;
35 using syncer::SyncError
;
36 using syncer::SyncErrorFactory
;
37 using syncer::SyncMergeResult
;
41 class MockChangeProcessor
: public SyncChangeProcessor
{
43 MockChangeProcessor() {}
44 ~MockChangeProcessor() override
{}
46 // SyncChangeProcessor implementation:
47 SyncError
ProcessSyncChanges(const tracked_objects::Location
& from_here
,
48 const SyncChangeList
& change_list
) override
;
50 SyncDataList
GetAllSyncData(syncer::ModelType type
) const override
{
51 return SyncDataList();
54 const SyncChangeList
& changes() const { return change_list_
; }
55 SyncChange
GetChange(const std::string
& id
) const;
58 SyncChangeList change_list_
;
61 SyncError
MockChangeProcessor::ProcessSyncChanges(
62 const tracked_objects::Location
& from_here
,
63 const SyncChangeList
& change_list
) {
64 change_list_
= change_list
;
68 SyncChange
MockChangeProcessor::GetChange(const std::string
& id
) const {
69 for (const SyncChange
& sync_change
: change_list_
) {
70 if (sync_change
.sync_data().GetSpecifics().managed_user().id() == id
)
76 // Callback for SupervisedUserSyncService::GetSupervisedUsersAsync().
77 void GetSupervisedUsersCallback(const base::DictionaryValue
** dict
,
78 const base::DictionaryValue
* supervised_users
) {
79 *dict
= supervised_users
;
84 class SupervisedUserSyncServiceTest
: public ::testing::Test
{
86 SupervisedUserSyncServiceTest();
87 ~SupervisedUserSyncServiceTest() override
;
90 scoped_ptr
<SyncChangeProcessor
> CreateChangeProcessor();
91 scoped_ptr
<SyncErrorFactory
> CreateErrorFactory();
92 SyncData
CreateRemoteData(const std::string
& id
,
93 const std::string
& name
,
94 const std::string
& avatar
);
96 PrefService
* prefs() { return profile_
.GetPrefs(); }
97 SupervisedUserSyncService
* service() { return service_
; }
98 MockChangeProcessor
* change_processor() { return change_processor_
; }
101 content::TestBrowserThreadBundle thread_bundle_
;
102 TestingProfile profile_
;
103 SupervisedUserSyncService
* service_
;
105 // Owned by the SupervisedUserSyncService.
106 MockChangeProcessor
* change_processor_
;
108 // A unique ID for creating "remote" Sync data.
112 SupervisedUserSyncServiceTest::SupervisedUserSyncServiceTest()
113 : change_processor_(NULL
),
115 service_
= SupervisedUserSyncServiceFactory::GetForProfile(&profile_
);
118 SupervisedUserSyncServiceTest::~SupervisedUserSyncServiceTest() {}
120 scoped_ptr
<SyncChangeProcessor
>
121 SupervisedUserSyncServiceTest::CreateChangeProcessor() {
122 EXPECT_FALSE(change_processor_
);
123 change_processor_
= new MockChangeProcessor();
124 return scoped_ptr
<SyncChangeProcessor
>(change_processor_
);
127 scoped_ptr
<SyncErrorFactory
>
128 SupervisedUserSyncServiceTest::CreateErrorFactory() {
129 return scoped_ptr
<SyncErrorFactory
>(new syncer::SyncErrorFactoryMock());
132 SyncData
SupervisedUserSyncServiceTest::CreateRemoteData(
133 const std::string
& id
,
134 const std::string
& name
,
135 const std::string
& chrome_avatar
) {
136 ::sync_pb::EntitySpecifics specifics
;
137 specifics
.mutable_managed_user()->set_id(id
);
138 specifics
.mutable_managed_user()->set_name(name
);
139 specifics
.mutable_managed_user()->set_acknowledged(true);
140 if (!chrome_avatar
.empty())
141 specifics
.mutable_managed_user()->set_chrome_avatar(chrome_avatar
);
143 return SyncData::CreateRemoteData(
147 syncer::AttachmentIdList(),
148 syncer::AttachmentServiceProxyForTest::Create());
151 TEST_F(SupervisedUserSyncServiceTest
, MergeEmpty
) {
152 SyncMergeResult result
=
153 service()->MergeDataAndStartSyncing(SUPERVISED_USERS
,
155 CreateChangeProcessor(),
156 CreateErrorFactory());
157 EXPECT_FALSE(result
.error().IsSet());
158 EXPECT_EQ(0, result
.num_items_added());
159 EXPECT_EQ(0, result
.num_items_modified());
160 EXPECT_EQ(0, result
.num_items_deleted());
161 EXPECT_EQ(0, result
.num_items_before_association());
162 EXPECT_EQ(0, result
.num_items_after_association());
163 EXPECT_EQ(0u, service()->GetSupervisedUsers()->size());
164 EXPECT_EQ(0u, change_processor()->changes().size());
166 service()->StopSyncing(SUPERVISED_USERS
);
167 service()->Shutdown();
170 TEST_F(SupervisedUserSyncServiceTest
, MergeExisting
) {
171 const char kNameKey
[] = "name";
172 const char kAcknowledgedKey
[] = "acknowledged";
173 const char kChromeAvatarKey
[] = "chromeAvatar";
175 const char kUserId1
[] = "aaaaa";
176 const char kUserId2
[] = "bbbbb";
177 const char kUserId3
[] = "ccccc";
178 const char kUserId4
[] = "ddddd";
179 const char kName1
[] = "Anchor";
180 const char kName2
[] = "Buzz";
181 const char kName3
[] = "Crush";
182 const char kName4
[] = "Dory";
183 const char kAvatar1
[] = "";
184 #if defined(OS_CHROMEOS)
185 const char kAvatar2
[] = "chromeos-avatar-index:0";
186 const char kAvatar3
[] = "chromeos-avatar-index:20";
188 const char kAvatar2
[] = "chrome-avatar-index:0";
189 const char kAvatar3
[] = "chrome-avatar-index:20";
191 const char kAvatar4
[] = "";
193 DictionaryPrefUpdate
update(prefs(), prefs::kSupervisedUsers
);
194 base::DictionaryValue
* supervised_users
= update
.Get();
195 base::DictionaryValue
* dict
= new base::DictionaryValue
;
196 dict
->SetString(kNameKey
, kName1
);
197 supervised_users
->Set(kUserId1
, dict
);
198 dict
= new base::DictionaryValue
;
199 dict
->SetString(kNameKey
, kName2
);
200 dict
->SetBoolean(kAcknowledgedKey
, true);
201 supervised_users
->Set(kUserId2
, dict
);
204 const base::DictionaryValue
* async_supervised_users
= NULL
;
205 service()->GetSupervisedUsersAsync(
206 base::Bind(&GetSupervisedUsersCallback
, &async_supervised_users
));
208 SyncDataList initial_sync_data
;
209 initial_sync_data
.push_back(CreateRemoteData(kUserId2
, kName2
, kAvatar2
));
210 initial_sync_data
.push_back(CreateRemoteData(kUserId3
, kName3
, kAvatar3
));
211 initial_sync_data
.push_back(CreateRemoteData(kUserId4
, kName4
, kAvatar4
));
213 SyncMergeResult result
=
214 service()->MergeDataAndStartSyncing(SUPERVISED_USERS
,
216 CreateChangeProcessor(),
217 CreateErrorFactory());
218 EXPECT_FALSE(result
.error().IsSet());
219 EXPECT_EQ(2, result
.num_items_added());
220 EXPECT_EQ(1, result
.num_items_modified());
221 EXPECT_EQ(0, result
.num_items_deleted());
222 EXPECT_EQ(2, result
.num_items_before_association());
223 EXPECT_EQ(4, result
.num_items_after_association());
225 const base::DictionaryValue
* supervised_users
=
226 service()->GetSupervisedUsers();
227 EXPECT_EQ(4u, supervised_users
->size());
228 EXPECT_TRUE(async_supervised_users
);
229 EXPECT_TRUE(supervised_users
->Equals(async_supervised_users
));
232 const base::DictionaryValue
* supervised_user
= NULL
;
233 ASSERT_TRUE(supervised_users
->GetDictionary(kUserId2
, &supervised_user
));
234 ASSERT_TRUE(supervised_user
);
236 EXPECT_TRUE(supervised_user
->GetString(kNameKey
, &name
));
237 EXPECT_EQ(kName2
, name
);
238 bool acknowledged
= false;
239 EXPECT_TRUE(supervised_user
->GetBoolean(kAcknowledgedKey
, &acknowledged
));
240 EXPECT_TRUE(acknowledged
);
242 EXPECT_TRUE(supervised_user
->GetString(kChromeAvatarKey
, &avatar
));
243 EXPECT_EQ(kAvatar2
, avatar
);
246 const base::DictionaryValue
* supervised_user
= NULL
;
247 ASSERT_TRUE(supervised_users
->GetDictionary(kUserId3
, &supervised_user
));
248 ASSERT_TRUE(supervised_user
);
250 EXPECT_TRUE(supervised_user
->GetString(kNameKey
, &name
));
251 EXPECT_EQ(kName3
, name
);
252 bool acknowledged
= false;
253 EXPECT_TRUE(supervised_user
->GetBoolean(kAcknowledgedKey
, &acknowledged
));
254 EXPECT_TRUE(acknowledged
);
256 EXPECT_TRUE(supervised_user
->GetString(kChromeAvatarKey
, &avatar
));
257 EXPECT_EQ(kAvatar3
, avatar
);
260 const base::DictionaryValue
* supervised_user
= NULL
;
261 ASSERT_TRUE(supervised_users
->GetDictionary(kUserId4
, &supervised_user
));
262 ASSERT_TRUE(supervised_user
);
264 EXPECT_TRUE(supervised_user
->GetString(kNameKey
, &name
));
265 EXPECT_EQ(kName4
, name
);
266 bool acknowledged
= false;
267 EXPECT_TRUE(supervised_user
->GetBoolean(kAcknowledgedKey
, &acknowledged
));
268 EXPECT_TRUE(acknowledged
);
270 EXPECT_TRUE(supervised_user
->GetString(kChromeAvatarKey
, &avatar
));
271 EXPECT_EQ(kAvatar4
, avatar
);
274 EXPECT_EQ(1u, change_processor()->changes().size());
276 SyncChange change
= change_processor()->GetChange(kUserId1
);
277 ASSERT_TRUE(change
.IsValid());
278 EXPECT_EQ(SyncChange::ACTION_ADD
, change
.change_type());
279 const ManagedUserSpecifics
& supervised_user
=
280 change
.sync_data().GetSpecifics().managed_user();
281 EXPECT_EQ(kName1
, supervised_user
.name());
282 EXPECT_FALSE(supervised_user
.acknowledged());
283 EXPECT_EQ(kAvatar1
, supervised_user
.chrome_avatar());
287 TEST_F(SupervisedUserSyncServiceTest
, GetAvatarIndex
) {
289 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(std::string(),
291 EXPECT_EQ(SupervisedUserSyncService::kNoAvatar
, avatar
);
293 int avatar_index
= 4;
294 #if defined(OS_CHROMEOS)
295 avatar_index
+= user_manager::kFirstDefaultImageIndex
;
297 std::string avatar_str
=
298 SupervisedUserSyncService::BuildAvatarString(avatar_index
);
299 #if defined(OS_CHROMEOS)
300 EXPECT_EQ(base::StringPrintf("chromeos-avatar-index:%d", avatar_index
),
303 EXPECT_EQ(base::StringPrintf("chrome-avatar-index:%d", avatar_index
),
306 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(avatar_str
, &avatar
));
307 EXPECT_EQ(avatar_index
, avatar
);
310 #if defined(OS_CHROMEOS)
311 avatar_index
+= user_manager::kFirstDefaultImageIndex
;
313 avatar_str
= SupervisedUserSyncService::BuildAvatarString(avatar_index
);
314 #if defined(OS_CHROMEOS)
315 EXPECT_EQ(base::StringPrintf("chromeos-avatar-index:%d", avatar_index
),
318 EXPECT_EQ(base::StringPrintf("chrome-avatar-index:%d", avatar_index
),
321 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(avatar_str
, &avatar
));
322 EXPECT_EQ(avatar_index
, avatar
);
324 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex("wrong-prefix:5",
326 #if defined(OS_CHROMEOS)
327 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
328 "chromeos-avatar-indes:2",
332 SupervisedUserSyncService::GetAvatarIndex("chromeos-avatar-indexxx:2",
335 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
336 "chromeos-avatar-index:",
339 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
340 "chromeos-avatar-index:x",
343 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
344 "chrome-avatar-index:5",
347 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
348 "chrome-avatar-indes:2",
351 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
352 "chrome-avatar-indexxx:2",
355 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
356 "chrome-avatar-index:",
359 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
360 "chrome-avatar-index:x",
363 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex(
364 "chromeos-avatar-index:5",