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. 4 5 #include <string> 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/prefs/scoped_user_pref_update.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/threading/sequenced_worker_pool.h" 13 #include "chrome/browser/supervised_user/supervised_user_sync_service.h" 14 #include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h" 15 #include "chrome/common/pref_names.h" 16 #include "chrome/test/base/testing_profile.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" 23 24 #if defined(OS_CHROMEOS) 25 #include "components/user_manager/user_image/default_user_images.h" 26 #endif 27 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; 38 39 namespace { 40 41 class MockChangeProcessor : public SyncChangeProcessor { 42 public: 43 MockChangeProcessor() {} 44 virtual ~MockChangeProcessor() {} 45 46 // SyncChangeProcessor implementation: 47 virtual SyncError ProcessSyncChanges( 48 const tracked_objects::Location& from_here, 49 const SyncChangeList& change_list) OVERRIDE; 50 51 virtual SyncDataList GetAllSyncData(syncer::ModelType type) const 52 OVERRIDE { 53 return SyncDataList(); 54 } 55 56 const SyncChangeList& changes() const { return change_list_; } 57 SyncChange GetChange(const std::string& id) const; 58 59 private: 60 SyncChangeList change_list_; 61 }; 62 63 SyncError MockChangeProcessor::ProcessSyncChanges( 64 const tracked_objects::Location& from_here, 65 const SyncChangeList& change_list) { 66 change_list_ = change_list; 67 return SyncError(); 68 } 69 70 SyncChange MockChangeProcessor::GetChange(const std::string& id) const { 71 for (SyncChangeList::const_iterator it = change_list_.begin(); 72 it != change_list_.end(); ++it) { 73 if (it->sync_data().GetSpecifics().managed_user().id() == id) 74 return *it; 75 } 76 return SyncChange(); 77 } 78 79 // Callback for SupervisedUserSyncService::GetSupervisedUsersAsync(). 80 void GetSupervisedUsersCallback(const base::DictionaryValue** dict, 81 const base::DictionaryValue* supervised_users) { 82 *dict = supervised_users; 83 } 84 85 } // namespace 86 87 class SupervisedUserSyncServiceTest : public ::testing::Test { 88 public: 89 SupervisedUserSyncServiceTest(); 90 virtual ~SupervisedUserSyncServiceTest(); 91 92 protected: 93 scoped_ptr<SyncChangeProcessor> CreateChangeProcessor(); 94 scoped_ptr<SyncErrorFactory> CreateErrorFactory(); 95 SyncData CreateRemoteData(const std::string& id, 96 const std::string& name, 97 const std::string& avatar); 98 99 PrefService* prefs() { return profile_.GetPrefs(); } 100 SupervisedUserSyncService* service() { return service_; } 101 MockChangeProcessor* change_processor() { return change_processor_; } 102 103 private: 104 base::MessageLoop message_loop; 105 TestingProfile profile_; 106 SupervisedUserSyncService* service_; 107 108 // Owned by the SupervisedUserSyncService. 109 MockChangeProcessor* change_processor_; 110 111 // A unique ID for creating "remote" Sync data. 112 int64 sync_data_id_; 113 }; 114 115 SupervisedUserSyncServiceTest::SupervisedUserSyncServiceTest() 116 : change_processor_(NULL), 117 sync_data_id_(0) { 118 service_ = SupervisedUserSyncServiceFactory::GetForProfile(&profile_); 119 } 120 121 SupervisedUserSyncServiceTest::~SupervisedUserSyncServiceTest() {} 122 123 scoped_ptr<SyncChangeProcessor> 124 SupervisedUserSyncServiceTest::CreateChangeProcessor() { 125 EXPECT_FALSE(change_processor_); 126 change_processor_ = new MockChangeProcessor(); 127 return scoped_ptr<SyncChangeProcessor>(change_processor_); 128 } 129 130 scoped_ptr<SyncErrorFactory> 131 SupervisedUserSyncServiceTest::CreateErrorFactory() { 132 return scoped_ptr<SyncErrorFactory>(new syncer::SyncErrorFactoryMock()); 133 } 134 135 SyncData SupervisedUserSyncServiceTest::CreateRemoteData( 136 const std::string& id, 137 const std::string& name, 138 const std::string& chrome_avatar) { 139 ::sync_pb::EntitySpecifics specifics; 140 specifics.mutable_managed_user()->set_id(id); 141 specifics.mutable_managed_user()->set_name(name); 142 specifics.mutable_managed_user()->set_acknowledged(true); 143 if (!chrome_avatar.empty()) 144 specifics.mutable_managed_user()->set_chrome_avatar(chrome_avatar); 145 146 return SyncData::CreateRemoteData( 147 ++sync_data_id_, 148 specifics, 149 base::Time(), 150 syncer::AttachmentIdList(), 151 syncer::AttachmentServiceProxyForTest::Create()); 152 } 153 154 TEST_F(SupervisedUserSyncServiceTest, MergeEmpty) { 155 SyncMergeResult result = 156 service()->MergeDataAndStartSyncing(SUPERVISED_USERS, 157 SyncDataList(), 158 CreateChangeProcessor(), 159 CreateErrorFactory()); 160 EXPECT_FALSE(result.error().IsSet()); 161 EXPECT_EQ(0, result.num_items_added()); 162 EXPECT_EQ(0, result.num_items_modified()); 163 EXPECT_EQ(0, result.num_items_deleted()); 164 EXPECT_EQ(0, result.num_items_before_association()); 165 EXPECT_EQ(0, result.num_items_after_association()); 166 EXPECT_EQ(0u, service()->GetSupervisedUsers()->size()); 167 EXPECT_EQ(0u, change_processor()->changes().size()); 168 169 service()->StopSyncing(SUPERVISED_USERS); 170 service()->Shutdown(); 171 } 172 173 TEST_F(SupervisedUserSyncServiceTest, MergeExisting) { 174 const char kNameKey[] = "name"; 175 const char kAcknowledgedKey[] = "acknowledged"; 176 const char kChromeAvatarKey[] = "chromeAvatar"; 177 178 const char kUserId1[] = "aaaaa"; 179 const char kUserId2[] = "bbbbb"; 180 const char kUserId3[] = "ccccc"; 181 const char kUserId4[] = "ddddd"; 182 const char kName1[] = "Anchor"; 183 const char kName2[] = "Buzz"; 184 const char kName3[] = "Crush"; 185 const char kName4[] = "Dory"; 186 const char kAvatar1[] = ""; 187 #if defined(OS_CHROMEOS) 188 const char kAvatar2[] = "chromeos-avatar-index:0"; 189 const char kAvatar3[] = "chromeos-avatar-index:20"; 190 #else 191 const char kAvatar2[] = "chrome-avatar-index:0"; 192 const char kAvatar3[] = "chrome-avatar-index:20"; 193 #endif 194 const char kAvatar4[] = ""; 195 { 196 DictionaryPrefUpdate update(prefs(), prefs::kSupervisedUsers); 197 base::DictionaryValue* supervised_users = update.Get(); 198 base::DictionaryValue* dict = new base::DictionaryValue; 199 dict->SetString(kNameKey, kName1); 200 supervised_users->Set(kUserId1, dict); 201 dict = new base::DictionaryValue; 202 dict->SetString(kNameKey, kName2); 203 dict->SetBoolean(kAcknowledgedKey, true); 204 supervised_users->Set(kUserId2, dict); 205 } 206 207 const base::DictionaryValue* async_supervised_users = NULL; 208 service()->GetSupervisedUsersAsync( 209 base::Bind(&GetSupervisedUsersCallback, &async_supervised_users)); 210 211 SyncDataList initial_sync_data; 212 initial_sync_data.push_back(CreateRemoteData(kUserId2, kName2, kAvatar2)); 213 initial_sync_data.push_back(CreateRemoteData(kUserId3, kName3, kAvatar3)); 214 initial_sync_data.push_back(CreateRemoteData(kUserId4, kName4, kAvatar4)); 215 216 SyncMergeResult result = 217 service()->MergeDataAndStartSyncing(SUPERVISED_USERS, 218 initial_sync_data, 219 CreateChangeProcessor(), 220 CreateErrorFactory()); 221 EXPECT_FALSE(result.error().IsSet()); 222 EXPECT_EQ(2, result.num_items_added()); 223 EXPECT_EQ(1, result.num_items_modified()); 224 EXPECT_EQ(0, result.num_items_deleted()); 225 EXPECT_EQ(2, result.num_items_before_association()); 226 EXPECT_EQ(4, result.num_items_after_association()); 227 228 const base::DictionaryValue* supervised_users = 229 service()->GetSupervisedUsers(); 230 EXPECT_EQ(4u, supervised_users->size()); 231 EXPECT_TRUE(async_supervised_users); 232 EXPECT_TRUE(supervised_users->Equals(async_supervised_users)); 233 234 { 235 const base::DictionaryValue* supervised_user = NULL; 236 ASSERT_TRUE(supervised_users->GetDictionary(kUserId2, &supervised_user)); 237 ASSERT_TRUE(supervised_user); 238 std::string name; 239 EXPECT_TRUE(supervised_user->GetString(kNameKey, &name)); 240 EXPECT_EQ(kName2, name); 241 bool acknowledged = false; 242 EXPECT_TRUE(supervised_user->GetBoolean(kAcknowledgedKey, &acknowledged)); 243 EXPECT_TRUE(acknowledged); 244 std::string avatar; 245 EXPECT_TRUE(supervised_user->GetString(kChromeAvatarKey, &avatar)); 246 EXPECT_EQ(kAvatar2, avatar); 247 } 248 { 249 const base::DictionaryValue* supervised_user = NULL; 250 ASSERT_TRUE(supervised_users->GetDictionary(kUserId3, &supervised_user)); 251 ASSERT_TRUE(supervised_user); 252 std::string name; 253 EXPECT_TRUE(supervised_user->GetString(kNameKey, &name)); 254 EXPECT_EQ(kName3, name); 255 bool acknowledged = false; 256 EXPECT_TRUE(supervised_user->GetBoolean(kAcknowledgedKey, &acknowledged)); 257 EXPECT_TRUE(acknowledged); 258 std::string avatar; 259 EXPECT_TRUE(supervised_user->GetString(kChromeAvatarKey, &avatar)); 260 EXPECT_EQ(kAvatar3, avatar); 261 } 262 { 263 const base::DictionaryValue* supervised_user = NULL; 264 ASSERT_TRUE(supervised_users->GetDictionary(kUserId4, &supervised_user)); 265 ASSERT_TRUE(supervised_user); 266 std::string name; 267 EXPECT_TRUE(supervised_user->GetString(kNameKey, &name)); 268 EXPECT_EQ(kName4, name); 269 bool acknowledged = false; 270 EXPECT_TRUE(supervised_user->GetBoolean(kAcknowledgedKey, &acknowledged)); 271 EXPECT_TRUE(acknowledged); 272 std::string avatar; 273 EXPECT_TRUE(supervised_user->GetString(kChromeAvatarKey, &avatar)); 274 EXPECT_EQ(kAvatar4, avatar); 275 } 276 277 EXPECT_EQ(1u, change_processor()->changes().size()); 278 { 279 SyncChange change = change_processor()->GetChange(kUserId1); 280 ASSERT_TRUE(change.IsValid()); 281 EXPECT_EQ(SyncChange::ACTION_ADD, change.change_type()); 282 const ManagedUserSpecifics& supervised_user = 283 change.sync_data().GetSpecifics().managed_user(); 284 EXPECT_EQ(kName1, supervised_user.name()); 285 EXPECT_FALSE(supervised_user.acknowledged()); 286 EXPECT_EQ(kAvatar1, supervised_user.chrome_avatar()); 287 } 288 } 289 290 TEST_F(SupervisedUserSyncServiceTest, GetAvatarIndex) { 291 int avatar = 100; 292 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(std::string(), 293 &avatar)); 294 EXPECT_EQ(SupervisedUserSyncService::kNoAvatar, avatar); 295 296 int avatar_index = 4; 297 #if defined(OS_CHROMEOS) 298 avatar_index += user_manager::kFirstDefaultImageIndex; 299 #endif 300 std::string avatar_str = 301 SupervisedUserSyncService::BuildAvatarString(avatar_index); 302 #if defined(OS_CHROMEOS) 303 EXPECT_EQ(base::StringPrintf("chromeos-avatar-index:%d", avatar_index), 304 avatar_str); 305 #else 306 EXPECT_EQ(base::StringPrintf("chrome-avatar-index:%d", avatar_index), 307 avatar_str); 308 #endif 309 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(avatar_str, &avatar)); 310 EXPECT_EQ(avatar_index, avatar); 311 312 avatar_index = 0; 313 #if defined(OS_CHROMEOS) 314 avatar_index += user_manager::kFirstDefaultImageIndex; 315 #endif 316 avatar_str = SupervisedUserSyncService::BuildAvatarString(avatar_index); 317 #if defined(OS_CHROMEOS) 318 EXPECT_EQ(base::StringPrintf("chromeos-avatar-index:%d", avatar_index), 319 avatar_str); 320 #else 321 EXPECT_EQ(base::StringPrintf("chrome-avatar-index:%d", avatar_index), 322 avatar_str); 323 #endif 324 EXPECT_TRUE(SupervisedUserSyncService::GetAvatarIndex(avatar_str, &avatar)); 325 EXPECT_EQ(avatar_index, avatar); 326 327 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex("wrong-prefix:5", 328 &avatar)); 329 #if defined(OS_CHROMEOS) 330 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 331 "chromeos-avatar-indes:2", 332 &avatar)); 333 334 EXPECT_FALSE( 335 SupervisedUserSyncService::GetAvatarIndex("chromeos-avatar-indexxx:2", 336 &avatar)); 337 338 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 339 "chromeos-avatar-index:", 340 &avatar)); 341 342 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 343 "chromeos-avatar-index:x", 344 &avatar)); 345 346 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 347 "chrome-avatar-index:5", 348 &avatar)); 349 #else 350 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 351 "chrome-avatar-indes:2", 352 &avatar)); 353 354 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 355 "chrome-avatar-indexxx:2", 356 &avatar)); 357 358 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 359 "chrome-avatar-index:", 360 &avatar)); 361 362 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 363 "chrome-avatar-index:x", 364 &avatar)); 365 366 EXPECT_FALSE(SupervisedUserSyncService::GetAvatarIndex( 367 "chromeos-avatar-index:5", 368 &avatar)); 369 #endif 370 } 371