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.
5 #include "chrome/browser/chromeos/login/login_utils.h"
7 #include "base/basictypes.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/enterprise_install_attributes.h"
26 #include "chrome/browser/chromeos/profiles/profile_helper.h"
27 #include "chrome/browser/chromeos/settings/cros_settings.h"
28 #include "chrome/browser/chromeos/settings/device_settings_service.h"
29 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
30 #include "chrome/browser/chromeos/settings/mock_owner_key_util.h"
31 #include "chrome/browser/io_thread.h"
32 #include "chrome/browser/net/predictor.h"
33 #include "chrome/browser/policy/browser_policy_connector.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/chrome_switches.h"
39 #include "chrome/common/pref_names.h"
40 #include "chrome/test/base/scoped_testing_local_state.h"
41 #include "chrome/test/base/testing_browser_process.h"
42 #include "chromeos/chromeos_switches.h"
43 #include "chromeos/cryptohome/mock_async_method_caller.h"
44 #include "chromeos/cryptohome/system_salt_getter.h"
45 #include "chromeos/dbus/fake_dbus_thread_manager.h"
46 #include "chromeos/disks/disk_mount_manager.h"
47 #include "chromeos/disks/mock_disk_mount_manager.h"
48 #include "chromeos/login/login_state.h"
49 #include "chromeos/network/network_handler.h"
50 #include "chromeos/system/mock_statistics_provider.h"
51 #include "chromeos/system/statistics_provider.h"
52 #include "components/policy/core/common/cloud/device_management_service.h"
53 #include "components/policy/core/common/policy_service.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"
69 #if defined(ENABLE_RLZ)
70 #include "rlz/lib/rlz_value_store.h"
73 using ::testing::AnyNumber
;
79 namespace em
= enterprise_management
;
81 using ::testing::DoAll
;
82 using ::testing::Return
;
83 using ::testing::SaveArg
;
84 using ::testing::SetArgPointee
;
86 using content::BrowserThread
;
88 const char kDomain
[] = "domain.com";
89 const char kUsername
[] = "user@domain.com";
90 const char kDeviceId
[] = "100200300";
91 const char kUsernameOtherDomain
[] = "user@other.com";
93 const char kOAuthTokenCookie
[] = "oauth_token=1234";
95 const char kGaiaAccountDisabledResponse
[] = "Error=AccountDeleted";
97 const char kOAuth2TokenPairData
[] =
99 " \"refresh_token\": \"1234\","
100 " \"access_token\": \"5678\","
101 " \"expires_in\": 3600"
104 const char kOAuth2AccessTokenData
[] =
106 " \"access_token\": \"5678\","
107 " \"expires_in\": 3600"
110 const char kDMServer
[] = "http://server/device_management";
111 const char kDMRegisterRequest
[] =
112 "http://server/device_management?request=register";
113 const char kDMPolicyRequest
[] =
114 "http://server/device_management?request=policy";
116 const char kDMToken
[] = "1234";
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.
122 void BlockLoop(base::WaitableEvent
* completion
, base::Callback
<bool()> work
) {
125 } while (work
.Run());
126 base::MessageLoop::current()->QuitNow();
129 void CopyLockResult(base::RunLoop
* loop
,
130 policy::EnterpriseInstallAttributes::LockResult
* out
,
131 policy::EnterpriseInstallAttributes::LockResult result
) {
136 class LoginUtilsTest
: public testing::Test
,
137 public LoginUtils::Delegate
,
138 public LoginStatusConsumer
{
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.
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
),
159 prepared_profile_(NULL
) {}
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.
169 // See InvokeOnIO() below for a way to perform specific tasks on IO, when
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(
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
189 new content::TestBrowserThread(BrowserThread::IO
, fake_io_loop
));
191 ASSERT_TRUE(scoped_temp_dir_
.CreateUniqueTempDir());
193 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
194 command_line
->AppendSwitchASCII(
195 ::switches::kDeviceManagementUrl
, kDMServer
);
196 command_line
->AppendSwitchASCII(switches::kLoginProfile
, "user");
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();
203 SystemSaltGetter::Initialize();
204 LoginState::Initialize();
206 EXPECT_CALL(mock_statistics_provider_
, GetMachineStatistic(_
, _
))
207 .WillRepeatedly(Return(false));
208 chromeos::system::StatisticsProvider::SetTestProvider(
209 &mock_statistics_provider_
);
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();
216 mock_async_method_caller_
= new cryptohome::MockAsyncMethodCaller
;
217 cryptohome::AsyncMethodCaller::InitializeForTesting(
218 mock_async_method_caller_
);
220 test_device_settings_service_
.reset(new ScopedTestDeviceSettingsService
);
221 test_cros_settings_
.reset(new ScopedTestCrosSettings
);
222 test_user_manager_
.reset(new ScopedTestUserManager
);
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();
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_
= browser_process_
->browser_policy_connector();
236 connector_
->Init(local_state_
.Get(),
237 browser_process_
->system_request_context());
239 io_thread_state_
.reset(new IOThread(local_state_
.Get(),
240 browser_process_
->policy_service(),
242 browser_process_
->SetIOThread(io_thread_state_
.get());
244 #if defined(ENABLE_RLZ)
245 rlz_initialized_cb_
= base::Bind(&base::DoNothing
);
246 rlz_lib::testing::SetRlzStoreDirectory(scoped_temp_dir_
.path());
247 RLZTracker::EnableZeroDelayForTesting();
253 virtual void TearDown() OVERRIDE
{
254 cryptohome::AsyncMethodCaller::Shutdown();
255 mock_async_method_caller_
= NULL
;
257 test_user_manager_
.reset();
260 base::Bind(&LoginUtilsTest::TearDownOnIO
, base::Unretained(this)));
262 // LoginUtils instance must not outlive Profile instances.
263 LoginUtils::Set(NULL
);
265 input_method::Shutdown();
266 LoginState::Shutdown();
267 SystemSaltGetter::Shutdown();
269 // These trigger some tasks that have to run while BrowserThread::UI
270 // exists. Delete all the profiles before deleting the connector.
271 browser_process_
->SetProfileManager(NULL
);
273 browser_process_
->SetBrowserPolicyConnector(NULL
);
278 void TearDownOnIO() {
279 // chrome_browser_net::Predictor usually skips its shutdown routines on
280 // unit_tests, but does the full thing when
281 // g_browser_process->profile_manager() is valid during initialization.
282 // That includes a WaitableEvent on UI waiting for a task on IO, so that
283 // task must execute. Do it directly from here now.
284 std::vector
<Profile
*> profiles
=
285 browser_process_
->profile_manager()->GetLoadedProfiles();
286 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
287 chrome_browser_net::Predictor
* predictor
=
288 profiles
[i
]->GetNetworkPredictor();
290 predictor
->EnablePredictorOnIOThread(false);
291 predictor
->Shutdown();
296 void RunUntilIdle() {
297 loop_
.RunUntilIdle();
298 BrowserThread::GetBlockingPool()->FlushForTesting();
299 loop_
.RunUntilIdle();
302 // Invokes |task| on the IO loop and returns after it has executed.
303 void InvokeOnIO(const base::Closure
& task
) {
304 fake_io_thread_work_
= task
;
305 fake_io_thread_completion_
.Signal();
306 content::RunMessageLoop();
309 // Makes the fake IO loop return.
311 fake_io_thread_completion_
.Signal();
312 content::RunMessageLoop();
315 // Helper for BlockLoop, InvokeOnIO and QuitIOLoop.
317 bool has_work
= !fake_io_thread_work_
.is_null();
319 fake_io_thread_work_
.Run();
320 fake_io_thread_work_
.Reset();
321 BrowserThread::PostTask(
322 BrowserThread::UI
, FROM_HERE
,
323 base::MessageLoop::QuitWhenIdleClosure());
324 // If there was work then keep waiting for more work.
325 // If there was no work then quit the fake IO loop.
329 virtual void OnProfilePrepared(Profile
* profile
) OVERRIDE
{
330 EXPECT_FALSE(prepared_profile_
);
331 prepared_profile_
= profile
;
334 #if defined(ENABLE_RLZ)
335 virtual void OnRlzInitialized(Profile
* profile
) OVERRIDE
{
336 rlz_initialized_cb_
.Run();
340 virtual void OnLoginFailure(const LoginFailure
& error
) OVERRIDE
{
341 FAIL() << "OnLoginFailure not expected";
344 virtual void OnLoginSuccess(const UserContext
& user_context
) OVERRIDE
{
345 FAIL() << "OnLoginSuccess not expected";
348 void EnrollDevice(const std::string
& username
) {
350 policy::EnterpriseInstallAttributes::LockResult result
;
351 connector_
->GetInstallAttributes()->LockDevice(
352 username
, policy::DEVICE_MODE_ENTERPRISE
, kDeviceId
,
353 base::Bind(&CopyLockResult
, &loop
, &result
));
355 EXPECT_EQ(policy::EnterpriseInstallAttributes::LOCK_SUCCESS
, result
);
359 void PrepareProfile(const std::string
& username
) {
360 // Normally this would happen during browser startup, but for tests
361 // we need to trigger creation of Profile-related services.
362 ChromeBrowserMainExtraPartsProfiles::
363 EnsureBrowserContextKeyedServiceFactoriesBuilt();
365 DeviceSettingsTestHelper device_settings_test_helper
;
366 DeviceSettingsService::Get()->SetSessionManager(
367 &device_settings_test_helper
, new MockOwnerKeyUtil());
369 EXPECT_CALL(*mock_async_method_caller_
, AsyncMount(_
, _
, _
, _
))
370 .WillRepeatedly(Return());
371 EXPECT_CALL(*mock_async_method_caller_
, AsyncGetSanitizedUsername(_
, _
))
372 .WillRepeatedly(Return());
374 scoped_refptr
<Authenticator
> authenticator
=
375 LoginUtils::Get()->CreateAuthenticator(this);
376 authenticator
->CompleteLogin(ProfileHelper::GetSigninProfile(),
377 UserContext(username
,
380 username
)); // username_hash
382 const bool kUsingOAuth
= true;
383 // Setting |kHasCookies| to false prevents ProfileAuthData::Transfer from
384 // waiting for an IO task before proceeding.
385 const bool kHasCookies
= false;
386 const bool kHasActiveSession
= false;
387 LoginUtils::Get()->PrepareProfile(
388 UserContext(username
, "password", std::string(), username
, kUsingOAuth
),
389 std::string(), kHasCookies
, kHasActiveSession
, this);
390 device_settings_test_helper
.Flush();
393 DeviceSettingsService::Get()->UnsetSessionManager();
396 net::TestURLFetcher
* PrepareOAuthFetcher(const GURL
& expected_url
) {
397 net::TestURLFetcher
* fetcher
= test_url_fetcher_factory_
.GetFetcherByID(0);
398 EXPECT_TRUE(fetcher
);
401 EXPECT_TRUE(fetcher
->delegate());
402 EXPECT_TRUE(StartsWithASCII(fetcher
->GetOriginalURL().spec(),
405 fetcher
->set_url(fetcher
->GetOriginalURL());
406 fetcher
->set_response_code(200);
407 fetcher
->set_status(net::URLRequestStatus());
411 net::TestURLFetcher
* PrepareDMServiceFetcher(
412 const std::string
& expected_url
,
413 const em::DeviceManagementResponse
& response
) {
414 net::TestURLFetcher
* fetcher
= test_url_fetcher_factory_
.GetFetcherByID(
415 policy::DeviceManagementService::kURLFetcherID
);
416 EXPECT_TRUE(fetcher
);
419 EXPECT_TRUE(fetcher
->delegate());
420 EXPECT_TRUE(StartsWithASCII(fetcher
->GetOriginalURL().spec(),
423 fetcher
->set_url(fetcher
->GetOriginalURL());
424 fetcher
->set_response_code(200);
425 fetcher
->set_status(net::URLRequestStatus());
427 EXPECT_TRUE(response
.SerializeToString(&data
));
428 fetcher
->SetResponseString(data
);
432 net::TestURLFetcher
* PrepareDMRegisterFetcher() {
433 em::DeviceManagementResponse response
;
434 em::DeviceRegisterResponse
* register_response
=
435 response
.mutable_register_response();
436 register_response
->set_device_management_token(kDMToken
);
437 register_response
->set_enrollment_type(
438 em::DeviceRegisterResponse::ENTERPRISE
);
439 return PrepareDMServiceFetcher(kDMRegisterRequest
, response
);
442 net::TestURLFetcher
* PrepareDMPolicyFetcher() {
443 em::DeviceManagementResponse response
;
444 response
.mutable_policy_response()->add_response();
445 return PrepareDMServiceFetcher(kDMPolicyRequest
, response
);
449 // Must be the first member variable as browser_process_ and local_state_
450 // rely on this being set up.
451 TestingBrowserProcessInitializer initializer_
;
453 base::Closure fake_io_thread_work_
;
454 base::WaitableEvent fake_io_thread_completion_
;
455 base::Thread fake_io_thread_
;
457 base::MessageLoopForIO loop_
;
458 TestingBrowserProcess
* browser_process_
;
459 ScopedTestingLocalState local_state_
;
461 content::TestBrowserThread ui_thread_
;
462 content::TestBrowserThread db_thread_
;
463 content::TestBrowserThread file_thread_
;
464 scoped_ptr
<content::TestBrowserThread
> io_thread_
;
465 scoped_ptr
<IOThread
> io_thread_state_
;
467 input_method::MockInputMethodManager
* mock_input_method_manager_
;
468 disks::MockDiskMountManager mock_disk_mount_manager_
;
469 net::TestURLFetcherFactory test_url_fetcher_factory_
;
471 cryptohome::MockAsyncMethodCaller
* mock_async_method_caller_
;
473 chromeos::system::MockStatisticsProvider mock_statistics_provider_
;
475 policy::BrowserPolicyConnector
* connector_
;
477 scoped_ptr
<ScopedTestDeviceSettingsService
> test_device_settings_service_
;
478 scoped_ptr
<ScopedTestCrosSettings
> test_cros_settings_
;
479 scoped_ptr
<ScopedTestUserManager
> test_user_manager_
;
481 Profile
* prepared_profile_
;
483 base::Closure rlz_initialized_cb_
;
486 base::ScopedTempDir scoped_temp_dir_
;
488 std::string device_policy_
;
489 std::string user_policy_
;
491 DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest
);
494 class LoginUtilsBlockingLoginTest
495 : public LoginUtilsTest
,
496 public testing::WithParamInterface
<int> {};
498 TEST_F(LoginUtilsTest
, NormalLoginDoesntBlock
) {
499 UserManager
* user_manager
= UserManager::Get();
500 EXPECT_FALSE(user_manager
->IsUserLoggedIn());
501 EXPECT_FALSE(connector_
->IsEnterpriseManaged());
502 EXPECT_FALSE(prepared_profile_
);
503 EXPECT_EQ(policy::USER_AFFILIATION_NONE
,
504 connector_
->GetUserAffiliation(kUsername
));
506 // The profile will be created without waiting for a policy response.
507 PrepareProfile(kUsername
);
509 EXPECT_TRUE(prepared_profile_
);
510 ASSERT_TRUE(user_manager
->IsUserLoggedIn());
511 EXPECT_EQ(kUsername
, user_manager
->GetLoggedInUser()->email());
514 TEST_F(LoginUtilsTest
, EnterpriseLoginDoesntBlockForNormalUser
) {
515 UserManager
* user_manager
= UserManager::Get();
516 EXPECT_FALSE(user_manager
->IsUserLoggedIn());
517 EXPECT_FALSE(connector_
->IsEnterpriseManaged());
518 EXPECT_FALSE(prepared_profile_
);
520 // Enroll the device.
521 EnrollDevice(kUsername
);
523 EXPECT_FALSE(user_manager
->IsUserLoggedIn());
524 EXPECT_TRUE(connector_
->IsEnterpriseManaged());
525 EXPECT_EQ(kDomain
, connector_
->GetEnterpriseDomain());
526 EXPECT_FALSE(prepared_profile_
);
527 EXPECT_EQ(policy::USER_AFFILIATION_NONE
,
528 connector_
->GetUserAffiliation(kUsernameOtherDomain
));
530 // Login with a non-enterprise user shouldn't block.
531 PrepareProfile(kUsernameOtherDomain
);
533 EXPECT_TRUE(prepared_profile_
);
534 ASSERT_TRUE(user_manager
->IsUserLoggedIn());
535 EXPECT_EQ(kUsernameOtherDomain
, user_manager
->GetLoggedInUser()->email());
538 #if defined(ENABLE_RLZ)
539 TEST_F(LoginUtilsTest
, RlzInitialized
) {
540 // No RLZ brand code set initially.
541 EXPECT_FALSE(local_state_
.Get()->HasPrefPath(prefs::kRLZBrand
));
543 base::RunLoop wait_for_rlz_init
;
544 rlz_initialized_cb_
= wait_for_rlz_init
.QuitClosure();
546 PrepareProfile(kUsername
);
548 wait_for_rlz_init
.Run();
549 // Wait for blocking RLZ tasks to complete.
552 // RLZ brand code has been set to empty string.
553 EXPECT_TRUE(local_state_
.Get()->HasPrefPath(prefs::kRLZBrand
));
554 EXPECT_EQ(std::string(), local_state_
.Get()->GetString(prefs::kRLZBrand
));
556 // RLZ value for homepage access point should have been initialized.
557 base::string16 rlz_string
;
558 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(
559 RLZTracker::CHROME_HOME_PAGE
, &rlz_string
));
560 EXPECT_EQ(base::string16(), rlz_string
);
564 TEST_P(LoginUtilsBlockingLoginTest
, EnterpriseLoginBlocksForEnterpriseUser
) {
565 UserManager
* user_manager
= UserManager::Get();
566 EXPECT_FALSE(user_manager
->IsUserLoggedIn());
567 EXPECT_FALSE(connector_
->IsEnterpriseManaged());
568 EXPECT_FALSE(prepared_profile_
);
570 // Enroll the device.
571 EnrollDevice(kUsername
);
573 EXPECT_FALSE(user_manager
->IsUserLoggedIn());
574 EXPECT_TRUE(connector_
->IsEnterpriseManaged());
575 EXPECT_EQ(kDomain
, connector_
->GetEnterpriseDomain());
576 EXPECT_FALSE(prepared_profile_
);
577 EXPECT_EQ(policy::USER_AFFILIATION_MANAGED
,
578 connector_
->GetUserAffiliation(kUsername
));
579 EXPECT_FALSE(user_manager
->IsKnownUser(kUsername
));
581 // Login with a user of the enterprise domain waits for policy.
582 PrepareProfile(kUsername
);
584 EXPECT_FALSE(prepared_profile_
);
585 ASSERT_TRUE(user_manager
->IsUserLoggedIn());
586 EXPECT_TRUE(user_manager
->IsCurrentUserNew());
588 GaiaUrls
* gaia_urls
= GaiaUrls::GetInstance();
589 net::TestURLFetcher
* fetcher
;
591 // |steps| is the test parameter, and is the number of successful fetches.
592 // The first incomplete fetch will fail. In any case, the profile creation
594 int steps
= GetParam();
596 // The next expected fetcher ID. This is used to make it fail.
597 int next_expected_fetcher_id
= 0;
600 if (steps
< 1) break;
602 // Fake refresh token retrieval:
603 fetcher
= PrepareOAuthFetcher(gaia_urls
->client_login_to_oauth2_url());
604 ASSERT_TRUE(fetcher
);
605 net::ResponseCookies cookies
;
606 cookies
.push_back(kOAuthTokenCookie
);
607 fetcher
->set_cookies(cookies
);
608 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
609 if (steps
< 2) break;
611 // Fake OAuth2 token pair retrieval:
612 fetcher
= PrepareOAuthFetcher(gaia_urls
->oauth2_token_url());
613 ASSERT_TRUE(fetcher
);
614 fetcher
->SetResponseString(kOAuth2TokenPairData
);
615 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
616 if (steps
< 3) break;
618 // Fake OAuth2 access token retrieval:
619 fetcher
= PrepareOAuthFetcher(gaia_urls
->oauth2_token_url());
620 ASSERT_TRUE(fetcher
);
621 fetcher
->SetResponseString(kOAuth2AccessTokenData
);
622 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
624 // The cloud policy subsystem is now ready to fetch the dmtoken and the user
626 next_expected_fetcher_id
= policy::DeviceManagementService::kURLFetcherID
;
628 if (steps
< 4) break;
630 fetcher
= PrepareDMRegisterFetcher();
631 ASSERT_TRUE(fetcher
);
632 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
633 // The policy fetch job has now been scheduled, run it:
635 if (steps
< 5) break;
637 // Verify that there is no profile prepared just before the policy fetch.
638 EXPECT_FALSE(prepared_profile_
);
640 fetcher
= PrepareDMPolicyFetcher();
641 ASSERT_TRUE(fetcher
);
642 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
647 // Verify that the profile hasn't been created yet.
648 EXPECT_FALSE(prepared_profile_
);
650 // Make the current fetcher fail with a Gaia error.
651 net::TestURLFetcher
* fetcher
= test_url_fetcher_factory_
.GetFetcherByID(
652 next_expected_fetcher_id
);
653 ASSERT_TRUE(fetcher
);
654 EXPECT_TRUE(fetcher
->delegate());
655 fetcher
->set_url(fetcher
->GetOriginalURL());
656 fetcher
->set_response_code(401);
657 // This response body is important to make the gaia fetcher skip its delayed
658 // retry behavior, which makes testing harder. If this is sent to the policy
659 // fetchers then it will make them fail too.
660 fetcher
->SetResponseString(kGaiaAccountDisabledResponse
);
661 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
665 // The profile is finally ready:
666 EXPECT_TRUE(prepared_profile_
);
669 INSTANTIATE_TEST_CASE_P(
670 LoginUtilsBlockingLoginTestInstance
,
671 LoginUtilsBlockingLoginTest
,
672 testing::Values(0, 1, 2, 3, 4, 5));
676 } // namespace chromeos