kiosk_browsertest.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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                  // Param defining is multi-profiles enabled.
139                  public testing::WithParamInterface<bool> {
140 public:
141  KioskTest() : chromeos::CrosInProcessBrowserTest() {
142    SetExitWhenLastBrowserCloses(false);
143  }
144
145 protected:
146
147  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
148    if (GetParam()) {
149      command_line->AppendSwitch(::switches::kMultiProfiles);
150    }
151    command_line->AppendSwitch(chromeos::switches::kLoginManager);
152    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
153    command_line->AppendSwitch(
154        chromeos::switches::kDisableChromeCaptivePortalDetector);
155    command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
156    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
157
158    ASSERT_TRUE(test_server()->Start());
159    net::HostPortPair host_port = test_server()->host_port_pair();
160    std::string test_gallery_url = base::StringPrintf(
161        "http://%s:%d/files/chromeos/app_mode/webstore",
162        kWebstoreDomain, host_port.port());
163    command_line->AppendSwitchASCII(
164        ::switches::kAppsGalleryURL, test_gallery_url);
165
166    std::string test_gallery_download_url = test_gallery_url;
167    test_gallery_download_url.append("/downloads/%s.crx");
168    command_line->AppendSwitchASCII(
169        ::switches::kAppsGalleryDownloadURL, test_gallery_download_url);
170  }
171
172  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
173    content_browser_client_.reset(new TestContentBrowserClient());
174    original_content_browser_client_ = content::SetBrowserClientForTesting(
175        content_browser_client_.get());
176    host_resolver()->AddRule(kWebstoreDomain, "127.0.0.1");
177  }
178
179  virtual void CleanUpOnMainThread() OVERRIDE {
180    // Clean up while main thread still runs.
181    // See http://crbug.com/176659.
182    chromeos::KioskAppManager::Get()->CleanUp();
183  }
184
185  void ReloadKioskApps() {
186    chromeos::KioskAppManager::Get()->AddApp(kTestKioskApp);
187  }
188
189  scoped_ptr<TestContentBrowserClient> content_browser_client_;
190  content::ContentBrowserClient* original_content_browser_client_;
191  std::string service_login_response_;
192};
193
194IN_PROC_BROWSER_TEST_P(KioskTest, InstallAndLaunchApp) {
195  // Start UI, find menu entry for this app and launch it.
196  chromeos::WizardController::SkipPostLoginScreensForTesting();
197  chromeos::WizardController* wizard_controller =
198      chromeos::WizardController::default_controller();
199  CHECK(wizard_controller);
200  wizard_controller->SkipToLoginForTesting();
201
202  ReloadKioskApps();
203
204  // The first loop exits after we receive NOTIFICATION_KIOSK_APP_LAUNCHED
205  // notification - right at app launch.
206  scoped_refptr<content::MessageLoopRunner> runner =
207      new content::MessageLoopRunner;
208  content_browser_client_->browser_main_extra_parts_->set_quit_task(
209      runner->QuitClosure());
210  runner->Run();
211
212  // Check installer status.
213  EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
214            chromeos::KioskAppLaunchError::Get());
215
216  // Check if the kiosk webapp is really installed for the default profile.
217  ASSERT_TRUE(ProfileManager::GetDefaultProfile());
218  const extensions::Extension* app =
219      extensions::ExtensionSystem::Get(ProfileManager::GetDefaultProfile())->
220      extension_service()->GetInstalledExtension(kTestKioskApp);
221  EXPECT_TRUE(app);
222
223  // The second loop exits when kiosk app terminates and we receive
224  // NOTIFICATION_RENDERER_PROCESS_CLOSED.
225  scoped_refptr<content::MessageLoopRunner> runner2 =
226      new content::MessageLoopRunner;
227  content_browser_client_->browser_main_extra_parts_->set_quit_task(
228      runner2->QuitClosure());
229  runner2->Run();
230}
231
232INSTANTIATE_TEST_CASE_P(KioskTestInstantiation, KioskTest, testing::Bool());
233
234}  // namespace chromeos
235