Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / chromeos / login / supervised / supervised_user_test_base.cc
blobf8e1a675921418374224c658bf91ff696610ee8b
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.
5 #include "chrome/browser/chromeos/login/supervised/supervised_user_test_base.h"
7 #include <string>
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_manager_test.h"
17 #include "chrome/browser/chromeos/login/startup_utils.h"
18 #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
19 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
20 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
21 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
22 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
23 #include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.h"
24 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
25 #include "chrome/browser/chromeos/profiles/profile_helper.h"
26 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
27 #include "chrome/browser/profiles/profile_impl.h"
28 #include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility.h"
29 #include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility_stub.h"
30 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h"
31 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
32 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service.h"
33 #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service_factory.h"
34 #include "chrome/browser/supervised_user/supervised_user_constants.h"
35 #include "chromeos/cryptohome/mock_async_method_caller.h"
36 #include "chromeos/cryptohome/mock_homedir_methods.h"
37 #include "chromeos/login/auth/key.h"
38 #include "chromeos/login/auth/user_context.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/test/browser_test_utils.h"
41 #include "content/public/test/test_utils.h"
42 #include "sync/api/fake_sync_change_processor.h"
43 #include "sync/api/sync_change.h"
44 #include "sync/api/sync_error_factory_mock.h"
45 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
46 #include "sync/protocol/sync.pb.h"
48 using testing::_;
49 using base::StringPrintf;
51 namespace chromeos {
53 namespace {
55 const char kCurrentPage[] = "$('supervised-user-creation').currentPage_";
57 const char kStubEthernetGuid[] = "eth0";
61 SupervisedUsersSyncTestAdapter::SupervisedUsersSyncTestAdapter(Profile* profile)
62 : processor_(), next_sync_data_id_(0) {
63 service_ = SupervisedUserSyncServiceFactory::GetForProfile(profile);
64 processor_ = new syncer::FakeSyncChangeProcessor();
65 service_->MergeDataAndStartSyncing(
66 syncer::SUPERVISED_USERS,
67 syncer::SyncDataList(),
68 scoped_ptr<syncer::SyncChangeProcessor>(processor_),
69 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock));
72 scoped_ptr< ::sync_pb::ManagedUserSpecifics>
73 SupervisedUsersSyncTestAdapter::GetFirstChange() {
74 scoped_ptr< ::sync_pb::ManagedUserSpecifics> result(
75 new ::sync_pb::ManagedUserSpecifics);
76 CHECK(HasChanges())
77 << "GetFirstChange() should only be callled if HasChanges() is true";
78 const syncer::SyncData& data = processor_->changes().front().sync_data();
79 EXPECT_EQ(syncer::SUPERVISED_USERS, data.GetDataType());
80 result->CopyFrom(data.GetSpecifics().managed_user());
81 return result.Pass();
84 void SupervisedUsersSyncTestAdapter::AddChange(
85 const ::sync_pb::ManagedUserSpecifics& proto,
86 bool update) {
87 sync_pb::EntitySpecifics specifics;
89 specifics.mutable_managed_user()->CopyFrom(proto);
91 syncer::SyncData change_data = syncer::SyncData::CreateRemoteData(
92 ++next_sync_data_id_,
93 specifics,
94 base::Time(),
95 syncer::AttachmentIdList(),
96 syncer::AttachmentServiceProxyForTest::Create());
97 syncer::SyncChange change(FROM_HERE,
98 update ? syncer::SyncChange::ACTION_UPDATE
99 : syncer::SyncChange::ACTION_ADD,
100 change_data);
102 syncer::SyncChangeList change_list;
103 change_list.push_back(change);
105 service_->ProcessSyncChanges(FROM_HERE, change_list);
108 SupervisedUsersSharedSettingsSyncTestAdapter::
109 SupervisedUsersSharedSettingsSyncTestAdapter(Profile* profile)
110 : processor_(), next_sync_data_id_(0) {
111 service_ =
112 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext(profile);
113 processor_ = new syncer::FakeSyncChangeProcessor();
114 service_->MergeDataAndStartSyncing(
115 syncer::SUPERVISED_USER_SHARED_SETTINGS,
116 syncer::SyncDataList(),
117 scoped_ptr<syncer::SyncChangeProcessor>(processor_),
118 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock));
121 scoped_ptr< ::sync_pb::ManagedUserSharedSettingSpecifics>
122 SupervisedUsersSharedSettingsSyncTestAdapter::GetFirstChange() {
123 scoped_ptr< ::sync_pb::ManagedUserSharedSettingSpecifics> result(
124 new ::sync_pb::ManagedUserSharedSettingSpecifics);
125 CHECK(HasChanges())
126 << "GetFirstChange() should only be callled if HasChanges() is true";
127 const syncer::SyncData& data = processor_->changes().front().sync_data();
128 EXPECT_EQ(syncer::SUPERVISED_USER_SHARED_SETTINGS, data.GetDataType());
129 result->CopyFrom(data.GetSpecifics().managed_user_shared_setting());
130 return result.Pass();
133 void SupervisedUsersSharedSettingsSyncTestAdapter::AddChange(
134 const ::sync_pb::ManagedUserSharedSettingSpecifics& proto,
135 bool update) {
136 sync_pb::EntitySpecifics specifics;
138 specifics.mutable_managed_user_shared_setting()->CopyFrom(proto);
140 syncer::SyncData change_data = syncer::SyncData::CreateRemoteData(
141 ++next_sync_data_id_,
142 specifics,
143 base::Time(),
144 syncer::AttachmentIdList(),
145 syncer::AttachmentServiceProxyForTest::Create());
146 syncer::SyncChange change(FROM_HERE,
147 update ? syncer::SyncChange::ACTION_UPDATE
148 : syncer::SyncChange::ACTION_ADD,
149 change_data);
151 syncer::SyncChangeList change_list;
152 change_list.push_back(change);
154 service_->ProcessSyncChanges(FROM_HERE, change_list);
157 void SupervisedUsersSharedSettingsSyncTestAdapter::AddChange(
158 const std::string& mu_id,
159 const std::string& key,
160 const base::Value& value,
161 bool acknowledged,
162 bool update) {
163 syncer::SyncData data =
164 SupervisedUserSharedSettingsService::CreateSyncDataForSetting(
165 mu_id, key, value, acknowledged);
166 AddChange(data.GetSpecifics().managed_user_shared_setting(), update);
169 SupervisedUserTestBase::SupervisedUserTestBase()
170 : LoginManagerTest(true),
171 mock_async_method_caller_(NULL),
172 mock_homedir_methods_(NULL),
173 network_portal_detector_(NULL),
174 registration_utility_stub_(NULL) {
177 SupervisedUserTestBase::~SupervisedUserTestBase() {
180 void SupervisedUserTestBase::SetUpInProcessBrowserTestFixture() {
181 LoginManagerTest::SetUpInProcessBrowserTestFixture();
182 mock_async_method_caller_ = new cryptohome::MockAsyncMethodCaller;
183 mock_async_method_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
184 cryptohome::AsyncMethodCaller::InitializeForTesting(
185 mock_async_method_caller_);
187 mock_homedir_methods_ = new cryptohome::MockHomedirMethods;
188 mock_homedir_methods_->SetUp(true, cryptohome::MOUNT_ERROR_NONE);
189 cryptohome::HomedirMethods::InitializeForTesting(mock_homedir_methods_);
191 registration_utility_stub_ = new SupervisedUserRegistrationUtilityStub();
192 scoped_utility_.reset(new ScopedTestingSupervisedUserRegistrationUtility(
193 registration_utility_stub_));
195 // Setup network portal detector to return online state for both
196 // ethernet and wifi networks. Ethernet is an active network by
197 // default.
198 network_portal_detector_ = new NetworkPortalDetectorTestImpl();
199 NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
200 NetworkPortalDetector::CaptivePortalState online_state;
201 online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
202 online_state.response_code = 204;
203 network_portal_detector_->SetDefaultNetworkForTesting(kStubEthernetGuid);
204 network_portal_detector_->SetDetectionResultsForTesting(kStubEthernetGuid,
205 online_state);
208 void SupervisedUserTestBase::TearDown() {
209 cryptohome::AsyncMethodCaller::Shutdown();
210 cryptohome::HomedirMethods::Shutdown();
211 mock_homedir_methods_ = NULL;
212 mock_async_method_caller_ = NULL;
213 LoginManagerTest::TearDown();
216 void SupervisedUserTestBase::TearDownInProcessBrowserTestFixture() {
217 NetworkPortalDetector::Shutdown();
220 void SupervisedUserTestBase::JSEval(const std::string& script) {
221 EXPECT_TRUE(content::ExecuteScript(web_contents(), script)) << script;
224 void SupervisedUserTestBase::JSEvalOrExitBrowser(const std::string& script) {
225 ignore_result(content::ExecuteScript(web_contents(), script));
228 void SupervisedUserTestBase::JSExpectAsync(const std::string& function) {
229 bool result;
230 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
231 web_contents(),
232 StringPrintf(
233 "(%s)(function() { window.domAutomationController.send(true); });",
234 function.c_str()),
235 &result)) << function;
236 EXPECT_TRUE(result);
239 void SupervisedUserTestBase::JSSetTextField(const std::string& element_selector,
240 const std::string& value) {
241 std::string function =
242 StringPrintf("document.querySelector('%s').value = '%s'",
243 element_selector.c_str(),
244 value.c_str());
245 JSEval(function);
248 void SupervisedUserTestBase::PrepareUsers() {
249 RegisterUser(kTestManager);
250 RegisterUser(kTestOtherUser);
251 chromeos::StartupUtils::MarkOobeCompleted();
254 void SupervisedUserTestBase::StartFlowLoginAsManager() {
255 // Navigate to supervised user creation screen.
256 JSEval("chrome.send('showSupervisedUserCreationScreen')");
258 // Read intro and proceed.
259 JSExpect(StringPrintf("%s == 'intro'", kCurrentPage));
261 JSEval("$('supervised-user-creation-start-button').click()");
263 // Check that both users appear as managers, and test-manager@gmail.com is
264 // the first one.
265 JSExpect(StringPrintf("%s == 'manager'", kCurrentPage));
267 std::string manager_pods =
268 "document.querySelectorAll('#supervised-user-creation-managers-pane "
269 ".manager-pod')";
270 std::string selected_manager_pods =
271 "document.querySelectorAll('#supervised-user-creation-managers-pane "
272 ".manager-pod.focused')";
274 int managers_on_device = 2;
276 JSExpect(StringPrintf("%s.length == 1", selected_manager_pods.c_str()));
278 JSExpect(StringPrintf(
279 "$('supervised-user-creation').managerList_.pods.length == %d",
280 managers_on_device));
281 JSExpect(StringPrintf(
282 "%s.length == %d", manager_pods.c_str(), managers_on_device));
283 JSExpect(StringPrintf("%s[%d].user.emailAddress == '%s'",
284 manager_pods.c_str(),
286 kTestManager));
288 // Select the first user as manager, and enter password.
289 JSExpect("$('supervised-user-creation-next-button').disabled");
290 JSSetTextField("#supervised-user-creation .manager-pod.focused input",
291 kTestManagerPassword);
293 JSEval("$('supervised-user-creation').updateNextButtonForManager_()");
295 // Next button is now enabled.
296 JSExpect("!$('supervised-user-creation-next-button').disabled");
297 UserContext user_context(kTestManager);
298 user_context.SetGaiaID(GetGaiaIDForUserID(kTestManager));
299 user_context.SetKey(Key(kTestManagerPassword));
300 SetExpectedCredentials(user_context);
301 content::WindowedNotificationObserver login_observer(
302 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
303 content::NotificationService::AllSources());
305 // Log in as manager.
306 JSEval("$('supervised-user-creation-next-button').click()");
307 login_observer.Wait();
309 // OAuth token is valid.
310 user_manager::UserManager::Get()->SaveUserOAuthStatus(
311 kTestManager, user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
312 base::RunLoop().RunUntilIdle();
314 // Check the page have changed.
315 JSExpect(StringPrintf("%s == 'username'", kCurrentPage));
318 void SupervisedUserTestBase::FillNewUserData(const std::string& display_name) {
319 JSExpect("$('supervised-user-creation-next-button').disabled");
320 JSSetTextField("#supervised-user-creation-name", display_name);
321 JSEval("$('supervised-user-creation').checkUserName_()");
323 base::RunLoop().RunUntilIdle();
325 JSSetTextField("#supervised-user-creation-password",
326 kTestSupervisedUserPassword);
327 JSSetTextField("#supervised-user-creation-password-confirm",
328 kTestSupervisedUserPassword);
330 JSEval("$('supervised-user-creation').updateNextButtonForUser_()");
331 JSExpect("!$('supervised-user-creation-next-button').disabled");
334 void SupervisedUserTestBase::StartUserCreation(
335 const std::string& button_id,
336 const std::string& expected_display_name) {
337 EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1);
338 EXPECT_CALL(*mock_homedir_methods_, AddKeyEx(_, _, _, _, _)).Times(1);
340 JSEval(std::string("$('").append(button_id).append("').click()"));
342 ::testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
344 EXPECT_TRUE(registration_utility_stub_->register_was_called());
345 EXPECT_EQ(registration_utility_stub_->display_name(),
346 base::UTF8ToUTF16(expected_display_name));
348 registration_utility_stub_->RunSuccessCallback("token");
350 // Token writing moves control to BlockingPool and back.
351 content::RunAllBlockingPoolTasksUntilIdle();
353 JSExpect(StringPrintf("%s == 'created'", kCurrentPage));
354 JSEvalOrExitBrowser("$('supervised-user-creation-gotit-button').click()");
357 void SupervisedUserTestBase::SigninAsSupervisedUser(
358 bool check_homedir_calls,
359 int user_index,
360 const std::string& expected_display_name) {
361 if (check_homedir_calls)
362 EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1);
364 // Log in as supervised user, make sure that everything works.
365 ASSERT_EQ(3UL, user_manager::UserManager::Get()->GetUsers().size());
367 // Created supervised user have to be first in a list.
368 const user_manager::User* user =
369 user_manager::UserManager::Get()->GetUsers().at(user_index);
370 ASSERT_EQ(base::UTF8ToUTF16(expected_display_name), user->display_name());
372 // Clean first run flag before logging in.
373 static_cast<SupervisedUserManagerImpl*>(
374 ChromeUserManager::Get()->GetSupervisedUserManager())
375 ->CheckForFirstRun(user->email());
377 LoginUser(user->email());
378 if (check_homedir_calls)
379 ::testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
380 Profile* profile = ProfileHelper::Get()->GetProfileByUserUnsafe(user);
381 shared_settings_adapter_.reset(
382 new SupervisedUsersSharedSettingsSyncTestAdapter(profile));
384 // Check ChromeOS preference is initialized.
385 EXPECT_TRUE(
386 static_cast<ProfileImpl*>(profile)->chromeos_preferences_);
389 void SupervisedUserTestBase::SigninAsManager(int user_index) {
390 // Log in as supervised user, make sure that everything works.
391 ASSERT_EQ(3UL, user_manager::UserManager::Get()->GetUsers().size());
393 // Created supervised user have to be first in a list.
394 const user_manager::User* user =
395 user_manager::UserManager::Get()->GetUsers().at(user_index);
396 LoginUser(user->email());
397 Profile* profile = ProfileHelper::Get()->GetProfileByUserUnsafe(user);
398 shared_settings_adapter_.reset(
399 new SupervisedUsersSharedSettingsSyncTestAdapter(profile));
400 supervised_users_adapter_.reset(new SupervisedUsersSyncTestAdapter(profile));
403 void SupervisedUserTestBase::RemoveSupervisedUser(
404 size_t original_user_count,
405 int user_index,
406 const std::string& expected_display_name) {
407 // Remove supervised user.
408 ASSERT_EQ(original_user_count,
409 user_manager::UserManager::Get()->GetUsers().size());
411 // Created supervised user have to be first in a list.
412 const user_manager::User* user =
413 user_manager::UserManager::Get()->GetUsers().at(user_index);
414 ASSERT_EQ(base::UTF8ToUTF16(expected_display_name), user->display_name());
416 // Open pod menu.
417 JSExpect(
418 StringPrintf("!$('pod-row').pods[%d].isActionBoxMenuActive", user_index));
419 JSEval(StringPrintf(
420 "$('pod-row').pods[%d].querySelector('.action-box-button').click()",
421 user_index));
422 JSExpect(
423 StringPrintf("$('pod-row').pods[%d].isActionBoxMenuActive", user_index));
425 // Select "Remove user" element.
426 JSExpect(StringPrintf(
427 "$('pod-row').pods[%d].actionBoxRemoveUserWarningElement.hidden",
428 user_index));
429 JSEval(StringPrintf(
430 "$('pod-row').pods[%d].querySelector('.action-box-menu-remove').click()",
431 user_index));
432 JSExpect(StringPrintf(
433 "!$('pod-row').pods[%d].actionBoxRemoveUserWarningElement.hidden",
434 user_index));
436 EXPECT_CALL(*mock_async_method_caller_, AsyncRemove(_, _)).Times(1);
438 // Confirm deletion.
439 JSEval(StringPrintf(
440 "$('pod-row').pods[%d].querySelector('.remove-warning-button').click()",
441 user_index));
443 // Make sure there is no supervised user in list.
444 ASSERT_EQ(original_user_count - 1,
445 user_manager::UserManager::Get()->GetUsers().size());
448 } // namespace chromeos