shared_options_browsertest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "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/login/users/user_manager.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/ui/browser.h" 16#include "chrome/browser/ui/browser_commands.h" 17#include "chrome/browser/ui/tabs/tab_strip_model.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/test/base/ui_test_utils.h" 20#include "chromeos/settings/cros_settings_names.h" 21#include "content/public/browser/web_contents.h" 22#include "content/public/test/browser_test_utils.h" 23#include "content/public/test/test_utils.h" 24 25namespace chromeos { 26 27namespace { 28 29const char* kTestOwner = "test-owner@example.com"; 30const char* kTestNonOwner = "test-user1@example.com"; 31 32const char* kKnownSettings[] = { 33 kDeviceOwner, 34 kAccountsPrefAllowGuest, 35 kAccountsPrefAllowNewUser, 36 kAccountsPrefDeviceLocalAccounts, 37 kAccountsPrefShowUserNamesOnSignIn, 38 kAccountsPrefSupervisedUsersEnabled, 39}; 40 41// Stub settings provider that only handles the settings we need to control. 42// StubCrosSettingsProvider handles more settings but leaves many of them unset 43// which the Settings page doesn't expect. 44class StubAccountSettingsProvider : public StubCrosSettingsProvider { 45 public: 46 StubAccountSettingsProvider() { 47 } 48 49 virtual ~StubAccountSettingsProvider() { 50 } 51 52 // StubCrosSettingsProvider implementation. 53 virtual bool HandlesSetting(const std::string& path) const OVERRIDE { 54 const char** end = kKnownSettings + arraysize(kKnownSettings); 55 return std::find(kKnownSettings, end, path) != end; 56 } 57}; 58 59struct PrefTest { 60 const char* pref_name; 61 bool owner_only; 62 bool indicator; 63}; 64 65const PrefTest kPrefTests[] = { 66 { kSystemTimezone, false, false }, 67 { prefs::kUse24HourClock, false, false }, 68 { kAttestationForContentProtectionEnabled, true, true }, 69 { kAccountsPrefAllowGuest, true, false }, 70 { kAccountsPrefAllowNewUser, true, false }, 71 { kAccountsPrefShowUserNamesOnSignIn, true, false }, 72 { kAccountsPrefSupervisedUsersEnabled, true, false }, 73#if defined(GOOGLE_CHROME_BUILD) 74 { kStatsReportingPref, true, true }, 75 { prefs::kSpellCheckUseSpellingService, false, false }, 76#endif 77}; 78 79} // namespace 80 81class SharedOptionsTest : public LoginManagerTest { 82 public: 83 SharedOptionsTest() 84 : LoginManagerTest(false), 85 device_settings_provider_(NULL) { 86 stub_settings_provider_.Set(kDeviceOwner, base::StringValue(kTestOwner)); 87 } 88 89 virtual ~SharedOptionsTest() { 90 } 91 92 virtual void SetUpOnMainThread() OVERRIDE { 93 LoginManagerTest::SetUpOnMainThread(); 94 95 CrosSettings* settings = CrosSettings::Get(); 96 97 // Add the stub settings provider, moving the device settings provider 98 // behind it so our stub takes precedence. 99 device_settings_provider_ = settings->GetProvider(kDeviceOwner); 100 settings->RemoveSettingsProvider(device_settings_provider_); 101 settings->AddSettingsProvider(&stub_settings_provider_); 102 settings->AddSettingsProvider(device_settings_provider_); 103 } 104 105 virtual void CleanUpOnMainThread() OVERRIDE { 106 CrosSettings* settings = CrosSettings::Get(); 107 settings->RemoveSettingsProvider(&stub_settings_provider_); 108 LoginManagerTest::CleanUpOnMainThread(); 109 } 110 111 protected: 112 void CheckOptionsUI(const User* user, bool is_owner, bool is_primary) { 113 Browser* browser = CreateBrowserForUser(user); 114 content::WebContents* contents = 115 browser->tab_strip_model()->GetActiveWebContents(); 116 117 for (size_t i = 0; i < sizeof(kPrefTests) / sizeof(kPrefTests[0]); i++) { 118 CheckPreference(contents, 119 kPrefTests[i].pref_name, 120 !is_owner && kPrefTests[i].owner_only, 121 !is_owner && kPrefTests[i].indicator ? "owner" : 122 std::string()); 123 } 124 CheckBanner(contents, is_primary); 125 CheckSharedSections(contents, is_primary); 126 CheckAccountsOverlay(contents, is_owner); 127 } 128 129 // Creates a browser and navigates to the Settings page. 130 Browser* CreateBrowserForUser(const User* user) { 131 Profile* profile = UserManager::Get()->GetProfileByUser(user); 132 profile->GetPrefs()->SetString(prefs::kGoogleServicesUsername, 133 user->email()); 134 135 ui_test_utils::BrowserAddedObserver observer; 136 Browser* browser = CreateBrowser(profile); 137 observer.WaitForSingleNewBrowser(); 138 139 ui_test_utils::NavigateToURL(browser, 140 GURL("chrome://settings-frame")); 141 return browser; 142 } 143 144 // Verifies a preference's disabled state and controlled-by indicator. 145 void CheckPreference(content::WebContents* contents, 146 std::string pref_name, 147 bool disabled, 148 std::string controlled_by) { 149 bool success; 150 std::string js_expression = base::StringPrintf( 151 "var prefSelector = '[pref=\"%s\"]';" 152 "var controlledBy = '%s';" 153 "var input = document.querySelector(" 154 " 'input' + prefSelector + ', select' + prefSelector);" 155 "var success = false;" 156 "if (input) {" 157 " success = input.disabled == %d;" 158 " var indicator = document.querySelector(input.tagName +" 159 " prefSelector + ' + span span.controlled-setting-indicator');" 160 " if (controlledBy) {" 161 " success = success && indicator &&" 162 " indicator.getAttribute('controlled-by') == controlledBy;" 163 " } else {" 164 " success = success && (!indicator ||" 165 " !indicator.hasAttribute('controlled-by') ||" 166 " indicator.getAttribute('controlled-by') == '')" 167 " }" 168 "}" 169 "window.domAutomationController.send(!!success);", 170 pref_name.c_str(), controlled_by.c_str(), disabled); 171 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 172 contents, js_expression, &success)); 173 EXPECT_TRUE(success); 174 } 175 176 // Verifies a checkbox's disabled state, controlled-by indicator and value. 177 void CheckBooleanPreference(content::WebContents* contents, 178 std::string pref_name, 179 bool disabled, 180 std::string controlled_by, 181 bool expected_value) { 182 CheckPreference(contents, pref_name, disabled, controlled_by); 183 bool actual_value; 184 std::string js_expression = base::StringPrintf( 185 "window.domAutomationController.send(document.querySelector('" 186 " input[type=\"checkbox\"][pref=\"%s\"]').checked);", 187 pref_name.c_str()); 188 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 189 contents, js_expression, &actual_value)); 190 EXPECT_EQ(expected_value, actual_value); 191 } 192 193 // Verifies that the shared settings banner is visible only for 194 // secondary users. 195 void CheckBanner(content::WebContents* contents, 196 bool is_primary) { 197 bool banner_visible; 198 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 199 contents, 200 "var e = $('secondary-user-banner');" 201 "window.domAutomationController.send(e && !e.hidden);", 202 &banner_visible)); 203 EXPECT_EQ(!is_primary, banner_visible); 204 } 205 206 // Verifies that sections of shared settings have the appropriate indicator. 207 void CheckSharedSections(content::WebContents* contents, 208 bool is_primary) { 209 // This only applies to the Internet options section. 210 std::string controlled_by; 211 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 212 contents, 213 "var e = document.querySelector(" 214 " '#network-section-header span.controlled-setting-indicator');" 215 "if (!e || !e.getAttribute('controlled-by')) {" 216 " window.domAutomationController.send('');" 217 "} else {" 218 " window.domAutomationController.send(" 219 " e.getAttribute('controlled-by'));" 220 "}", 221 &controlled_by)); 222 EXPECT_EQ(!is_primary ? "shared" : std::string(), controlled_by); 223 } 224 225 // Checks the Accounts header and non-checkbox inputs. 226 void CheckAccountsOverlay(content::WebContents* contents, bool is_owner) { 227 // Set cros.accounts.allowGuest to false so we can test the accounts list. 228 // This has to be done after the PRE_* test or we can't add the owner. 229 stub_settings_provider_.Set( 230 kAccountsPrefAllowNewUser, base::FundamentalValue(false)); 231 232 bool success; 233 std::string js_expression = base::StringPrintf( 234 "var controlled = %d;" 235 "var warning = $('ownerOnlyWarning');" 236 "var userList = $('userList');" 237 "var input = $('userNameEdit');" 238 "var success;" 239 "if (controlled)" 240 " success = warning && !warning.hidden && userList.disabled &&" 241 " input.disabled;" 242 "else" 243 " success = (!warning || warning.hidden) && !userList.disabled &&" 244 " !input.disabled;" 245 "window.domAutomationController.send(!!success);", 246 !is_owner); 247 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 248 contents, js_expression, &success)); 249 EXPECT_TRUE(success) << "Accounts overlay incorrect for " << 250 (is_owner ? "owner." : "non-owner."); 251 } 252 253 StubAccountSettingsProvider stub_settings_provider_; 254 CrosSettingsProvider* device_settings_provider_; 255 256 private: 257 DISALLOW_COPY_AND_ASSIGN(SharedOptionsTest); 258}; 259 260IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_SharedOptions) { 261 RegisterUser(kTestOwner); 262 RegisterUser(kTestNonOwner); 263 StartupUtils::MarkOobeCompleted(); 264} 265 266IN_PROC_BROWSER_TEST_F(SharedOptionsTest, SharedOptions) { 267 // Log in the owner first, then add a secondary user. 268 LoginUser(kTestOwner); 269 UserAddingScreen::Get()->Start(); 270 content::RunAllPendingInMessageLoop(); 271 AddUser(kTestNonOwner); 272 273 UserManager* manager = UserManager::Get(); 274 ASSERT_EQ(2u, manager->GetLoggedInUsers().size()); 275 { 276 SCOPED_TRACE("Checking settings for owner, primary user."); 277 CheckOptionsUI(manager->FindUser(manager->GetOwnerEmail()), true, true); 278 } 279 { 280 SCOPED_TRACE("Checking settings for non-owner, secondary user."); 281 CheckOptionsUI(manager->FindUser(kTestNonOwner), false, false); 282 } 283 // TODO(michaelpg): Add tests for non-primary owner and primary non-owner 284 // when the owner-only multiprofile restriction is removed, probably M38. 285} 286 287IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_ScreenLockPreference) { 288 RegisterUser(kTestOwner); 289 RegisterUser(kTestNonOwner); 290 StartupUtils::MarkOobeCompleted(); 291} 292 293// Tests that a shared setting indicator appears for the auto-lock setting 294// when the user has the checkbox unselected but another user has enabled 295// auto-lock. (The checkbox is unset if the user's preference is false, 296// but if any other signed-in user has enabled this preference, the shared 297// setting indicator explains this.) 298IN_PROC_BROWSER_TEST_F(SharedOptionsTest, ScreenLockPreference) { 299 LoginUser(kTestOwner); 300 UserAddingScreen::Get()->Start(); 301 content::RunAllPendingInMessageLoop(); 302 AddUser(kTestNonOwner); 303 304 UserManager* manager = UserManager::Get(); 305 const User* user1 = manager->FindUser(kTestOwner); 306 const User* user2 = manager->FindUser(kTestNonOwner); 307 308 PrefService* prefs1 = manager->GetProfileByUser(user1)->GetPrefs(); 309 PrefService* prefs2 = manager->GetProfileByUser(user2)->GetPrefs(); 310 prefs1->SetBoolean(prefs::kEnableAutoScreenLock, false); 311 prefs2->SetBoolean(prefs::kEnableAutoScreenLock, false); 312 313 Browser* browser1 = CreateBrowserForUser(user1); 314 Browser* browser2 = CreateBrowserForUser(user2); 315 content::WebContents* contents1 = 316 browser1->tab_strip_model()->GetActiveWebContents(); 317 content::WebContents* contents2 = 318 browser2->tab_strip_model()->GetActiveWebContents(); 319 320 bool disabled = false; 321 bool expected_value; 322 std::string empty_controlled; 323 std::string shared_controlled("shared"); 324 325 // First test case: secondary user dependent on primary user. 326 { 327 SCOPED_TRACE("Screen lock false for both users"); 328 expected_value = false; 329 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 330 empty_controlled, expected_value); 331 CheckBooleanPreference(contents2, prefs::kEnableAutoScreenLock, disabled, 332 empty_controlled, expected_value); 333 } 334 // Set the preference to true for the primary user and check that the value 335 // changes appropriately. 336 prefs1->SetBoolean(prefs::kEnableAutoScreenLock, true); 337 { 338 SCOPED_TRACE("Screen lock true for primary user"); 339 expected_value = true; 340 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 341 empty_controlled, expected_value); 342 } 343 // Reload the secondary user's browser to see the updated controlled-by 344 // indicator. Also reload the primary user's to make sure the setting still 345 // starts out correctly. 346 chrome::Reload(browser1, CURRENT_TAB); 347 chrome::Reload(browser2, CURRENT_TAB); 348 content::WaitForLoadStop(contents1); 349 content::WaitForLoadStop(contents2); 350 { 351 SCOPED_TRACE("Screen lock true for primary user, false for secondary user"); 352 expected_value = true; 353 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 354 empty_controlled, expected_value); 355 expected_value = false; 356 CheckBooleanPreference(contents2, prefs::kEnableAutoScreenLock, disabled, 357 shared_controlled, expected_value); 358 } 359 // Set the preference to true for the secondary user and check that the 360 // indicator disappears. 361 prefs2->SetBoolean(prefs::kEnableAutoScreenLock, true); 362 { 363 SCOPED_TRACE("Screen lock true for secondary user"); 364 expected_value = true; 365 CheckBooleanPreference(contents2, prefs::kEnableAutoScreenLock, disabled, 366 empty_controlled, expected_value); 367 } 368 369 // Second test case: primary user dependent on secondary user. 370 chrome::Reload(browser1, CURRENT_TAB); 371 chrome::Reload(browser2, CURRENT_TAB); 372 content::WaitForLoadStop(contents1); 373 content::WaitForLoadStop(contents2); 374 { 375 SCOPED_TRACE("Screen lock true for both users"); 376 expected_value = true; 377 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 378 empty_controlled, expected_value); 379 CheckBooleanPreference(contents2, prefs::kEnableAutoScreenLock, disabled, 380 empty_controlled, expected_value); 381 } 382 // Set the preference to false for the primary user and check that the 383 // value changes correctly. 384 prefs1->SetBoolean(prefs::kEnableAutoScreenLock, false); 385 { 386 SCOPED_TRACE("Screen lock false for primary user"); 387 expected_value = false; 388 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 389 shared_controlled, expected_value); 390 } 391 // The primary user should now see a shared setting indicator. 392 chrome::Reload(browser1, CURRENT_TAB); 393 chrome::Reload(browser2, CURRENT_TAB); 394 content::WaitForLoadStop(contents1); 395 content::WaitForLoadStop(contents2); 396 { 397 SCOPED_TRACE("Screen lock false for primary user, true for secondary user"); 398 expected_value = false; 399 CheckBooleanPreference(contents1, prefs::kEnableAutoScreenLock, disabled, 400 shared_controlled, expected_value); 401 expected_value = true; 402 CheckBooleanPreference(contents2, prefs::kEnableAutoScreenLock, disabled, 403 empty_controlled, expected_value); 404 } 405} 406 407} // namespace chromeos 408