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