Home | History | Annotate | Download | only in supervised_user
      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