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