device_local_account_browsertest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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/file_util.h" 12#include "base/files/file_path.h" 13#include "base/files/scoped_temp_dir.h" 14#include "base/message_loop.h" 15#include "base/path_service.h" 16#include "base/run_loop.h" 17#include "base/stl_util.h" 18#include "base/strings/string_util.h" 19#include "base/strings/utf_string_conversions.h" 20#include "chrome/browser/browser_process.h" 21#include "chrome/browser/chromeos/login/existing_user_controller.h" 22#include "chrome/browser/chromeos/login/login_display_host.h" 23#include "chrome/browser/chromeos/login/login_display_host_impl.h" 24#include "chrome/browser/chromeos/login/user.h" 25#include "chrome/browser/chromeos/login/user_manager.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/enterprise_install_attributes.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/proto/chromeos/install_attributes.pb.h" 35#include "chrome/browser/policy/test/local_policy_test_server.h" 36#include "chrome/browser/prefs/session_startup_pref.h" 37#include "chrome/browser/ui/browser.h" 38#include "chrome/browser/ui/browser_finder.h" 39#include "chrome/browser/ui/host_desktop.h" 40#include "chrome/browser/ui/tabs/tab_strip_model.h" 41#include "chrome/common/chrome_notification_types.h" 42#include "chrome/common/chrome_switches.h" 43#include "chrome/test/base/in_process_browser_test.h" 44#include "chromeos/chromeos_paths.h" 45#include "chromeos/chromeos_switches.h" 46#include "chromeos/dbus/cryptohome_client.h" 47#include "chromeos/dbus/dbus_method_call_status.h" 48#include "chromeos/dbus/dbus_thread_manager.h" 49#include "chromeos/dbus/fake_cryptohome_client.h" 50#include "chromeos/dbus/fake_session_manager_client.h" 51#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h" 52#include "chromeos/dbus/session_manager_client.h" 53#include "content/public/browser/web_contents.h" 54#include "content/public/test/test_utils.h" 55#include "testing/gmock/include/gmock/gmock.h" 56#include "third_party/cros_system_api/dbus/service_constants.h" 57 58namespace em = enterprise_management; 59 60using testing::Return; 61 62namespace policy { 63 64namespace { 65 66const char kAccountId1[] = "dla1@example.com"; 67const char kAccountId2[] = "dla2@example.com"; 68const char kDisplayName1[] = "display name for account 1"; 69const char kDisplayName2[] = "display name for account 2"; 70const char* kStartupURLs[] = { 71 "chrome://policy", 72 "chrome://about", 73}; 74 75} // namespace 76 77class DeviceLocalAccountTest : public InProcessBrowserTest { 78 protected: 79 DeviceLocalAccountTest() 80 : user_id_1_(GenerateDeviceLocalAccountUserId( 81 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), 82 user_id_2_(GenerateDeviceLocalAccountUserId( 83 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {} 84 85 virtual ~DeviceLocalAccountTest() {} 86 87 virtual void SetUp() OVERRIDE { 88 // Configure and start the test server. 89 scoped_ptr<crypto::RSAPrivateKey> signing_key( 90 PolicyBuilder::CreateTestSigningKey()); 91 ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get())); 92 signing_key.reset(); 93 test_server_.RegisterClient(PolicyBuilder::kFakeToken, 94 PolicyBuilder::kFakeDeviceId); 95 ASSERT_TRUE(test_server_.Start()); 96 97 InProcessBrowserTest::SetUp(); 98 } 99 100 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 101 command_line->AppendSwitch(chromeos::switches::kLoginManager); 102 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 103 command_line->AppendSwitchASCII( 104 switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec()); 105 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 106 } 107 108 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 109 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 110 111 // Clear command-line arguments (but keep command-line switches) so the 112 // startup pages policy takes effect. 113 CommandLine* command_line = CommandLine::ForCurrentProcess(); 114 CommandLine::StringVector argv(command_line->argv()); 115 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(), 116 argv.end()); 117 command_line->InitFromArgv(argv); 118 119 // Mark the device enterprise-enrolled. 120 SetUpInstallAttributes(); 121 122 // Redirect session_manager DBus calls to FakeSessionManagerClient. 123 chromeos::MockDBusThreadManagerWithoutGMock* dbus_thread_manager = 124 new chromeos::MockDBusThreadManagerWithoutGMock(); 125 session_manager_client_ = 126 dbus_thread_manager->fake_session_manager_client(); 127 chromeos::DBusThreadManager::InitializeForTesting(dbus_thread_manager); 128 129 SetUpPolicy(); 130 } 131 132 virtual void CleanUpOnMainThread() OVERRIDE { 133 // This shuts down the login UI. 134 base::MessageLoop::current()->PostTask(FROM_HERE, 135 base::Bind(&chrome::AttemptExit)); 136 base::RunLoop().RunUntilIdle(); 137 } 138 139 void SetUpInstallAttributes() { 140 cryptohome::SerializedInstallAttributes install_attrs_proto; 141 cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL; 142 143 attribute = install_attrs_proto.add_attributes(); 144 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned); 145 attribute->set_value("true"); 146 147 attribute = install_attrs_proto.add_attributes(); 148 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser); 149 attribute->set_value(PolicyBuilder::kFakeUsername); 150 151 base::FilePath install_attrs_file = 152 temp_dir_.path().AppendASCII("install_attributes.pb"); 153 const std::string install_attrs_blob( 154 install_attrs_proto.SerializeAsString()); 155 ASSERT_EQ(static_cast<int>(install_attrs_blob.size()), 156 file_util::WriteFile(install_attrs_file, 157 install_attrs_blob.c_str(), 158 install_attrs_blob.size())); 159 ASSERT_TRUE(PathService::Override(chromeos::FILE_INSTALL_ATTRIBUTES, 160 install_attrs_file)); 161 } 162 163 void SetUpPolicy() { 164 // Configure two device-local accounts in device settings. 165 DevicePolicyBuilder device_policy; 166 device_policy.policy_data().set_public_key_version(1); 167 em::ChromeDeviceSettingsProto& proto(device_policy.payload()); 168 proto.mutable_show_user_names()->set_show_user_names(true); 169 em::DeviceLocalAccountInfoProto* account1 = 170 proto.mutable_device_local_accounts()->add_account(); 171 account1->set_account_id(kAccountId1); 172 account1->set_type( 173 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 174 em::DeviceLocalAccountInfoProto* account2 = 175 proto.mutable_device_local_accounts()->add_account(); 176 account2->set_account_id(kAccountId2); 177 account2->set_type( 178 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 179 device_policy.Build(); 180 session_manager_client_->set_device_policy(device_policy.GetBlob()); 181 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, 182 std::string(), proto.SerializeAsString()); 183 184 // Install the owner key. 185 base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key"); 186 std::vector<uint8> owner_key_bits; 187 ASSERT_TRUE(device_policy.signing_key()->ExportPublicKey(&owner_key_bits)); 188 ASSERT_EQ( 189 static_cast<int>(owner_key_bits.size()), 190 file_util::WriteFile( 191 owner_key_file, 192 reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)), 193 owner_key_bits.size())); 194 ASSERT_TRUE( 195 PathService::Override(chromeos::FILE_OWNER_KEY, owner_key_file)); 196 197 // Configure device-local account policy for the first device-local account. 198 UserPolicyBuilder device_local_account_policy; 199 device_local_account_policy.policy_data().set_policy_type( 200 dm_protocol::kChromePublicAccountPolicyType); 201 device_local_account_policy.policy_data().set_username(kAccountId1); 202 device_local_account_policy.policy_data().set_settings_entity_id( 203 kAccountId1); 204 device_local_account_policy.policy_data().set_public_key_version(1); 205 device_local_account_policy.payload().mutable_restoreonstartup()->set_value( 206 SessionStartupPref::kPrefValueURLs); 207 em::StringListPolicyProto* startup_urls_proto = 208 device_local_account_policy.payload().mutable_restoreonstartupurls(); 209 for (size_t i = 0; i < arraysize(kStartupURLs); ++i) 210 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); 211 device_local_account_policy.payload().mutable_userdisplayname()->set_value( 212 kDisplayName1); 213 device_local_account_policy.Build(); 214 session_manager_client_->set_device_local_account_policy( 215 kAccountId1, device_local_account_policy.GetBlob()); 216 test_server_.UpdatePolicy( 217 dm_protocol::kChromePublicAccountPolicyType, kAccountId1, 218 device_local_account_policy.payload().SerializeAsString()); 219 220 // Make policy for the second account available from the server. 221 device_local_account_policy.payload().mutable_userdisplayname()->set_value( 222 kDisplayName2); 223 test_server_.UpdatePolicy( 224 dm_protocol::kChromePublicAccountPolicyType, kAccountId2, 225 device_local_account_policy.payload().SerializeAsString()); 226 227 // Don't install policy for |kAccountId2| yet so initial download gets 228 // test coverage. 229 ASSERT_TRUE(session_manager_client_->device_local_account_policy( 230 kAccountId2).empty()); 231 } 232 233 void CheckPublicSessionPresent(const std::string& id) { 234 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id); 235 ASSERT_TRUE(user); 236 EXPECT_EQ(id, user->email()); 237 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); 238 } 239 240 const std::string user_id_1_; 241 const std::string user_id_2_; 242 243 LocalPolicyTestServer test_server_; 244 base::ScopedTempDir temp_dir_; 245 246 chromeos::FakeSessionManagerClient* session_manager_client_; 247}; 248 249static bool IsKnownUser(const std::string& account_id) { 250 return chromeos::UserManager::Get()->IsKnownUser(account_id); 251} 252 253IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { 254 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 255 base::Bind(&IsKnownUser, user_id_1_)) 256 .Wait(); 257 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 258 base::Bind(&IsKnownUser, user_id_2_)) 259 .Wait(); 260 261 CheckPublicSessionPresent(user_id_1_); 262 CheckPublicSessionPresent(user_id_2_); 263} 264 265static bool DisplayNameMatches(const std::string& account_id, 266 const std::string& display_name) { 267 const chromeos::User* user = 268 chromeos::UserManager::Get()->FindUser(account_id); 269 if (!user || user->display_name().empty()) 270 return false; 271 EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name()); 272 return true; 273} 274 275IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { 276 content::WindowedNotificationObserver( 277 chrome::NOTIFICATION_USER_LIST_CHANGED, 278 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Wait(); 279} 280 281IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { 282 // Policy for kAccountId2 is not installed in session_manager_client, make 283 // sure it gets fetched from the server. Note that the test setup doesn't set 284 // up policy for kAccountId2, so the presence of the display name can be used 285 // as signal to indicate successful policy download. 286 content::WindowedNotificationObserver( 287 chrome::NOTIFICATION_USER_LIST_CHANGED, 288 base::Bind(&DisplayNameMatches, user_id_2_, kDisplayName2)).Wait(); 289 290 // Sanity check: The policy should be present now. 291 ASSERT_FALSE(session_manager_client_->device_local_account_policy( 292 kAccountId2).empty()); 293} 294 295static bool IsNotKnownUser(const std::string& account_id) { 296 return !IsKnownUser(account_id); 297} 298 299IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { 300 // Wait until the login screen is up. 301 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 302 base::Bind(&IsKnownUser, user_id_1_)) 303 .Wait(); 304 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 305 base::Bind(&IsKnownUser, user_id_2_)) 306 .Wait(); 307 308 // Update policy to remove kAccountId2. 309 em::ChromeDeviceSettingsProto policy; 310 policy.mutable_show_user_names()->set_show_user_names(true); 311 em::DeviceLocalAccountInfoProto* account1 = 312 policy.mutable_device_local_accounts()->add_account(); 313 account1->set_account_id(kAccountId1); 314 account1->set_type( 315 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 316 317 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(), 318 policy.SerializeAsString()); 319 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 320 321 // Make sure the second device-local account disappears. 322 content::WindowedNotificationObserver( 323 chrome::NOTIFICATION_USER_LIST_CHANGED, 324 base::Bind(&IsNotKnownUser, user_id_2_)).Wait(); 325} 326 327static bool IsSessionStarted() { 328 return chromeos::UserManager::Get()->IsSessionStarted(); 329} 330 331IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { 332 // This observes the display name becoming available as this indicates 333 // device-local account policy is fully loaded, which is a prerequisite for 334 // successful login. 335 content::WindowedNotificationObserver( 336 chrome::NOTIFICATION_USER_LIST_CHANGED, 337 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName1)).Wait(); 338 339 chromeos::LoginDisplayHost* host = 340 chromeos::LoginDisplayHostImpl::default_host(); 341 ASSERT_TRUE(host); 342 host->StartSignInScreen(); 343 chromeos::ExistingUserController* controller = 344 chromeos::ExistingUserController::current_controller(); 345 ASSERT_TRUE(controller); 346 controller->LoginAsPublicAccount(user_id_1_); 347 348 // Wait for the session to start. 349 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 350 base::Bind(IsSessionStarted)).Wait(); 351 352 // Check that the startup pages specified in policy were opened. 353 EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); 354 Browser* browser = 355 chrome::FindLastActiveWithHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH); 356 ASSERT_TRUE(browser); 357 358 TabStripModel* tabs = browser->tab_strip_model(); 359 ASSERT_TRUE(tabs); 360 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs)); 361 EXPECT_EQ(expected_tab_count, tabs->count()); 362 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) 363 EXPECT_EQ(GURL(kStartupURLs[i]), tabs->GetWebContentsAt(i)->GetURL()); 364} 365 366} // namespace policy 367