kiosk_browsertest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 "apps/shell_window.h" 6#include "apps/shell_window_registry.h" 7#include "apps/ui/native_app_window.h" 8#include "ash/desktop_background/desktop_background_controller.h" 9#include "ash/desktop_background/desktop_background_controller_observer.h" 10#include "ash/shell.h" 11#include "base/bind.h" 12#include "base/bind_helpers.h" 13#include "base/command_line.h" 14#include "base/location.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/message_loop/message_loop.h" 17#include "base/path_service.h" 18#include "base/prefs/scoped_user_pref_update.h" 19#include "chrome/browser/browser_process.h" 20#include "chrome/browser/chrome_browser_main.h" 21#include "chrome/browser/chrome_browser_main_extra_parts.h" 22#include "chrome/browser/chrome_content_browser_client.h" 23#include "chrome/browser/chrome_notification_types.h" 24#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h" 25#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 26#include "chrome/browser/chromeos/login/app_launch_controller.h" 27#include "chrome/browser/chromeos/login/app_launch_signin_screen.h" 28#include "chrome/browser/chromeos/login/existing_user_controller.h" 29#include "chrome/browser/chromeos/login/fake_user_manager.h" 30#include "chrome/browser/chromeos/login/login_display_host_impl.h" 31#include "chrome/browser/chromeos/login/mock_user_manager.h" 32#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" 33#include "chrome/browser/chromeos/login/webui_login_display.h" 34#include "chrome/browser/chromeos/login/wizard_controller.h" 35#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" 36#include "chrome/browser/chromeos/settings/cros_settings.h" 37#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 38#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" 39#include "chrome/browser/extensions/extension_service.h" 40#include "chrome/browser/extensions/extension_system.h" 41#include "chrome/browser/extensions/extension_test_message_listener.h" 42#include "chrome/browser/lifetime/application_lifetime.h" 43#include "chrome/browser/policy/cloud/policy_builder.h" 44#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h" 45#include "chrome/browser/profiles/profile_manager.h" 46#include "chrome/browser/ui/browser.h" 47#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 48#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" 49#include "chrome/common/chrome_paths.h" 50#include "chrome/common/chrome_switches.h" 51#include "chrome/common/pref_names.h" 52#include "chrome/test/base/in_process_browser_test.h" 53#include "chrome/test/base/interactive_test_utils.h" 54#include "chrome/test/base/ui_test_utils.h" 55#include "chromeos/chromeos_switches.h" 56#include "chromeos/settings/cros_settings_names.h" 57#include "content/public/browser/notification_observer.h" 58#include "content/public/browser/notification_registrar.h" 59#include "content/public/browser/notification_service.h" 60#include "content/public/test/browser_test_utils.h" 61#include "content/public/test/test_utils.h" 62#include "extensions/common/extension.h" 63#include "google_apis/gaia/fake_gaia.h" 64#include "google_apis/gaia/gaia_switches.h" 65#include "net/base/network_change_notifier.h" 66#include "net/dns/mock_host_resolver.h" 67#include "net/test/embedded_test_server/embedded_test_server.h" 68#include "net/test/embedded_test_server/http_request.h" 69#include "net/test/embedded_test_server/http_response.h" 70#include "testing/gmock/include/gmock/gmock.h" 71#include "testing/gtest/include/gtest/gtest.h" 72#include "ui/aura/window.h" 73#include "ui/compositor/layer.h" 74 75namespace em = enterprise_management; 76 77namespace chromeos { 78 79namespace { 80 81// This is a simple test app that creates an app window and immediately closes 82// it again. Webstore data json is in 83// chrome/test/data/chromeos/app_mode/webstore/inlineinstall/ 84// detail/ggbflgnkafappblpkiflbgpmkfdpnhhe 85const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe"; 86 87// This app creates a window and declares usage of the identity API in its 88// manifest, so we can test device robot token minting via the identity API. 89// Webstore data json is in 90// chrome/test/data/chromeos/app_mode/webstore/inlineinstall/ 91// detail/ibjkkfdnfcaoapcpheeijckmpcfkifob 92const char kTestEnterpriseKioskApp[] = "ibjkkfdnfcaoapcpheeijckmpcfkifob"; 93 94// Timeout while waiting for network connectivity during tests. 95const int kTestNetworkTimeoutSeconds = 1; 96 97// Email of owner account for test. 98const char kTestOwnerEmail[] = "owner@example.com"; 99 100const char kTestEnterpriseAccountId[] = "enterprise-kiosk-app@localhost"; 101const char kTestEnterpriseServiceAccountId[] = "service_account@example.com"; 102const char kTestRefreshToken[] = "fake-refresh-token"; 103const char kTestAccessToken[] = "fake-access-token"; 104 105// Helper function for GetConsumerKioskModeStatusCallback. 106void ConsumerKioskModeStatusCheck( 107 KioskAppManager::ConsumerKioskModeStatus* out_status, 108 const base::Closure& runner_quit_task, 109 KioskAppManager::ConsumerKioskModeStatus in_status) { 110 LOG(INFO) << "KioskAppManager::ConsumerKioskModeStatus = " << in_status; 111 *out_status = in_status; 112 runner_quit_task.Run(); 113} 114 115// Helper KioskAppManager::EnableKioskModeCallback implementation. 116void ConsumerKioskModeLockCheck( 117 bool* out_locked, 118 const base::Closure& runner_quit_task, 119 bool in_locked) { 120 LOG(INFO) << "kiosk locked = " << in_locked; 121 *out_locked = in_locked; 122 runner_quit_task.Run(); 123} 124 125// Helper function for WaitForNetworkTimeOut. 126void OnNetworkWaitTimedOut(const base::Closure& runner_quit_task) { 127 runner_quit_task.Run(); 128} 129 130// Helper function for DeviceOAuth2TokenServiceFactory::Get(). 131void CopyTokenService(DeviceOAuth2TokenService** out_token_service, 132 DeviceOAuth2TokenService* in_token_service) { 133 *out_token_service = in_token_service; 134} 135 136// Helper functions for CanConfigureNetwork mock. 137class ScopedCanConfigureNetwork { 138 public: 139 explicit ScopedCanConfigureNetwork(bool can_configure) 140 : can_configure_(can_configure), 141 callback_(base::Bind(&ScopedCanConfigureNetwork::CanConfigureNetwork, 142 base::Unretained(this))) { 143 AppLaunchController::SetCanConfigureNetworkCallbackForTesting(&callback_); 144 } 145 ~ScopedCanConfigureNetwork() { 146 AppLaunchController::SetCanConfigureNetworkCallbackForTesting(NULL); 147 } 148 149 bool CanConfigureNetwork() { 150 return can_configure_; 151 } 152 153 private: 154 bool can_configure_; 155 AppLaunchController::CanConfigureNetworkCallback callback_; 156 DISALLOW_COPY_AND_ASSIGN(ScopedCanConfigureNetwork); 157}; 158 159} // namespace 160 161// Fake NetworkChangeNotifier used to simulate network connectivity. 162class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier { 163 public: 164 FakeNetworkChangeNotifier() : connection_type_(CONNECTION_NONE) {} 165 166 virtual ConnectionType GetCurrentConnectionType() const OVERRIDE { 167 return connection_type_; 168 } 169 170 void GoOnline() { 171 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 172 } 173 174 void GoOffline() { 175 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE); 176 } 177 178 void SetConnectionType(ConnectionType type) { 179 connection_type_ = type; 180 NotifyObserversOfNetworkChange(type); 181 base::RunLoop().RunUntilIdle(); 182 } 183 184 virtual ~FakeNetworkChangeNotifier() {} 185 186 private: 187 ConnectionType connection_type_; 188 DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifier); 189}; 190 191// Helper class that monitors app windows to wait for a window to appear. 192class ShellWindowObserver : public apps::ShellWindowRegistry::Observer { 193 public: 194 ShellWindowObserver(apps::ShellWindowRegistry* registry, 195 const std::string& app_id) 196 : registry_(registry), app_id_(app_id), window_(NULL), running_(false) { 197 registry_->AddObserver(this); 198 } 199 virtual ~ShellWindowObserver() { 200 registry_->RemoveObserver(this); 201 } 202 203 apps::ShellWindow* Wait() { 204 running_ = true; 205 message_loop_runner_ = new content::MessageLoopRunner; 206 message_loop_runner_->Run(); 207 EXPECT_TRUE(window_); 208 return window_; 209 } 210 211 // ShellWindowRegistry::Observer 212 virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE { 213 if (!running_) 214 return; 215 216 if (shell_window->extension_id() == app_id_) { 217 window_ = shell_window; 218 message_loop_runner_->Quit(); 219 running_ = false; 220 } 221 } 222 virtual void OnShellWindowIconChanged( 223 apps::ShellWindow* shell_window) OVERRIDE {} 224 virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE {} 225 226 private: 227 apps::ShellWindowRegistry* registry_; 228 std::string app_id_; 229 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 230 apps::ShellWindow* window_; 231 bool running_; 232 233 DISALLOW_COPY_AND_ASSIGN(ShellWindowObserver); 234}; 235 236class KioskTest : public InProcessBrowserTest { 237 public: 238 KioskTest() { 239 set_exit_when_last_browser_closes(false); 240 } 241 242 virtual ~KioskTest() {} 243 244 protected: 245 virtual void SetUp() OVERRIDE { 246 base::FilePath test_data_dir; 247 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); 248 embedded_test_server()->ServeFilesFromDirectory(test_data_dir); 249 embedded_test_server()->RegisterRequestHandler( 250 base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_))); 251 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 252 253 mock_user_manager_.reset(new MockUserManager); 254 AppLaunchController::SkipSplashWaitForTesting(); 255 AppLaunchController::SetNetworkWaitForTesting(kTestNetworkTimeoutSeconds); 256 257 InProcessBrowserTest::SetUp(); 258 } 259 260 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 261 host_resolver()->AddRule("*", "127.0.0.1"); 262 } 263 264 virtual void CleanUpOnMainThread() OVERRIDE { 265 // We need to clean up these objects in this specific order. 266 fake_network_notifier_.reset(NULL); 267 disable_network_notifier_.reset(NULL); 268 269 AppLaunchController::SetNetworkTimeoutCallbackForTesting(NULL); 270 AppLaunchSigninScreen::SetUserManagerForTesting(NULL); 271 272 // If the login display is still showing, exit gracefully. 273 if (LoginDisplayHostImpl::default_host()) { 274 base::MessageLoop::current()->PostTask(FROM_HERE, 275 base::Bind(&chrome::AttemptExit)); 276 content::RunMessageLoop(); 277 } 278 279 // Clean up while main thread still runs. 280 // See http://crbug.com/176659. 281 KioskAppManager::Get()->CleanUp(); 282 } 283 284 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 285 command_line->AppendSwitch(chromeos::switches::kLoginManager); 286 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); 287 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); 288 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 289 290 // Create gaia and webstore URL from test server url but using different 291 // host names. This is to avoid gaia response being tagged as from 292 // webstore in chrome_resource_dispatcher_host_delegate.cc. 293 const GURL& server_url = embedded_test_server()->base_url(); 294 295 std::string gaia_host("gaia"); 296 GURL::Replacements replace_gaia_host; 297 replace_gaia_host.SetHostStr(gaia_host); 298 GURL gaia_url = server_url.ReplaceComponents(replace_gaia_host); 299 command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); 300 command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); 301 command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, 302 gaia_url.spec()); 303 304 std::string webstore_host("webstore"); 305 GURL::Replacements replace_webstore_host; 306 replace_webstore_host.SetHostStr(webstore_host); 307 GURL webstore_url = server_url.ReplaceComponents(replace_webstore_host); 308 command_line->AppendSwitchASCII( 309 ::switches::kAppsGalleryURL, 310 webstore_url.Resolve("/chromeos/app_mode/webstore").spec()); 311 command_line->AppendSwitchASCII( 312 ::switches::kAppsGalleryDownloadURL, 313 webstore_url.Resolve( 314 "/chromeos/app_mode/webstore/downloads/%s.crx").spec()); 315 } 316 317 void ReloadKioskApps() { 318 KioskAppManager::Get()->AddApp(kTestKioskApp); 319 } 320 321 void ReloadAutolaunchKioskApps() { 322 KioskAppManager::Get()->AddApp(kTestKioskApp); 323 KioskAppManager::Get()->SetAutoLaunchApp(kTestKioskApp); 324 } 325 326 void StartAppLaunchFromLoginScreen(bool has_connectivity) { 327 EnableConsumerKioskMode(); 328 329 // Start UI, find menu entry for this app and launch it. 330 content::WindowedNotificationObserver login_signal( 331 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 332 content::NotificationService::AllSources()); 333 chromeos::WizardController::SkipPostLoginScreensForTesting(); 334 chromeos::WizardController* wizard_controller = 335 chromeos::WizardController::default_controller(); 336 CHECK(wizard_controller); 337 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 338 login_signal.Wait(); 339 340 // Wait for the Kiosk App configuration to reload, then launch the app. 341 content::WindowedNotificationObserver apps_loaded_signal( 342 chrome::NOTIFICATION_KIOSK_APPS_LOADED, 343 content::NotificationService::AllSources()); 344 ReloadKioskApps(); 345 apps_loaded_signal.Wait(); 346 347 if (!has_connectivity) 348 SimulateNetworkOffline(); 349 350 GetLoginUI()->CallJavascriptFunction( 351 "login.AppsMenuButton.runAppForTesting", 352 base::StringValue(kTestKioskApp)); 353 } 354 355 void WaitForAppLaunchSuccess() { 356 SimulateNetworkOnline(); 357 358 ExtensionTestMessageListener 359 launch_data_check_listener("launchData.isKioskSession = true", false); 360 361 // Wait for the Kiosk App to launch. 362 content::WindowedNotificationObserver( 363 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, 364 content::NotificationService::AllSources()).Wait(); 365 366 // Default profile switches to app profile after app is launched. 367 Profile* app_profile = ProfileManager::GetDefaultProfile(); 368 ASSERT_TRUE(app_profile); 369 370 // Check installer status. 371 EXPECT_EQ(chromeos::KioskAppLaunchError::NONE, 372 chromeos::KioskAppLaunchError::Get()); 373 374 // Check if the kiosk webapp is really installed for the default profile. 375 const extensions::Extension* app = 376 extensions::ExtensionSystem::Get(app_profile)-> 377 extension_service()->GetInstalledExtension(kTestKioskApp); 378 EXPECT_TRUE(app); 379 380 // App should appear with its window. 381 apps::ShellWindowRegistry* shell_window_registry = 382 apps::ShellWindowRegistry::Get(app_profile); 383 apps::ShellWindow* window = 384 ShellWindowObserver(shell_window_registry, kTestKioskApp).Wait(); 385 EXPECT_TRUE(window); 386 387 // Login screen should be gone or fading out. 388 chromeos::LoginDisplayHost* login_display_host = 389 chromeos::LoginDisplayHostImpl::default_host(); 390 EXPECT_TRUE( 391 login_display_host == NULL || 392 login_display_host->GetNativeWindow()->layer()->GetTargetOpacity() == 393 0.0f); 394 395 // Wait until the app terminates if it is still running. 396 if (!shell_window_registry->GetShellWindowsForApp(kTestKioskApp).empty()) 397 content::RunMessageLoop(); 398 399 // Check that the app had been informed that it is running in a kiosk 400 // session. 401 EXPECT_TRUE(launch_data_check_listener.was_satisfied()); 402 } 403 404 void SimulateNetworkOffline() { 405 disable_network_notifier_.reset( 406 new net::NetworkChangeNotifier::DisableForTest); 407 408 fake_network_notifier_.reset(new FakeNetworkChangeNotifier); 409 } 410 411 void SimulateNetworkOnline() { 412 if (fake_network_notifier_.get()) 413 fake_network_notifier_->GoOnline(); 414 } 415 416 void WaitForAppLaunchNetworkTimeout() { 417 if (GetAppLaunchController()->network_wait_timedout()) 418 return; 419 420 scoped_refptr<content::MessageLoopRunner> runner = 421 new content::MessageLoopRunner; 422 423 base::Closure callback = base::Bind( 424 &OnNetworkWaitTimedOut, runner->QuitClosure()); 425 AppLaunchController::SetNetworkTimeoutCallbackForTesting(&callback); 426 427 runner->Run(); 428 429 CHECK(GetAppLaunchController()->network_wait_timedout()); 430 AppLaunchController::SetNetworkTimeoutCallbackForTesting(NULL); 431 } 432 433 void EnableConsumerKioskMode() { 434 scoped_ptr<bool> locked(new bool(false)); 435 scoped_refptr<content::MessageLoopRunner> runner = 436 new content::MessageLoopRunner; 437 KioskAppManager::Get()->EnableConsumerModeKiosk( 438 base::Bind(&ConsumerKioskModeLockCheck, 439 locked.get(), 440 runner->QuitClosure())); 441 runner->Run(); 442 EXPECT_TRUE(*locked.get()); 443 } 444 445 KioskAppManager::ConsumerKioskModeStatus GetConsumerKioskModeStatus() { 446 KioskAppManager::ConsumerKioskModeStatus status = 447 static_cast<KioskAppManager::ConsumerKioskModeStatus>(-1); 448 scoped_refptr<content::MessageLoopRunner> runner = 449 new content::MessageLoopRunner; 450 KioskAppManager::Get()->GetConsumerKioskModeStatus( 451 base::Bind(&ConsumerKioskModeStatusCheck, 452 &status, 453 runner->QuitClosure())); 454 runner->Run(); 455 CHECK_NE(status, static_cast<KioskAppManager::ConsumerKioskModeStatus>(-1)); 456 return status; 457 } 458 459 void JsExpect(const std::string& expression) { 460 bool result; 461 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 462 GetLoginUI()->GetWebContents(), 463 "window.domAutomationController.send(!!(" + expression + "));", 464 &result)); 465 ASSERT_TRUE(result) << expression; 466 } 467 468 content::WebUI* GetLoginUI() { 469 return static_cast<chromeos::LoginDisplayHostImpl*>( 470 chromeos::LoginDisplayHostImpl::default_host())->GetOobeUI()->web_ui(); 471 } 472 473 SigninScreenHandler* GetSigninScreenHandler() { 474 return static_cast<chromeos::LoginDisplayHostImpl*>( 475 chromeos::LoginDisplayHostImpl::default_host()) 476 ->GetOobeUI() 477 ->signin_screen_handler_for_test(); 478 } 479 480 AppLaunchController* GetAppLaunchController() { 481 return chromeos::LoginDisplayHostImpl::default_host() 482 ->GetAppLaunchController(); 483 } 484 485 FakeGaia fake_gaia_; 486 scoped_ptr<net::NetworkChangeNotifier::DisableForTest> 487 disable_network_notifier_; 488 scoped_ptr<FakeNetworkChangeNotifier> fake_network_notifier_; 489 scoped_ptr<MockUserManager> mock_user_manager_; 490}; 491 492IN_PROC_BROWSER_TEST_F(KioskTest, InstallAndLaunchApp) { 493 StartAppLaunchFromLoginScreen(true); 494 WaitForAppLaunchSuccess(); 495} 496 497IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDown) { 498 // Mock network could be configured. 499 ScopedCanConfigureNetwork can_configure_network(true); 500 501 // Start app launch and wait for network connectivity timeout. 502 StartAppLaunchFromLoginScreen(false); 503 OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH); 504 splash_waiter.Wait(); 505 WaitForAppLaunchNetworkTimeout(); 506 507 // Configure network link should be visible. 508 JsExpect("$('splash-config-network').hidden == false"); 509 510 // Set up fake user manager with an owner for the test. 511 mock_user_manager_->SetActiveUser(kTestOwnerEmail); 512 AppLaunchSigninScreen::SetUserManagerForTesting(mock_user_manager_.get()); 513 static_cast<LoginDisplayHostImpl*>(LoginDisplayHostImpl::default_host()) 514 ->GetOobeUI()->ShowOobeUI(false); 515 516 // Configure network should bring up lock screen for owner. 517 OobeScreenWaiter lock_screen_waiter(OobeDisplay::SCREEN_ACCOUNT_PICKER); 518 static_cast<AppLaunchSplashScreenActor::Delegate*>(GetAppLaunchController()) 519 ->OnConfigureNetwork(); 520 lock_screen_waiter.Wait(); 521 522 // A network error screen should be shown after authenticating. 523 OobeScreenWaiter error_screen_waiter(OobeDisplay::SCREEN_ERROR_MESSAGE); 524 static_cast<AppLaunchSigninScreen::Delegate*>(GetAppLaunchController()) 525 ->OnOwnerSigninSuccess(); 526 error_screen_waiter.Wait(); 527 528 ASSERT_TRUE(GetAppLaunchController()->showing_network_dialog()); 529 530 WaitForAppLaunchSuccess(); 531} 532 533IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDownConfigureNotAllowed) { 534 // Mock network could not be configured. 535 ScopedCanConfigureNetwork can_configure_network(false); 536 537 // Start app launch and wait for network connectivity timeout. 538 StartAppLaunchFromLoginScreen(false); 539 OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH); 540 splash_waiter.Wait(); 541 WaitForAppLaunchNetworkTimeout(); 542 543 // Configure network link should not be visible. 544 JsExpect("$('splash-config-network').hidden == true"); 545 546 // Network becomes online and app launch is resumed. 547 WaitForAppLaunchSuccess(); 548} 549 550IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppUserCancel) { 551 StartAppLaunchFromLoginScreen(false); 552 OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH); 553 splash_waiter.Wait(); 554 555 CrosSettings::Get()->SetBoolean( 556 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, true); 557 content::WindowedNotificationObserver signal( 558 chrome::NOTIFICATION_APP_TERMINATING, 559 content::NotificationService::AllSources()); 560 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 561 base::StringValue("app_launch_bailout")); 562 signal.Wait(); 563 EXPECT_EQ(chromeos::KioskAppLaunchError::USER_CANCEL, 564 chromeos::KioskAppLaunchError::Get()); 565} 566 567IN_PROC_BROWSER_TEST_F(KioskTest, AutolaunchWarningCancel) { 568 EnableConsumerKioskMode(); 569 // Start UI, find menu entry for this app and launch it. 570 chromeos::WizardController::SkipPostLoginScreensForTesting(); 571 chromeos::WizardController* wizard_controller = 572 chromeos::WizardController::default_controller(); 573 CHECK(wizard_controller); 574 ReloadAutolaunchKioskApps(); 575 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 576 577 EXPECT_FALSE(KioskAppManager::Get()->GetAutoLaunchApp().empty()); 578 EXPECT_FALSE(KioskAppManager::Get()->IsAutoLaunchEnabled()); 579 580 // Wait for the auto launch warning come up. 581 content::WindowedNotificationObserver( 582 chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE, 583 content::NotificationService::AllSources()).Wait(); 584 GetLoginUI()->CallJavascriptFunction( 585 "login.AutolaunchScreen.confirmAutoLaunchForTesting", 586 base::FundamentalValue(false)); 587 588 // Wait for the auto launch warning to go away. 589 content::WindowedNotificationObserver( 590 chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED, 591 content::NotificationService::AllSources()).Wait(); 592 593 EXPECT_FALSE(KioskAppManager::Get()->IsAutoLaunchEnabled()); 594} 595 596IN_PROC_BROWSER_TEST_F(KioskTest, AutolaunchWarningConfirm) { 597 EnableConsumerKioskMode(); 598 // Start UI, find menu entry for this app and launch it. 599 chromeos::WizardController::SkipPostLoginScreensForTesting(); 600 chromeos::WizardController* wizard_controller = 601 chromeos::WizardController::default_controller(); 602 CHECK(wizard_controller); 603 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 604 605 ReloadAutolaunchKioskApps(); 606 EXPECT_FALSE(KioskAppManager::Get()->GetAutoLaunchApp().empty()); 607 EXPECT_FALSE(KioskAppManager::Get()->IsAutoLaunchEnabled()); 608 609 // Wait for the auto launch warning come up. 610 content::WindowedNotificationObserver( 611 chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE, 612 content::NotificationService::AllSources()).Wait(); 613 GetLoginUI()->CallJavascriptFunction( 614 "login.AutolaunchScreen.confirmAutoLaunchForTesting", 615 base::FundamentalValue(true)); 616 617 // Wait for the auto launch warning to go away. 618 content::WindowedNotificationObserver( 619 chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED, 620 content::NotificationService::AllSources()).Wait(); 621 622 EXPECT_FALSE(KioskAppManager::Get()->GetAutoLaunchApp().empty()); 623 EXPECT_TRUE(KioskAppManager::Get()->IsAutoLaunchEnabled()); 624 625 WaitForAppLaunchSuccess(); 626} 627 628IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableCancel) { 629 chromeos::WizardController::SkipPostLoginScreensForTesting(); 630 chromeos::WizardController* wizard_controller = 631 chromeos::WizardController::default_controller(); 632 CHECK(wizard_controller); 633 634 // Check Kiosk mode status. 635 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE, 636 GetConsumerKioskModeStatus()); 637 638 // Wait for the login UI to come up and switch to the kiosk_enable screen. 639 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 640 content::WindowedNotificationObserver( 641 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 642 content::NotificationService::AllSources()).Wait(); 643 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 644 base::StringValue("kiosk_enable")); 645 646 // Wait for the kiosk_enable screen to show and cancel the screen. 647 content::WindowedNotificationObserver( 648 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE, 649 content::NotificationService::AllSources()).Wait(); 650 GetLoginUI()->CallJavascriptFunction( 651 "login.KioskEnableScreen.enableKioskForTesting", 652 base::FundamentalValue(false)); 653 654 // Wait for the kiosk_enable screen to disappear. 655 content::WindowedNotificationObserver( 656 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED, 657 content::NotificationService::AllSources()).Wait(); 658 659 // Check that the status still says configurable. 660 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE, 661 GetConsumerKioskModeStatus()); 662} 663 664IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableConfirmed) { 665 // Start UI, find menu entry for this app and launch it. 666 chromeos::WizardController::SkipPostLoginScreensForTesting(); 667 chromeos::WizardController* wizard_controller = 668 chromeos::WizardController::default_controller(); 669 CHECK(wizard_controller); 670 671 // Check Kiosk mode status. 672 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE, 673 GetConsumerKioskModeStatus()); 674 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 675 676 // Wait for the login UI to come up and switch to the kiosk_enable screen. 677 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 678 content::WindowedNotificationObserver( 679 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 680 content::NotificationService::AllSources()).Wait(); 681 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 682 base::StringValue("kiosk_enable")); 683 684 // Wait for the kiosk_enable screen to show and cancel the screen. 685 content::WindowedNotificationObserver( 686 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE, 687 content::NotificationService::AllSources()).Wait(); 688 GetLoginUI()->CallJavascriptFunction( 689 "login.KioskEnableScreen.enableKioskForTesting", 690 base::FundamentalValue(true)); 691 692 // Wait for the signal that indicates Kiosk Mode is enabled. 693 content::WindowedNotificationObserver( 694 chrome::NOTIFICATION_KIOSK_ENABLED, 695 content::NotificationService::AllSources()).Wait(); 696 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_ENABLED, 697 GetConsumerKioskModeStatus()); 698} 699 700IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableAbortedWithAutoEnrollment) { 701 // Fake an auto enrollment is going to be enforced. 702 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 703 switches::kEnterpriseEnrollmentInitialModulus, "1"); 704 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 705 switches::kEnterpriseEnrollmentModulusLimit, "2"); 706 g_browser_process->local_state()->SetBoolean(prefs::kShouldAutoEnroll, true); 707 g_browser_process->local_state()->SetInteger( 708 prefs::kAutoEnrollmentPowerLimit, 3); 709 710 // Start UI, find menu entry for this app and launch it. 711 chromeos::WizardController::SkipPostLoginScreensForTesting(); 712 chromeos::WizardController* wizard_controller = 713 chromeos::WizardController::default_controller(); 714 CHECK(wizard_controller); 715 716 // Check Kiosk mode status. 717 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE, 718 GetConsumerKioskModeStatus()); 719 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 720 721 // Wait for the login UI to come up and switch to the kiosk_enable screen. 722 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 723 content::WindowedNotificationObserver( 724 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 725 content::NotificationService::AllSources()).Wait(); 726 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 727 base::StringValue("kiosk_enable")); 728 729 // The flow should be aborted due to auto enrollment enforcement. 730 scoped_refptr<content::MessageLoopRunner> runner = 731 new content::MessageLoopRunner; 732 GetSigninScreenHandler()->set_kiosk_enable_flow_aborted_callback_for_test( 733 runner->QuitClosure()); 734 runner->Run(); 735} 736 737IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableAfter2ndSigninScreen) { 738 // Fake an auto enrollment is not going to be enforced. 739 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 740 switches::kEnterpriseEnrollmentInitialModulus, "1"); 741 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 742 switches::kEnterpriseEnrollmentModulusLimit, "2"); 743 g_browser_process->local_state()->SetBoolean(prefs::kShouldAutoEnroll, false); 744 g_browser_process->local_state()->SetInteger( 745 prefs::kAutoEnrollmentPowerLimit, -1); 746 747 chromeos::WizardController::SkipPostLoginScreensForTesting(); 748 chromeos::WizardController* wizard_controller = 749 chromeos::WizardController::default_controller(); 750 CHECK(wizard_controller); 751 752 // Check Kiosk mode status. 753 EXPECT_EQ(KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE, 754 GetConsumerKioskModeStatus()); 755 756 // Wait for the login UI to come up and switch to the kiosk_enable screen. 757 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 758 content::WindowedNotificationObserver( 759 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 760 content::NotificationService::AllSources()).Wait(); 761 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 762 base::StringValue("kiosk_enable")); 763 764 // Wait for the kiosk_enable screen to show and cancel the screen. 765 content::WindowedNotificationObserver( 766 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE, 767 content::NotificationService::AllSources()).Wait(); 768 GetLoginUI()->CallJavascriptFunction( 769 "login.KioskEnableScreen.enableKioskForTesting", 770 base::FundamentalValue(false)); 771 772 // Wait for the kiosk_enable screen to disappear. 773 content::WindowedNotificationObserver( 774 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED, 775 content::NotificationService::AllSources()).Wait(); 776 777 // Show signin screen again. 778 chromeos::LoginDisplayHostImpl::default_host()->StartSignInScreen( 779 LoginScreenContext()); 780 OobeScreenWaiter(OobeDisplay::SCREEN_GAIA_SIGNIN).Wait(); 781 782 // Show kiosk enable screen again. 783 GetLoginUI()->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator", 784 base::StringValue("kiosk_enable")); 785 786 // And it should show up. 787 content::WindowedNotificationObserver( 788 chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE, 789 content::NotificationService::AllSources()).Wait(); 790} 791 792class KioskEnterpriseTest : public KioskTest { 793 protected: 794 KioskEnterpriseTest() {} 795 796 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 797 device_policy_test_helper_.MarkAsEnterpriseOwned(); 798 device_policy_test_helper_.InstallOwnerKey(); 799 800 KioskTest::SetUpInProcessBrowserTestFixture(); 801 } 802 803 virtual void SetUpOnMainThread() OVERRIDE { 804 // Configure kTestEnterpriseKioskApp in device policy. 805 em::DeviceLocalAccountsProto* accounts = 806 device_policy_test_helper_.device_policy()->payload() 807 .mutable_device_local_accounts(); 808 em::DeviceLocalAccountInfoProto* account = accounts->add_account(); 809 account->set_account_id(kTestEnterpriseAccountId); 810 account->set_type( 811 em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_KIOSK_APP); 812 account->mutable_kiosk_app()->set_app_id(kTestEnterpriseKioskApp); 813 accounts->set_auto_login_id(kTestEnterpriseAccountId); 814 em::PolicyData& policy_data = 815 device_policy_test_helper_.device_policy()->policy_data(); 816 policy_data.set_service_account_identity(kTestEnterpriseServiceAccountId); 817 device_policy_test_helper_.device_policy()->Build(); 818 DBusThreadManager::Get()->GetSessionManagerClient()->StoreDevicePolicy( 819 device_policy_test_helper_.device_policy()->GetBlob(), 820 base::Bind(&KioskEnterpriseTest::StorePolicyCallback)); 821 822 DeviceSettingsService::Get()->Load(); 823 824 // Configure OAuth authentication. 825 FakeGaia::AccessTokenInfo token_info; 826 token_info.token = kTestAccessToken; 827 token_info.email = kTestEnterpriseServiceAccountId; 828 fake_gaia_.IssueOAuthToken(kTestRefreshToken, token_info); 829 DeviceOAuth2TokenService* token_service = NULL; 830 DeviceOAuth2TokenServiceFactory::Get( 831 base::Bind(&CopyTokenService, &token_service)); 832 base::RunLoop().RunUntilIdle(); 833 ASSERT_TRUE(token_service); 834 token_service->SetAndSaveRefreshToken(kTestRefreshToken); 835 836 KioskTest::SetUpOnMainThread(); 837 } 838 839 static void StorePolicyCallback(bool result) { 840 ASSERT_TRUE(result); 841 } 842 843 policy::DevicePolicyCrosTestHelper device_policy_test_helper_; 844 845 private: 846 DISALLOW_COPY_AND_ASSIGN(KioskEnterpriseTest); 847}; 848 849// Disabled due to failures; http://crbug.com/306611. 850IN_PROC_BROWSER_TEST_F(KioskEnterpriseTest, DISABLED_EnterpriseKioskApp) { 851 chromeos::WizardController::SkipPostLoginScreensForTesting(); 852 chromeos::WizardController* wizard_controller = 853 chromeos::WizardController::default_controller(); 854 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 855 856 // Wait for the Kiosk App configuration to reload, then launch the app. 857 KioskAppManager::App app; 858 content::WindowedNotificationObserver( 859 chrome::NOTIFICATION_KIOSK_APPS_LOADED, 860 base::Bind(&KioskAppManager::GetApp, 861 base::Unretained(KioskAppManager::Get()), 862 kTestEnterpriseKioskApp, &app)).Wait(); 863 864 GetLoginUI()->CallJavascriptFunction( 865 "login.AppsMenuButton.runAppForTesting", 866 base::StringValue(kTestEnterpriseKioskApp)); 867 868 // Wait for the Kiosk App to launch. 869 content::WindowedNotificationObserver( 870 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, 871 content::NotificationService::AllSources()).Wait(); 872 873 // Check installer status. 874 EXPECT_EQ(chromeos::KioskAppLaunchError::NONE, 875 chromeos::KioskAppLaunchError::Get()); 876 877 // Wait for the window to appear. 878 apps::ShellWindow* window = ShellWindowObserver( 879 apps::ShellWindowRegistry::Get(ProfileManager::GetDefaultProfile()), 880 kTestEnterpriseKioskApp).Wait(); 881 ASSERT_TRUE(window); 882 883 // Check whether the app can retrieve an OAuth2 access token. 884 std::string result; 885 EXPECT_TRUE(content::ExecuteScriptAndExtractString( 886 window->web_contents(), 887 "chrome.identity.getAuthToken({ 'interactive': false }, function(token) {" 888 " window.domAutomationController.send(token);" 889 "});", 890 &result)); 891 EXPECT_EQ(kTestAccessToken, result); 892 893 // Terminate the app. 894 window->GetBaseWindow()->Close(); 895 content::RunAllPendingInMessageLoop(); 896} 897 898// Specialized test fixture for testing kiosk mode on the 899// hidden WebUI initialization flow for slow hardware. 900class KioskHiddenWebUITest : public KioskTest, 901 public ash::DesktopBackgroundControllerObserver { 902 public: 903 KioskHiddenWebUITest() : wallpaper_loaded_(false) {} 904 905 // KioskTest overrides: 906 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 907 KioskTest::SetUpCommandLine(command_line); 908 command_line->AppendSwitchASCII(switches::kDeviceRegistered, "1"); 909 command_line->AppendSwitch(switches::kDisableBootAnimation); 910 command_line->AppendSwitch(switches::kDisableOobeAnimation); 911 } 912 913 virtual void SetUpOnMainThread() OVERRIDE { 914 KioskTest::SetUpOnMainThread(); 915 ash::Shell::GetInstance()->desktop_background_controller() 916 ->AddObserver(this); 917 } 918 919 virtual void TearDownOnMainThread() OVERRIDE { 920 ash::Shell::GetInstance()->desktop_background_controller() 921 ->RemoveObserver(this); 922 KioskTest::TearDownOnMainThread(); 923 } 924 925 void WaitForWallpaper() { 926 if (!wallpaper_loaded_) { 927 runner_ = new content::MessageLoopRunner; 928 runner_->Run(); 929 } 930 } 931 932 bool wallpaper_loaded() const { return wallpaper_loaded_; } 933 934 // ash::DesktopBackgroundControllerObserver overrides: 935 virtual void OnWallpaperDataChanged() OVERRIDE { 936 wallpaper_loaded_ = true; 937 if (runner_.get()) 938 runner_->Quit(); 939 } 940 941 bool wallpaper_loaded_; 942 scoped_refptr<content::MessageLoopRunner> runner_; 943 944 DISALLOW_COPY_AND_ASSIGN(KioskHiddenWebUITest); 945}; 946 947IN_PROC_BROWSER_TEST_F(KioskHiddenWebUITest, AutolaunchWarning) { 948 // Add a device owner. 949 FakeUserManager* user_manager = new FakeUserManager(); 950 user_manager->AddUser(kTestOwnerEmail); 951 ScopedUserManagerEnabler enabler(user_manager); 952 953 // Set kiosk app to autolaunch. 954 EnableConsumerKioskMode(); 955 chromeos::WizardController::SkipPostLoginScreensForTesting(); 956 chromeos::WizardController* wizard_controller = 957 chromeos::WizardController::default_controller(); 958 CHECK(wizard_controller); 959 ReloadAutolaunchKioskApps(); 960 wizard_controller->SkipToLoginForTesting(LoginScreenContext()); 961 962 EXPECT_FALSE(KioskAppManager::Get()->GetAutoLaunchApp().empty()); 963 EXPECT_FALSE(KioskAppManager::Get()->IsAutoLaunchEnabled()); 964 965 // Wait for the auto launch warning come up. 966 content::WindowedNotificationObserver( 967 chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE, 968 content::NotificationService::AllSources()).Wait(); 969 970 // Wait for the wallpaper to load. 971 WaitForWallpaper(); 972 EXPECT_TRUE(wallpaper_loaded()); 973} 974 975} // namespace chromeos 976