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