1 // Copyright 2013 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/bind.h" 6 #include "base/message_loop/message_loop.h" 7 #include "base/run_loop.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "base/threading/sequenced_worker_pool.h" 10 #include "chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h" 11 #include "chrome/browser/managed_mode/managed_user_registration_utility.h" 12 #include "chrome/browser/managed_mode/managed_user_sync_service.h" 13 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h" 14 #include "chrome/browser/prefs/scoped_user_pref_update.h" 15 #include "chrome/common/pref_names.h" 16 #include "chrome/test/base/testing_pref_service_syncable.h" 17 #include "chrome/test/base/testing_profile.h" 18 #include "content/public/browser/browser_thread.h" 19 #include "google_apis/gaia/google_service_auth_error.h" 20 #include "sync/api/sync_change.h" 21 #include "sync/api/sync_error_factory_mock.h" 22 #include "sync/protocol/sync.pb.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 using sync_pb::ManagedUserSpecifics; 26 using syncer::MANAGED_USERS; 27 using syncer::SyncChange; 28 using syncer::SyncChangeList; 29 using syncer::SyncChangeProcessor; 30 using syncer::SyncData; 31 using syncer::SyncDataList; 32 using syncer::SyncError; 33 using syncer::SyncErrorFactory; 34 using syncer::SyncMergeResult; 35 36 namespace { 37 38 const char kManagedUserToken[] = "managedusertoken"; 39 40 class MockChangeProcessor : public SyncChangeProcessor { 41 public: 42 MockChangeProcessor() {} 43 virtual ~MockChangeProcessor() {} 44 45 // SyncChangeProcessor implementation: 46 virtual SyncError ProcessSyncChanges( 47 const tracked_objects::Location& from_here, 48 const SyncChangeList& change_list) OVERRIDE; 49 50 const SyncChangeList& changes() const { return change_list_; } 51 52 private: 53 SyncChangeList change_list_; 54 }; 55 56 SyncError MockChangeProcessor::ProcessSyncChanges( 57 const tracked_objects::Location& from_here, 58 const SyncChangeList& change_list) { 59 change_list_ = change_list; 60 return SyncError(); 61 } 62 63 class MockManagedUserRefreshTokenFetcher 64 : public ManagedUserRefreshTokenFetcher { 65 public: 66 MockManagedUserRefreshTokenFetcher() {} 67 virtual ~MockManagedUserRefreshTokenFetcher() {} 68 69 // ManagedUserRefreshTokenFetcher implementation: 70 virtual void Start(const std::string& managed_user_id, 71 const std::string& device_name, 72 const TokenCallback& callback) OVERRIDE { 73 GoogleServiceAuthError error(GoogleServiceAuthError::NONE); 74 callback.Run(error, kManagedUserToken); 75 } 76 }; 77 78 } // namespace 79 80 class ManagedUserRegistrationUtilityTest : public ::testing::Test { 81 public: 82 ManagedUserRegistrationUtilityTest(); 83 virtual ~ManagedUserRegistrationUtilityTest(); 84 85 virtual void TearDown() OVERRIDE; 86 87 protected: 88 scoped_ptr<SyncChangeProcessor> CreateChangeProcessor(); 89 scoped_ptr<SyncErrorFactory> CreateErrorFactory(); 90 SyncData CreateRemoteData(const std::string& id, const std::string& name); 91 92 SyncMergeResult StartInitialSync(); 93 94 ManagedUserRegistrationUtility::RegistrationCallback 95 GetRegistrationCallback(); 96 97 void Acknowledge(); 98 99 PrefService* prefs() { return profile_.GetTestingPrefService(); } 100 ManagedUserSyncService* service() { return service_; } 101 MockChangeProcessor* change_processor() { return change_processor_; } 102 103 bool received_callback() const { return received_callback_; } 104 const GoogleServiceAuthError& error() const { return error_; } 105 const std::string& token() const { return token_; } 106 107 private: 108 void OnManagedUserRegistered(const GoogleServiceAuthError& error, 109 const std::string& token); 110 111 base::MessageLoop message_loop_; 112 base::RunLoop run_loop_; 113 base::WeakPtrFactory<ManagedUserRegistrationUtilityTest> weak_ptr_factory_; 114 TestingProfile profile_; 115 ManagedUserSyncService* service_; 116 117 // Owned by the ManagedUserSyncService. 118 MockChangeProcessor* change_processor_; 119 120 // A unique ID for creating "remote" Sync data. 121 int64 sync_data_id_; 122 123 // Whether OnManagedUserRegistered has been called. 124 bool received_callback_; 125 126 // Hold the registration result (either an error, or a token). 127 GoogleServiceAuthError error_; 128 std::string token_; 129 }; 130 131 ManagedUserRegistrationUtilityTest::ManagedUserRegistrationUtilityTest() 132 : weak_ptr_factory_(this), 133 change_processor_(NULL), 134 sync_data_id_(0), 135 received_callback_(false), 136 error_(GoogleServiceAuthError::NUM_STATES) { 137 service_ = ManagedUserSyncServiceFactory::GetForProfile(&profile_); 138 } 139 140 ManagedUserRegistrationUtilityTest::~ManagedUserRegistrationUtilityTest() { 141 EXPECT_FALSE(weak_ptr_factory_.HasWeakPtrs()); 142 } 143 144 void ManagedUserRegistrationUtilityTest::TearDown() { 145 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 146 base::RunLoop().RunUntilIdle(); 147 } 148 149 scoped_ptr<SyncChangeProcessor> 150 ManagedUserRegistrationUtilityTest::CreateChangeProcessor() { 151 EXPECT_FALSE(change_processor_); 152 change_processor_ = new MockChangeProcessor(); 153 return scoped_ptr<SyncChangeProcessor>(change_processor_); 154 } 155 156 scoped_ptr<SyncErrorFactory> 157 ManagedUserRegistrationUtilityTest::CreateErrorFactory() { 158 return scoped_ptr<SyncErrorFactory>(new syncer::SyncErrorFactoryMock()); 159 } 160 161 SyncMergeResult ManagedUserRegistrationUtilityTest::StartInitialSync() { 162 SyncDataList initial_sync_data; 163 SyncMergeResult result = 164 service()->MergeDataAndStartSyncing(MANAGED_USERS, 165 initial_sync_data, 166 CreateChangeProcessor(), 167 CreateErrorFactory()); 168 EXPECT_FALSE(result.error().IsSet()); 169 return result; 170 } 171 172 ManagedUserRegistrationUtility::RegistrationCallback 173 ManagedUserRegistrationUtilityTest::GetRegistrationCallback() { 174 return base::Bind( 175 &ManagedUserRegistrationUtilityTest::OnManagedUserRegistered, 176 weak_ptr_factory_.GetWeakPtr()); 177 } 178 179 void ManagedUserRegistrationUtilityTest::Acknowledge() { 180 SyncChangeList new_changes; 181 const SyncChangeList& changes = change_processor()->changes(); 182 for (SyncChangeList::const_iterator it = changes.begin(); it != changes.end(); 183 ++it) { 184 EXPECT_EQ(SyncChange::ACTION_ADD, it->change_type()); 185 ::sync_pb::EntitySpecifics specifics = it->sync_data().GetSpecifics(); 186 EXPECT_FALSE(specifics.managed_user().acknowledged()); 187 specifics.mutable_managed_user()->set_acknowledged(true); 188 new_changes.push_back( 189 SyncChange(FROM_HERE, SyncChange::ACTION_UPDATE, 190 SyncData::CreateRemoteData(++sync_data_id_, 191 specifics, 192 base::Time()))); 193 } 194 service()->ProcessSyncChanges(FROM_HERE, new_changes); 195 196 run_loop_.Run(); 197 } 198 199 void ManagedUserRegistrationUtilityTest::OnManagedUserRegistered( 200 const GoogleServiceAuthError& error, 201 const std::string& token) { 202 received_callback_ = true; 203 error_ = error; 204 token_ = token; 205 run_loop_.Quit(); 206 } 207 208 TEST_F(ManagedUserRegistrationUtilityTest, Register) { 209 StartInitialSync(); 210 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher( 211 new MockManagedUserRefreshTokenFetcher); 212 ManagedUserRegistrationUtility registration_utility(prefs(), 213 token_fetcher.Pass(), 214 service()); 215 registration_utility.Register( 216 ManagedUserRegistrationUtility::GenerateNewManagedUserId(), 217 ManagedUserRegistrationInfo(ASCIIToUTF16("Dug")), 218 GetRegistrationCallback()); 219 EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 220 Acknowledge(); 221 222 EXPECT_TRUE(received_callback()); 223 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 224 EXPECT_FALSE(token().empty()); 225 } 226 227 TEST_F(ManagedUserRegistrationUtilityTest, RegisterBeforeInitialSync) { 228 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher( 229 new MockManagedUserRefreshTokenFetcher); 230 ManagedUserRegistrationUtility registration_utility(prefs(), 231 token_fetcher.Pass(), 232 service()); 233 registration_utility.Register( 234 ManagedUserRegistrationUtility::GenerateNewManagedUserId(), 235 ManagedUserRegistrationInfo(ASCIIToUTF16("Nemo")), 236 GetRegistrationCallback()); 237 EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 238 StartInitialSync(); 239 Acknowledge(); 240 241 EXPECT_TRUE(received_callback()); 242 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 243 EXPECT_FALSE(token().empty()); 244 } 245 246 TEST_F(ManagedUserRegistrationUtilityTest, SyncServiceShutdownBeforeRegFinish) { 247 StartInitialSync(); 248 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher( 249 new MockManagedUserRefreshTokenFetcher); 250 ManagedUserRegistrationUtility registration_utility(prefs(), 251 token_fetcher.Pass(), 252 service()); 253 registration_utility.Register( 254 ManagedUserRegistrationUtility::GenerateNewManagedUserId(), 255 ManagedUserRegistrationInfo(ASCIIToUTF16("Remy")), 256 GetRegistrationCallback()); 257 EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 258 service()->Shutdown(); 259 EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 260 EXPECT_TRUE(received_callback()); 261 EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state()); 262 EXPECT_EQ(std::string(), token()); 263 } 264 265 TEST_F(ManagedUserRegistrationUtilityTest, StopSyncingBeforeRegFinish) { 266 StartInitialSync(); 267 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher( 268 new MockManagedUserRefreshTokenFetcher); 269 ManagedUserRegistrationUtility registration_utility(prefs(), 270 token_fetcher.Pass(), 271 service()); 272 registration_utility.Register( 273 ManagedUserRegistrationUtility::GenerateNewManagedUserId(), 274 ManagedUserRegistrationInfo(ASCIIToUTF16("Mike")), 275 GetRegistrationCallback()); 276 EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 277 service()->StopSyncing(MANAGED_USERS); 278 EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kManagedUsers)->size()); 279 EXPECT_TRUE(received_callback()); 280 EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state()); 281 EXPECT_EQ(std::string(), token()); 282 } 283