oobe_browsertest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 "chrome/browser/chrome_browser_main.h"
8#include "chrome/browser/chrome_browser_main_extra_parts.h"
9#include "chrome/browser/chrome_content_browser_client.h"
10#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
11#include "chrome/browser/chromeos/login/existing_user_controller.h"
12#include "chrome/browser/chromeos/login/webui_login_display.h"
13#include "chrome/browser/chromeos/login/wizard_controller.h"
14#include "chrome/browser/google_apis/test_server/http_request.h"
15#include "chrome/browser/google_apis/test_server/http_response.h"
16#include "chrome/browser/google_apis/test_server/http_server.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/common/chrome_notification_types.h"
19#include "chrome/common/chrome_paths.h"
20#include "chrome/common/chrome_switches.h"
21#include "chrome/test/base/in_process_browser_test.h"
22#include "chrome/test/base/interactive_test_utils.h"
23#include "chrome/test/base/ui_test_utils.h"
24#include "chromeos/chromeos_switches.h"
25#include "content/public/browser/notification_observer.h"
26#include "content/public/browser/notification_registrar.h"
27#include "content/public/browser/notification_service.h"
28#include "content/public/test/test_utils.h"
29#include "google_apis/gaia/gaia_switches.h"
30#include "testing/gmock/include/gmock/gmock.h"
31#include "testing/gtest/include/gtest/gtest.h"
32
33using namespace google_apis;
34using namespace google_apis::test_server;
35
36namespace {
37
38// Used to add an observer to NotificationService after it's created.
39class TestBrowserMainExtraParts
40    : public ChromeBrowserMainExtraParts,
41      public content::NotificationObserver {
42 public:
43  TestBrowserMainExtraParts()
44      : webui_visible_(false),
45        browsing_data_removed_(false),
46        signin_screen_shown_(false) {}
47  virtual ~TestBrowserMainExtraParts() {}
48
49  // ChromeBrowserMainExtraParts implementation.
50  virtual void PreEarlyInitialization() OVERRIDE {
51    registrar_.Add(this, chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE,
52                   content::NotificationService::AllSources());
53    registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED,
54                   content::NotificationService::AllSources());
55    registrar_.Add(this, chrome::NOTIFICATION_BROWSING_DATA_REMOVED,
56                   content::NotificationService::AllSources());
57  }
58
59  void set_quit_task(const base::Closure& quit_task) { quit_task_ = quit_task; }
60  void set_gaia_url(const std::string& url) { gaia_url_ = url; }
61
62 private:
63  // Overridden from content::NotificationObserver:
64  virtual void Observe(int type,
65                       const content::NotificationSource& source,
66                       const content::NotificationDetails& details) OVERRIDE {
67    if (type == chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE) {
68      LOG(INFO) << "NOTIFICATION_LOGIN_WEBUI_VISIBLE";
69      webui_visible_ = true;
70      if (browsing_data_removed_ && !signin_screen_shown_) {
71        signin_screen_shown_ = true;
72        ShowSigninScreen();
73      }
74    } else if (type == chrome::NOTIFICATION_BROWSING_DATA_REMOVED) {
75      LOG(INFO) << "chrome::NOTIFICATION_BROWSING_DATA_REMOVED";
76      browsing_data_removed_ = true;
77      if (webui_visible_ && !signin_screen_shown_) {
78        signin_screen_shown_ = true;
79        ShowSigninScreen();
80      }
81    } else if (type == chrome::NOTIFICATION_SESSION_STARTED) {
82      LOG(INFO) << "chrome::NOTIFICATION_SESSION_STARTED";
83      quit_task_.Run();
84    } else {
85      NOTREACHED();
86    }
87  }
88
89  void ShowSigninScreen() {
90    chromeos::ExistingUserController* controller =
91        chromeos::ExistingUserController::current_controller();
92    CHECK(controller);
93    chromeos::WebUILoginDisplay* webui_login_display =
94        static_cast<chromeos::WebUILoginDisplay*>(
95            controller->login_display());
96    CHECK(webui_login_display);
97    webui_login_display->SetGaiaOriginForTesting(gaia_url_);
98    webui_login_display->ShowSigninScreenForCreds("username", "password");
99    // TODO(glotov): mock GAIA server (test_server_) should support
100    // username/password configuration.
101  }
102
103  bool webui_visible_, browsing_data_removed_, signin_screen_shown_;
104  content::NotificationRegistrar registrar_;
105  base::Closure quit_task_;
106  std::string gaia_url_;
107
108  DISALLOW_COPY_AND_ASSIGN(TestBrowserMainExtraParts);
109};
110
111class TestContentBrowserClient : public chrome::ChromeContentBrowserClient {
112 public:
113  TestContentBrowserClient() {}
114  virtual ~TestContentBrowserClient() {}
115
116  virtual content::BrowserMainParts* CreateBrowserMainParts(
117      const content::MainFunctionParams& parameters) OVERRIDE {
118    ChromeBrowserMainParts* main_parts = static_cast<ChromeBrowserMainParts*>(
119        ChromeContentBrowserClient::CreateBrowserMainParts(parameters));
120
121    browser_main_extra_parts_ = new TestBrowserMainExtraParts();
122    main_parts->AddParts(browser_main_extra_parts_);
123    return main_parts;
124  }
125
126  TestBrowserMainExtraParts* browser_main_extra_parts_;
127
128 private:
129  DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient);
130};
131
132const base::FilePath kServiceLogin("chromeos/service_login.html");
133
134class OobeTest : public chromeos::CrosInProcessBrowserTest {
135 protected:
136  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
137    command_line->AppendSwitch(chromeos::switches::kLoginManager);
138    command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
139    command_line->AppendSwitch(switches::kDisableChromeCaptivePortalDetector);
140    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
141    command_line->AppendSwitchASCII(switches::kAuthExtensionPath, "gaia_auth");
142  }
143
144  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
145    content_browser_client_.reset(new TestContentBrowserClient());
146    original_content_browser_client_ = content::SetBrowserClientForTesting(
147        content_browser_client_.get());
148    base::FilePath test_data_dir;
149    PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
150    CHECK(file_util::ReadFileToString(test_data_dir.Append(kServiceLogin),
151                                      &service_login_response_));
152  }
153
154  virtual void SetUpOnMainThread() OVERRIDE {
155    test_server_ = new HttpServer(
156        content::BrowserThread::GetMessageLoopProxyForThread(
157            content::BrowserThread::IO));
158    CHECK(test_server_->InitializeAndWaitUntilReady());
159    test_server_->RegisterRequestHandler(
160        base::Bind(&OobeTest::HandleRequest, base::Unretained(this)));
161    LOG(INFO) << "Set up http server at " << test_server_->base_url();
162    CHECK(test_server_->port() >= 8040 && test_server_->port() < 8045)
163        << "Current manifest_test.json for gaia_login restrictions "
164        << "does not allow this port";
165
166    const std::string gaia_url =
167        "http://localhost:" + test_server_->base_url().port();
168    content_browser_client_->browser_main_extra_parts_->set_gaia_url(gaia_url);
169  }
170
171  virtual void CleanUpOnMainThread() OVERRIDE {
172    LOG(INFO) << "Stopping the http server.";
173    EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete());
174    delete test_server_;  // Destructor wants UI thread.
175  }
176
177  scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
178    GURL url = test_server_->GetURL(request.relative_url);
179    LOG(INFO) << "Http request: " << url.spec();
180
181    scoped_ptr<HttpResponse> http_response(new HttpResponse());
182    if (url.path() == "/ServiceLogin") {
183      http_response->set_code(test_server::SUCCESS);
184      http_response->set_content(service_login_response_);
185      http_response->set_content_type("text/html");
186    } else if (url.path() == "/ServiceLoginAuth") {
187      LOG(INFO) << "Params: " << request.content;
188      static const char kContinueParam[] = "continue=";
189      int continue_arg_begin = request.content.find(kContinueParam) +
190          arraysize(kContinueParam) - 1;
191      int continue_arg_end = request.content.find("&", continue_arg_begin);
192      const std::string continue_url = request.content.substr(
193          continue_arg_begin, continue_arg_end - continue_arg_begin);
194      http_response->set_code(test_server::SUCCESS);
195      const std::string redirect_js =
196          "document.location.href = unescape('" + continue_url + "');";
197      http_response->set_content(
198          "<HTML><HEAD><SCRIPT>\n" + redirect_js + "\n</SCRIPT></HEAD></HTML>");
199      http_response->set_content_type("text/html");
200    } else {
201      NOTREACHED() << url.path();
202    }
203    return http_response.Pass();
204  }
205
206  scoped_ptr<TestContentBrowserClient> content_browser_client_;
207  content::ContentBrowserClient* original_content_browser_client_;
208  std::string service_login_response_;
209  HttpServer* test_server_;  // cant use scoped_ptr because destructor
210                             // needs UI thread.
211};
212
213IN_PROC_BROWSER_TEST_F(OobeTest, NewUser) {
214  chromeos::WizardController::SkipPostLoginScreensForTesting();
215  chromeos::WizardController* wizard_controller =
216      chromeos::WizardController::default_controller();
217  CHECK(wizard_controller);
218  wizard_controller->SkipToLoginForTesting();
219
220  scoped_refptr<content::MessageLoopRunner> runner =
221      new content::MessageLoopRunner;
222  content_browser_client_->browser_main_extra_parts_->set_quit_task(
223      runner->QuitClosure());
224  runner->Run();
225}
226
227}
228