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