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 "base/basictypes.h"
6 #include "base/compiler_specific.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/chromeos/login/login_manager_test.h"
10 #include "chrome/browser/chromeos/login/startup_utils.h"
11 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
12 #include "chrome/browser/chromeos/profiles/profile_helper.h"
13 #include "chrome/browser/chromeos/settings/cros_settings.h"
14 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_commands.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "chromeos/settings/cros_settings_names.h"
22 #include "components/signin/core/browser/signin_manager.h"
23 #include "components/user_manager/user_manager.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/test/browser_test_utils.h"
26 #include "content/public/test/test_utils.h"
32 const char* kTestOwner
= "test-owner@example.com";
33 const char* kTestNonOwner
= "test-user1@example.com";
35 const char* kKnownSettings
[] = {
37 kAccountsPrefAllowGuest
,
38 kAccountsPrefAllowNewUser
,
39 kAccountsPrefDeviceLocalAccounts
,
40 kAccountsPrefShowUserNamesOnSignIn
,
41 kAccountsPrefSupervisedUsersEnabled
,
44 // Stub settings provider that only handles the settings we need to control.
45 // StubCrosSettingsProvider handles more settings but leaves many of them unset
46 // which the Settings page doesn't expect.
47 class StubAccountSettingsProvider
: public StubCrosSettingsProvider
{
49 StubAccountSettingsProvider() {
52 ~StubAccountSettingsProvider() override
{}
54 // StubCrosSettingsProvider implementation.
55 bool HandlesSetting(const std::string
& path
) const override
{
56 const char** end
= kKnownSettings
+ arraysize(kKnownSettings
);
57 return std::find(kKnownSettings
, end
, path
) != end
;
62 const char* pref_name
;
67 const PrefTest kPrefTests
[] = {
68 { kSystemTimezone
, false, false },
69 { prefs::kUse24HourClock
, false, false },
70 { kAttestationForContentProtectionEnabled
, true, true },
71 { kAccountsPrefAllowGuest
, true, false },
72 { kAccountsPrefAllowNewUser
, true, false },
73 { kAccountsPrefShowUserNamesOnSignIn
, true, false },
74 { kAccountsPrefSupervisedUsersEnabled
, true, false },
75 #if defined(GOOGLE_CHROME_BUILD)
76 { kStatsReportingPref
, true, true },
77 { prefs::kSpellCheckUseSpellingService
, false, false },
83 class SharedOptionsTest
: public LoginManagerTest
{
86 : LoginManagerTest(false),
87 device_settings_provider_(NULL
) {
88 stub_settings_provider_
.Set(kDeviceOwner
, base::StringValue(kTestOwner
));
91 ~SharedOptionsTest() override
{}
93 void SetUpOnMainThread() override
{
94 LoginManagerTest::SetUpOnMainThread();
96 CrosSettings
* settings
= CrosSettings::Get();
98 // Add the stub settings provider, moving the device settings provider
99 // behind it so our stub takes precedence.
100 device_settings_provider_
= settings
->GetProvider(kDeviceOwner
);
101 settings
->RemoveSettingsProvider(device_settings_provider_
);
102 settings
->AddSettingsProvider(&stub_settings_provider_
);
103 settings
->AddSettingsProvider(device_settings_provider_
);
106 void TearDownOnMainThread() override
{
107 CrosSettings
* settings
= CrosSettings::Get();
108 settings
->RemoveSettingsProvider(&stub_settings_provider_
);
109 LoginManagerTest::TearDownOnMainThread();
113 void CheckOptionsUI(const user_manager::User
* user
,
116 Browser
* browser
= CreateBrowserForUser(user
);
117 content::WebContents
* contents
=
118 browser
->tab_strip_model()->GetActiveWebContents();
120 for (size_t i
= 0; i
< sizeof(kPrefTests
) / sizeof(kPrefTests
[0]); i
++) {
121 bool disabled
= !is_owner
&& kPrefTests
[i
].owner_only
;
122 if (strcmp(kPrefTests
[i
].pref_name
, kSystemTimezone
) == 0) {
123 disabled
= ProfileHelper::Get()
124 ->GetProfileByUserUnsafe(user
)
126 ->GetBoolean(prefs::kResolveTimezoneByGeolocation
);
130 contents
, kPrefTests
[i
].pref_name
, disabled
,
131 !is_owner
&& kPrefTests
[i
].indicator
? "owner" : std::string());
133 CheckBanner(contents
, is_primary
);
134 CheckSharedSections(contents
, is_primary
);
135 CheckAccountsOverlay(contents
, is_owner
);
138 // Creates a browser and navigates to the Settings page.
139 Browser
* CreateBrowserForUser(const user_manager::User
* user
) {
140 Profile
* profile
= ProfileHelper::Get()->GetProfileByUserUnsafe(user
);
141 SigninManagerFactory::GetForProfile(profile
)->
142 SetAuthenticatedAccountInfo(GetGaiaIDForUserID(user
->email()),
145 ui_test_utils::BrowserAddedObserver observer
;
146 Browser
* browser
= CreateBrowser(profile
);
147 observer
.WaitForSingleNewBrowser();
149 ui_test_utils::NavigateToURL(browser
,
150 GURL("chrome://settings-frame"));
154 // Verifies a preference's disabled state and controlled-by indicator.
155 void CheckPreference(content::WebContents
* contents
,
156 std::string pref_name
,
158 std::string controlled_by
) {
160 std::string js_expression
= base::StringPrintf(
161 "var prefSelector = '[pref=\"%s\"]';"
162 "var controlledBy = '%s';"
163 "var input = document.querySelector("
164 " 'input' + prefSelector + ', select' + prefSelector);"
165 "var success = false;"
167 " success = input.disabled == %d;"
168 " var indicator = input.parentNode.parentNode.querySelector("
169 " '.controlled-setting-indicator');"
170 " if (controlledBy) {"
171 " success = success && indicator &&"
172 " indicator.getAttribute('controlled-by') == controlledBy;"
174 " success = success && (!indicator ||"
175 " !indicator.hasAttribute('controlled-by') ||"
176 " indicator.getAttribute('controlled-by') == '')"
179 "window.domAutomationController.send(!!success);",
180 pref_name
.c_str(), controlled_by
.c_str(), disabled
);
181 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
182 contents
, js_expression
, &success
));
183 EXPECT_TRUE(success
);
186 // Verifies a checkbox's disabled state, controlled-by indicator and value.
187 void CheckBooleanPreference(content::WebContents
* contents
,
188 std::string pref_name
,
190 std::string controlled_by
,
191 bool expected_value
) {
192 CheckPreference(contents
, pref_name
, disabled
, controlled_by
);
194 std::string js_expression
= base::StringPrintf(
195 "window.domAutomationController.send(document.querySelector('"
196 " input[type=\"checkbox\"][pref=\"%s\"]').checked);",
198 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
199 contents
, js_expression
, &actual_value
));
200 EXPECT_EQ(expected_value
, actual_value
);
203 // Verifies that the shared settings banner is visible only for
205 void CheckBanner(content::WebContents
* contents
,
208 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
210 "var e = $('secondary-user-banner');"
211 "window.domAutomationController.send(e && !e.hidden);",
213 EXPECT_EQ(!is_primary
, banner_visible
);
216 // Verifies that sections of shared settings have the appropriate indicator.
217 void CheckSharedSections(content::WebContents
* contents
,
219 // This only applies to the Internet options section.
220 std::string controlled_by
;
221 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
223 "var e = document.querySelector("
224 " '#network-section-header span.controlled-setting-indicator');"
225 "if (!e || !e.getAttribute('controlled-by')) {"
226 " window.domAutomationController.send('');"
228 " window.domAutomationController.send("
229 " e.getAttribute('controlled-by'));"
232 EXPECT_EQ(!is_primary
? "shared" : std::string(), controlled_by
);
235 // Checks the Accounts header and non-checkbox inputs.
236 void CheckAccountsOverlay(content::WebContents
* contents
, bool is_owner
) {
237 // Set cros.accounts.allowGuest to false so we can test the accounts list.
238 // This has to be done after the PRE_* test or we can't add the owner.
239 stub_settings_provider_
.Set(
240 kAccountsPrefAllowNewUser
, base::FundamentalValue(false));
243 std::string js_expression
= base::StringPrintf(
244 "var controlled = %d;"
245 "var warning = $('ownerOnlyWarning');"
246 "var userList = $('userList');"
247 "var input = $('userNameEdit');"
250 " success = warning && !warning.hidden && userList.disabled &&"
253 " success = (!warning || warning.hidden) && !userList.disabled &&"
255 "window.domAutomationController.send(!!success);",
257 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
258 contents
, js_expression
, &success
));
259 EXPECT_TRUE(success
) << "Accounts overlay incorrect for " <<
260 (is_owner
? "owner." : "non-owner.");
263 StubAccountSettingsProvider stub_settings_provider_
;
264 CrosSettingsProvider
* device_settings_provider_
;
267 DISALLOW_COPY_AND_ASSIGN(SharedOptionsTest
);
270 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_SharedOptions
) {
271 RegisterUser(kTestOwner
);
272 RegisterUser(kTestNonOwner
);
273 StartupUtils::MarkOobeCompleted();
276 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, SharedOptions
) {
277 // Log in the owner first, then add a secondary user.
278 LoginUser(kTestOwner
);
279 UserAddingScreen::Get()->Start();
280 content::RunAllPendingInMessageLoop();
281 AddUser(kTestNonOwner
);
283 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
284 ASSERT_EQ(2u, manager
->GetLoggedInUsers().size());
286 SCOPED_TRACE("Checking settings for owner, primary user.");
287 CheckOptionsUI(manager
->FindUser(manager
->GetOwnerEmail()), true, true);
290 SCOPED_TRACE("Checking settings for non-owner, secondary user.");
291 CheckOptionsUI(manager
->FindUser(kTestNonOwner
), false, false);
293 // TODO(michaelpg): Add tests for non-primary owner and primary non-owner
294 // when the owner-only multiprofile restriction is removed, probably M38.
297 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_ScreenLockPreferencePrimary
) {
298 RegisterUser(kTestOwner
);
299 RegisterUser(kTestNonOwner
);
300 StartupUtils::MarkOobeCompleted();
303 // Tests the shared setting indicator for the primary user's auto-lock setting
304 // when the secondary user has enabled or disabled their preference.
305 // (The checkbox is unset if the current user's preference is false, but if any
306 // other signed-in user has enabled this preference, the shared setting
307 // indicator explains this.)
308 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, ScreenLockPreferencePrimary
) {
309 LoginUser(kTestOwner
);
310 UserAddingScreen::Get()->Start();
311 content::RunAllPendingInMessageLoop();
312 AddUser(kTestNonOwner
);
314 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
315 const user_manager::User
* user1
= manager
->FindUser(kTestOwner
);
316 const user_manager::User
* user2
= manager
->FindUser(kTestNonOwner
);
318 PrefService
* prefs1
=
319 ProfileHelper::Get()->GetProfileByUserUnsafe(user1
)->GetPrefs();
320 PrefService
* prefs2
=
321 ProfileHelper::Get()->GetProfileByUserUnsafe(user2
)->GetPrefs();
323 // Set both users' preference to false, then change the secondary user's to
324 // true. We'll do the opposite in the next test. Doesn't provide 100% coverage
325 // but reloading the settings page is super slow on debug builds.
326 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
327 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
329 Browser
* browser
= CreateBrowserForUser(user1
);
330 content::WebContents
* contents
=
331 browser
->tab_strip_model()->GetActiveWebContents();
333 bool disabled
= false;
335 std::string empty_controlled
;
336 std::string
shared_controlled("shared");
339 SCOPED_TRACE("Screen lock false for both users");
340 expected_value
= false;
341 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
342 empty_controlled
, expected_value
);
345 // Set the secondary user's preference to true, and reload the primary user's
346 // browser to see the updated controlled-by indicator.
347 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
348 chrome::Reload(browser
, CURRENT_TAB
);
349 content::WaitForLoadStop(contents
);
351 SCOPED_TRACE("Screen lock false for primary user");
352 expected_value
= false;
353 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
354 shared_controlled
, expected_value
);
357 // Set the preference to true for the primary user and check that the
358 // indicator disappears.
359 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
361 SCOPED_TRACE("Screen lock true for both users");
362 expected_value
= true;
363 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
364 empty_controlled
, expected_value
);
368 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_ScreenLockPreferenceSecondary
) {
369 RegisterUser(kTestOwner
);
370 RegisterUser(kTestNonOwner
);
371 StartupUtils::MarkOobeCompleted();
374 // Tests the shared setting indicator for the secondary user's auto-lock setting
375 // when the primary user has enabled or disabled their preference.
376 // (The checkbox is unset if the current user's preference is false, but if any
377 // other signed-in user has enabled this preference, the shared setting
378 // indicator explains this.)
379 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, ScreenLockPreferenceSecondary
) {
380 LoginUser(kTestOwner
);
381 UserAddingScreen::Get()->Start();
382 content::RunAllPendingInMessageLoop();
383 AddUser(kTestNonOwner
);
385 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
386 const user_manager::User
* user1
= manager
->FindUser(kTestOwner
);
387 const user_manager::User
* user2
= manager
->FindUser(kTestNonOwner
);
389 PrefService
* prefs1
=
390 ProfileHelper::Get()->GetProfileByUserUnsafe(user1
)->GetPrefs();
391 PrefService
* prefs2
=
392 ProfileHelper::Get()->GetProfileByUserUnsafe(user2
)->GetPrefs();
394 // Set both users' preference to true, then change the secondary user's to
396 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
397 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
399 Browser
* browser
= CreateBrowserForUser(user2
);
400 content::WebContents
* contents
=
401 browser
->tab_strip_model()->GetActiveWebContents();
403 bool disabled
= false;
405 std::string empty_controlled
;
406 std::string
shared_controlled("shared");
409 SCOPED_TRACE("Screen lock true for both users");
410 expected_value
= true;
411 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
412 empty_controlled
, expected_value
);
415 // Set the secondary user's preference to false and check that the
416 // controlled-by indicator is shown.
417 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
419 SCOPED_TRACE("Screen lock false for secondary user");
420 expected_value
= false;
421 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
422 shared_controlled
, expected_value
);
425 // Set the preference to false for the primary user and check that the
426 // indicator disappears.
427 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
428 chrome::Reload(browser
, CURRENT_TAB
);
429 content::WaitForLoadStop(contents
);
431 SCOPED_TRACE("Screen lock false for both users");
432 expected_value
= false;
433 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
434 empty_controlled
, expected_value
);
438 } // namespace chromeos