device_local_account_browsertest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/bind_helpers.h" 11#include "base/callback.h" 12#include "base/command_line.h" 13#include "base/file_util.h" 14#include "base/files/file_path.h" 15#include "base/json/json_reader.h" 16#include "base/memory/scoped_ptr.h" 17#include "base/message_loop/message_loop.h" 18#include "base/path_service.h" 19#include "base/run_loop.h" 20#include "base/strings/string_util.h" 21#include "base/strings/stringprintf.h" 22#include "base/strings/utf_string_conversions.h" 23#include "base/values.h" 24#include "chrome/browser/browser_process.h" 25#include "chrome/browser/chrome_notification_types.h" 26#include "chrome/browser/chromeos/login/existing_user_controller.h" 27#include "chrome/browser/chromeos/login/login_display_host.h" 28#include "chrome/browser/chromeos/login/login_display_host_impl.h" 29#include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 30#include "chrome/browser/chromeos/login/screens/wizard_screen.h" 31#include "chrome/browser/chromeos/login/user.h" 32#include "chrome/browser/chromeos/login/user_manager.h" 33#include "chrome/browser/chromeos/login/webui_login_view.h" 34#include "chrome/browser/chromeos/login/wizard_controller.h" 35#include "chrome/browser/chromeos/policy/device_local_account.h" 36#include "chrome/browser/chromeos/policy/device_policy_builder.h" 37#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" 38#include "chrome/browser/extensions/extension_service.h" 39#include "chrome/browser/extensions/extension_system.h" 40#include "chrome/browser/lifetime/application_lifetime.h" 41#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 42#include "chrome/browser/policy/cloud/policy_builder.h" 43#include "chrome/browser/policy/policy_service.h" 44#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" 45#include "chrome/browser/policy/test/local_policy_test_server.h" 46#include "chrome/browser/prefs/session_startup_pref.h" 47#include "chrome/browser/profiles/profile.h" 48#include "chrome/browser/profiles/profile_manager.h" 49#include "chrome/browser/ui/browser.h" 50#include "chrome/browser/ui/browser_commands.h" 51#include "chrome/browser/ui/browser_finder.h" 52#include "chrome/browser/ui/browser_list.h" 53#include "chrome/browser/ui/browser_window.h" 54#include "chrome/browser/ui/host_desktop.h" 55#include "chrome/browser/ui/tabs/tab_strip_model.h" 56#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 57#include "chrome/common/chrome_paths.h" 58#include "chrome/common/chrome_switches.h" 59#include "chrome/common/extensions/extension.h" 60#include "chromeos/chromeos_switches.h" 61#include "chromeos/dbus/cryptohome_client.h" 62#include "chromeos/dbus/dbus_method_call_status.h" 63#include "chromeos/dbus/fake_session_manager_client.h" 64#include "chromeos/dbus/session_manager_client.h" 65#include "content/public/browser/notification_details.h" 66#include "content/public/browser/notification_source.h" 67#include "content/public/browser/web_contents.h" 68#include "content/public/browser/web_ui.h" 69#include "content/public/test/browser_test_utils.h" 70#include "content/public/test/test_utils.h" 71#include "crypto/rsa_private_key.h" 72#include "grit/chromium_strings.h" 73#include "grit/generated_resources.h" 74#include "net/base/url_util.h" 75#include "net/http/http_status_code.h" 76#include "net/test/embedded_test_server/embedded_test_server.h" 77#include "net/test/embedded_test_server/http_request.h" 78#include "net/test/embedded_test_server/http_response.h" 79#include "testing/gmock/include/gmock/gmock.h" 80#include "third_party/cros_system_api/dbus/service_constants.h" 81#include "ui/base/l10n/l10n_util.h" 82#include "url/gurl.h" 83 84namespace em = enterprise_management; 85 86using testing::InvokeWithoutArgs; 87using testing::Return; 88using testing::_; 89 90namespace policy { 91 92namespace { 93 94const char kDomain[] = "example.com"; 95const char kAccountId1[] = "dla1@example.com"; 96const char kAccountId2[] = "dla2@example.com"; 97const char kDisplayName[] = "display name"; 98const char* kStartupURLs[] = { 99 "chrome://policy", 100 "chrome://about", 101}; 102const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt"; 103const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt"; 104const char kRelativeUpdateURL[] = "/service/update2/crx"; 105const char kUpdateManifestHeader[] = 106 "<?xml version='1.0' encoding='UTF-8'?>\n" 107 "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n"; 108const char kUpdateManifestTemplate[] = 109 " <app appid='%s'>\n" 110 " <updatecheck codebase='%s' version='%s' />\n" 111 " </app>\n"; 112const char kUpdateManifestFooter[] = 113 "</gupdate>\n"; 114const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi"; 115const char kHostedAppCRXPath[] = "extensions/hosted_app.crx"; 116const char kHostedAppVersion[] = "0.1"; 117const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 118const char kGoodExtensionPath[] = "extensions/good.crx"; 119const char kGoodExtensionVersion[] = "1.0"; 120 121// Helper that serves extension update manifests to Chrome. 122class TestingUpdateManifestProvider { 123 public: 124 125 // Update manifests will be served at |relative_update_url|. 126 explicit TestingUpdateManifestProvider( 127 const std::string& relative_update_url); 128 ~TestingUpdateManifestProvider(); 129 130 // When an update manifest is requested for the given extension |id|, indicate 131 // that |version| of the extension can be downloaded at |crx_url|. 132 void AddUpdate(const std::string& id, 133 const std::string& version, 134 const GURL& crx_url); 135 136 // This method must be registered with the test's EmbeddedTestServer to start 137 // serving update manifests. 138 scoped_ptr<net::test_server::HttpResponse> HandleRequest( 139 const net::test_server::HttpRequest& request); 140 141 private: 142 struct Update { 143 public: 144 Update(const std::string& version, const GURL& crx_url); 145 Update(); 146 147 std::string version; 148 GURL crx_url; 149 }; 150 typedef std::map<std::string, Update> UpdateMap; 151 UpdateMap updates_; 152 153 const std::string relative_update_url_; 154 155 DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider); 156}; 157 158TestingUpdateManifestProvider::Update::Update(const std::string& version, 159 const GURL& crx_url) 160 : version(version), 161 crx_url(crx_url) { 162} 163 164TestingUpdateManifestProvider::Update::Update() { 165} 166 167TestingUpdateManifestProvider::TestingUpdateManifestProvider( 168 const std::string& relative_update_url) 169 : relative_update_url_(relative_update_url) { 170} 171 172TestingUpdateManifestProvider::~TestingUpdateManifestProvider() { 173} 174 175void TestingUpdateManifestProvider::AddUpdate(const std::string& id, 176 const std::string& version, 177 const GURL& crx_url) { 178 updates_[id] = Update(version, crx_url); 179} 180 181scoped_ptr<net::test_server::HttpResponse> 182 TestingUpdateManifestProvider::HandleRequest( 183 const net::test_server::HttpRequest& request) { 184 const GURL url("http://localhost" + request.relative_url); 185 if (url.path() != relative_update_url_) 186 return scoped_ptr<net::test_server::HttpResponse>(); 187 188 std::string content = kUpdateManifestHeader; 189 for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { 190 if (it.GetKey() != "x") 191 continue; 192 // Extract the extension id from the subquery. Since GetValueForKeyInQuery() 193 // expects a complete URL, dummy scheme and host must be prepended. 194 std::string id; 195 net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()), 196 "id", &id); 197 UpdateMap::const_iterator entry = updates_.find(id); 198 if (entry != updates_.end()) { 199 content += base::StringPrintf(kUpdateManifestTemplate, 200 id.c_str(), 201 entry->second.crx_url.spec().c_str(), 202 entry->second.version.c_str()); 203 } 204 } 205 content += kUpdateManifestFooter; 206 scoped_ptr<net::test_server::BasicHttpResponse> 207 http_response(new net::test_server::BasicHttpResponse); 208 http_response->set_code(net::HTTP_OK); 209 http_response->set_content(content); 210 http_response->set_content_type("text/xml"); 211 return http_response.PassAs<net::test_server::HttpResponse>(); 212} 213 214bool DoesInstallSuccessReferToId(const std::string& id, 215 const content::NotificationSource& source, 216 const content::NotificationDetails& details) { 217 return content::Details<const extensions::InstalledExtensionInfo>(details)-> 218 extension->id() == id; 219} 220 221bool DoesInstallFailureReferToId(const std::string& id, 222 const content::NotificationSource& source, 223 const content::NotificationDetails& details) { 224 return content::Details<const string16>(details)->find(UTF8ToUTF16(id)) != 225 string16::npos; 226} 227 228} // namespace 229 230class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest { 231 protected: 232 DeviceLocalAccountTest() 233 : user_id_1_(GenerateDeviceLocalAccountUserId( 234 kAccountId1, DeviceLocalAccount::TYPE_PUBLIC_SESSION)), 235 user_id_2_(GenerateDeviceLocalAccountUserId( 236 kAccountId2, DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {} 237 238 virtual ~DeviceLocalAccountTest() {} 239 240 virtual void SetUp() OVERRIDE { 241 // Configure and start the test server. 242 scoped_ptr<crypto::RSAPrivateKey> signing_key( 243 PolicyBuilder::CreateTestSigningKey()); 244 ASSERT_TRUE(test_server_.SetSigningKey(signing_key.get())); 245 signing_key.reset(); 246 test_server_.RegisterClient(PolicyBuilder::kFakeToken, 247 PolicyBuilder::kFakeDeviceId); 248 ASSERT_TRUE(test_server_.Start()); 249 250 DevicePolicyCrosBrowserTest::SetUp(); 251 } 252 253 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 254 command_line->AppendSwitch(chromeos::switches::kLoginManager); 255 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 256 command_line->AppendSwitchASCII( 257 switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec()); 258 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 259 } 260 261 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 262 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); 263 264 // Clear command-line arguments (but keep command-line switches) so the 265 // startup pages policy takes effect. 266 CommandLine* command_line = CommandLine::ForCurrentProcess(); 267 CommandLine::StringVector argv(command_line->argv()); 268 argv.erase(argv.begin() + argv.size() - command_line->GetArgs().size(), 269 argv.end()); 270 command_line->InitFromArgv(argv); 271 272 InstallOwnerKey(); 273 MarkAsEnterpriseOwned(); 274 275 InitializePolicy(); 276 } 277 278 virtual void CleanUpOnMainThread() OVERRIDE { 279 // This shuts down the login UI. 280 base::MessageLoop::current()->PostTask(FROM_HERE, 281 base::Bind(&chrome::AttemptExit)); 282 base::RunLoop().RunUntilIdle(); 283 } 284 285 void InitializePolicy() { 286 device_policy()->policy_data().set_public_key_version(1); 287 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 288 proto.mutable_show_user_names()->set_show_user_names(true); 289 290 device_local_account_policy_.policy_data().set_policy_type( 291 dm_protocol::kChromePublicAccountPolicyType); 292 device_local_account_policy_.policy_data().set_username(kAccountId1); 293 device_local_account_policy_.policy_data().set_settings_entity_id( 294 kAccountId1); 295 device_local_account_policy_.policy_data().set_public_key_version(1); 296 device_local_account_policy_.payload().mutable_userdisplayname()->set_value( 297 kDisplayName); 298 } 299 300 void BuildDeviceLocalAccountPolicy() { 301 device_local_account_policy_.SetDefaultSigningKey(); 302 device_local_account_policy_.Build(); 303 } 304 305 void UploadDeviceLocalAccountPolicy() { 306 BuildDeviceLocalAccountPolicy(); 307 ASSERT_TRUE(session_manager_client()->device_local_account_policy( 308 kAccountId1).empty()); 309 test_server_.UpdatePolicy( 310 dm_protocol::kChromePublicAccountPolicyType, kAccountId1, 311 device_local_account_policy_.payload().SerializeAsString()); 312 } 313 314 void UploadAndInstallDeviceLocalAccountPolicy() { 315 UploadDeviceLocalAccountPolicy(); 316 session_manager_client()->set_device_local_account_policy( 317 kAccountId1, device_local_account_policy_.GetBlob()); 318 } 319 320 void AddPublicSessionToDevicePolicy(const std::string& username) { 321 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 322 em::DeviceLocalAccountInfoProto* account = 323 proto.mutable_device_local_accounts()->add_account(); 324 account->set_account_id(username); 325 account->set_type( 326 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 327 RefreshDevicePolicy(); 328 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, 329 std::string(), proto.SerializeAsString()); 330 } 331 332 void CheckPublicSessionPresent(const std::string& id) { 333 const chromeos::User* user = chromeos::UserManager::Get()->FindUser(id); 334 ASSERT_TRUE(user); 335 EXPECT_EQ(id, user->email()); 336 EXPECT_EQ(chromeos::User::USER_TYPE_PUBLIC_ACCOUNT, user->GetType()); 337 } 338 339 const std::string user_id_1_; 340 const std::string user_id_2_; 341 342 UserPolicyBuilder device_local_account_policy_; 343 LocalPolicyTestServer test_server_; 344}; 345 346static bool IsKnownUser(const std::string& account_id) { 347 return chromeos::UserManager::Get()->IsKnownUser(account_id); 348} 349 350IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginScreen) { 351 AddPublicSessionToDevicePolicy(kAccountId1); 352 AddPublicSessionToDevicePolicy(kAccountId2); 353 354 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 355 base::Bind(&IsKnownUser, user_id_1_)) 356 .Wait(); 357 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 358 base::Bind(&IsKnownUser, user_id_2_)) 359 .Wait(); 360 361 CheckPublicSessionPresent(user_id_1_); 362 CheckPublicSessionPresent(user_id_2_); 363} 364 365static bool DisplayNameMatches(const std::string& account_id, 366 const std::string& display_name) { 367 const chromeos::User* user = 368 chromeos::UserManager::Get()->FindUser(account_id); 369 if (!user || user->display_name().empty()) 370 return false; 371 EXPECT_EQ(UTF8ToUTF16(display_name), user->display_name()); 372 return true; 373} 374 375IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DisplayName) { 376 UploadAndInstallDeviceLocalAccountPolicy(); 377 AddPublicSessionToDevicePolicy(kAccountId1); 378 379 content::WindowedNotificationObserver( 380 chrome::NOTIFICATION_USER_LIST_CHANGED, 381 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 382} 383 384IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyDownload) { 385 UploadDeviceLocalAccountPolicy(); 386 AddPublicSessionToDevicePolicy(kAccountId1); 387 388 // Policy for the account is not installed in session_manager_client. Because 389 // of this, the presence of the display name (which comes from policy) can be 390 // used as a signal that indicates successful policy download. 391 content::WindowedNotificationObserver( 392 chrome::NOTIFICATION_USER_LIST_CHANGED, 393 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 394 395 // Sanity check: The policy should be present now. 396 ASSERT_FALSE(session_manager_client()->device_local_account_policy( 397 kAccountId1).empty()); 398} 399 400static bool IsNotKnownUser(const std::string& account_id) { 401 return !IsKnownUser(account_id); 402} 403 404IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, DevicePolicyChange) { 405 AddPublicSessionToDevicePolicy(kAccountId1); 406 AddPublicSessionToDevicePolicy(kAccountId2); 407 408 // Wait until the login screen is up. 409 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 410 base::Bind(&IsKnownUser, user_id_1_)) 411 .Wait(); 412 content::WindowedNotificationObserver(chrome::NOTIFICATION_USER_LIST_CHANGED, 413 base::Bind(&IsKnownUser, user_id_2_)) 414 .Wait(); 415 416 // Update policy to remove kAccountId2. 417 em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); 418 proto.mutable_device_local_accounts()->clear_account(); 419 AddPublicSessionToDevicePolicy(kAccountId1); 420 421 em::ChromeDeviceSettingsProto policy; 422 policy.mutable_show_user_names()->set_show_user_names(true); 423 em::DeviceLocalAccountInfoProto* account1 = 424 policy.mutable_device_local_accounts()->add_account(); 425 account1->set_account_id(kAccountId1); 426 account1->set_type( 427 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION); 428 429 test_server_.UpdatePolicy(dm_protocol::kChromeDevicePolicyType, std::string(), 430 policy.SerializeAsString()); 431 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 432 433 // Make sure the second device-local account disappears. 434 content::WindowedNotificationObserver( 435 chrome::NOTIFICATION_USER_LIST_CHANGED, 436 base::Bind(&IsNotKnownUser, user_id_2_)).Wait(); 437} 438 439static bool IsSessionStarted() { 440 return chromeos::UserManager::Get()->IsSessionStarted(); 441} 442 443IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, StartSession) { 444 // Specify startup pages. 445 device_local_account_policy_.payload().mutable_restoreonstartup()->set_value( 446 SessionStartupPref::kPrefValueURLs); 447 em::StringListPolicyProto* startup_urls_proto = 448 device_local_account_policy_.payload().mutable_restoreonstartupurls(); 449 for (size_t i = 0; i < arraysize(kStartupURLs); ++i) 450 startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); 451 UploadAndInstallDeviceLocalAccountPolicy(); 452 AddPublicSessionToDevicePolicy(kAccountId1); 453 454 // This observes the display name becoming available as this indicates 455 // device-local account policy is fully loaded, which is a prerequisite for 456 // successful login. 457 content::WindowedNotificationObserver( 458 chrome::NOTIFICATION_USER_LIST_CHANGED, 459 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 460 461 // Wait for the login UI to be ready. 462 chromeos::LoginDisplayHostImpl* host = 463 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 464 chromeos::LoginDisplayHostImpl::default_host()); 465 ASSERT_TRUE(host); 466 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 467 ASSERT_TRUE(oobe_ui); 468 base::RunLoop run_loop; 469 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 470 if (!oobe_ui_ready) 471 run_loop.Run(); 472 473 // Start login into the device-local account. 474 host->StartSignInScreen(); 475 chromeos::ExistingUserController* controller = 476 chromeos::ExistingUserController::current_controller(); 477 ASSERT_TRUE(controller); 478 controller->LoginAsPublicAccount(user_id_1_); 479 480 // Wait for the session to start. 481 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 482 base::Bind(IsSessionStarted)).Wait(); 483 484 // Check that the startup pages specified in policy were opened. 485 BrowserList* browser_list = 486 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 487 EXPECT_EQ(1U, browser_list->size()); 488 Browser* browser = browser_list->get(0); 489 ASSERT_TRUE(browser); 490 491 TabStripModel* tabs = browser->tab_strip_model(); 492 ASSERT_TRUE(tabs); 493 int expected_tab_count = static_cast<int>(arraysize(kStartupURLs)); 494 EXPECT_EQ(expected_tab_count, tabs->count()); 495 for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) { 496 EXPECT_EQ(GURL(kStartupURLs[i]), 497 tabs->GetWebContentsAt(i)->GetVisibleURL()); 498 } 499} 500 501IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) { 502 UploadAndInstallDeviceLocalAccountPolicy(); 503 AddPublicSessionToDevicePolicy(kAccountId1); 504 505 // This observes the display name becoming available as this indicates 506 // device-local account policy is fully loaded, which is a prerequisite for 507 // successful login. 508 content::WindowedNotificationObserver( 509 chrome::NOTIFICATION_USER_LIST_CHANGED, 510 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 511 512 // Wait for the login UI to be ready. 513 chromeos::LoginDisplayHostImpl* host = 514 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 515 chromeos::LoginDisplayHostImpl::default_host()); 516 ASSERT_TRUE(host); 517 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 518 ASSERT_TRUE(oobe_ui); 519 base::RunLoop run_loop; 520 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 521 if (!oobe_ui_ready) 522 run_loop.Run(); 523 524 // Ensure that the browser stays alive, even though no windows are opened 525 // during session start. 526 chrome::StartKeepAlive(); 527 528 // Start login into the device-local account. 529 host->StartSignInScreen(); 530 chromeos::ExistingUserController* controller = 531 chromeos::ExistingUserController::current_controller(); 532 ASSERT_TRUE(controller); 533 controller->LoginAsPublicAccount(user_id_1_); 534 535 // Wait for the session to start. 536 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 537 base::Bind(IsSessionStarted)).Wait(); 538 539 // Open a browser window. 540 chrome::NewEmptyWindow(ProfileManager::GetDefaultProfile(), 541 chrome::HOST_DESKTOP_TYPE_ASH); 542 BrowserList* browser_list = 543 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 544 EXPECT_EQ(1U, browser_list->size()); 545 Browser* browser = browser_list->get(0); 546 ASSERT_TRUE(browser); 547 BrowserWindow* browser_window = browser->window(); 548 ASSERT_TRUE(browser_window); 549 chrome::EndKeepAlive(); 550 551 // Verify that an attempt to enter fullscreen mode is denied. 552 EXPECT_FALSE(browser_window->IsFullscreen()); 553 chrome::ToggleFullscreenMode(browser); 554 EXPECT_FALSE(browser_window->IsFullscreen()); 555} 556 557IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionWhitelist) { 558 // Make it possible to force-install a hosted app and an extension. 559 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 560 TestingUpdateManifestProvider testing_update_manifest_provider( 561 kRelativeUpdateURL); 562 testing_update_manifest_provider.AddUpdate( 563 kHostedAppID, 564 kHostedAppVersion, 565 embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath)); 566 testing_update_manifest_provider.AddUpdate( 567 kGoodExtensionID, 568 kGoodExtensionVersion, 569 embedded_test_server()->GetURL(std::string("/") + kGoodExtensionPath)); 570 embedded_test_server()->RegisterRequestHandler( 571 base::Bind(&TestingUpdateManifestProvider::HandleRequest, 572 base::Unretained(&testing_update_manifest_provider))); 573 574 // Specify policy to force-install the hosted app and the extension. 575 em::StringList* forcelist = device_local_account_policy_.payload() 576 .mutable_extensioninstallforcelist()->mutable_value(); 577 forcelist->add_entries(base::StringPrintf( 578 "%s;%s", 579 kHostedAppID, 580 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 581 forcelist->add_entries(base::StringPrintf( 582 "%s;%s", 583 kGoodExtensionID, 584 embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str())); 585 586 UploadAndInstallDeviceLocalAccountPolicy(); 587 AddPublicSessionToDevicePolicy(kAccountId1); 588 589 // This observes the display name becoming available as this indicates 590 // device-local account policy is fully loaded, which is a prerequisite for 591 // successful login. 592 content::WindowedNotificationObserver( 593 chrome::NOTIFICATION_USER_LIST_CHANGED, 594 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 595 596 // Wait for the login UI to be ready. 597 chromeos::LoginDisplayHostImpl* host = 598 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 599 chromeos::LoginDisplayHostImpl::default_host()); 600 ASSERT_TRUE(host); 601 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 602 ASSERT_TRUE(oobe_ui); 603 base::RunLoop run_loop; 604 const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); 605 if (!oobe_ui_ready) 606 run_loop.Run(); 607 608 // Ensure that the browser stays alive, even though no windows are opened 609 // during session start. 610 chrome::StartKeepAlive(); 611 612 // Start listening for app/extension installation results. 613 content::WindowedNotificationObserver hosted_app_observer( 614 chrome::NOTIFICATION_EXTENSION_INSTALLED, 615 base::Bind(DoesInstallSuccessReferToId, kHostedAppID)); 616 content::WindowedNotificationObserver extension_observer( 617 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 618 base::Bind(DoesInstallFailureReferToId, kGoodExtensionID)); 619 620 // Start login into the device-local account. 621 host->StartSignInScreen(); 622 chromeos::ExistingUserController* controller = 623 chromeos::ExistingUserController::current_controller(); 624 ASSERT_TRUE(controller); 625 controller->LoginAsPublicAccount(user_id_1_); 626 627 // Wait for the hosted app installation to succeed and the extension 628 // installation to fail. 629 hosted_app_observer.Wait(); 630 extension_observer.Wait(); 631 632 // Verify that the hosted app was installed. 633 Profile* profile = ProfileManager::GetDefaultProfile(); 634 ASSERT_TRUE(profile); 635 ExtensionService* extension_service = 636 extensions::ExtensionSystem::Get(profile)->extension_service(); 637 EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true)); 638 639 // Verify that the extension was not installed. 640 EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true)); 641} 642 643class TermsOfServiceTest : public DeviceLocalAccountTest, 644 public testing::WithParamInterface<bool> { 645}; 646 647IN_PROC_BROWSER_TEST_P(TermsOfServiceTest, TermsOfServiceScreen) { 648 // Specify Terms of Service URL. 649 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 650 device_local_account_policy_.payload().mutable_termsofserviceurl()->set_value( 651 embedded_test_server()->GetURL( 652 std::string("/") + 653 (GetParam() ? kExistentTermsOfServicePath 654 : kNonexistentTermsOfServicePath)).spec()); 655 UploadAndInstallDeviceLocalAccountPolicy(); 656 AddPublicSessionToDevicePolicy(kAccountId1); 657 658 // Wait for the device-local account policy to be fully loaded. 659 content::WindowedNotificationObserver( 660 chrome::NOTIFICATION_USER_LIST_CHANGED, 661 base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait(); 662 663 // Wait for the login UI to be ready. 664 chromeos::LoginDisplayHostImpl* host = 665 reinterpret_cast<chromeos::LoginDisplayHostImpl*>( 666 chromeos::LoginDisplayHostImpl::default_host()); 667 ASSERT_TRUE(host); 668 chromeos::OobeUI* oobe_ui = host->GetOobeUI(); 669 ASSERT_TRUE(oobe_ui); 670 base::RunLoop oobe_ui_wait_run_loop; 671 const bool oobe_ui_ready = 672 oobe_ui->IsJSReady(oobe_ui_wait_run_loop.QuitClosure()); 673 if (!oobe_ui_ready) 674 oobe_ui_wait_run_loop.Run(); 675 676 // Start login into the device-local account. 677 host->StartSignInScreen(); 678 chromeos::ExistingUserController* controller = 679 chromeos::ExistingUserController::current_controller(); 680 ASSERT_TRUE(controller); 681 controller->LoginAsPublicAccount(user_id_1_); 682 683 // Set up an observer that will quit the message loop when login has succeeded 684 // and the first wizard screen, if any, is being shown. 685 base::RunLoop login_wait_run_loop; 686 chromeos::MockConsumer login_status_consumer; 687 EXPECT_CALL(login_status_consumer, OnLoginSuccess(_, false, false)) 688 .Times(1) 689 .WillOnce(InvokeWithoutArgs(&login_wait_run_loop, &base::RunLoop::Quit)); 690 691 // Spin the loop until the observer fires. Then, unregister the observer. 692 controller->set_login_status_consumer(&login_status_consumer); 693 login_wait_run_loop.Run(); 694 controller->set_login_status_consumer(NULL); 695 696 // Verify that the Terms of Service screen is being shown. 697 chromeos::WizardController* wizard_controller = 698 chromeos::WizardController::default_controller(); 699 ASSERT_TRUE(wizard_controller); 700 ASSERT_TRUE(wizard_controller->current_screen()); 701 EXPECT_EQ(chromeos::WizardController::kTermsOfServiceScreenName, 702 wizard_controller->current_screen()->GetName()); 703 704 // Wait for the Terms of Service to finish downloading, then get the status of 705 // the screen's UI elements. 706 chromeos::WebUILoginView* web_ui_login_view = host->GetWebUILoginView(); 707 ASSERT_TRUE(web_ui_login_view); 708 content::WebUI* web_ui = web_ui_login_view->GetWebUI(); 709 ASSERT_TRUE(web_ui); 710 content::WebContents* contents = web_ui->GetWebContents(); 711 ASSERT_TRUE(contents); 712 std::string json; 713 ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, 714 "var screen = document.getElementById('terms-of-service');" 715 "function SendReplyIfDownloadDone() {" 716 " if (screen.classList.contains('tos-loading'))" 717 " return false;" 718 " var status = {};" 719 " status.heading = document.getElementById('tos-heading').textContent;" 720 " status.subheading =" 721 " document.getElementById('tos-subheading').textContent;" 722 " status.contentHeading =" 723 " document.getElementById('tos-content-heading').textContent;" 724 " status.content =" 725 " document.getElementById('tos-content-main').textContent;" 726 " status.error = screen.classList.contains('error');" 727 " status.acceptEnabled =" 728 " !document.getElementById('tos-accept-button').disabled;" 729 " domAutomationController.send(JSON.stringify(status));" 730 " observer.disconnect();" 731 " return true;" 732 "}" 733 "var observer = new MutationObserver(SendReplyIfDownloadDone);" 734 "if (!SendReplyIfDownloadDone()) {" 735 " var options = { attributes: true, attributeFilter: [ 'class' ] };" 736 " observer.observe(screen, options);" 737 "}", 738 &json)); 739 scoped_ptr<base::Value> value_ptr(base::JSONReader::Read(json)); 740 const base::DictionaryValue* status = NULL; 741 ASSERT_TRUE(value_ptr.get()); 742 ASSERT_TRUE(value_ptr->GetAsDictionary(&status)); 743 std::string heading; 744 EXPECT_TRUE(status->GetString("heading", &heading)); 745 std::string subheading; 746 EXPECT_TRUE(status->GetString("subheading", &subheading)); 747 std::string content_heading; 748 EXPECT_TRUE(status->GetString("contentHeading", &content_heading)); 749 std::string content; 750 EXPECT_TRUE(status->GetString("content", &content)); 751 bool error; 752 EXPECT_TRUE(status->GetBoolean("error", &error)); 753 bool accept_enabled; 754 EXPECT_TRUE(status->GetBoolean("acceptEnabled", &accept_enabled)); 755 756 // Verify that the screen's headings have been set correctly. 757 EXPECT_EQ( 758 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_HEADING, 759 UTF8ToUTF16(kDomain)), 760 heading); 761 EXPECT_EQ( 762 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_SUBHEADING, 763 UTF8ToUTF16(kDomain)), 764 subheading); 765 EXPECT_EQ( 766 l10n_util::GetStringFUTF8(IDS_TERMS_OF_SERVICE_SCREEN_CONTENT_HEADING, 767 UTF8ToUTF16(kDomain)), 768 content_heading); 769 770 if (!GetParam()) { 771 // The Terms of Service URL was invalid. Verify that the screen is showing 772 // an error and the accept button is disabled. 773 EXPECT_TRUE(error); 774 EXPECT_FALSE(accept_enabled); 775 return; 776 } 777 778 // The Terms of Service URL was valid. Verify that the screen is showing the 779 // downloaded Terms of Service and the accept button is enabled. 780 base::FilePath test_dir; 781 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); 782 std::string terms_of_service; 783 ASSERT_TRUE(base::ReadFileToString( 784 test_dir.Append(kExistentTermsOfServicePath), &terms_of_service)); 785 EXPECT_EQ(terms_of_service, content); 786 EXPECT_FALSE(error); 787 EXPECT_TRUE(accept_enabled); 788 789 // Click the accept button. 790 ASSERT_TRUE(content::ExecuteScript(contents, 791 "$('tos-accept-button').click();")); 792 793 // Wait for the session to start. 794 if (!IsSessionStarted()) { 795 content::WindowedNotificationObserver(chrome::NOTIFICATION_SESSION_STARTED, 796 base::Bind(IsSessionStarted)).Wait(); 797 } 798} 799 800INSTANTIATE_TEST_CASE_P(TermsOfServiceTestInstance, 801 TermsOfServiceTest, testing::Bool()); 802 803} // namespace policy 804