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