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