device_local_account_browsertest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2013 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 <map> 6#include <string> 7 8#include "base/basictypes.h" 9#include "base/bind.h" 10#include "base/command_line.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/message_loop.h" 13#include "base/run_loop.h" 14#include "base/strings/string_util.h" 15#include "base/strings/utf_string_conversions.h" 16#include "chrome/browser/browser_process.h" 17#include "chrome/browser/chrome_notification_types.h" 18#include "chrome/browser/chromeos/login/existing_user_controller.h" 19#include "chrome/browser/chromeos/login/login_display_host.h" 20#include "chrome/browser/chromeos/login/login_display_host_impl.h" 21#include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 22#include "chrome/browser/chromeos/login/screens/wizard_screen.h" 23#include "chrome/browser/chromeos/login/user.h" 24#include "chrome/browser/chromeos/login/user_manager.h" 25#include "chrome/browser/chromeos/login/wizard_controller.h" 26#include "chrome/browser/chromeos/policy/device_local_account.h" 27#include "chrome/browser/chromeos/policy/device_policy_builder.h" 28#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" 29#include "chrome/browser/lifetime/application_lifetime.h" 30#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 31#include "chrome/browser/policy/cloud/policy_builder.h" 32#include "chrome/browser/policy/policy_service.h" 33#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" 34#include "chrome/browser/policy/test/local_policy_test_server.h" 35#include "chrome/browser/prefs/session_startup_pref.h" 36#include "chrome/browser/ui/browser.h" 37#include "chrome/browser/ui/browser_finder.h" 38#include "chrome/browser/ui/host_desktop.h" 39#include "chrome/browser/ui/tabs/tab_strip_model.h" 40#include "chrome/common/chrome_switches.h" 41#include "chromeos/chromeos_switches.h" 42#include "chromeos/dbus/cryptohome_client.h" 43#include "chromeos/dbus/dbus_method_call_status.h" 44#include "chromeos/dbus/fake_cryptohome_client.h" 45#include "chromeos/dbus/fake_session_manager_client.h" 46#include "chromeos/dbus/session_manager_client.h" 47#include "content/public/browser/web_contents.h" 48#include "content/public/test/test_utils.h" 49#include "crypto/rsa_private_key.h" 50#include "testing/gmock/include/gmock/gmock.h" 51#include "third_party/cros_system_api/dbus/service_constants.h" 52 53namespace em = enterprise_management; 54 55using testing::InvokeWithoutArgs; 56using testing::Return; 57using testing::_; 58 59namespace policy { 60 61namespace { 62 63const char kAccountId1[] = "dla1@example.com"; 64const char kAccountId2[] = "dla2@example.com"; 65const char kDisplayName[] = "display name"; 66const char* kStartupURLs[] = { 67 "chrome://policy", 68 "chrome://about", 69}; 70 71} // namespace 72 73class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest { 74 protected: 75 DeviceLocalAccountTest() 76 : user_id_1_(GenerateDeviceLocalAccountUserId( 77 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), 78 user_id_2_(GenerateDeviceLocalAccountUserId( 79 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {} 80 81 virtual ~DeviceLocalAccountTest() {} 82 83 virtual void SetUp() OVERRIDE { 84 // Configure and start the test server. 85 scoped_ptr<crypto::RSAPrivateKey> signing_key( 86 PolicyBuilder::CreateTestSigningKey()); 87 ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get())); 88 signing_key.reset(); 89 test_server_.RegisterClient(PolicyBuilder::kFakeToken, 90 PolicyBuilder::kFakeDeviceId); 91 ASSERT_TRUE(test_server_.Start()); 92 93 DevicePolicyCrosBrowserTest::SetUp(); 94 } 95 96 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 97 command_line->AppendSwitch(chromeos::switches::kLoginManager); 98 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 99 command_line->AppendSwitchASCII( 100 switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec()); 101 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 102 } 103 104 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 105 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); 106 107 // Clear command-line arguments (but keep command-line switches) so the 108 // startup pages policy takes effect. 109 CommandLine* command_line = CommandLine::ForCurrentProcess(); 110 CommandLine::StringVector argv(command_line->argv()); 111 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(), 112 argv.end()); 113 command_line->InitFromArgv(argv); 114 115 InstallOwnerKey(); 116 MarkAsEnterpriseOwned(); 117 118 InitializePolicy(); 119 } 120 121 virtual void CleanUpOnMainThread() OVERRIDE { 122 // This shuts down the login UI. 123 base::MessageLoop::current()->PostTask(FROM_HERE, 124 base::Bind(&chrome::AttemptExit)); 125 base::RunLoop().RunUntilIdle(); 126 } 127 128 void RemoveOwnerPrivateKeyFromPolicyBuilders() { 129 // Any instances of the private half of the owner key held by policy 130 // builders must be dropped as otherwise the NSS library will tell Chrome 131 // that the key is available - which is incorrect and leads to Chrome 132 // behaving as if a local owner were logged in. 133 device_policy()->set_signing_key(scoped_ptr<crypto::RSAPrivateKey>()); 134 device_policy()->set_new_signing_key(scoped_ptr<crypto::RSAPrivateKey>()); 135 device_local_account_policy_.set_signing_key( 136 scoped_ptr<crypto::RSAPrivateKey>()); 137 device_local_account_policy_.set_new_signing_key( 138 scoped_ptr<crypto::RSAPrivateKey>()); 139 } 140 141 void InitializePolicy() { 142 device_policy()->policy_data().set_public_key_version(1); 143 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 144 proto.mutable_show_user_names()->set_show_user_names(true); 145 146 device_local_account_policy_.policy_data().set_policy_type( 147 dm_protocol::kChromePublicAccountPolicyType); 148 device_local_account_policy_.policy_data().set_username(kAccountId1); 149 device_local_account_policy_.policy_data().set_settings_entity_id( 150 kAccountId1); 151 device_local_account_policy_.policy_data().set_public_key_version(1); 152 device_local_account_policy_.payload().mutable_userdisplayname()->set_value( 153 kDisplayName); 154 155 RemoveOwnerPrivateKeyFromPolicyBuilders(); 156 } 157 158 void BuildDeviceLocalAccountPolicy() { 159 device_local_account_policy_.set_signing_key( 160 PolicyBuilder::CreateTestSigningKey()); 161 device_local_account_policy_.Build(); 162 RemoveOwnerPrivateKeyFromPolicyBuilders(); 163 } 164 165 void InstallDeviceLocalAccountPolicy() { 166 BuildDeviceLocalAccountPolicy(); 167 session_manager_client()->set_device_local_account_policy( 168 kAccountId1, device_local_account_policy_.GetBlob()); 169 } 170 171 void UploadDeviceLocalAccountPolicy() { 172 BuildDeviceLocalAccountPolicy(); 173 ASSERT_TRUE(session_manager_client()->device_local_account_policy( 174 kAccountId1).empty()); 175 test_server_.UpdatePolicy( 176 dm_protocol::kChromePublicAccountPolicyType, kAccountId1, 177 device_local_account_policy_.payload().SerializeAsString()); 178 } 179 180 void AddPublicSessionToDevicePolicy(const std::string& username) { 181 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 182 em::DeviceLocalAccountInfoProto* account = 183 proto.mutable_device_local_accounts()->add_account(); 184 account->set_account_id(username); 185 account->set_type( 186 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 187 RefreshDevicePolicy(); 188 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, 189 std::string(), proto.SerializeAsString()); 190 } 191 192 void CheckPublicSessionPresent(const std::string& id) { 193 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id); 194 ASSERT_TRUE(user); 195 EXPECT_EQ(id, user->email()); 196 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); 197 } 198 199 const std::string user_id_1_; 200 const std::string user_id_2_; 201 202 UserPolicyBuilder device_local_account_policy_; 203 LocalPolicyTestServer test_server_; 204}; 205 206static bool IsKnownUser(const std::string& account_id) { 207 return chromeos::UserManager::Get()->IsKnownUser(account_id); 208} 209 210IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { 211 AddPublicSessionToDevicePolicy(kAccountId1); 212 AddPublicSessionToDevicePolicy(kAccountId2); 213 214 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 215 base::Bind(&IsKnownUser, user_id_1_)) 216 .Wait(); 217 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 218 base::Bind(&IsKnownUser, user_id_2_)) 219 .Wait(); 220 221 CheckPublicSessionPresent(user_id_1_); 222 CheckPublicSessionPresent(user_id_2_); 223} 224 225static bool DisplayNameMatches(const std::string& account_id, 226 const std::string& display_name) { 227 const chromeos::User* user = 228 chromeos::UserManager::Get()->FindUser(account_id); 229 if (!user || user->display_name().empty()) 230 return false; 231 EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name()); 232 return true; 233} 234 235IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { 236 InstallDeviceLocalAccountPolicy(); 237 AddPublicSessionToDevicePolicy(kAccountId1); 238 239 content::WindowedNotificationObserver( 240 chrome::NOTIFICATION_USER_LIST_CHANGED, 241 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 242} 243 244IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { 245 UploadDeviceLocalAccountPolicy(); 246 AddPublicSessionToDevicePolicy(kAccountId1); 247 248 // Policy for the account is not installed in session_manager_client. Because 249 // of this, the presence of the display name (which comes from policy) can be 250 // used as a signal that indicates successful policy download. 251 content::WindowedNotificationObserver( 252 chrome::NOTIFICATION_USER_LIST_CHANGED, 253 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 254 255 // Sanity check: The policy should be present now. 256 ASSERT_FALSE(session_manager_client()->device_local_account_policy( 257 kAccountId1).empty()); 258} 259 260static bool IsNotKnownUser(const std::string& account_id) { 261 return !IsKnownUser(account_id); 262} 263 264IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { 265 AddPublicSessionToDevicePolicy(kAccountId1); 266 AddPublicSessionToDevicePolicy(kAccountId2); 267 268 // Wait until the login screen is up. 269 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 270 base::Bind(&IsKnownUser, user_id_1_)) 271 .Wait(); 272 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 273 base::Bind(&IsKnownUser, user_id_2_)) 274 .Wait(); 275 276 // Update policy to remove kAccountId2. 277 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 278 proto.mutable_device_local_accounts()->clear_account(); 279 AddPublicSessionToDevicePolicy(kAccountId1); 280 281 em::ChromeDeviceSettingsProto policy; 282 policy.mutable_show_user_names()->set_show_user_names(true); 283 em::DeviceLocalAccountInfoProto* account1 = 284 policy.mutable_device_local_accounts()->add_account(); 285 account1->set_account_id(kAccountId1); 286 account1->set_type( 287 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 288 289 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(), 290 policy.SerializeAsString()); 291 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 292 293 // Make sure the second device-local account disappears. 294 content::WindowedNotificationObserver( 295 chrome::NOTIFICATION_USER_LIST_CHANGED, 296 base::Bind(&IsNotKnownUser, user_id_2_)).Wait(); 297} 298 299static bool IsSessionStarted() { 300 return chromeos::UserManager::Get()->IsSessionStarted(); 301} 302 303IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { 304 // Specify startup pages. 305 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value( 306 SessionStartupPref::kPrefValueURLs); 307 em::StringListPolicyProto* startup_urls_proto = 308 device_local_account_policy_.payload().mutable_restoreonstartupurls(); 309 for (size_t i = 0; i < arraysize(kStartupURLs); ++i) 310 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); 311 InstallDeviceLocalAccountPolicy(); 312 AddPublicSessionToDevicePolicy(kAccountId1); 313 314 // This observes the display name becoming available as this indicates 315 // device-local account policy is fully loaded, which is a prerequisite for 316 // successful login. 317 content::WindowedNotificationObserver( 318 chrome::NOTIFICATION_USER_LIST_CHANGED, 319 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 320 321 chromeos::LoginDisplayHost* host = 322 chromeos::LoginDisplayHostImpl::default_host(); 323 ASSERT_TRUE(host); 324 host->StartSignInScreen(); 325 chromeos::ExistingUserController* controller = 326 chromeos::ExistingUserController::current_controller(); 327 ASSERT_TRUE(controller); 328 controller->LoginAsPublicAccount(user_id_1_); 329 330 // Wait for the session to start. 331 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 332 base::Bind(IsSessionStarted)).Wait(); 333 334 // Check that the startup pages specified in policy were opened. 335 EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); 336 Browser* browser = 337 chrome::FindLastActiveWithHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH); 338 ASSERT_TRUE(browser); 339 340 TabStripModel* tabs = browser->tab_strip_model(); 341 ASSERT_TRUE(tabs); 342 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs)); 343 EXPECT_EQ(expected_tab_count, tabs->count()); 344 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) 345 EXPECT_EQ(GURL(kStartupURLs[i]), tabs->GetWebContentsAt(i)->GetURL()); 346} 347 348IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, TermsOfService) { 349 // Specify Terms of Service. The URL does not really matter as the test does 350 // not wait for the terms to load. 351 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value( 352 "http://localhost/tos"); 353 InstallDeviceLocalAccountPolicy(); 354 AddPublicSessionToDevicePolicy(kAccountId1); 355 356 // Wait for the device-local account policy to be fully loaded. 357 content::WindowedNotificationObserver( 358 chrome::NOTIFICATION_USER_LIST_CHANGED, 359 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 360 361 // Start login into the device-local account. 362 chromeos::LoginDisplayHost* host = 363 chromeos::LoginDisplayHostImpl::default_host(); 364 ASSERT_TRUE(host); 365 host->StartSignInScreen(); 366 chromeos::ExistingUserController* controller = 367 chromeos::ExistingUserController::current_controller(); 368 ASSERT_TRUE(controller); 369 controller->LoginAsPublicAccount(user_id_1_); 370 371 // Set up an observer that will quit the message loop when login has succeeded 372 // and the first wizard screen, if any, is being shown. 373 base::RunLoop run_loop; 374 chromeos::MockConsumer login_status_consumer; 375 EXPECT_CALL(login_status_consumer, OnLoginSuccess(_, false, false)) 376 .Times(1) 377 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 378 379 // Spin the loop until the observer fires. Then, unregister the observer. 380 controller->set_login_status_consumer(&login_status_consumer); 381 run_loop.Run(); 382 controller->set_login_status_consumer(NULL); 383 384 // Verify that the Terms of Service screen is being shown. 385 chromeos::WizardController* wizard_controller = 386 chromeos::WizardController::default_controller(); 387 ASSERT_TRUE(wizard_controller); 388 ASSERT_TRUE(wizard_controller->current_screen()); 389 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName, 390 wizard_controller->current_screen()->GetName()); 391} 392 393} // namespace policy 394