login_utils_browsertest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 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 "chrome/browser/chromeos/login/login_utils.h"
6
7#include "base/basictypes.h"
8#include "base/bind.h"
9#include "base/command_line.h"
10#include "base/files/scoped_temp_dir.h"
11#include "base/message_loop/message_loop.h"
12#include "base/path_service.h"
13#include "base/prefs/pref_registry_simple.h"
14#include "base/run_loop.h"
15#include "base/strings/string_util.h"
16#include "base/synchronization/waitable_event.h"
17#include "base/threading/sequenced_worker_pool.h"
18#include "base/threading/thread.h"
19#include "chrome/browser/chrome_notification_types.h"
20#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
21#include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
22#include "chrome/browser/chromeos/login/authenticator.h"
23#include "chrome/browser/chromeos/login/login_status_consumer.h"
24#include "chrome/browser/chromeos/login/user_manager.h"
25#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
26#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
27#include "chrome/browser/chromeos/profiles/profile_helper.h"
28#include "chrome/browser/chromeos/settings/cros_settings.h"
29#include "chrome/browser/chromeos/settings/device_settings_service.h"
30#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
31#include "chrome/browser/chromeos/settings/mock_owner_key_util.h"
32#include "chrome/browser/io_thread.h"
33#include "chrome/browser/net/predictor.h"
34#include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h"
35#include "chrome/browser/profiles/profile_manager.h"
36#include "chrome/browser/rlz/rlz.h"
37#include "chrome/common/chrome_paths.h"
38#include "chrome/common/pref_names.h"
39#include "chrome/test/base/scoped_testing_local_state.h"
40#include "chrome/test/base/testing_browser_process.h"
41#include "chromeos/chromeos_switches.h"
42#include "chromeos/cryptohome/mock_async_method_caller.h"
43#include "chromeos/cryptohome/system_salt_getter.h"
44#include "chromeos/dbus/fake_dbus_thread_manager.h"
45#include "chromeos/disks/disk_mount_manager.h"
46#include "chromeos/disks/mock_disk_mount_manager.h"
47#include "chromeos/login/login_state.h"
48#include "chromeos/network/network_handler.h"
49#include "chromeos/system/mock_statistics_provider.h"
50#include "chromeos/system/statistics_provider.h"
51#include "components/policy/core/common/cloud/device_management_service.h"
52#include "components/policy/core/common/policy_service.h"
53#include "components/policy/core/common/policy_switches.h"
54#include "content/public/browser/browser_thread.h"
55#include "content/public/test/test_browser_thread.h"
56#include "content/public/test/test_utils.h"
57#include "google_apis/gaia/gaia_auth_consumer.h"
58#include "google_apis/gaia/gaia_urls.h"
59#include "net/url_request/test_url_fetcher_factory.h"
60#include "net/url_request/url_fetcher_delegate.h"
61#include "net/url_request/url_request.h"
62#include "net/url_request/url_request_context_getter.h"
63#include "net/url_request/url_request_status.h"
64#include "net/url_request/url_request_test_util.h"
65#include "policy/proto/device_management_backend.pb.h"
66#include "testing/gmock/include/gmock/gmock.h"
67#include "testing/gtest/include/gtest/gtest.h"
68
69#if defined(ENABLE_RLZ)
70#include "rlz/lib/rlz_value_store.h"
71#endif
72
73using ::testing::AnyNumber;
74
75namespace chromeos {
76
77namespace {
78
79namespace em = enterprise_management;
80
81using ::testing::DoAll;
82using ::testing::Return;
83using ::testing::SaveArg;
84using ::testing::SetArgPointee;
85using ::testing::_;
86using content::BrowserThread;
87
88const char kDomain[] = "domain.com";
89const char kUsername[] = "user@domain.com";
90const char kDeviceId[] = "100200300";
91const char kUsernameOtherDomain[] = "user@other.com";
92
93const char kOAuthTokenCookie[] = "oauth_token=1234";
94
95const char kGaiaAccountDisabledResponse[] = "Error=AccountDeleted";
96
97const char kOAuth2TokenPairData[] =
98    "{"
99    "  \"refresh_token\": \"1234\","
100    "  \"access_token\": \"5678\","
101    "  \"expires_in\": 3600"
102    "}";
103
104const char kOAuth2AccessTokenData[] =
105    "{"
106    "  \"access_token\": \"5678\","
107    "  \"expires_in\": 3600"
108    "}";
109
110const char kDMServer[] = "http://server/device_management";
111const char kDMRegisterRequest[] =
112    "http://server/device_management?request=register";
113const char kDMPolicyRequest[] =
114    "http://server/device_management?request=policy";
115
116const char kDMToken[] = "1234";
117
118// Single task of the fake IO loop used in the test, that just waits until
119// it is signaled to quit or perform some work.
120// |completion| is the event to wait for, and |work| is the task to invoke
121// when signaled. If the task returns false then this quits the IO loop.
122void BlockLoop(base::WaitableEvent* completion, base::Callback<bool()> work) {
123  do {
124    completion->Wait();
125  } while (work.Run());
126  base::MessageLoop::current()->QuitNow();
127}
128
129void CopyLockResult(base::RunLoop* loop,
130                    policy::EnterpriseInstallAttributes::LockResult* out,
131                    policy::EnterpriseInstallAttributes::LockResult result) {
132  *out = result;
133  loop->Quit();
134}
135
136class LoginUtilsTest : public testing::Test,
137                       public LoginUtils::Delegate,
138                       public LoginStatusConsumer {
139 public:
140  // Initialization here is important. The UI thread gets the test's
141  // message loop, as does the file thread (which never actually gets
142  // started - so this is a way to fake multiple threads on a single
143  // test thread).  The IO thread does not get the message loop set,
144  // and is never started.  This is necessary so that we skip various
145  // bits of initialization that get posted to the IO thread.  We do
146  // however, at one point in the test, temporarily set the message
147  // loop for the IO thread.
148  LoginUtilsTest()
149      : fake_io_thread_completion_(false, false),
150        fake_io_thread_("fake_io_thread"),
151        browser_process_(TestingBrowserProcess::GetGlobal()),
152        local_state_(browser_process_),
153        ui_thread_(BrowserThread::UI, &loop_),
154        db_thread_(BrowserThread::DB, &loop_),
155        file_thread_(BrowserThread::FILE, &loop_),
156        mock_input_method_manager_(NULL),
157        mock_async_method_caller_(NULL),
158        connector_(NULL),
159        prepared_profile_(NULL) {}
160
161  virtual void SetUp() OVERRIDE {
162    // This test is not a full blown InProcessBrowserTest, and doesn't have
163    // all the usual threads running. However a lot of subsystems pulled from
164    // ProfileImpl post to IO (usually from ProfileIOData), and DCHECK that
165    // those tasks were posted. Those tasks in turn depend on a lot of other
166    // components that aren't there during this test, so this kludge is used to
167    // have a running IO loop that doesn't really execute any tasks.
168    //
169    // See InvokeOnIO() below for a way to perform specific tasks on IO, when
170    // that's necessary.
171
172    // A thread is needed to create a new MessageLoop, since there can be only
173    // one loop per thread.
174    fake_io_thread_.StartWithOptions(
175        base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
176    base::MessageLoop* fake_io_loop = fake_io_thread_.message_loop();
177    // Make this loop enter the single task, BlockLoop(). Pass in the completion
178    // event and the work callback.
179    fake_io_thread_.StopSoon();
180    fake_io_loop->PostTask(
181        FROM_HERE,
182        base::Bind(
183          BlockLoop,
184          &fake_io_thread_completion_,
185          base::Bind(&LoginUtilsTest::DoIOWork, base::Unretained(this))));
186    // Map BrowserThread::IO to this loop. This allows posting to IO but nothing
187    // will be executed.
188    io_thread_.reset(
189        new content::TestBrowserThread(BrowserThread::IO, fake_io_loop));
190
191    ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
192
193    CommandLine* command_line = CommandLine::ForCurrentProcess();
194    command_line->AppendSwitchASCII(
195        policy::switches::kDeviceManagementUrl, kDMServer);
196    command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
197
198    // DBusThreadManager should be initialized before io_thread_state_, as
199    // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl,
200    // which is part of io_thread_state_.
201    DBusThreadManager::InitializeWithStub();
202
203    SystemSaltGetter::Initialize();
204    LoginState::Initialize();
205
206    EXPECT_CALL(mock_statistics_provider_, GetMachineStatistic(_, _))
207        .WillRepeatedly(Return(false));
208    chromeos::system::StatisticsProvider::SetTestProvider(
209        &mock_statistics_provider_);
210
211    mock_input_method_manager_ = new input_method::MockInputMethodManager();
212    input_method::InitializeForTesting(mock_input_method_manager_);
213    disks::DiskMountManager::InitializeForTesting(&mock_disk_mount_manager_);
214    mock_disk_mount_manager_.SetupDefaultReplies();
215
216    mock_async_method_caller_ = new cryptohome::MockAsyncMethodCaller;
217    cryptohome::AsyncMethodCaller::InitializeForTesting(
218        mock_async_method_caller_);
219
220    test_device_settings_service_.reset(new ScopedTestDeviceSettingsService);
221    test_cros_settings_.reset(new ScopedTestCrosSettings);
222    test_user_manager_.reset(new ScopedTestUserManager);
223
224    // IOThread creates ProxyConfigServiceImpl and
225    // BrowserPolicyConnector::Init() creates a NetworkConfigurationUpdater,
226    // which both access NetworkHandler. Thus initialize it here before creating
227    // IOThread and before calling BrowserPolicyConnector::Init().
228    NetworkHandler::Initialize();
229
230    browser_process_->SetProfileManager(
231        new ProfileManagerWithoutInit(scoped_temp_dir_.path()));
232    browser_process_->SetSystemRequestContext(
233        new net::TestURLRequestContextGetter(
234            base::MessageLoopProxy::current()));
235    connector_ =
236        browser_process_->platform_part()->browser_policy_connector_chromeos();
237    connector_->Init(local_state_.Get(),
238                     browser_process_->system_request_context());
239
240    io_thread_state_.reset(new IOThread(local_state_.Get(),
241                                        browser_process_->policy_service(),
242                                        NULL, NULL));
243    browser_process_->SetIOThread(io_thread_state_.get());
244
245#if defined(ENABLE_RLZ)
246    rlz_initialized_cb_ = base::Bind(&base::DoNothing);
247    rlz_lib::testing::SetRlzStoreDirectory(scoped_temp_dir_.path());
248    RLZTracker::EnableZeroDelayForTesting();
249#endif
250
251    RunUntilIdle();
252  }
253
254  virtual void TearDown() OVERRIDE {
255    cryptohome::AsyncMethodCaller::Shutdown();
256    mock_async_method_caller_ = NULL;
257
258    test_user_manager_.reset();
259
260    InvokeOnIO(
261        base::Bind(&LoginUtilsTest::TearDownOnIO, base::Unretained(this)));
262
263    // LoginUtils instance must not outlive Profile instances.
264    LoginUtils::Set(NULL);
265
266    input_method::Shutdown();
267    LoginState::Shutdown();
268    SystemSaltGetter::Shutdown();
269
270    // These trigger some tasks that have to run while BrowserThread::UI
271    // exists. Delete all the profiles before deleting the connector.
272    browser_process_->SetProfileManager(NULL);
273    connector_ = NULL;
274    browser_process_->SetBrowserPolicyConnector(NULL);
275    QuitIOLoop();
276    RunUntilIdle();
277  }
278
279  void TearDownOnIO() {
280    // chrome_browser_net::Predictor usually skips its shutdown routines on
281    // unit_tests, but does the full thing when
282    // g_browser_process->profile_manager() is valid during initialization.
283    // That includes a WaitableEvent on UI waiting for a task on IO, so that
284    // task must execute. Do it directly from here now.
285    std::vector<Profile*> profiles =
286        browser_process_->profile_manager()->GetLoadedProfiles();
287    for (size_t i = 0; i < profiles.size(); ++i) {
288      chrome_browser_net::Predictor* predictor =
289          profiles[i]->GetNetworkPredictor();
290      if (predictor) {
291        predictor->EnablePredictorOnIOThread(false);
292        predictor->Shutdown();
293      }
294    }
295  }
296
297  void RunUntilIdle() {
298    loop_.RunUntilIdle();
299    BrowserThread::GetBlockingPool()->FlushForTesting();
300    loop_.RunUntilIdle();
301  }
302
303  // Invokes |task| on the IO loop and returns after it has executed.
304  void InvokeOnIO(const base::Closure& task) {
305    fake_io_thread_work_ = task;
306    fake_io_thread_completion_.Signal();
307    content::RunMessageLoop();
308  }
309
310  // Makes the fake IO loop return.
311  void QuitIOLoop() {
312    fake_io_thread_completion_.Signal();
313    content::RunMessageLoop();
314  }
315
316  // Helper for BlockLoop, InvokeOnIO and QuitIOLoop.
317  bool DoIOWork() {
318    bool has_work = !fake_io_thread_work_.is_null();
319    if (has_work)
320      fake_io_thread_work_.Run();
321    fake_io_thread_work_.Reset();
322    BrowserThread::PostTask(
323        BrowserThread::UI, FROM_HERE,
324        base::MessageLoop::QuitWhenIdleClosure());
325    // If there was work then keep waiting for more work.
326    // If there was no work then quit the fake IO loop.
327    return has_work;
328  }
329
330  virtual void OnProfilePrepared(Profile* profile) OVERRIDE {
331    EXPECT_FALSE(prepared_profile_);
332    prepared_profile_ = profile;
333  }
334
335#if defined(ENABLE_RLZ)
336  virtual void OnRlzInitialized(Profile* profile) OVERRIDE {
337    rlz_initialized_cb_.Run();
338  }
339#endif
340
341  virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE {
342    FAIL() << "OnLoginFailure not expected";
343  }
344
345  virtual void OnLoginSuccess(const UserContext& user_context) OVERRIDE {
346    FAIL() << "OnLoginSuccess not expected";
347  }
348
349  void EnrollDevice(const std::string& username) {
350    base::RunLoop loop;
351    policy::EnterpriseInstallAttributes::LockResult result;
352    connector_->GetInstallAttributes()->LockDevice(
353        username, policy::DEVICE_MODE_ENTERPRISE, kDeviceId,
354        base::Bind(&CopyLockResult, &loop, &result));
355    loop.Run();
356    EXPECT_EQ(policy::EnterpriseInstallAttributes::LOCK_SUCCESS, result);
357    RunUntilIdle();
358  }
359
360  void PrepareProfile(const std::string& username) {
361    // Normally this would happen during browser startup, but for tests
362    // we need to trigger creation of Profile-related services.
363    ChromeBrowserMainExtraPartsProfiles::
364        EnsureBrowserContextKeyedServiceFactoriesBuilt();
365
366    DeviceSettingsTestHelper device_settings_test_helper;
367    DeviceSettingsService::Get()->SetSessionManager(
368        &device_settings_test_helper, new MockOwnerKeyUtil());
369
370    EXPECT_CALL(*mock_async_method_caller_, AsyncMount(_, _, _, _))
371        .WillRepeatedly(Return());
372    EXPECT_CALL(*mock_async_method_caller_, AsyncGetSanitizedUsername(_, _))
373        .WillRepeatedly(Return());
374
375    scoped_refptr<Authenticator> authenticator =
376        LoginUtils::Get()->CreateAuthenticator(this);
377    authenticator->CompleteLogin(ProfileHelper::GetSigninProfile(),
378                                 UserContext(username,
379                                             "password",
380                                             std::string(),
381                                             username));   // username_hash
382
383    const bool kUsingOAuth = true;
384    // Setting |kHasCookies| to false prevents ProfileAuthData::Transfer from
385    // waiting for an IO task before proceeding.
386    const bool kHasCookies = false;
387    const bool kHasActiveSession = false;
388    LoginUtils::Get()->PrepareProfile(
389        UserContext(username,
390                    "password",
391                    std::string(),
392                    username,
393                    kUsingOAuth,
394                    UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML),
395        std::string(), kHasCookies, kHasActiveSession, this);
396    device_settings_test_helper.Flush();
397    RunUntilIdle();
398
399    DeviceSettingsService::Get()->UnsetSessionManager();
400  }
401
402  net::TestURLFetcher* PrepareOAuthFetcher(const GURL& expected_url) {
403    net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(0);
404    EXPECT_TRUE(fetcher);
405    if (!fetcher)
406      return NULL;
407    EXPECT_TRUE(fetcher->delegate());
408    EXPECT_TRUE(StartsWithASCII(fetcher->GetOriginalURL().spec(),
409                                expected_url.spec(),
410                                true));
411    fetcher->set_url(fetcher->GetOriginalURL());
412    fetcher->set_response_code(200);
413    fetcher->set_status(net::URLRequestStatus());
414    return fetcher;
415  }
416
417  net::TestURLFetcher* PrepareDMServiceFetcher(
418      const std::string& expected_url,
419      const em::DeviceManagementResponse& response) {
420    net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(
421        policy::DeviceManagementService::kURLFetcherID);
422    EXPECT_TRUE(fetcher);
423    if (!fetcher)
424      return NULL;
425    EXPECT_TRUE(fetcher->delegate());
426    EXPECT_TRUE(StartsWithASCII(fetcher->GetOriginalURL().spec(),
427                                expected_url,
428                                true));
429    fetcher->set_url(fetcher->GetOriginalURL());
430    fetcher->set_response_code(200);
431    fetcher->set_status(net::URLRequestStatus());
432    std::string data;
433    EXPECT_TRUE(response.SerializeToString(&data));
434    fetcher->SetResponseString(data);
435    return fetcher;
436  }
437
438  net::TestURLFetcher* PrepareDMRegisterFetcher() {
439    em::DeviceManagementResponse response;
440    em::DeviceRegisterResponse* register_response =
441        response.mutable_register_response();
442    register_response->set_device_management_token(kDMToken);
443    register_response->set_enrollment_type(
444        em::DeviceRegisterResponse::ENTERPRISE);
445    return PrepareDMServiceFetcher(kDMRegisterRequest, response);
446  }
447
448  net::TestURLFetcher* PrepareDMPolicyFetcher() {
449    em::DeviceManagementResponse response;
450    response.mutable_policy_response()->add_response();
451    return PrepareDMServiceFetcher(kDMPolicyRequest, response);
452  }
453
454 protected:
455  // Must be the first member variable as browser_process_ and local_state_
456  // rely on this being set up.
457  TestingBrowserProcessInitializer initializer_;
458
459  base::Closure fake_io_thread_work_;
460  base::WaitableEvent fake_io_thread_completion_;
461  base::Thread fake_io_thread_;
462
463  base::MessageLoopForIO loop_;
464  TestingBrowserProcess* browser_process_;
465  ScopedTestingLocalState local_state_;
466
467  content::TestBrowserThread ui_thread_;
468  content::TestBrowserThread db_thread_;
469  content::TestBrowserThread file_thread_;
470  scoped_ptr<content::TestBrowserThread> io_thread_;
471  scoped_ptr<IOThread> io_thread_state_;
472
473  input_method::MockInputMethodManager* mock_input_method_manager_;
474  disks::MockDiskMountManager mock_disk_mount_manager_;
475  net::TestURLFetcherFactory test_url_fetcher_factory_;
476
477  cryptohome::MockAsyncMethodCaller* mock_async_method_caller_;
478
479  chromeos::system::MockStatisticsProvider mock_statistics_provider_;
480
481  policy::BrowserPolicyConnectorChromeOS* connector_;
482
483  scoped_ptr<ScopedTestDeviceSettingsService> test_device_settings_service_;
484  scoped_ptr<ScopedTestCrosSettings> test_cros_settings_;
485  scoped_ptr<ScopedTestUserManager> test_user_manager_;
486
487  Profile* prepared_profile_;
488
489  base::Closure rlz_initialized_cb_;
490
491 private:
492  base::ScopedTempDir scoped_temp_dir_;
493
494  std::string device_policy_;
495  std::string user_policy_;
496
497  DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest);
498};
499
500class LoginUtilsBlockingLoginTest
501    : public LoginUtilsTest,
502      public testing::WithParamInterface<int> {};
503
504TEST_F(LoginUtilsTest, NormalLoginDoesntBlock) {
505  UserManager* user_manager = UserManager::Get();
506  EXPECT_FALSE(user_manager->IsUserLoggedIn());
507  EXPECT_FALSE(connector_->IsEnterpriseManaged());
508  EXPECT_FALSE(prepared_profile_);
509  EXPECT_EQ(policy::USER_AFFILIATION_NONE,
510            connector_->GetUserAffiliation(kUsername));
511
512  // The profile will be created without waiting for a policy response.
513  PrepareProfile(kUsername);
514
515  EXPECT_TRUE(prepared_profile_);
516  ASSERT_TRUE(user_manager->IsUserLoggedIn());
517  EXPECT_EQ(kUsername, user_manager->GetLoggedInUser()->email());
518}
519
520TEST_F(LoginUtilsTest, EnterpriseLoginDoesntBlockForNormalUser) {
521  UserManager* user_manager = UserManager::Get();
522  EXPECT_FALSE(user_manager->IsUserLoggedIn());
523  EXPECT_FALSE(connector_->IsEnterpriseManaged());
524  EXPECT_FALSE(prepared_profile_);
525
526  // Enroll the device.
527  EnrollDevice(kUsername);
528
529  EXPECT_FALSE(user_manager->IsUserLoggedIn());
530  EXPECT_TRUE(connector_->IsEnterpriseManaged());
531  EXPECT_EQ(kDomain, connector_->GetEnterpriseDomain());
532  EXPECT_FALSE(prepared_profile_);
533  EXPECT_EQ(policy::USER_AFFILIATION_NONE,
534            connector_->GetUserAffiliation(kUsernameOtherDomain));
535
536  // Login with a non-enterprise user shouldn't block.
537  PrepareProfile(kUsernameOtherDomain);
538
539  EXPECT_TRUE(prepared_profile_);
540  ASSERT_TRUE(user_manager->IsUserLoggedIn());
541  EXPECT_EQ(kUsernameOtherDomain, user_manager->GetLoggedInUser()->email());
542}
543
544#if defined(ENABLE_RLZ)
545TEST_F(LoginUtilsTest, RlzInitialized) {
546  // No RLZ brand code set initially.
547  EXPECT_FALSE(local_state_.Get()->HasPrefPath(prefs::kRLZBrand));
548
549  base::RunLoop wait_for_rlz_init;
550  rlz_initialized_cb_ = wait_for_rlz_init.QuitClosure();
551
552  PrepareProfile(kUsername);
553
554  wait_for_rlz_init.Run();
555  // Wait for blocking RLZ tasks to complete.
556  RunUntilIdle();
557
558  // RLZ brand code has been set to empty string.
559  EXPECT_TRUE(local_state_.Get()->HasPrefPath(prefs::kRLZBrand));
560  EXPECT_EQ(std::string(), local_state_.Get()->GetString(prefs::kRLZBrand));
561
562  // RLZ value for homepage access point should have been initialized.
563  base::string16 rlz_string;
564  EXPECT_TRUE(RLZTracker::GetAccessPointRlz(
565      RLZTracker::CHROME_HOME_PAGE, &rlz_string));
566  EXPECT_EQ(base::string16(), rlz_string);
567}
568#endif
569
570TEST_P(LoginUtilsBlockingLoginTest, EnterpriseLoginBlocksForEnterpriseUser) {
571  UserManager* user_manager = UserManager::Get();
572  EXPECT_FALSE(user_manager->IsUserLoggedIn());
573  EXPECT_FALSE(connector_->IsEnterpriseManaged());
574  EXPECT_FALSE(prepared_profile_);
575
576  // Enroll the device.
577  EnrollDevice(kUsername);
578
579  EXPECT_FALSE(user_manager->IsUserLoggedIn());
580  EXPECT_TRUE(connector_->IsEnterpriseManaged());
581  EXPECT_EQ(kDomain, connector_->GetEnterpriseDomain());
582  EXPECT_FALSE(prepared_profile_);
583  EXPECT_EQ(policy::USER_AFFILIATION_MANAGED,
584            connector_->GetUserAffiliation(kUsername));
585  EXPECT_FALSE(user_manager->IsKnownUser(kUsername));
586
587  // Login with a user of the enterprise domain waits for policy.
588  PrepareProfile(kUsername);
589
590  EXPECT_FALSE(prepared_profile_);
591  ASSERT_TRUE(user_manager->IsUserLoggedIn());
592  EXPECT_TRUE(user_manager->IsCurrentUserNew());
593
594  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
595  net::TestURLFetcher* fetcher;
596
597  // |steps| is the test parameter, and is the number of successful fetches.
598  // The first incomplete fetch will fail. In any case, the profile creation
599  // should resume.
600  int steps = GetParam();
601
602  // The next expected fetcher ID. This is used to make it fail.
603  int next_expected_fetcher_id = 0;
604
605  do {
606    if (steps < 1) break;
607
608    // Fake refresh token retrieval:
609    fetcher = PrepareOAuthFetcher(gaia_urls->client_login_to_oauth2_url());
610    ASSERT_TRUE(fetcher);
611    net::ResponseCookies cookies;
612    cookies.push_back(kOAuthTokenCookie);
613    fetcher->set_cookies(cookies);
614    fetcher->delegate()->OnURLFetchComplete(fetcher);
615    if (steps < 2) break;
616
617    // Fake OAuth2 token pair retrieval:
618    fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
619    ASSERT_TRUE(fetcher);
620    fetcher->SetResponseString(kOAuth2TokenPairData);
621    fetcher->delegate()->OnURLFetchComplete(fetcher);
622    if (steps < 3) break;
623
624    // Fake OAuth2 access token retrieval:
625    fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
626    ASSERT_TRUE(fetcher);
627    fetcher->SetResponseString(kOAuth2AccessTokenData);
628    fetcher->delegate()->OnURLFetchComplete(fetcher);
629
630    // The cloud policy subsystem is now ready to fetch the dmtoken and the user
631    // policy.
632    next_expected_fetcher_id = policy::DeviceManagementService::kURLFetcherID;
633    RunUntilIdle();
634    if (steps < 4) break;
635
636    fetcher = PrepareDMRegisterFetcher();
637    ASSERT_TRUE(fetcher);
638    fetcher->delegate()->OnURLFetchComplete(fetcher);
639    // The policy fetch job has now been scheduled, run it:
640    RunUntilIdle();
641    if (steps < 5) break;
642
643    // Verify that there is no profile prepared just before the policy fetch.
644    EXPECT_FALSE(prepared_profile_);
645
646    fetcher = PrepareDMPolicyFetcher();
647    ASSERT_TRUE(fetcher);
648    fetcher->delegate()->OnURLFetchComplete(fetcher);
649    RunUntilIdle();
650  } while (0);
651
652  if (steps < 5) {
653    // Verify that the profile hasn't been created yet.
654    EXPECT_FALSE(prepared_profile_);
655
656    // Make the current fetcher fail with a Gaia error.
657    net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(
658        next_expected_fetcher_id);
659    ASSERT_TRUE(fetcher);
660    EXPECT_TRUE(fetcher->delegate());
661    fetcher->set_url(fetcher->GetOriginalURL());
662    fetcher->set_response_code(401);
663    // This response body is important to make the gaia fetcher skip its delayed
664    // retry behavior, which makes testing harder. If this is sent to the policy
665    // fetchers then it will make them fail too.
666    fetcher->SetResponseString(kGaiaAccountDisabledResponse);
667    fetcher->delegate()->OnURLFetchComplete(fetcher);
668    RunUntilIdle();
669  }
670
671  // The profile is finally ready:
672  EXPECT_TRUE(prepared_profile_);
673}
674
675INSTANTIATE_TEST_CASE_P(
676    LoginUtilsBlockingLoginTestInstance,
677    LoginUtilsBlockingLoginTest,
678    testing::Values(0, 1, 2, 3, 4, 5));
679
680}  // namespace
681
682}  // namespace chromeos
683