kiosk_browsertest.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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/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";
54
55// Webstore data json is in
56//   chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
57//       detail/ggbflgnkafappblpkiflbgpmkfdpnhhe
58const char kTestKioskApp[] = "ggbflgnkafappblpkiflbgpmkfdpnhhe";
59
60// Used to add an observer to NotificationService after it's created.
61class TestBrowserMainExtraParts
62    : public ChromeBrowserMainExtraParts,
63      public content::NotificationObserver {
64 public:
65  TestBrowserMainExtraParts() {}
66
67  virtual ~TestBrowserMainExtraParts() {}
68
69  // ChromeBrowserMainExtraParts implementation.
70  virtual void PreEarlyInitialization() OVERRIDE {
71    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
72                   content::NotificationService::AllSources());
73    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APPS_LOADED,
74                   content::NotificationService::AllSources());
75    registrar_.Add(this, chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
76                   content::NotificationService::AllSources());
77  }
78
79  void set_quit_task(const base::Closure& quit_task) { quit_task_ = quit_task; }
80
81 private:
82  // Overridden from content::NotificationObserver:
83  virtual void Observe(int type,
84                       const content::NotificationSource& source,
85                       const content::NotificationDetails& details) OVERRIDE {
86    if (type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE) {
87      LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
88    } else if (type == chrome::NOTIFICATION_KIOSK_APPS_LOADED) {
89      LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APPS_LOADED";
90      content::WebUI* web_ui = static_cast<chromeos::LoginDisplayHostImpl*>(
91          chromeos::LoginDisplayHostImpl::default_host())->
92              GetOobeUI()->web_ui();
93      web_ui->CallJavascriptFunction("login.AppsMenuButton.runAppForTesting",
94                                     base::StringValue(kTestKioskApp));
95    } else if (type == chrome::NOTIFICATION_KIOSK_APP_LAUNCHED) {
96      LOG(INFO) << "chrome::NOTIFICATION_KIOSK_APP_LAUNCHED";
97      registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
98                     content::NotificationService::AllSources());
99      quit_task_.Run();
100    } else if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED) {
101      LOG(INFO) << "content::NOTIFICATION_RENDERER_PROCESS_CLOSED";
102      quit_task_.Run();
103    } else {
104      NOTREACHED();
105    }
106  }
107
108  content::NotificationRegistrar registrar_;
109  base::Closure quit_task_;
110
111  DISALLOW_COPY_AND_ASSIGN(TestBrowserMainExtraParts);
112};
113
114class TestContentBrowserClient : public chrome::ChromeContentBrowserClient {
115 public:
116  TestContentBrowserClient() {}
117  virtual ~TestContentBrowserClient() {}
118
119  virtual content::BrowserMainParts* CreateBrowserMainParts(
120      const content::MainFunctionParams& parameters) OVERRIDE {
121    ChromeBrowserMainParts* main_parts = static_cast<ChromeBrowserMainParts*>(
122        ChromeContentBrowserClient::CreateBrowserMainParts(parameters));
123
124    browser_main_extra_parts_ = new TestBrowserMainExtraParts();
125    main_parts->AddParts(browser_main_extra_parts_);
126    return main_parts;
127  }
128
129  TestBrowserMainExtraParts* browser_main_extra_parts_;
130
131 private:
132  DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient);
133};
134
135}  // namespace
136
137class KioskTest : public chromeos::CrosInProcessBrowserTest {
138 public:
139  KioskTest() : chromeos::CrosInProcessBrowserTest() {
140    SetExitWhenLastBrowserCloses(false);
141  }
142
143 protected:
144
145  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
146    command_line->AppendSwitch(chromeos::switches::kLoginManager);
147    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
148    command_line->AppendSwitch(
149        chromeos::switches::kDisableChromeCaptivePortalDetector);
150    command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
151    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
152
153    ASSERT_TRUE(test_server()->Start());
154    net::HostPortPair host_port = test_server()->host_port_pair();
155    std::string test_gallery_url = base::StringPrintf(
156        "http://%s:%d/files/chromeos/app_mode/webstore",
157        kWebstoreDomain, host_port.port());
158    command_line->AppendSwitchASCII(
159        ::switches::kAppsGalleryURL, test_gallery_url);
160
161    std::string test_gallery_download_url = test_gallery_url;
162    test_gallery_download_url.append("/downloads/%s.crx");
163    command_line->AppendSwitchASCII(
164        ::switches::kAppsGalleryDownloadURL, test_gallery_download_url);
165  }
166
167  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
168    content_browser_client_.reset(new TestContentBrowserClient());
169    original_content_browser_client_ = content::SetBrowserClientForTesting(
170        content_browser_client_.get());
171    host_resolver()->AddRule(kWebstoreDomain, "127.0.0.1");
172  }
173
174  virtual void CleanUpOnMainThread() OVERRIDE {
175    // Clean up while main thread still runs.
176    // See http://crbug.com/176659.
177    chromeos::KioskAppManager::Get()->CleanUp();
178  }
179
180  void ReloadKioskApps() {
181    chromeos::KioskAppManager::Get()->AddApp(kTestKioskApp);
182  }
183
184  scoped_ptr<TestContentBrowserClient> content_browser_client_;
185  content::ContentBrowserClient* original_content_browser_client_;
186  std::string service_login_response_;
187};
188
189IN_PROC_BROWSER_TEST_F(KioskTest, InstallAndLaunchApp) {
190  // Start UI, find menu entry for this app and launch it.
191  chromeos::WizardController::SkipPostLoginScreensForTesting();
192  chromeos::WizardController* wizard_controller =
193      chromeos::WizardController::default_controller();
194  CHECK(wizard_controller);
195  wizard_controller->SkipToLoginForTesting();
196
197  ReloadKioskApps();
198
199  // The first loop exits after we receive NOTIFICATION_KIOSK_APP_LAUNCHED
200  // notification - right at app launch.
201  scoped_refptr<content::MessageLoopRunner> runner =
202      new content::MessageLoopRunner;
203  content_browser_client_->browser_main_extra_parts_->set_quit_task(
204      runner->QuitClosure());
205  runner->Run();
206
207  // Check installer status.
208  EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
209            chromeos::KioskAppLaunchError::Get());
210
211  // Check if the kiosk webapp is really installed for the default profile.
212  ASSERT_TRUE(ProfileManager::GetDefaultProfile());
213  const extensions::Extension* app =
214      extensions::ExtensionSystem::Get(ProfileManager::GetDefaultProfile())->
215      extension_service()->GetInstalledExtension(kTestKioskApp);
216  EXPECT_TRUE(app);
217
218  // The second loop exits when kiosk app terminates and we receive
219  // NOTIFICATION_RENDERER_PROCESS_CLOSED.
220  scoped_refptr<content::MessageLoopRunner> runner2 =
221      new content::MessageLoopRunner;
222  content_browser_client_->browser_main_extra_parts_->set_quit_task(
223      runner2->QuitClosure());
224  runner2->Run();
225}
226
227}  // namespace chromeos
228