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