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