OLD | NEW |
(Empty) | |
| 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 "chrome/browser/chromeos/login/managed/managed_user_test_base.h" |
| 6 |
| 7 #include <string> |
| 8 |
| 9 #include "base/compiler_specific.h" |
| 10 #include "base/run_loop.h" |
| 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/threading/sequenced_worker_pool.h" |
| 15 #include "chrome/browser/chrome_notification_types.h" |
| 16 #include "chrome/browser/chromeos/login/login_display_host_impl.h" |
| 17 #include "chrome/browser/chromeos/login/login_manager_test.h" |
| 18 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h
" |
| 19 #include "chrome/browser/chromeos/login/startup_utils.h" |
| 20 #include "chrome/browser/chromeos/login/supervised_user_manager.h" |
| 21 #include "chrome/browser/chromeos/login/webui_login_view.h" |
| 22 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h" |
| 23 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" |
| 24 #include "chrome/browser/managed_mode/managed_user_constants.h" |
| 25 #include "chrome/browser/managed_mode/managed_user_registration_utility.h" |
| 26 #include "chrome/browser/managed_mode/managed_user_registration_utility_stub.h" |
| 27 #include "chrome/browser/managed_mode/managed_user_shared_settings_service.h" |
| 28 #include "chrome/browser/managed_mode/managed_user_shared_settings_service_facto
ry.h" |
| 29 #include "chrome/browser/managed_mode/managed_user_sync_service.h" |
| 30 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h" |
| 31 #include "chromeos/cryptohome/mock_async_method_caller.h" |
| 32 #include "chromeos/cryptohome/mock_homedir_methods.h" |
| 33 #include "content/public/browser/notification_service.h" |
| 34 #include "content/public/test/browser_test_utils.h" |
| 35 #include "content/public/test/test_utils.h" |
| 36 #include "sync/api/attachments/attachment_service_proxy_for_test.h" |
| 37 #include "sync/api/fake_sync_change_processor.h" |
| 38 #include "sync/api/sync_change.h" |
| 39 #include "sync/api/sync_error_factory_mock.h" |
| 40 #include "sync/protocol/sync.pb.h" |
| 41 |
| 42 using testing::_; |
| 43 using base::StringPrintf; |
| 44 |
| 45 namespace chromeos { |
| 46 |
| 47 namespace testing { |
| 48 |
| 49 namespace { |
| 50 |
| 51 const char kCurrentPage[] = "$('managed-user-creation').currentPage_"; |
| 52 } |
| 53 |
| 54 ManagedUsersSyncTestAdapter::ManagedUsersSyncTestAdapter(Profile* profile) |
| 55 : processor_(), next_sync_data_id_(0) { |
| 56 service_ = ManagedUserSyncServiceFactory::GetForProfile(profile); |
| 57 processor_ = new syncer::FakeSyncChangeProcessor(); |
| 58 service_->MergeDataAndStartSyncing( |
| 59 syncer::MANAGED_USERS, |
| 60 syncer::SyncDataList(), |
| 61 scoped_ptr<syncer::SyncChangeProcessor>(processor_), |
| 62 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock)); |
| 63 } |
| 64 |
| 65 scoped_ptr< ::sync_pb::ManagedUserSpecifics> |
| 66 ManagedUsersSyncTestAdapter::GetFirstChange() { |
| 67 scoped_ptr< ::sync_pb::ManagedUserSpecifics> result( |
| 68 new ::sync_pb::ManagedUserSpecifics); |
| 69 CHECK(HasChanges()) |
| 70 << "GetFirstChange() should only be callled if HasChanges() is true"; |
| 71 const syncer::SyncData& data = processor_->changes().front().sync_data(); |
| 72 EXPECT_EQ(syncer::MANAGED_USERS, data.GetDataType()); |
| 73 result->CopyFrom(data.GetSpecifics().managed_user()); |
| 74 return result.Pass(); |
| 75 } |
| 76 |
| 77 void ManagedUsersSyncTestAdapter::AddChange( |
| 78 const ::sync_pb::ManagedUserSpecifics& proto, |
| 79 bool update) { |
| 80 sync_pb::EntitySpecifics specifics; |
| 81 |
| 82 specifics.mutable_managed_user()->CopyFrom(proto); |
| 83 |
| 84 syncer::SyncData change_data = syncer::SyncData::CreateRemoteData( |
| 85 ++next_sync_data_id_, |
| 86 specifics, |
| 87 base::Time(), |
| 88 syncer::AttachmentIdList(), |
| 89 syncer::AttachmentServiceProxyForTest::Create()); |
| 90 syncer::SyncChange change(FROM_HERE, |
| 91 update ? syncer::SyncChange::ACTION_UPDATE |
| 92 : syncer::SyncChange::ACTION_ADD, |
| 93 change_data); |
| 94 |
| 95 syncer::SyncChangeList change_list; |
| 96 change_list.push_back(change); |
| 97 |
| 98 service_->ProcessSyncChanges(FROM_HERE, change_list); |
| 99 } |
| 100 |
| 101 ManagedUsersSharedSettingsSyncTestAdapter:: |
| 102 ManagedUsersSharedSettingsSyncTestAdapter(Profile* profile) |
| 103 : processor_(), next_sync_data_id_(0) { |
| 104 service_ = |
| 105 ManagedUserSharedSettingsServiceFactory::GetForBrowserContext(profile); |
| 106 processor_ = new syncer::FakeSyncChangeProcessor(); |
| 107 service_->MergeDataAndStartSyncing( |
| 108 syncer::MANAGED_USER_SHARED_SETTINGS, |
| 109 syncer::SyncDataList(), |
| 110 scoped_ptr<syncer::SyncChangeProcessor>(processor_), |
| 111 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock)); |
| 112 } |
| 113 |
| 114 scoped_ptr< ::sync_pb::ManagedUserSharedSettingSpecifics> |
| 115 ManagedUsersSharedSettingsSyncTestAdapter::GetFirstChange() { |
| 116 scoped_ptr< ::sync_pb::ManagedUserSharedSettingSpecifics> result( |
| 117 new ::sync_pb::ManagedUserSharedSettingSpecifics); |
| 118 CHECK(HasChanges()) |
| 119 << "GetFirstChange() should only be callled if HasChanges() is true"; |
| 120 const syncer::SyncData& data = processor_->changes().front().sync_data(); |
| 121 EXPECT_EQ(syncer::MANAGED_USER_SHARED_SETTINGS, data.GetDataType()); |
| 122 result->CopyFrom(data.GetSpecifics().managed_user_shared_setting()); |
| 123 return result.Pass(); |
| 124 } |
| 125 |
| 126 void ManagedUsersSharedSettingsSyncTestAdapter::AddChange( |
| 127 const ::sync_pb::ManagedUserSharedSettingSpecifics& proto, |
| 128 bool update) { |
| 129 sync_pb::EntitySpecifics specifics; |
| 130 |
| 131 specifics.mutable_managed_user_shared_setting()->CopyFrom(proto); |
| 132 |
| 133 syncer::SyncData change_data = syncer::SyncData::CreateRemoteData( |
| 134 ++next_sync_data_id_, |
| 135 specifics, |
| 136 base::Time(), |
| 137 syncer::AttachmentIdList(), |
| 138 syncer::AttachmentServiceProxyForTest::Create()); |
| 139 syncer::SyncChange change(FROM_HERE, |
| 140 update ? syncer::SyncChange::ACTION_UPDATE |
| 141 : syncer::SyncChange::ACTION_ADD, |
| 142 change_data); |
| 143 |
| 144 syncer::SyncChangeList change_list; |
| 145 change_list.push_back(change); |
| 146 |
| 147 service_->ProcessSyncChanges(FROM_HERE, change_list); |
| 148 } |
| 149 |
| 150 void ManagedUsersSharedSettingsSyncTestAdapter::AddChange( |
| 151 const std::string& mu_id, |
| 152 const std::string& key, |
| 153 const base::Value& value, |
| 154 bool acknowledged, |
| 155 bool update) { |
| 156 syncer::SyncData data = |
| 157 ManagedUserSharedSettingsService::CreateSyncDataForSetting( |
| 158 mu_id, key, value, acknowledged); |
| 159 AddChange(data.GetSpecifics().managed_user_shared_setting(), update); |
| 160 } |
| 161 |
| 162 ManagedUserTestBase::ManagedUserTestBase() |
| 163 : LoginManagerTest(true), |
| 164 mock_async_method_caller_(NULL), |
| 165 mock_homedir_methods_(NULL), |
| 166 network_portal_detector_(NULL), |
| 167 registration_utility_stub_(NULL) { |
| 168 } |
| 169 |
| 170 ManagedUserTestBase::~ManagedUserTestBase() { |
| 171 } |
| 172 |
| 173 void ManagedUserTestBase::SetUpInProcessBrowserTestFixture() { |
| 174 LoginManagerTest::SetUpInProcessBrowserTestFixture(); |
| 175 mock_async_method_caller_ = new cryptohome::MockAsyncMethodCaller; |
| 176 mock_async_method_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| 177 cryptohome::AsyncMethodCaller::InitializeForTesting( |
| 178 mock_async_method_caller_); |
| 179 |
| 180 mock_homedir_methods_ = new cryptohome::MockHomedirMethods; |
| 181 mock_homedir_methods_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| 182 cryptohome::HomedirMethods::InitializeForTesting(mock_homedir_methods_); |
| 183 |
| 184 registration_utility_stub_ = new ManagedUserRegistrationUtilityStub(); |
| 185 scoped_utility_.reset(new ScopedTestingManagedUserRegistrationUtility( |
| 186 registration_utility_stub_)); |
| 187 |
| 188 // Setup network portal detector to return online state for both |
| 189 // ethernet and wifi networks. Ethernet is an active network by |
| 190 // default. |
| 191 network_portal_detector_ = new NetworkPortalDetectorTestImpl(); |
| 192 NetworkPortalDetector::InitializeForTesting(network_portal_detector_); |
| 193 NetworkPortalDetector::CaptivePortalState online_state; |
| 194 online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE; |
| 195 online_state.response_code = 204; |
| 196 network_portal_detector_->SetDefaultNetworkPathForTesting( |
| 197 kStubEthernetServicePath); |
| 198 network_portal_detector_->SetDetectionResultsForTesting( |
| 199 kStubEthernetServicePath, online_state); |
| 200 } |
| 201 |
| 202 void ManagedUserTestBase::CleanUpOnMainThread() { |
| 203 LoginManagerTest::CleanUpOnMainThread(); |
| 204 } |
| 205 |
| 206 void ManagedUserTestBase::TearDown() { |
| 207 cryptohome::AsyncMethodCaller::Shutdown(); |
| 208 cryptohome::HomedirMethods::Shutdown(); |
| 209 mock_homedir_methods_ = NULL; |
| 210 mock_async_method_caller_ = NULL; |
| 211 LoginManagerTest::TearDown(); |
| 212 } |
| 213 |
| 214 void ManagedUserTestBase::TearDownInProcessBrowserTestFixture() { |
| 215 NetworkPortalDetector::Shutdown(); |
| 216 } |
| 217 |
| 218 void ManagedUserTestBase::JSEval(const std::string& script) { |
| 219 EXPECT_TRUE(content::ExecuteScript(web_contents(), script)); |
| 220 } |
| 221 |
| 222 void ManagedUserTestBase::JSExpectAsync(const std::string& function) { |
| 223 bool result; |
| 224 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
| 225 web_contents(), |
| 226 StringPrintf( |
| 227 "(%s)(function() { window.domAutomationController.send(true); });", |
| 228 function.c_str()), |
| 229 &result)); |
| 230 EXPECT_TRUE(result); |
| 231 } |
| 232 |
| 233 void ManagedUserTestBase::JSSetTextField(const std::string& element_selector, |
| 234 const std::string& value) { |
| 235 std::string function = |
| 236 StringPrintf("document.querySelector('%s').value = '%s'", |
| 237 element_selector.c_str(), |
| 238 value.c_str()); |
| 239 JSEval(function); |
| 240 } |
| 241 |
| 242 void ManagedUserTestBase::PrepareUsers() { |
| 243 RegisterUser(kTestManager); |
| 244 RegisterUser(kTestOtherUser); |
| 245 chromeos::StartupUtils::MarkOobeCompleted(); |
| 246 } |
| 247 |
| 248 void ManagedUserTestBase::StartFlowLoginAsManager() { |
| 249 // Navigate to supervised user creation screen. |
| 250 JSEval("chrome.send('showLocallyManagedUserCreationScreen')"); |
| 251 |
| 252 // Read intro and proceed. |
| 253 JSExpect(StringPrintf("%s == 'intro'", kCurrentPage)); |
| 254 |
| 255 JSEval("$('managed-user-creation-start-button').click()"); |
| 256 |
| 257 // Check that both users appear as managers, and test-manager@gmail.com is |
| 258 // the first one. |
| 259 JSExpect(StringPrintf("%s == 'manager'", kCurrentPage)); |
| 260 |
| 261 std::string manager_pods = |
| 262 "document.querySelectorAll('#managed-user-creation-managers-pane " |
| 263 ".manager-pod')"; |
| 264 std::string selected_manager_pods = |
| 265 "document.querySelectorAll('#managed-user-creation-managers-pane " |
| 266 ".manager-pod.focused')"; |
| 267 |
| 268 int managers_on_device = 2; |
| 269 |
| 270 JSExpect(StringPrintf("%s.length == 1", selected_manager_pods.c_str())); |
| 271 |
| 272 JSExpect( |
| 273 StringPrintf("$('managed-user-creation').managerList_.pods.length == %d", |
| 274 managers_on_device)); |
| 275 JSExpect(StringPrintf( |
| 276 "%s.length == %d", manager_pods.c_str(), managers_on_device)); |
| 277 JSExpect(StringPrintf("%s[%d].user.emailAddress == '%s'", |
| 278 manager_pods.c_str(), |
| 279 0, |
| 280 kTestManager)); |
| 281 |
| 282 // Select the first user as manager, and enter password. |
| 283 JSExpect("$('managed-user-creation-next-button').disabled"); |
| 284 JSSetTextField("#managed-user-creation .manager-pod.focused input", |
| 285 kTestManagerPassword); |
| 286 |
| 287 JSEval("$('managed-user-creation').updateNextButtonForManager_()"); |
| 288 |
| 289 // Next button is now enabled. |
| 290 JSExpect("!$('managed-user-creation-next-button').disabled"); |
| 291 SetExpectedCredentials(kTestManager, kTestManagerPassword); |
| 292 content::WindowedNotificationObserver login_observer( |
| 293 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, |
| 294 content::NotificationService::AllSources()); |
| 295 |
| 296 // Log in as manager. |
| 297 JSEval("$('managed-user-creation-next-button').click()"); |
| 298 login_observer.Wait(); |
| 299 |
| 300 // OAuth token is valid. |
| 301 UserManager::Get()->SaveUserOAuthStatus(kTestManager, |
| 302 User::OAUTH2_TOKEN_STATUS_VALID); |
| 303 base::RunLoop().RunUntilIdle(); |
| 304 |
| 305 // Check the page have changed. |
| 306 JSExpect(StringPrintf("%s == 'username'", kCurrentPage)); |
| 307 } |
| 308 |
| 309 void ManagedUserTestBase::FillNewUserData(const std::string& display_name) { |
| 310 JSExpect("$('managed-user-creation-next-button').disabled"); |
| 311 JSSetTextField("#managed-user-creation-name", display_name); |
| 312 JSEval("$('managed-user-creation').checkUserName_()"); |
| 313 |
| 314 base::RunLoop().RunUntilIdle(); |
| 315 |
| 316 JSSetTextField("#managed-user-creation-password", |
| 317 kTestSupervisedUserPassword); |
| 318 JSSetTextField("#managed-user-creation-password-confirm", |
| 319 kTestSupervisedUserPassword); |
| 320 |
| 321 JSEval("$('managed-user-creation').updateNextButtonForUser_()"); |
| 322 JSExpect("!$('managed-user-creation-next-button').disabled"); |
| 323 } |
| 324 |
| 325 void ManagedUserTestBase::StartUserCreation( |
| 326 const std::string& button_id, |
| 327 const std::string& expected_display_name) { |
| 328 EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1); |
| 329 EXPECT_CALL(*mock_homedir_methods_, AddKeyEx(_, _, _, _, _)).Times(1); |
| 330 |
| 331 JSEval(std::string("$('").append(button_id).append("').click()")); |
| 332 |
| 333 ::testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_); |
| 334 |
| 335 EXPECT_TRUE(registration_utility_stub_->register_was_called()); |
| 336 EXPECT_EQ(registration_utility_stub_->display_name(), |
| 337 base::UTF8ToUTF16(expected_display_name)); |
| 338 |
| 339 registration_utility_stub_->RunSuccessCallback("token"); |
| 340 |
| 341 // Token writing moves control to BlockingPool and back. |
| 342 base::RunLoop().RunUntilIdle(); |
| 343 content::BrowserThread::GetBlockingPool()->FlushForTesting(); |
| 344 base::RunLoop().RunUntilIdle(); |
| 345 |
| 346 JSExpect(StringPrintf("%s == 'created'", kCurrentPage)); |
| 347 JSEval("$('managed-user-creation-gotit-button').click()"); |
| 348 } |
| 349 |
| 350 void ManagedUserTestBase::SigninAsSupervisedUser( |
| 351 bool check_homedir_calls, |
| 352 int user_index, |
| 353 const std::string& expected_display_name) { |
| 354 if (check_homedir_calls) |
| 355 EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1); |
| 356 |
| 357 // Log in as supervised user, make sure that everything works. |
| 358 ASSERT_EQ(3UL, UserManager::Get()->GetUsers().size()); |
| 359 |
| 360 // Created supervised user have to be first in a list. |
| 361 const User* user = UserManager::Get()->GetUsers().at(user_index); |
| 362 ASSERT_EQ(base::UTF8ToUTF16(expected_display_name), user->display_name()); |
| 363 LoginUser(user->email()); |
| 364 if (check_homedir_calls) |
| 365 ::testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_); |
| 366 Profile* profile = UserManager::Get()->GetProfileByUser(user); |
| 367 shared_settings_adapter_.reset( |
| 368 new ManagedUsersSharedSettingsSyncTestAdapter(profile)); |
| 369 } |
| 370 |
| 371 void ManagedUserTestBase::SigninAsManager(int user_index) { |
| 372 // Log in as supervised user, make sure that everything works. |
| 373 ASSERT_EQ(3UL, UserManager::Get()->GetUsers().size()); |
| 374 |
| 375 // Created supervised user have to be first in a list. |
| 376 const User* user = UserManager::Get()->GetUsers().at(user_index); |
| 377 LoginUser(user->email()); |
| 378 Profile* profile = UserManager::Get()->GetProfileByUser(user); |
| 379 shared_settings_adapter_.reset( |
| 380 new ManagedUsersSharedSettingsSyncTestAdapter(profile)); |
| 381 managed_users_adapter_.reset(new ManagedUsersSyncTestAdapter(profile)); |
| 382 } |
| 383 |
| 384 void ManagedUserTestBase::RemoveSupervisedUser( |
| 385 unsigned long original_user_count, |
| 386 int user_index, |
| 387 const std::string& expected_display_name) { |
| 388 // Remove supervised user. |
| 389 ASSERT_EQ(original_user_count, UserManager::Get()->GetUsers().size()); |
| 390 |
| 391 // Created supervised user have to be first in a list. |
| 392 const User* user = UserManager::Get()->GetUsers().at(user_index); |
| 393 ASSERT_EQ(base::UTF8ToUTF16(expected_display_name), user->display_name()); |
| 394 |
| 395 // Open pod menu. |
| 396 JSExpect( |
| 397 StringPrintf("!$('pod-row').pods[%d].isActionBoxMenuActive", user_index)); |
| 398 JSEval(StringPrintf( |
| 399 "$('pod-row').pods[%d].querySelector('.action-box-button').click()", |
| 400 user_index)); |
| 401 JSExpect( |
| 402 StringPrintf("$('pod-row').pods[%d].isActionBoxMenuActive", user_index)); |
| 403 |
| 404 // Select "Remove user" element. |
| 405 JSExpect(StringPrintf( |
| 406 "$('pod-row').pods[%d].actionBoxRemoveUserWarningElement.hidden", |
| 407 user_index)); |
| 408 JSEval(StringPrintf( |
| 409 "$('pod-row').pods[%d].querySelector('.action-box-menu-remove').click()", |
| 410 user_index)); |
| 411 JSExpect(StringPrintf( |
| 412 "!$('pod-row').pods[%d].actionBoxRemoveUserWarningElement.hidden", |
| 413 user_index)); |
| 414 |
| 415 EXPECT_CALL(*mock_async_method_caller_, AsyncRemove(_, _)).Times(1); |
| 416 |
| 417 // Confirm deletion. |
| 418 JSEval(StringPrintf( |
| 419 "$('pod-row').pods[%d].querySelector('.remove-warning-button').click()", |
| 420 user_index)); |
| 421 |
| 422 // Make sure there is no supervised user in list. |
| 423 ASSERT_EQ(original_user_count - 1, UserManager::Get()->GetUsers().size()); |
| 424 } |
| 425 |
| 426 } // namespace testing |
| 427 |
| 428 } // namespace chromeos |
OLD | NEW |