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 // Because policy is not needed in this test it is better to use e-mails that
33 // are definitely not enterprise. This lets us to avoid faking of policy fetch
35 const char* kTestOwner
= "test-owner@gmail.com";
36 const char* kTestNonOwner
= "test-user1@gmail.com";
38 const char* kKnownSettings
[] = {
40 kAccountsPrefAllowGuest
,
41 kAccountsPrefAllowNewUser
,
42 kAccountsPrefDeviceLocalAccounts
,
43 kAccountsPrefShowUserNamesOnSignIn
,
44 kAccountsPrefSupervisedUsersEnabled
,
47 // Stub settings provider that only handles the settings we need to control.
48 // StubCrosSettingsProvider handles more settings but leaves many of them unset
49 // which the Settings page doesn't expect.
50 class StubAccountSettingsProvider
: public StubCrosSettingsProvider
{
52 StubAccountSettingsProvider() {
55 ~StubAccountSettingsProvider() override
{}
57 // StubCrosSettingsProvider implementation.
58 bool HandlesSetting(const std::string
& path
) const override
{
59 const char** end
= kKnownSettings
+ arraysize(kKnownSettings
);
60 return std::find(kKnownSettings
, end
, path
) != end
;
65 const char* pref_name
;
70 const PrefTest kPrefTests
[] = {
71 { kSystemTimezone
, false, false },
72 { prefs::kUse24HourClock
, false, false },
73 { kAttestationForContentProtectionEnabled
, true, true },
74 { kAccountsPrefAllowGuest
, true, false },
75 { kAccountsPrefAllowNewUser
, true, false },
76 { kAccountsPrefShowUserNamesOnSignIn
, true, false },
77 { kAccountsPrefSupervisedUsersEnabled
, true, false },
78 #if defined(GOOGLE_CHROME_BUILD)
79 { kStatsReportingPref
, true, true },
80 { prefs::kSpellCheckUseSpellingService
, false, false },
86 class SharedOptionsTest
: public LoginManagerTest
{
89 : LoginManagerTest(false),
90 device_settings_provider_(NULL
) {
91 stub_settings_provider_
.Set(kDeviceOwner
, base::StringValue(kTestOwner
));
94 ~SharedOptionsTest() override
{}
96 void SetUpOnMainThread() override
{
97 LoginManagerTest::SetUpOnMainThread();
99 CrosSettings
* settings
= CrosSettings::Get();
101 // Add the stub settings provider, moving the device settings provider
102 // behind it so our stub takes precedence.
103 device_settings_provider_
= settings
->GetProvider(kDeviceOwner
);
104 settings
->RemoveSettingsProvider(device_settings_provider_
);
105 settings
->AddSettingsProvider(&stub_settings_provider_
);
106 settings
->AddSettingsProvider(device_settings_provider_
);
109 void TearDownOnMainThread() override
{
110 CrosSettings
* settings
= CrosSettings::Get();
111 settings
->RemoveSettingsProvider(&stub_settings_provider_
);
112 LoginManagerTest::TearDownOnMainThread();
116 void CheckOptionsUI(const user_manager::User
* user
,
119 Browser
* browser
= CreateBrowserForUser(user
);
120 content::WebContents
* contents
=
121 browser
->tab_strip_model()->GetActiveWebContents();
123 for (size_t i
= 0; i
< sizeof(kPrefTests
) / sizeof(kPrefTests
[0]); i
++) {
124 bool disabled
= !is_owner
&& kPrefTests
[i
].owner_only
;
125 if (strcmp(kPrefTests
[i
].pref_name
, kSystemTimezone
) == 0) {
126 disabled
= ProfileHelper::Get()
127 ->GetProfileByUserUnsafe(user
)
129 ->GetBoolean(prefs::kResolveTimezoneByGeolocation
);
133 contents
, kPrefTests
[i
].pref_name
, disabled
,
134 !is_owner
&& kPrefTests
[i
].indicator
? "owner" : std::string());
136 CheckBanner(contents
, is_primary
);
137 CheckSharedSections(contents
, is_primary
);
138 CheckAccountsOverlay(contents
, is_owner
);
141 // Creates a browser and navigates to the Settings page.
142 Browser
* CreateBrowserForUser(const user_manager::User
* user
) {
143 Profile
* profile
= ProfileHelper::Get()->GetProfileByUserUnsafe(user
);
144 SigninManagerFactory::GetForProfile(profile
)->
145 SetAuthenticatedAccountInfo(GetGaiaIDForUserID(user
->email()),
148 ui_test_utils::BrowserAddedObserver observer
;
149 Browser
* browser
= CreateBrowser(profile
);
150 observer
.WaitForSingleNewBrowser();
152 ui_test_utils::NavigateToURL(browser
,
153 GURL("chrome://settings-frame"));
157 // Verifies a preference's disabled state and controlled-by indicator.
158 void CheckPreference(content::WebContents
* contents
,
159 std::string pref_name
,
161 std::string controlled_by
) {
163 std::string js_expression
= base::StringPrintf(
164 "var prefSelector = '[pref=\"%s\"]';"
165 "var controlledBy = '%s';"
166 "var input = document.querySelector("
167 " 'input' + prefSelector + ', select' + prefSelector);"
168 "var success = false;"
170 " success = input.disabled == %d;"
171 " var indicator = input.parentNode.parentNode.querySelector("
172 " '.controlled-setting-indicator');"
173 " if (controlledBy) {"
174 " success = success && indicator &&"
175 " indicator.getAttribute('controlled-by') == controlledBy;"
177 " success = success && (!indicator ||"
178 " !indicator.hasAttribute('controlled-by') ||"
179 " indicator.getAttribute('controlled-by') == '')"
182 "window.domAutomationController.send(!!success);",
183 pref_name
.c_str(), controlled_by
.c_str(), disabled
);
184 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
185 contents
, js_expression
, &success
));
186 EXPECT_TRUE(success
);
189 // Verifies a checkbox's disabled state, controlled-by indicator and value.
190 void CheckBooleanPreference(content::WebContents
* contents
,
191 std::string pref_name
,
193 std::string controlled_by
,
194 bool expected_value
) {
195 CheckPreference(contents
, pref_name
, disabled
, controlled_by
);
197 std::string js_expression
= base::StringPrintf(
198 "window.domAutomationController.send(document.querySelector('"
199 " input[type=\"checkbox\"][pref=\"%s\"]').checked);",
201 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
202 contents
, js_expression
, &actual_value
));
203 EXPECT_EQ(expected_value
, actual_value
);
206 // Verifies that the shared settings banner is visible only for
208 void CheckBanner(content::WebContents
* contents
,
211 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
213 "var e = $('secondary-user-banner');"
214 "window.domAutomationController.send(e && !e.hidden);",
216 EXPECT_EQ(!is_primary
, banner_visible
);
219 // Verifies that sections of shared settings have the appropriate indicator.
220 void CheckSharedSections(content::WebContents
* contents
,
222 // This only applies to the Internet options section.
223 std::string controlled_by
;
224 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
226 "var e = document.querySelector("
227 " '#network-section-header span.controlled-setting-indicator');"
228 "if (!e || !e.getAttribute('controlled-by')) {"
229 " window.domAutomationController.send('');"
231 " window.domAutomationController.send("
232 " e.getAttribute('controlled-by'));"
235 EXPECT_EQ(!is_primary
? "shared" : std::string(), controlled_by
);
238 // Checks the Accounts header and non-checkbox inputs.
239 void CheckAccountsOverlay(content::WebContents
* contents
, bool is_owner
) {
240 // Set cros.accounts.allowGuest to false so we can test the accounts list.
241 // This has to be done after the PRE_* test or we can't add the owner.
242 stub_settings_provider_
.Set(
243 kAccountsPrefAllowNewUser
, base::FundamentalValue(false));
246 std::string js_expression
= base::StringPrintf(
247 "var controlled = %d;"
248 "var warning = $('ownerOnlyWarning');"
249 "var userList = $('userList');"
250 "var input = $('userNameEdit');"
253 " success = warning && !warning.hidden && userList.disabled &&"
256 " success = (!warning || warning.hidden) && !userList.disabled &&"
258 "window.domAutomationController.send(!!success);",
260 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
261 contents
, js_expression
, &success
));
262 EXPECT_TRUE(success
) << "Accounts overlay incorrect for " <<
263 (is_owner
? "owner." : "non-owner.");
266 StubAccountSettingsProvider stub_settings_provider_
;
267 CrosSettingsProvider
* device_settings_provider_
;
270 DISALLOW_COPY_AND_ASSIGN(SharedOptionsTest
);
273 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_SharedOptions
) {
274 RegisterUser(kTestOwner
);
275 RegisterUser(kTestNonOwner
);
276 StartupUtils::MarkOobeCompleted();
279 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, SharedOptions
) {
280 // Log in the owner first, then add a secondary user.
281 LoginUser(kTestOwner
);
282 UserAddingScreen::Get()->Start();
283 content::RunAllPendingInMessageLoop();
284 AddUser(kTestNonOwner
);
286 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
287 ASSERT_EQ(2u, manager
->GetLoggedInUsers().size());
289 SCOPED_TRACE("Checking settings for owner, primary user.");
290 CheckOptionsUI(manager
->FindUser(manager
->GetOwnerEmail()), true, true);
293 SCOPED_TRACE("Checking settings for non-owner, secondary user.");
294 CheckOptionsUI(manager
->FindUser(kTestNonOwner
), false, false);
296 // TODO(michaelpg): Add tests for non-primary owner and primary non-owner
297 // when the owner-only multiprofile restriction is removed, probably M38.
300 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_ScreenLockPreferencePrimary
) {
301 RegisterUser(kTestOwner
);
302 RegisterUser(kTestNonOwner
);
303 StartupUtils::MarkOobeCompleted();
306 // Tests the shared setting indicator for the primary user's auto-lock setting
307 // when the secondary user has enabled or disabled their preference.
308 // (The checkbox is unset if the current user's preference is false, but if any
309 // other signed-in user has enabled this preference, the shared setting
310 // indicator explains this.)
311 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, ScreenLockPreferencePrimary
) {
312 LoginUser(kTestOwner
);
313 UserAddingScreen::Get()->Start();
314 content::RunAllPendingInMessageLoop();
315 AddUser(kTestNonOwner
);
317 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
318 const user_manager::User
* user1
= manager
->FindUser(kTestOwner
);
319 const user_manager::User
* user2
= manager
->FindUser(kTestNonOwner
);
321 PrefService
* prefs1
=
322 ProfileHelper::Get()->GetProfileByUserUnsafe(user1
)->GetPrefs();
323 PrefService
* prefs2
=
324 ProfileHelper::Get()->GetProfileByUserUnsafe(user2
)->GetPrefs();
326 // Set both users' preference to false, then change the secondary user's to
327 // true. We'll do the opposite in the next test. Doesn't provide 100% coverage
328 // but reloading the settings page is super slow on debug builds.
329 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
330 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
332 Browser
* browser
= CreateBrowserForUser(user1
);
333 content::WebContents
* contents
=
334 browser
->tab_strip_model()->GetActiveWebContents();
336 bool disabled
= false;
338 std::string empty_controlled
;
339 std::string
shared_controlled("shared");
342 SCOPED_TRACE("Screen lock false for both users");
343 expected_value
= false;
344 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
345 empty_controlled
, expected_value
);
348 // Set the secondary user's preference to true, and reload the primary user's
349 // browser to see the updated controlled-by indicator.
350 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
351 chrome::Reload(browser
, CURRENT_TAB
);
352 content::WaitForLoadStop(contents
);
354 SCOPED_TRACE("Screen lock false for primary user");
355 expected_value
= false;
356 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
357 shared_controlled
, expected_value
);
360 // Set the preference to true for the primary user and check that the
361 // indicator disappears.
362 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
364 SCOPED_TRACE("Screen lock true for both users");
365 expected_value
= true;
366 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
367 empty_controlled
, expected_value
);
371 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, PRE_ScreenLockPreferenceSecondary
) {
372 RegisterUser(kTestOwner
);
373 RegisterUser(kTestNonOwner
);
374 StartupUtils::MarkOobeCompleted();
377 // Tests the shared setting indicator for the secondary user's auto-lock setting
378 // when the primary user has enabled or disabled their preference.
379 // (The checkbox is unset if the current user's preference is false, but if any
380 // other signed-in user has enabled this preference, the shared setting
381 // indicator explains this.)
382 IN_PROC_BROWSER_TEST_F(SharedOptionsTest
, ScreenLockPreferenceSecondary
) {
383 LoginUser(kTestOwner
);
384 UserAddingScreen::Get()->Start();
385 content::RunAllPendingInMessageLoop();
386 AddUser(kTestNonOwner
);
388 user_manager::UserManager
* manager
= user_manager::UserManager::Get();
389 const user_manager::User
* user1
= manager
->FindUser(kTestOwner
);
390 const user_manager::User
* user2
= manager
->FindUser(kTestNonOwner
);
392 PrefService
* prefs1
=
393 ProfileHelper::Get()->GetProfileByUserUnsafe(user1
)->GetPrefs();
394 PrefService
* prefs2
=
395 ProfileHelper::Get()->GetProfileByUserUnsafe(user2
)->GetPrefs();
397 // Set both users' preference to true, then change the secondary user's to
399 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
400 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, true);
402 Browser
* browser
= CreateBrowserForUser(user2
);
403 content::WebContents
* contents
=
404 browser
->tab_strip_model()->GetActiveWebContents();
406 bool disabled
= false;
408 std::string empty_controlled
;
409 std::string
shared_controlled("shared");
412 SCOPED_TRACE("Screen lock true for both users");
413 expected_value
= true;
414 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
415 empty_controlled
, expected_value
);
418 // Set the secondary user's preference to false and check that the
419 // controlled-by indicator is shown.
420 prefs2
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
422 SCOPED_TRACE("Screen lock false for secondary user");
423 expected_value
= false;
424 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
425 shared_controlled
, expected_value
);
428 // Set the preference to false for the primary user and check that the
429 // indicator disappears.
430 prefs1
->SetBoolean(prefs::kEnableAutoScreenLock
, false);
431 chrome::Reload(browser
, CURRENT_TAB
);
432 content::WaitForLoadStop(contents
);
434 SCOPED_TRACE("Screen lock false for both users");
435 expected_value
= false;
436 CheckBooleanPreference(contents
, prefs::kEnableAutoScreenLock
, disabled
,
437 empty_controlled
, expected_value
);
441 } // namespace chromeos