kiosk_browsertest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 "base/command_line.h"
6#include "base/path_service.h"
7#include "base/strings/stringprintf.h"
8#include "chrome/browser/browser_process.h"
9#include "chrome/browser/chrome_browser_main.h"
10#include "chrome/browser/chrome_browser_main_extra_parts.h"
11#include "chrome/browser/chrome_content_browser_client.h"
12#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
13#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
14#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
15#include "chrome/browser/chromeos/login/existing_user_controller.h"
16#include "chrome/browser/chromeos/login/login_display_host_impl.h"
17#include "chrome/browser/chromeos/login/webui_login_display.h"
18#include "chrome/browser/chromeos/login/wizard_controller.h"
19#include "chrome/browser/extensions/extension_service.h"
20#include "chrome/browser/extensions/extension_system.h"
21#include "chrome/browser/lifetime/application_lifetime.h"
22#include "chrome/browser/prefs/scoped_user_pref_update.h"
23#include "chrome/browser/profiles/profile_manager.h"
24#include "chrome/browser/ui/browser.h"
25#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
26#include "chrome/common/chrome_notification_types.h"
27#include "chrome/common/chrome_paths.h"
28#include "chrome/common/chrome_switches.h"
29#include "chrome/common/extensions/extension.h"
30#include "chrome/test/base/in_process_browser_test.h"
31#include "chrome/test/base/interactive_test_utils.h"
32#include "chrome/test/base/ui_test_utils.h"
33#include "chromeos/chromeos_switches.h"
34#include "content/public/browser/notification_observer.h"
35#include "content/public/browser/notification_registrar.h"
36#include "content/public/browser/notification_service.h"
37#include "content/public/test/test_utils.h"
38#include "google_apis/gaia/gaia_switches.h"
39#include "net/base/host_port_pair.h"
40#include "net/dns/mock_host_resolver.h"
41#include "net/test/embedded_test_server/embedded_test_server.h"
42#include "net/test/embedded_test_server/http_request.h"
43#include "net/test/embedded_test_server/http_response.h"
44#include "testing/gmock/include/gmock/gmock.h"
45#include "testing/gtest/include/gtest/gtest.h"
46
47using namespace net::test_server;
48
49namespace chromeos {
50
51namespace {
52
53const char kWebstoreDomain[] = "cws.com";
54const base::FilePath kServiceLogin("chromeos/service_login.html");
55
56// Webstore data json is in
57//   chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
58//       detail/ggbflgnkafappblpkiflbgpmkfdpnhhe
59const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe";
60
61// Helper method for GetConsumerKioskModeStatusCallback.
62void ConsumerKioskModeStatusCheck(
63    KioskAppManager::ConsumerKioskModeStatus* out_status,
64    const base::Closure& runner_quit_task,
65    KioskAppManager::ConsumerKioskModeStatus in_status) {
66  LOG(INFO) << "KioskAppManager::ConsumerKioskModeStatus = " << in_status;
67  *out_status = in_status;
68  runner_quit_task.Run();
69}
70
71// Helper KioskAppManager::EnableKioskModeCallback implementation.
72void ConsumerKioskModeLockCheck(
73    bool* out_locked,
74    const base::Closure& runner_quit_task,
75    bool in_locked) {
76  LOG(INFO) << "kioks locked  = " << in_locked;
77  *out_locked = in_locked;
78  runner_quit_task.Run();
79}
80
81class TestBrowserMainExtraParts
82    : public ChromeBrowserMainExtraParts,
83      public content::NotificationObserver {
84 public:
85  TestBrowserMainExtraParts() {}
86  virtual ~TestBrowserMainExtraParts() {}
87
88  void set_quit_task(const base::Closure& quit_task) { quit_task_ = quit_task; }
89
90  void SetupSigninScreen() {
91    chromeos::ExistingUserController* controller =
92        chromeos::ExistingUserController::current_controller();
93    CHECK(controller);
94    chromeos::WebUILoginDisplay* webui_login_display =
95        static_cast<chromeos::WebUILoginDisplay*>(
96            controller->login_display());
97    CHECK(webui_login_display);
98    webui_login_display->ShowSigninScreenForCreds("username", "password");
99  }
100
101 protected:
102  content::NotificationRegistrar registrar_;
103  base::Closure quit_task_;
104
105  DISALLOW_COPY_AND_ASSIGN(TestBrowserMainExtraParts);
106};
107
108// Used to add an observer to NotificationService after it's created.
109class KioskAppLaunchScenarioHandler : public TestBrowserMainExtraParts {
110 public:
111  KioskAppLaunchScenarioHandler() {}
112
113  virtual ~KioskAppLaunchScenarioHandler() {}
114
115 private:
116  // ChromeBrowserMainExtraParts implementation.
117  virtual void PreEarlyInitialization() OVERRIDE {
118    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
119                   content::NotificationService::AllSources());
120    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APPS_LOADED,
121                   content::NotificationService::AllSources());
122    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
123                   content::NotificationService::AllSources());
124  }
125
126  // Overridden from content::NotificationObserver:
127  virtual void Observe(int type,
128                       const content::NotificationSource& source,
129                       const content::NotificationDetails& details) OVERRIDE {
130    if (type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE) {
131      LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
132      SetupSigninScreen();
133    } else if (type == chrome::NOTIFICATION_KIOSK_APPS_LOADED) {
134      LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APPS_LOADED";
135      content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
136          chromeos::LoginDisplayHostImpl::default_host())->
137              GetOobeUI()->web_ui();
138      web_ui->CallJavascriptFunction("login.AppsMenuButton.runAppForTesting",
139                                     base::StringValue(kTestKioskApp));
140    } else if (type == chrome::NOTIFICATION_KIOSK_APP_LAUNCHED) {
141      LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APP_LAUNCHED";
142      registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
143                     content::NotificationService::AllSources());
144      quit_task_.Run();
145    } else if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED) {
146      LOG(INFO) << "content::NOTIFICATION_RENDERER_PROCESS_CLOSED";
147      quit_task_.Run();
148    } else {
149      NOTREACHED();
150    }
151  }
152
153  DISALLOW_COPY_AND_ASSIGN(KioskAppLaunchScenarioHandler);
154};
155
156class AutostartWarningCancelScenarioHandler : public TestBrowserMainExtraParts {
157 public:
158  AutostartWarningCancelScenarioHandler() {
159  }
160
161  virtual ~AutostartWarningCancelScenarioHandler() {}
162
163 private:
164  // ChromeBrowserMainExtraParts implementation.
165  virtual void PreEarlyInitialization() OVERRIDE {
166    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE,
167                   content::NotificationService::AllSources());
168    registrar_.Add(this,
169                   chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED,
170                   content::NotificationService::AllSources());
171    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
172                   content::NotificationService::AllSources());
173  }
174
175  // Overridden from content::NotificationObserver:
176  virtual void Observe(int type,
177                       const content::NotificationSource& source,
178                       const content::NotificationDetails& details) OVERRIDE {
179    switch (type) {
180      case chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE: {
181        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE";
182        content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
183            chromeos::LoginDisplayHostImpl::default_host())->
184                GetOobeUI()->web_ui();
185        web_ui->CallJavascriptFunction(
186            "login.AutolaunchScreen.confirmAutoLaunchForTesting",
187            base::FundamentalValue(false));
188        break;
189      }
190      case chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED: {
191        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED";
192        quit_task_.Run();
193        break;
194      }
195      case chrome::NOTIFICATION_KIOSK_APP_LAUNCHED: {
196        LOG(FATAL) << "chrome::NOTIFICATION_KIOSK_APP_LAUNCHED";
197        break;
198      }
199      default: {
200        NOTREACHED();
201      }
202    }
203  }
204
205  DISALLOW_COPY_AND_ASSIGN(AutostartWarningCancelScenarioHandler);
206};
207
208class AutostartWarningConfirmScenarioHandler
209    : public TestBrowserMainExtraParts {
210 public:
211  AutostartWarningConfirmScenarioHandler() : first_pass_(true) {
212  }
213
214  virtual ~AutostartWarningConfirmScenarioHandler() {}
215
216 private:
217  // ChromeBrowserMainExtraParts implementation.
218  virtual void PreEarlyInitialization() OVERRIDE {
219    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE,
220                   content::NotificationService::AllSources());
221    registrar_.Add(this,
222                   chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED,
223                   content::NotificationService::AllSources());
224    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
225                   content::NotificationService::AllSources());
226  }
227
228  // Overridden from content::NotificationObserver:
229  virtual void Observe(int type,
230                       const content::NotificationSource& source,
231                       const content::NotificationDetails& details) OVERRIDE {
232    switch (type) {
233      case chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE: {
234        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE";
235        if (!first_pass_)
236          break;
237
238        content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
239            chromeos::LoginDisplayHostImpl::default_host())->
240                GetOobeUI()->web_ui();
241        web_ui->CallJavascriptFunction(
242            "login.AutolaunchScreen.confirmAutoLaunchForTesting",
243            base::FundamentalValue(true));
244      }
245      case chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED: {
246        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED";
247        first_pass_ = false;
248        break;
249      }
250      case chrome::NOTIFICATION_KIOSK_APP_LAUNCHED:
251        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APP_LAUNCHED";
252        registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
253                       content::NotificationService::AllSources());
254        quit_task_.Run();
255       break;
256      case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
257        LOG(INFO) << "chrome::NOTIFICATION_RENDERER_PROCESS_CLOSED";
258        quit_task_.Run();
259        break;
260      }
261      default: {
262        NOTREACHED();
263      }
264    }
265  }
266
267  bool first_pass_;
268
269  DISALLOW_COPY_AND_ASSIGN(AutostartWarningConfirmScenarioHandler);
270};
271
272
273class KioskEnableScenarioHandler
274    : public TestBrowserMainExtraParts {
275 public:
276  explicit KioskEnableScenarioHandler(bool enable_kiosk)
277      : enable_kiosk_(enable_kiosk) {
278  }
279
280  virtual ~KioskEnableScenarioHandler() {}
281
282 private:
283  // ChromeBrowserMainExtraParts implementation.
284  virtual void PreEarlyInitialization() OVERRIDE {
285    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
286                   content::NotificationService::AllSources());
287    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE,
288                   content::NotificationService::AllSources());
289    registrar_.Add(this,
290                   chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED,
291                   content::NotificationService::AllSources());
292    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_ENABLED,
293                   content::NotificationService::AllSources());
294  }
295
296  // Overridden from content::NotificationObserver:
297  virtual void Observe(int type,
298                       const content::NotificationSource& source,
299                       const content::NotificationDetails& details) OVERRIDE {
300    switch (type) {
301      case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: {
302        LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
303        SetupSigninScreen();
304        content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
305            chromeos::LoginDisplayHostImpl::default_host())->
306                GetOobeUI()->web_ui();
307        web_ui->CallJavascriptFunction("cr.ui.Oobe.handleAccelerator",
308                                       base::StringValue("kiosk_enable"));
309        break;
310      }
311      case chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE: {
312        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE";
313        content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
314            chromeos::LoginDisplayHostImpl::default_host())->
315                GetOobeUI()->web_ui();
316        web_ui->CallJavascriptFunction(
317            "login.KioskEnableScreen.enableKioskForTesting",
318            base::FundamentalValue(enable_kiosk_));
319        break;
320      }
321      case chrome::NOTIFICATION_KIOSK_ENABLED: {
322        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_ENABLED";
323        ASSERT_TRUE(enable_kiosk_);
324        quit_task_.Run();
325        break;
326      }
327      case chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED: {
328        LOG(INFO) << "chrome::NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED";
329        quit_task_.Run();
330        break;
331      }
332      default: {
333        NOTREACHED();
334        break;
335      }
336    }
337  }
338
339  bool enable_kiosk_;
340  DISALLOW_COPY_AND_ASSIGN(KioskEnableScenarioHandler);
341};
342
343class TestContentBrowserClient : public chrome::ChromeContentBrowserClient {
344 public:
345  enum LaunchEventSequence {
346    KioskAppLaunch,
347    AutostartWarningCanceled,
348    AutostartWarningConfirmed,
349    KioskEnableRejected,
350    KioskEnableConfirmed,
351  };
352
353  explicit TestContentBrowserClient(LaunchEventSequence sequence)
354      : browser_main_extra_parts_(NULL), sequence_(sequence) {
355  }
356
357  virtual ~TestContentBrowserClient() {}
358
359  virtual content::BrowserMainParts* CreateBrowserMainParts(
360      const content::MainFunctionParams& parameters) OVERRIDE {
361    ChromeBrowserMainParts* main_parts = static_cast<ChromeBrowserMainParts*>(
362        ChromeContentBrowserClient::CreateBrowserMainParts(parameters));
363
364    switch (sequence_) {
365      case KioskAppLaunch:
366        browser_main_extra_parts_ = new KioskAppLaunchScenarioHandler();
367        break;
368      case AutostartWarningCanceled:
369        browser_main_extra_parts_ = new AutostartWarningCancelScenarioHandler();
370        break;
371      case AutostartWarningConfirmed:
372        browser_main_extra_parts_ =
373            new AutostartWarningConfirmScenarioHandler();
374        break;
375      case KioskEnableRejected:
376        browser_main_extra_parts_ =
377            new KioskEnableScenarioHandler(false);
378        break;
379      case KioskEnableConfirmed:
380        browser_main_extra_parts_ =
381            new KioskEnableScenarioHandler(true);
382        break;
383    }
384
385    main_parts->AddParts(browser_main_extra_parts_);
386    return main_parts;
387  }
388
389  TestBrowserMainExtraParts* browser_main_extra_parts_;
390
391 private:
392  LaunchEventSequence sequence_;
393
394  DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient);
395};
396
397}  // namespace
398
399
400class KioskTest : public chromeos::CrosInProcessBrowserTest,
401                  // Param defining is multi-profiles enabled.
402                  public testing::WithParamInterface<bool> {
403 public:
404  KioskTest()
405     : chromeos::CrosInProcessBrowserTest(),
406       original_content_browser_client_(NULL),
407       test_server_(NULL) {
408    set_exit_when_last_browser_closes(false);
409  }
410
411  virtual ~KioskTest() {}
412
413 protected:
414  virtual void InitializeKioskTest() = 0;
415
416  virtual void SetUpOnMainThread() OVERRIDE {
417    test_server_ = new EmbeddedTestServer(
418        content::BrowserThread::GetMessageLoopProxyForThread(
419            content::BrowserThread::IO));
420    CHECK(test_server_->InitializeAndWaitUntilReady());
421    test_server_->RegisterRequestHandler(
422        base::Bind(&KioskTest::HandleRequest, base::Unretained(this)));
423    LOG(INFO) << "Set up http server at " << test_server_->base_url();
424
425    const GURL gaia_url("http://localhost:" + test_server_->base_url().port());
426    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
427        ::switches::kGaiaUrl, gaia_url.spec());
428  }
429
430  virtual void CleanUpOnMainThread() OVERRIDE {
431    // Clean up while main thread still runs.
432    // See http://crbug.com/176659.
433    KioskAppManager::Get()->CleanUp();
434
435    LOG(INFO) << "Stopping the http server.";
436    EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete());
437    delete test_server_;  // Destructor wants UI thread.
438  }
439
440  scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
441    GURL url = test_server_->GetURL(request.relative_url);
442    LOG(INFO) << "Http request: " << url.spec();
443
444    scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse());
445    if (url.path() == "/ServiceLogin") {
446      http_response->set_code(net::HTTP_OK);
447      http_response->set_content(service_login_response_);
448      http_response->set_content_type("text/html");
449    } else if (url.path() == "/ServiceLoginAuth") {
450      LOG(INFO) << "Params: " << request.content;
451      static const char kContinueParam[] = "continue=";
452      int continue_arg_begin = request.content.find(kContinueParam) +
453          arraysize(kContinueParam) - 1;
454      int continue_arg_end = request.content.find("&", continue_arg_begin);
455      const std::string continue_url = request.content.substr(
456          continue_arg_begin, continue_arg_end - continue_arg_begin);
457      http_response->set_code(net::HTTP_OK);
458      const std::string redirect_js =
459          "document.location.href = unescape('" + continue_url + "');";
460      http_response->set_content(
461          "<HTML><HEAD><SCRIPT>\n" + redirect_js + "\n</SCRIPT></HEAD></HTML>");
462      http_response->set_content_type("text/html");
463    } else {
464      LOG(ERROR) << "Unsupported url: " << url.path();
465    }
466    return http_response.PassAs<HttpResponse>();
467  }
468
469  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
470    if (GetParam()) {
471      command_line->AppendSwitch(::switches::kMultiProfiles);
472    }
473    command_line->AppendSwitch(chromeos::switches::kLoginManager);
474    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
475    command_line->AppendSwitch(
476        chromeos::switches::kDisableChromeCaptivePortalDetector);
477    command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
478    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
479
480    ASSERT_TRUE(test_server()->Start());
481    net::HostPortPair host_port = test_server()->host_port_pair();
482    std::string test_gallery_url = base::StringPrintf(
483        "http://%s:%d/files/chromeos/app_mode/webstore",
484        kWebstoreDomain, host_port.port());
485    command_line->AppendSwitchASCII(
486        ::switches::kAppsGalleryURL, test_gallery_url);
487
488    std::string test_gallery_download_url = test_gallery_url;
489    test_gallery_download_url.append("/downloads/%s.crx");
490    command_line->AppendSwitchASCII(
491        ::switches::kAppsGalleryDownloadURL, test_gallery_download_url);
492  }
493
494  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
495    InitializeKioskTest();
496    original_content_browser_client_ = content::SetBrowserClientForTesting(
497        content_browser_client_.get());
498
499    base::FilePath test_data_dir;
500    PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
501    CHECK(file_util::ReadFileToString(test_data_dir.Append(kServiceLogin),
502                                      &service_login_response_));
503
504    host_resolver()->AddRule(kWebstoreDomain, "127.0.0.1");
505  }
506
507  void ReloadKioskApps() {
508    KioskAppManager::Get()->AddApp(kTestKioskApp);
509  }
510
511  void ReloadAutolaunchKioskApps() {
512    KioskAppManager::Get()->AddApp(kTestKioskApp);
513    KioskAppManager::Get()->SetAutoLaunchApp(kTestKioskApp);
514  }
515
516  void EnableConsumerKioskMode() {
517    scoped_ptr<bool> locked(new bool(false));
518    scoped_refptr<content::MessageLoopRunner> runner =
519        new content::MessageLoopRunner;
520    KioskAppManager::Get()->EnableConsumerModeKiosk(
521        base::Bind(&ConsumerKioskModeLockCheck,
522                   locked.get(),
523                   runner->QuitClosure()));
524    runner->Run();
525    EXPECT_TRUE(*locked.get());
526  }
527
528  scoped_ptr<TestContentBrowserClient> content_browser_client_;
529  content::ContentBrowserClient* original_content_browser_client_;
530  std::string service_login_response_;
531  EmbeddedTestServer* test_server_;  // cant use scoped_ptr because destructor
532                                     // needs UI thread.
533 };
534
535class KioskLaunchTest : public KioskTest {
536 public:
537  KioskLaunchTest() : KioskTest() {}
538  virtual ~KioskLaunchTest() {}
539
540  // KioskTest overrides.
541  virtual void InitializeKioskTest() OVERRIDE {
542    content_browser_client_.reset(
543        new TestContentBrowserClient(TestContentBrowserClient::KioskAppLaunch));
544  }
545};
546
547IN_PROC_BROWSER_TEST_P(KioskLaunchTest, InstallAndLaunchApp) {
548  EnableConsumerKioskMode();
549  // Start UI, find menu entry for this app and launch it.
550  chromeos::WizardController::SkipPostLoginScreensForTesting();
551  chromeos::WizardController* wizard_controller =
552      chromeos::WizardController::default_controller();
553  CHECK(wizard_controller);
554  wizard_controller->SkipToLoginForTesting();
555
556  ReloadKioskApps();
557
558  // The first loop exits after we receive NOTIFICATION_KIOSK_APP_LAUNCHED
559  // notification - right at app launch.
560  scoped_refptr<content::MessageLoopRunner> runner =
561      new content::MessageLoopRunner;
562  content_browser_client_->browser_main_extra_parts_->set_quit_task(
563      runner->QuitClosure());
564  runner->Run();
565
566  // Check installer status.
567  EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
568            chromeos::KioskAppLaunchError::Get());
569
570  // Check if the kiosk webapp is really installed for the default profile.
571  ASSERT_TRUE(ProfileManager::GetDefaultProfile());
572  const extensions::Extension* app =
573      extensions::ExtensionSystem::Get(ProfileManager::GetDefaultProfile())->
574      extension_service()->GetInstalledExtension(kTestKioskApp);
575  EXPECT_TRUE(app);
576
577  // The second loop exits when kiosk app terminates and we receive
578  // NOTIFICATION_RENDERER_PROCESS_CLOSED.
579  scoped_refptr<content::MessageLoopRunner> runner2 =
580      new content::MessageLoopRunner;
581  content_browser_client_->browser_main_extra_parts_->set_quit_task(
582      runner2->QuitClosure());
583  runner2->Run();
584}
585
586class KioskAutolaunchCancelTest : public KioskTest {
587 public:
588  KioskAutolaunchCancelTest() : KioskTest(), login_display_host_(NULL) {}
589  virtual ~KioskAutolaunchCancelTest() {}
590
591 private:
592  // Overrides from KioskTest.
593  virtual void InitializeKioskTest() OVERRIDE {
594    content_browser_client_.reset(new TestContentBrowserClient(
595            TestContentBrowserClient::AutostartWarningCanceled));
596  }
597
598  virtual void SetUpOnMainThread() OVERRIDE {
599    login_display_host_ = LoginDisplayHostImpl::default_host();
600    KioskTest::SetUpOnMainThread();
601  }
602
603  virtual void CleanUpOnMainThread() OVERRIDE {
604    // LoginDisplayHost owns controllers and all windows.
605    base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE,
606                                                  login_display_host_);
607    KioskTest::CleanUpOnMainThread();
608  }
609
610  LoginDisplayHost* login_display_host_;
611};
612
613IN_PROC_BROWSER_TEST_P(KioskAutolaunchCancelTest, AutolaunchWarningCancel) {
614  EnableConsumerKioskMode();
615  // Start UI, find menu entry for this app and launch it.
616  chromeos::WizardController::SkipPostLoginScreensForTesting();
617  chromeos::WizardController* wizard_controller =
618      chromeos::WizardController::default_controller();
619  CHECK(wizard_controller);
620  ReloadAutolaunchKioskApps();
621  wizard_controller->SkipToLoginForTesting();
622
623  EXPECT_FALSE(
624      KioskAppManager::Get()->GetAutoLaunchApp().empty());
625  EXPECT_FALSE(
626      KioskAppManager::Get()->IsAutoLaunchEnabled());
627
628  // The loop exits after we receive
629  // NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_COMPLETED after
630  // NOTIFICATION_KIOSK_AUTOLAUNCH_WARNING_VISIBLE notification - right after
631  // auto launch is canceled.
632  scoped_refptr<content::MessageLoopRunner> runner =
633      new content::MessageLoopRunner;
634  content_browser_client_->browser_main_extra_parts_->set_quit_task(
635      runner->QuitClosure());
636  runner->Run();
637
638  EXPECT_FALSE(
639      KioskAppManager::Get()->IsAutoLaunchEnabled());
640}
641
642class KioskAutolaunchConfirmTest : public KioskTest {
643 public:
644  KioskAutolaunchConfirmTest() : KioskTest() {}
645  virtual ~KioskAutolaunchConfirmTest() {}
646
647 private:
648  // Overrides from KioskTest.
649  virtual void InitializeKioskTest() OVERRIDE {
650    content_browser_client_.reset(new TestContentBrowserClient(
651            TestContentBrowserClient::AutostartWarningConfirmed));
652  }
653};
654
655IN_PROC_BROWSER_TEST_P(KioskAutolaunchConfirmTest, AutolaunchWarningConfirm) {
656  EnableConsumerKioskMode();
657  // Start UI, find menu entry for this app and launch it.
658  chromeos::WizardController::SkipPostLoginScreensForTesting();
659  chromeos::WizardController* wizard_controller =
660      chromeos::WizardController::default_controller();
661  CHECK(wizard_controller);
662  wizard_controller->SkipToLoginForTesting();
663
664  ReloadAutolaunchKioskApps();
665  EXPECT_FALSE(
666      KioskAppManager::Get()->GetAutoLaunchApp().empty());
667  EXPECT_FALSE(
668      KioskAppManager::Get()->IsAutoLaunchEnabled());
669
670  // The loop exits after we receive NOTIFICATION_KIOSK_APP_LAUNCHED
671  // notification - right at app launch.
672  scoped_refptr<content::MessageLoopRunner> runner =
673      new content::MessageLoopRunner;
674  content_browser_client_->browser_main_extra_parts_->set_quit_task(
675      runner->QuitClosure());
676  runner->Run();
677
678  EXPECT_FALSE(
679      KioskAppManager::Get()->GetAutoLaunchApp().empty());
680  EXPECT_TRUE(
681      KioskAppManager::Get()->IsAutoLaunchEnabled());
682
683  // Check installer status.
684  EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
685            chromeos::KioskAppLaunchError::Get());
686
687  // Check if the kiosk webapp is really installed for the default profile.
688  ASSERT_TRUE(ProfileManager::GetDefaultProfile());
689  const extensions::Extension* app =
690      extensions::ExtensionSystem::Get(ProfileManager::GetDefaultProfile())->
691      extension_service()->GetInstalledExtension(kTestKioskApp);
692  EXPECT_TRUE(app);
693
694  // The second loop exits when kiosk app terminates and we receive
695  // NOTIFICATION_RENDERER_PROCESS_CLOSED.
696  scoped_refptr<content::MessageLoopRunner> runner2 =
697      new content::MessageLoopRunner;
698  content_browser_client_->browser_main_extra_parts_->set_quit_task(
699      runner2->QuitClosure());
700  runner2->Run();
701}
702
703class KioskEnableTest : public KioskTest {
704 public:
705  KioskEnableTest() : login_display_host_(NULL) {}
706  virtual ~KioskEnableTest() {}
707
708 private:
709  // Overrides from KioskTest.
710  virtual void SetUpOnMainThread() OVERRIDE {
711    login_display_host_ = LoginDisplayHostImpl::default_host();
712    KioskTest::SetUpOnMainThread();
713  }
714
715  virtual void CleanUpOnMainThread() OVERRIDE {
716    // LoginDisplayHost owns controllers and all windows.
717    base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE,
718                                                  login_display_host_);
719    KioskTest::CleanUpOnMainThread();
720  }
721
722  LoginDisplayHost* login_display_host_;
723};
724
725class KioskEnableCancelTest : public KioskEnableTest {
726 public:
727  KioskEnableCancelTest() {}
728  virtual ~KioskEnableCancelTest() {}
729
730 private:
731  // Overrides from KioskTest.
732  virtual void InitializeKioskTest() OVERRIDE {
733    content_browser_client_.reset(new TestContentBrowserClient(
734            TestContentBrowserClient::KioskEnableRejected));
735  }
736};
737
738IN_PROC_BROWSER_TEST_P(KioskEnableCancelTest, KioskEnableCancel) {
739  // Start UI, find menu entry for this app and launch it.
740  chromeos::WizardController::SkipPostLoginScreensForTesting();
741  chromeos::WizardController* wizard_controller =
742      chromeos::WizardController::default_controller();
743  CHECK(wizard_controller);
744
745  scoped_refptr<content::MessageLoopRunner> runner =
746      new content::MessageLoopRunner;
747  // Check the intial state of the consumer kiosk.
748  scoped_ptr<KioskAppManager::ConsumerKioskModeStatus> status(
749      new KioskAppManager::ConsumerKioskModeStatus(
750          KioskAppManager::CONSUMER_KIOSK_MODE_DISABLED));
751  KioskAppManager::Get()->GetConsumerKioskModeStatus(
752      base::Bind(&ConsumerKioskModeStatusCheck,
753                 status.get(),
754                 runner->QuitClosure()));
755  runner->Run();
756  EXPECT_EQ(*status.get(),  KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE);
757
758  wizard_controller->SkipToLoginForTesting();
759  // The loop exits after we receive
760  // NOTIFICATION_KIOSK_ENABLE_WARNING_COMPLETED after
761  // NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE notification - right after
762  // enable consumer kiosk screen is canceled.
763  scoped_refptr<content::MessageLoopRunner> runner2 =
764      new content::MessageLoopRunner;
765  content_browser_client_->browser_main_extra_parts_->set_quit_task(
766      runner2->QuitClosure());
767  runner2->Run();
768
769  scoped_refptr<content::MessageLoopRunner> runner3 =
770      new content::MessageLoopRunner;
771  // Check the end state of the consumer kiosk after disabling the feature.
772  KioskAppManager::Get()->GetConsumerKioskModeStatus(
773      base::Bind(&ConsumerKioskModeStatusCheck,
774                 status.get(),
775                 runner3->QuitClosure()));
776  runner3->Run();
777  EXPECT_EQ(*status.get(),  KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE);
778}
779
780
781class KioskEnableConfirmedTest : public KioskEnableTest {
782 public:
783  KioskEnableConfirmedTest() {}
784  virtual ~KioskEnableConfirmedTest() {}
785
786 private:
787  // Overrides from KioskTest.
788  virtual void InitializeKioskTest() OVERRIDE {
789    content_browser_client_.reset(new TestContentBrowserClient(
790            TestContentBrowserClient::KioskEnableConfirmed));
791  }
792};
793
794IN_PROC_BROWSER_TEST_P(KioskEnableConfirmedTest, KioskEnableConfirmed) {
795  // Start UI, find menu entry for this app and launch it.
796  chromeos::WizardController::SkipPostLoginScreensForTesting();
797  chromeos::WizardController* wizard_controller =
798      chromeos::WizardController::default_controller();
799  CHECK(wizard_controller);
800
801  scoped_refptr<content::MessageLoopRunner> runner =
802      new content::MessageLoopRunner;
803  // Check the intial state of the consumer kiosk.
804  scoped_ptr<KioskAppManager::ConsumerKioskModeStatus> status(
805      new KioskAppManager::ConsumerKioskModeStatus(
806          KioskAppManager::CONSUMER_KIOSK_MODE_DISABLED));
807  KioskAppManager::Get()->GetConsumerKioskModeStatus(
808      base::Bind(&ConsumerKioskModeStatusCheck,
809                 status.get(),
810                 runner->QuitClosure()));
811  runner->Run();
812  EXPECT_EQ(*status.get(),  KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE);
813
814  wizard_controller->SkipToLoginForTesting();
815  // The loop exits after we receive
816  // NOTIFICATION_KIOSK_ENABLED after
817  // NOTIFICATION_KIOSK_ENABLE_WARNING_VISIBLE notification - right after
818  // enable consumer kiosk screen is canceled.
819  scoped_refptr<content::MessageLoopRunner> runner2 =
820      new content::MessageLoopRunner;
821  content_browser_client_->browser_main_extra_parts_->set_quit_task(
822      runner2->QuitClosure());
823  runner2->Run();
824
825  scoped_refptr<content::MessageLoopRunner> runner3 =
826      new content::MessageLoopRunner;
827  // Check the end state of the consumer kiosk after disabling the feature.
828  KioskAppManager::Get()->GetConsumerKioskModeStatus(
829      base::Bind(&ConsumerKioskModeStatusCheck,
830                 status.get(),
831                 runner3->QuitClosure()));
832  runner3->Run();
833  EXPECT_EQ(*status.get(),  KioskAppManager::CONSUMER_KIOSK_MODE_ENABLED);
834}
835
836INSTANTIATE_TEST_CASE_P(KioskLaunchTestInstantiation,
837                        KioskLaunchTest,
838                        testing::Bool());
839
840INSTANTIATE_TEST_CASE_P(KioskAutolaunchCancelTestInstantiation,
841                        KioskAutolaunchCancelTest,
842                        testing::Bool());
843
844INSTANTIATE_TEST_CASE_P(KioskAutolaunchConfirmTestInstantiation,
845                        KioskAutolaunchConfirmTest,
846                        testing::Bool());
847
848INSTANTIATE_TEST_CASE_P(KioskEnableCancelTestInstantiation,
849                        KioskEnableCancelTest,
850                        testing::Bool());
851
852INSTANTIATE_TEST_CASE_P(KioskEnableConfirmedTestInstantiation,
853                        KioskEnableConfirmedTest,
854                        testing::Bool());
855
856}  // namespace chromeos
857