Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / blocking_login_browsertest.cc
1 // Copyright 2014 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 <string>
6 #include <vector>
7
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/run_loop.h"
11 #include "base/stl_util.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/chromeos/login/existing_user_controller.h"
15 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
16 #include "chrome/browser/chromeos/login/wizard_controller.h"
17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
18 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
19 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chromeos/chromeos_switches.h"
23 #include "components/policy/core/common/cloud/device_management_service.h"
24 #include "components/policy/core/common/policy_switches.h"
25 #include "components/user_manager/user_manager.h"
26 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/test/test_utils.h"
30 #include "google_apis/gaia/fake_gaia.h"
31 #include "google_apis/gaia/gaia_switches.h"
32 #include "google_apis/gaia/gaia_urls.h"
33 #include "net/http/http_status_code.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "net/test/embedded_test_server/http_request.h"
36 #include "net/test/embedded_test_server/http_response.h"
37 #include "policy/proto/device_management_backend.pb.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 namespace chromeos {
41
42 namespace {
43
44 namespace em = enterprise_management;
45
46 const char kDomain[] = "domain.com";
47 const char kUsername[] = "user@domain.com";
48 const char kUsernameOtherDomain[] = "user@other.com";
49
50 const char kOAuthCodeCookie[] = "oauth_code=1234; Secure; HttpOnly";
51
52 const char kOAuth2TokenPairData[] =
53     "{"
54     "  \"refresh_token\": \"1234\","
55     "  \"access_token\": \"5678\","
56     "  \"expires_in\": 3600"
57     "}";
58
59 const char kOAuth2AccessTokenData[] =
60     "{"
61     "  \"access_token\": \"5678\","
62     "  \"expires_in\": 3600"
63     "}";
64
65 const char kDMRegisterRequest[] = "/device_management?request=register";
66 const char kDMPolicyRequest[] = "/device_management?request=policy";
67
68 void CopyLockResult(base::RunLoop* loop,
69                     policy::EnterpriseInstallAttributes::LockResult* out,
70                     policy::EnterpriseInstallAttributes::LockResult result) {
71   *out = result;
72   loop->Quit();
73 }
74
75 }  // namespace
76
77 struct BlockingLoginTestParam {
78   const int steps;
79   const char* username;
80   const bool enroll_device;
81 };
82
83 class BlockingLoginTest
84     : public InProcessBrowserTest,
85       public content::NotificationObserver,
86       public testing::WithParamInterface<BlockingLoginTestParam> {
87  public:
88   BlockingLoginTest() : profile_added_(NULL) {}
89
90   virtual void SetUpCommandLine(CommandLine* command_line) override {
91     // Initialize the test server early, so that we can use its base url for
92     // the command line flags.
93     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
94
95     // Use the login manager screens and the gaia auth extension.
96     command_line->AppendSwitch(switches::kLoginManager);
97     command_line->AppendSwitch(switches::kForceLoginManagerInTests);
98     command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
99     command_line->AppendSwitchASCII(::switches::kAuthExtensionPath,
100                                     "gaia_auth");
101
102     // Redirect requests to gaia and the policy server to the test server.
103     command_line->AppendSwitchASCII(::switches::kGaiaUrl,
104                                     embedded_test_server()->base_url().spec());
105     command_line->AppendSwitchASCII(::switches::kLsoUrl,
106                                     embedded_test_server()->base_url().spec());
107     command_line->AppendSwitchASCII(
108         policy::switches::kDeviceManagementUrl,
109         embedded_test_server()->GetURL("/device_management").spec());
110   }
111
112   virtual void SetUpOnMainThread() override {
113     fake_gaia_.Initialize();
114
115     embedded_test_server()->RegisterRequestHandler(
116         base::Bind(&BlockingLoginTest::HandleRequest, base::Unretained(this)));
117     embedded_test_server()->RegisterRequestHandler(
118         base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_)));
119
120     registrar_.Add(this,
121                    chrome::NOTIFICATION_PROFILE_ADDED,
122                    content::NotificationService::AllSources());
123   }
124
125   virtual void TearDownOnMainThread() override {
126     RunUntilIdle();
127     EXPECT_TRUE(responses_.empty());
128     STLDeleteElements(&responses_);
129     EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
130   }
131
132   virtual void Observe(int type,
133                        const content::NotificationSource& source,
134                        const content::NotificationDetails& details) override {
135     ASSERT_EQ(chrome::NOTIFICATION_PROFILE_ADDED, type);
136     ASSERT_FALSE(profile_added_);
137     profile_added_ = content::Source<Profile>(source).ptr();
138   }
139
140   void RunUntilIdle() {
141     base::RunLoop().RunUntilIdle();
142   }
143
144   policy::BrowserPolicyConnectorChromeOS* browser_policy_connector() {
145     return g_browser_process->platform_part()
146         ->browser_policy_connector_chromeos();
147   }
148
149   void SkipToSigninScreen() {
150     WizardController::SkipPostLoginScreensForTesting();
151     WizardController* wizard_controller =
152         WizardController::default_controller();
153     ASSERT_TRUE(wizard_controller);
154     wizard_controller->SkipToLoginForTesting(LoginScreenContext());
155
156     content::WindowedNotificationObserver(
157         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
158         content::NotificationService::AllSources()).Wait();
159     RunUntilIdle();
160   }
161
162   void EnrollDevice(const std::string& username) {
163     base::RunLoop loop;
164     policy::EnterpriseInstallAttributes::LockResult result;
165     browser_policy_connector()->GetInstallAttributes()->LockDevice(
166         username, policy::DEVICE_MODE_ENTERPRISE, "100200300",
167         base::Bind(&CopyLockResult, &loop, &result));
168     loop.Run();
169     EXPECT_EQ(policy::EnterpriseInstallAttributes::LOCK_SUCCESS, result);
170     RunUntilIdle();
171   }
172
173   void Login(const std::string& username) {
174     content::WindowedNotificationObserver session_started_observer(
175         chrome::NOTIFICATION_SESSION_STARTED,
176         content::NotificationService::AllSources());
177
178     ExistingUserController* controller =
179         ExistingUserController::current_controller();
180     ASSERT_TRUE(controller);
181     WebUILoginDisplay* login_display =
182         static_cast<WebUILoginDisplay*>(controller->login_display());
183     ASSERT_TRUE(login_display);
184
185     login_display->ShowSigninScreenForCreds(username, "password");
186
187     // Wait for the session to start after submitting the credentials. This
188     // will wait until all the background requests are done.
189     session_started_observer.Wait();
190   }
191
192   // Handles an HTTP request sent to the test server. This handler either
193   // uses a canned response in |responses_| if the request path matches one
194   // of the URLs that we mock, otherwise this handler delegates to |fake_gaia_|.
195   scoped_ptr<net::test_server::HttpResponse> HandleRequest(
196       const net::test_server::HttpRequest& request) {
197     scoped_ptr<net::test_server::HttpResponse> response;
198
199     GaiaUrls* gaia = GaiaUrls::GetInstance();
200     if (request.relative_url == gaia->client_login_to_oauth2_url().path() ||
201         request.relative_url == gaia->oauth2_token_url().path() ||
202         request.relative_url.find(kDMRegisterRequest) == 0 ||
203         request.relative_url.find(kDMPolicyRequest) == 0) {
204       if (!responses_.empty()) {
205         response.reset(responses_.back());
206         responses_.pop_back();
207       }
208     }
209
210     return response.Pass();
211   }
212
213   // Creates a new canned response that will respond with the given HTTP
214   // status |code|. That response is appended to |responses_| and will be the
215   // next response used.
216   // Returns a reference to that response, so that it can be further customized.
217   net::test_server::BasicHttpResponse& PushResponse(net::HttpStatusCode code) {
218     net::test_server::BasicHttpResponse* response =
219         new net::test_server::BasicHttpResponse();
220     response->set_code(code);
221     responses_.push_back(response);
222     return *response;
223   }
224
225   // Returns the body of the register response from the policy server.
226   std::string GetRegisterResponse() {
227     em::DeviceManagementResponse response;
228     em::DeviceRegisterResponse* register_response =
229         response.mutable_register_response();
230     register_response->set_device_management_token("1234");
231     register_response->set_enrollment_type(
232         em::DeviceRegisterResponse::ENTERPRISE);
233     std::string data;
234     EXPECT_TRUE(response.SerializeToString(&data));
235     return data;
236   }
237
238   // Returns the body of the fetch response from the policy server.
239   std::string GetPolicyResponse() {
240     em::DeviceManagementResponse response;
241     response.mutable_policy_response()->add_response();
242     std::string data;
243     EXPECT_TRUE(response.SerializeToString(&data));
244     return data;
245   }
246
247  protected:
248   Profile* profile_added_;
249
250  private:
251   FakeGaia fake_gaia_;
252   std::vector<net::test_server::HttpResponse*> responses_;
253   content::NotificationRegistrar registrar_;
254
255   DISALLOW_COPY_AND_ASSIGN(BlockingLoginTest);
256 };
257
258 IN_PROC_BROWSER_TEST_P(BlockingLoginTest, LoginBlocksForUser) {
259   // Verify that there isn't a logged in user when the test starts.
260   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
261   EXPECT_FALSE(user_manager->IsUserLoggedIn());
262   EXPECT_FALSE(browser_policy_connector()->IsEnterpriseManaged());
263   EXPECT_FALSE(profile_added_);
264
265   // Enroll the device, if enrollment is enabled for this test instance.
266   if (GetParam().enroll_device) {
267     EnrollDevice(kUsername);
268
269     EXPECT_FALSE(user_manager->IsUserLoggedIn());
270     EXPECT_TRUE(browser_policy_connector()->IsEnterpriseManaged());
271     EXPECT_EQ(kDomain, browser_policy_connector()->GetEnterpriseDomain());
272     EXPECT_FALSE(profile_added_);
273     EXPECT_EQ(policy::USER_AFFILIATION_MANAGED,
274               browser_policy_connector()->GetUserAffiliation(kUsername));
275     RunUntilIdle();
276     EXPECT_FALSE(user_manager->IsKnownUser(kUsername));
277   }
278
279   // Skip the OOBE, go to the sign-in screen, and wait for the login screen to
280   // become visible.
281   SkipToSigninScreen();
282   EXPECT_FALSE(profile_added_);
283
284   // Prepare the fake HTTP responses.
285   if (GetParam().steps < 5) {
286     // If this instance is not going to complete the entire flow successfully
287     // then the last step will fail.
288
289     // This response body is important to make the gaia fetcher skip its delayed
290     // retry behavior, which makes testing harder. If this is sent to the policy
291     // fetchers then it will make them fail too.
292     PushResponse(net::HTTP_UNAUTHORIZED).set_content("Error=AccountDeleted");
293   }
294
295   // Push a response for each step that is going to succeed, in reverse order.
296   switch (GetParam().steps) {
297     default:
298       ADD_FAILURE() << "Invalid step number: " << GetParam().steps;
299       return;
300
301     case 5:
302       PushResponse(net::HTTP_OK).set_content(GetPolicyResponse());
303
304     case 4:
305       PushResponse(net::HTTP_OK).set_content(GetRegisterResponse());
306
307     case 3:
308       PushResponse(net::HTTP_OK).set_content(kOAuth2AccessTokenData);
309
310     case 2:
311       PushResponse(net::HTTP_OK).set_content(kOAuth2TokenPairData);
312
313     case 1:
314       PushResponse(net::HTTP_OK)
315           .AddCustomHeader("Set-Cookie", kOAuthCodeCookie);
316       break;
317
318     case 0:
319       break;
320   }
321
322   // Login now. This verifies that logging in with the canned responses (which
323   // may include failures) won't be blocked due to the potential failures.
324   EXPECT_FALSE(profile_added_);
325   Login(GetParam().username);
326   EXPECT_TRUE(profile_added_);
327   ASSERT_TRUE(user_manager->IsUserLoggedIn());
328   EXPECT_TRUE(user_manager->IsCurrentUserNew());
329 }
330
331 const BlockingLoginTestParam kBlockinLoginTestCases[] = {
332     { 0, kUsername, true },
333     { 1, kUsername, true },
334     { 2, kUsername, true },
335     { 3, kUsername, true },
336     { 4, kUsername, true },
337     { 5, kUsername, true },
338     { 0, kUsername, false },
339     { 1, kUsername, false },
340     { 2, kUsername, false },
341     { 3, kUsername, false },
342     { 4, kUsername, false },
343     { 5, kUsername, false },
344     { 0, kUsernameOtherDomain, true },
345     { 1, kUsernameOtherDomain, true },
346     { 2, kUsernameOtherDomain, true },
347     { 3, kUsernameOtherDomain, true },
348     { 4, kUsernameOtherDomain, true },
349     { 5, kUsernameOtherDomain, true },
350 };
351
352 INSTANTIATE_TEST_CASE_P(BlockingLoginTestInstance,
353                         BlockingLoginTest,
354                         testing::ValuesIn(kBlockinLoginTestCases));
355
356 }  // namespace chromeos