text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include <memory>
  #include <utility>
  
  #include "base/files/file_path.h"
  #include "base/run_loop.h"
  #include "base/threading/thread_task_runner_handle.h"
  #include "base/time/time.h"
  #include "build/build_config.h"
  #include "chrome/browser/browser_process.h"
  #include "chrome/browser/chrome_notification_types.h"
  #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
  #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
  #include "chrome/browser/prefs/browser_prefs.h"
  #include "chrome/browser/profiles/profile.h"
  #include "chrome/browser/signin/account_fetcher_service_factory.h"
  #include "chrome/browser/signin/chrome_signin_client_factory.h"
  #include "chrome/browser/signin/fake_account_fetcher_service_builder.h"
  #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
  #include "chrome/browser/signin/fake_signin_manager_builder.h"
  #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
  #include "chrome/browser/signin/signin_manager_factory.h"
  #include "chrome/browser/signin/test_signin_client_builder.h"
  #include "chrome/test/base/testing_browser_process.h"
  #include "chrome/test/base/testing_profile.h"
  #include "components/policy/core/browser/browser_policy_connector.h"
  #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
  #include "components/policy/core/common/cloud/cloud_policy_constants.h"
  #include "components/policy/core/common/cloud/mock_device_management_service.h"
  #include "components/policy/core/common/cloud/mock_user_cloud_policy_store.h"
  #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
  #include "components/policy/core/common/schema_registry.h"
  #include "components/prefs/pref_service.h"
  #include "components/signin/core/browser/account_tracker_service.h"
  #include "components/signin/core/browser/fake_account_fetcher_service.h"
  #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
  #include "components/signin/core/browser/signin_manager.h"
  #include "components/syncable_prefs/testing_pref_service_syncable.h"
  #include "content/public/browser/browser_context.h"
  #include "content/public/browser/notification_details.h"
  #include "content/public/browser/notification_service.h"
  #include "content/public/browser/notification_source.h"
  #include "content/public/test/test_browser_thread_bundle.h"
  #include "google_apis/gaia/gaia_constants.h"
  #include "google_apis/gaia/google_service_auth_error.h"
  #include "net/base/net_errors.h"
  #include "net/http/http_status_code.h"
  #include "net/url_request/test_url_fetcher_factory.h"
  #include "net/url_request/url_request_context_getter.h"
  #include "net/url_request/url_request_status.h"
  #include "net/url_request/url_request_test_util.h"
  #include "testing/gmock/include/gmock/gmock.h"
  #include "testing/gtest/include/gtest/gtest.h"
  
  #if defined(OS_ANDROID)
  #include "chrome/browser/policy/cloud/user_policy_signin_service_mobile.h"
  #else
  #include "chrome/browser/policy/cloud/user_policy_signin_service.h"
  #endif
  
  namespace em = enterprise_management;
  
  using testing::AnyNumber;
  using testing::Mock;
  using testing::_;
  
  namespace policy {
  
  namespace {
  
  const char kTestGaiaId[] = "gaia-id-testuser@test.com";
  const char kTestUser[] = "testuser@test.com";
  
  #if !defined(OS_ANDROID)
  const char kValidTokenResponse[] =
      "{"
      "  \"access_token\": \"at1\","
      "  \"expires_in\": 3600,"
      "  \"token_type\": \"Bearer\""
      "}";
  #endif
  
  const char kHostedDomainResponse[] =
      "{"
      "  \"hd\": \"test.com\""
      "}";
  
  UserCloudPolicyManager* BuildCloudPolicyManager(
      content::BrowserContext* context) {
    MockUserCloudPolicyStore* store = new MockUserCloudPolicyStore();
    EXPECT_CALL(*store, Load()).Times(AnyNumber());
  
    return new UserCloudPolicyManager(
        std::unique_ptr<UserCloudPolicyStore>(store), base::FilePath(),
        std::unique_ptr<CloudExternalDataManager>(),
        base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(),
        base::ThreadTaskRunnerHandle::Get());
  }
  
  class UserPolicySigninServiceTest : public testing::Test {
   public:
    UserPolicySigninServiceTest()
        : mock_store_(NULL),
          thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
          register_completed_(false) {}
  
    MOCK_METHOD1(OnPolicyRefresh, void(bool));
  
    void OnRegisterCompleted(const std::string& dm_token,
                             const std::string& client_id) {
      register_completed_ = true;
      dm_token_ = dm_token;
      client_id_ = client_id;
    }
  
    void RegisterPolicyClientWithCallback(UserPolicySigninService* service) {
      // Policy client registration on Android depends on Token Service having
      // a valid login token, while on other platforms, the login refresh token
      // is specified directly.
  #if defined(OS_ANDROID)
      GetTokenService()->UpdateCredentials(
          AccountTrackerService::PickAccountIdForAccount(
              profile_.get()->GetPrefs(), kTestGaiaId, kTestUser),
          "oauth2_login_refresh_token");
  #endif
      service->RegisterForPolicy(
          kTestUser,
  #if defined(OS_ANDROID)
          kTestGaiaId,
  #else
          "mock_oauth_token",
  #endif
          base::Bind(&UserPolicySigninServiceTest::OnRegisterCompleted,
                     base::Unretained(this)));
      ASSERT_TRUE(IsRequestActive());
    }
  
    void SetUp() override {
      UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting(
          &device_management_service_);
  
      local_state_.reset(new TestingPrefServiceSimple);
      chrome::RegisterLocalState(local_state_->registry());
      system_request_context_getter_ = new net::TestURLRequestContextGetter(
          base::ThreadTaskRunnerHandle::Get());
      TestingBrowserProcess::GetGlobal()->SetSystemRequestContext(
          system_request_context_getter_.get());
      TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get());
  
      g_browser_process->browser_policy_connector()->Init(
          local_state_.get(), system_request_context_getter_);
  
      // Create a testing profile with cloud-policy-on-signin enabled, and bring
      // up a UserCloudPolicyManager with a MockUserCloudPolicyStore.
      std::unique_ptr<syncable_prefs::TestingPrefServiceSyncable> prefs(
          new syncable_prefs::TestingPrefServiceSyncable());
      chrome::RegisterUserProfilePrefs(prefs->registry());
  
      // UserCloudPolicyManagerFactory isn't a real
      // BrowserContextKeyedServiceFactory (it derives from
      // BrowserContextKeyedBaseFactory and exposes its own APIs to get
      // instances) so we have to inject our testing factory via a special
      // API before creating the profile.
      UserCloudPolicyManagerFactory::GetInstance()->RegisterTestingFactory(
          BuildCloudPolicyManager);
      TestingProfile::Builder builder;
      builder.SetPrefService(
          std::unique_ptr<syncable_prefs::PrefServiceSyncable>(std::move(prefs)));
      builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                                BuildFakeSigninManagerBase);
      builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
                                BuildFakeProfileOAuth2TokenService);
      builder.AddTestingFactory(AccountFetcherServiceFactory::GetInstance(),
                                FakeAccountFetcherServiceBuilder::BuildForTests);
      builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(),
                                signin::BuildTestSigninClient);
  
      profile_ = builder.Build();
      url_factory_.set_remove_fetcher_on_delete(true);
  
      signin_manager_ = static_cast<FakeSigninManager*>(
          SigninManagerFactory::GetForProfile(profile_.get()));
      // Tests are responsible for freeing the UserCloudPolicyManager instances
      // they inject.
      manager_.reset(UserCloudPolicyManagerFactory::GetForBrowserContext(
          profile_.get()));
      manager_->Init(&schema_registry_);
      mock_store_ = static_cast<MockUserCloudPolicyStore*>(
          manager_->core()->store());
      DCHECK(mock_store_);
      AddProfile();
  
      Mock::VerifyAndClearExpectations(mock_store_);
    }
  
    void TearDown() override {
      UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting(NULL);
      UserCloudPolicyManagerFactory::GetInstance()->ClearTestingFactory();
      // Free the profile before we clear out the browser prefs.
      profile_.reset();
      TestingBrowserProcess* testing_browser_process =
          TestingBrowserProcess::GetGlobal();
      testing_browser_process->SetLocalState(NULL);
      local_state_.reset();
      testing_browser_process->ShutdownBrowserPolicyConnector();
      base::RunLoop run_loop;
      run_loop.RunUntilIdle();
    }
  
    virtual void AddProfile() {
      // For this test, the user should not be signed in yet.
      DCHECK(!signin_manager_->IsAuthenticated());
  
      // Initializing UserPolicySigninService while the user is not signed in
      // should result in the store being cleared to remove any lingering policy.
      EXPECT_CALL(*mock_store_, Clear());
  
      // Let the SigninService know that the profile has been created.
      content::NotificationService::current()->Notify(
          chrome::NOTIFICATION_PROFILE_ADDED,
          content::Source<Profile>(profile_.get()),
          content::NotificationService::NoDetails());
    }
  
    FakeProfileOAuth2TokenService* GetTokenService() {
      ProfileOAuth2TokenService* service =
          ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
      return static_cast<FakeProfileOAuth2TokenService*>(service);
    }
  
    bool IsRequestActive() {
      if (!GetTokenService()->GetPendingRequests().empty())
        return true;
      return url_factory_.GetFetcherByID(0);
    }
  
    void MakeOAuthTokenFetchSucceed() {
      ASSERT_TRUE(IsRequestActive());
  #if defined(OS_ANDROID)
      GetTokenService()->IssueTokenForAllPendingRequests("access_token",
                                                         base::Time::Now());
  #else
      net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
      fetcher->set_response_code(net::HTTP_OK);
      fetcher->SetResponseString(kValidTokenResponse);
      fetcher->delegate()->OnURLFetchComplete(fetcher);
  #endif
    }
  
    void ReportHostedDomainStatus(bool is_hosted_domain) {
      ASSERT_TRUE(IsRequestActive());
      net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
      fetcher->set_response_code(net::HTTP_OK);
      fetcher->SetResponseString(is_hosted_domain ? kHostedDomainResponse : "{}");
      fetcher->delegate()->OnURLFetchComplete(fetcher);
    }
  
    void TestSuccessfulSignin() {
      UserPolicySigninService* signin_service =
          UserPolicySigninServiceFactory::GetForProfile(profile_.get());
      EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(0);
      RegisterPolicyClientWithCallback(signin_service);
  
      // Mimic successful oauth token fetch.
      MakeOAuthTokenFetchSucceed();
  
      // When the user is from a hosted domain, this should kick off client
      // registration.
      MockDeviceManagementJob* register_request = NULL;
      EXPECT_CALL(device_management_service_,
                  CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION, _))
          .WillOnce(device_management_service_.CreateAsyncJob(
              &register_request));
      EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
          .Times(1);
  
      // Now mimic the user being a hosted domain - this should cause a Register()
      // call.
      ReportHostedDomainStatus(true);
  
      // Should have no more outstanding requests.
      ASSERT_FALSE(IsRequestActive());
      Mock::VerifyAndClearExpectations(this);
      ASSERT_TRUE(register_request);
  
      // Mimic successful client registration - this should register the client
      // and invoke the callback.
      em::DeviceManagementResponse registration_blob;
      std::string expected_dm_token = "dm_token";
      registration_blob.mutable_register_response()->set_device_management_token(
          expected_dm_token);
      registration_blob.mutable_register_response()->set_enrollment_type(
          em::DeviceRegisterResponse::ENTERPRISE);
      register_request->SendResponse(DM_STATUS_SUCCESS, registration_blob);
  
      // UserCloudPolicyManager should not be initialized yet.
      ASSERT_FALSE(manager_->core()->service());
      EXPECT_TRUE(register_completed_);
      EXPECT_EQ(dm_token_, expected_dm_token);
  
      // Now call to fetch policy - this should fire off a fetch request.
      MockDeviceManagementJob* fetch_request = NULL;
      EXPECT_CALL(device_management_service_,
                  CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, _))
          .WillOnce(device_management_service_.CreateAsyncJob(&fetch_request));
      EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
          .Times(1);
  
      signin_service->FetchPolicyForSignedInUser(
          kTestUser,
          dm_token_,
          client_id_,
          profile_->GetRequestContext(),
          base::Bind(&UserPolicySigninServiceTest::OnPolicyRefresh,
                     base::Unretained(this)));
  
      Mock::VerifyAndClearExpectations(this);
      ASSERT_TRUE(fetch_request);
  
      // UserCloudPolicyManager should now be initialized.
      EXPECT_EQ(mock_store_->signin_username_, kTestUser);
      ASSERT_TRUE(manager_->core()->service());
  
      // Make the policy fetch succeed - this should result in a write to the
      // store and ultimately result in a call to OnPolicyRefresh().
      EXPECT_CALL(*mock_store_, Store(_));
      EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(1);
  
      // Create a fake policy blob to deliver to the client.
      em::DeviceManagementResponse policy_blob;
      em::PolicyData policy_data;
      policy_data.set_policy_type(dm_protocol::kChromeUserPolicyType);
      em::PolicyFetchResponse* policy_response =
          policy_blob.mutable_policy_response()->add_response();
      ASSERT_TRUE(policy_data.SerializeToString(
          policy_response->mutable_policy_data()));
      fetch_request->SendResponse(DM_STATUS_SUCCESS, policy_blob);
  
      // Complete the store which should cause the policy fetch callback to be
      // invoked.
      mock_store_->NotifyStoreLoaded();
      Mock::VerifyAndClearExpectations(this);
    }
  
    std::unique_ptr<TestingProfile> profile_;
    MockUserCloudPolicyStore* mock_store_;  // Not owned.
    SchemaRegistry schema_registry_;
    std::unique_ptr<UserCloudPolicyManager> manager_;
  
    // BrowserPolicyConnector and UrlFetcherFactory want to initialize and free
    // various components asynchronously via tasks, so create fake threads here.
    content::TestBrowserThreadBundle thread_bundle_;
  
    net::TestURLFetcherFactory url_factory_;
  
    FakeSigninManager* signin_manager_;
  
    // Used in conjunction with OnRegisterCompleted() to test client registration
    // callbacks.
    std::string dm_token_;
    std::string client_id_;
  
    // True if OnRegisterCompleted() was called.
    bool register_completed_;
  
    // Weak ptr to the MockDeviceManagementService (object is owned by the
    // BrowserPolicyConnector).
    MockDeviceManagementService device_management_service_;
  
    std::unique_ptr<TestingPrefServiceSimple> local_state_;
    scoped_refptr<net::URLRequestContextGetter> system_request_context_getter_;
  };
  
  class UserPolicySigninServiceSignedInTest : public UserPolicySigninServiceTest {
   public:
    void AddProfile() override {
      // UserCloudPolicyManager should not be initialized.
      ASSERT_FALSE(manager_->core()->service());
  
      // Set the user as signed in.
      SigninManagerFactory::GetForProfile(profile_.get())->
          SetAuthenticatedAccountInfo(kTestGaiaId, kTestUser);
  
      // Let the SigninService know that the profile has been created.
      content::NotificationService::current()->Notify(
          chrome::NOTIFICATION_PROFILE_ADDED,
          content::Source<Profile>(profile_.get()),
          content::NotificationService::NoDetails());
    }
  };
  
  TEST_F(UserPolicySigninServiceTest, InitWhileSignedOut) {
    // Make sure user is not signed in.
    ASSERT_FALSE(SigninManagerFactory::GetForProfile(profile_.get())->
        IsAuthenticated());
  
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());
  }
  
    // TODO(joaodasilva): these tests rely on issuing the OAuth2 login refresh
    // token after signin. Revisit this after figuring how to handle that on
    // Android.
  #if !defined(OS_ANDROID)
  
  TEST_F(UserPolicySigninServiceSignedInTest, InitWhileSignedIn) {
    // UserCloudPolicyManager should be initialized.
    ASSERT_TRUE(manager_->core()->service());
  
    // Complete initialization of the store.
    mock_store_->NotifyStoreLoaded();
  
    // No oauth access token yet, so client registration should be deferred.
    ASSERT_FALSE(IsRequestActive());
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // Client registration should be in progress since we now have an oauth token.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceSignedInTest, InitWhileSignedInOAuthError) {
    // UserCloudPolicyManager should be initialized.
    ASSERT_TRUE(manager_->core()->service());
  
    // Complete initialization of the store.
    mock_store_->NotifyStoreLoaded();
  
    // No oauth access token yet, so client registration should be deferred.
    ASSERT_FALSE(IsRequestActive());
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // Client registration should be in progress since we now have an oauth token.
    ASSERT_TRUE(IsRequestActive());
  
    // Now fail the access token fetch.
    GoogleServiceAuthError error(
        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
    GetTokenService()->IssueErrorForAllPendingRequests(error);
    ASSERT_FALSE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, SignInAfterInit) {
    // UserCloudPolicyManager should not be initialized since there is no
    // signed-in user.
    ASSERT_FALSE(manager_->core()->service());
  
    // Now sign in the user.
    SigninManagerFactory::GetForProfile(profile_.get())
        ->SetAuthenticatedAccountInfo(kTestGaiaId, kTestUser);
  
    // Complete initialization of the store.
    mock_store_->NotifyStoreLoaded();
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // UserCloudPolicyManager should be initialized.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(manager_->core()->service());
  
    // Client registration should be in progress since we have an oauth token.
    ASSERT_TRUE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, SignInWithNonEnterpriseUser) {
    // UserCloudPolicyManager should not be initialized since there is no
    // signed-in user.
    ASSERT_FALSE(manager_->core()->service());
  
    // Now sign in a non-enterprise user (blacklisted gmail.com domain).
    SigninManagerFactory::GetForProfile(profile_.get())
        ->SetAuthenticatedAccountInfo("gaia-id-non_enterprise_user@gmail.com",
                                      "non_enterprise_user@gmail.com");
  
    // Complete initialization of the store.
    mock_store_->NotifyStoreLoaded();
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // UserCloudPolicyManager should not be initialized and there should be no
    // DMToken request active.
    ASSERT_TRUE(!manager_->core()->service());
    ASSERT_FALSE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, UnregisteredClient) {
    // UserCloudPolicyManager should not be initialized since there is no
    // signed-in user.
    ASSERT_FALSE(manager_->core()->service());
  
    // Now sign in the user.
    SigninManagerFactory::GetForProfile(profile_.get())
        ->SetAuthenticatedAccountInfo(kTestGaiaId, kTestUser);
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // UserCloudPolicyManager should be initialized.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(manager_->core()->service());
  
    // Client registration should not be in progress since the store is not
    // yet initialized.
    ASSERT_FALSE(IsRequestActive());
  
    // Complete initialization of the store with no policy (unregistered client).
    mock_store_->NotifyStoreLoaded();
  
    // Client registration should be in progress since we have an oauth token.
    ASSERT_TRUE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, RegisteredClient) {
    // UserCloudPolicyManager should not be initialized since there is no
    // signed-in user.
    ASSERT_FALSE(manager_->core()->service());
  
    // Now sign in the user.
    SigninManagerFactory::GetForProfile(profile_.get())
        ->SetAuthenticatedAccountInfo(kTestGaiaId, kTestUser);
  
    // Make oauth token available.
    GetTokenService()->UpdateCredentials(
        SigninManagerFactory::GetForProfile(profile_.get())
            ->GetAuthenticatedAccountId(),
        "oauth_login_refresh_token");
  
    // UserCloudPolicyManager should be initialized.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(manager_->core()->service());
  
    // Client registration should not be in progress since the store is not
    // yet initialized.
    ASSERT_FALSE(manager_->IsClientRegistered());
    ASSERT_FALSE(IsRequestActive());
  
    mock_store_->policy_.reset(new enterprise_management::PolicyData());
    mock_store_->policy_->set_request_token("fake token");
    mock_store_->policy_->set_device_id("fake client id");
  
    // Complete initialization of the store.
    mock_store_->NotifyStoreLoaded();
  
    // Client registration should not be in progress since the client should be
    // already registered.
    ASSERT_TRUE(manager_->IsClientRegistered());
    ASSERT_FALSE(IsRequestActive());
  }
  
  #endif  // !defined(OS_ANDROID)
  
  TEST_F(UserPolicySigninServiceSignedInTest, SignOutAfterInit) {
    // UserCloudPolicyManager should be initialized.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(manager_->core()->service());
  
    // Signing out will clear the policy from the store.
    EXPECT_CALL(*mock_store_, Clear());
  
    // Now sign out.
    SigninManagerFactory::GetForProfile(profile_.get())
        ->SignOut(signin_metrics::SIGNOUT_TEST,
                  signin_metrics::SignoutDelete::IGNORE_METRIC);
  
    // UserCloudPolicyManager should be shut down.
    ASSERT_FALSE(manager_->core()->service());
  }
  
  TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientOAuthFailure) {
    UserPolicySigninService* signin_service =
        UserPolicySigninServiceFactory::GetForProfile(profile_.get());
    RegisterPolicyClientWithCallback(signin_service);
    Mock::VerifyAndClearExpectations(this);
  
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());
    ASSERT_TRUE(IsRequestActive());
    EXPECT_FALSE(register_completed_);
  
    // Cause the access token fetch to fail - callback should be invoked.
  #if defined(OS_ANDROID)
    ASSERT_TRUE(!GetTokenService()->GetPendingRequests().empty());
    GetTokenService()->IssueErrorForAllPendingRequests(
        GoogleServiceAuthError::FromServiceError("fail"));
  #else
    net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
    fetcher->set_status(net::URLRequestStatus::FromError(net::ERR_FAILED));
    fetcher->delegate()->OnURLFetchComplete(fetcher);
  #endif
  
    EXPECT_TRUE(register_completed_);
    EXPECT_TRUE(dm_token_.empty());
    EXPECT_FALSE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientNonHostedDomain) {
    UserPolicySigninService* signin_service =
        UserPolicySigninServiceFactory::GetForProfile(profile_.get());
    RegisterPolicyClientWithCallback(signin_service);
  
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());
    ASSERT_TRUE(IsRequestActive());
  
    // Cause the access token request to succeed.
    MakeOAuthTokenFetchSucceed();
  
    // Should be a follow-up fetch to check the hosted-domain status.
    ASSERT_TRUE(IsRequestActive());
    Mock::VerifyAndClearExpectations(this);
  
    EXPECT_FALSE(register_completed_);
  
    // Report that the user is not on a hosted domain - callback should be
    // invoked reporting a failed fetch.
    ReportHostedDomainStatus(false);
  
    // Since this is not a hosted domain, we should not issue a request for a
    // DMToken.
    EXPECT_TRUE(register_completed_);
    EXPECT_TRUE(dm_token_.empty());
    ASSERT_FALSE(IsRequestActive());
  }
  
  TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientFailedRegistration) {
    UserPolicySigninService* signin_service =
        UserPolicySigninServiceFactory::GetForProfile(profile_.get());
    RegisterPolicyClientWithCallback(signin_service);
  
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());
  
    // Mimic successful oauth token fetch.
    MakeOAuthTokenFetchSucceed();
  
    EXPECT_FALSE(register_completed_);
  
    // When the user is from a hosted domain, this should kick off client
    // registration.
    MockDeviceManagementJob* register_request = NULL;
    EXPECT_CALL(device_management_service_,
                CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION, _))
        .WillOnce(device_management_service_.CreateAsyncJob(&register_request));
    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
          .Times(1);
  
    // Now mimic the user being a hosted domain - this should cause a Register()
    // call.
    ReportHostedDomainStatus(true);
  
    // Should have no more outstanding requests.
    ASSERT_FALSE(IsRequestActive());
    Mock::VerifyAndClearExpectations(this);
    ASSERT_TRUE(register_request);
    EXPECT_FALSE(register_completed_);
  
    // Make client registration fail (hosted domain user that is not managed).
    register_request->SendResponse(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED,
                                   em::DeviceManagementResponse());
    EXPECT_TRUE(register_completed_);
    EXPECT_TRUE(dm_token_.empty());
  }
  
  TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientSucceeded) {
    UserPolicySigninService* signin_service =
        UserPolicySigninServiceFactory::GetForProfile(profile_.get());
    RegisterPolicyClientWithCallback(signin_service);
  
    // Mimic successful oauth token fetch.
    MakeOAuthTokenFetchSucceed();
  
    // When the user is from a hosted domain, this should kick off client
    // registration.
    MockDeviceManagementJob* register_request = NULL;
    EXPECT_CALL(device_management_service_,
                CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION, _))
        .WillOnce(device_management_service_.CreateAsyncJob(&register_request));
    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
        .Times(1);
  
    // Now mimic the user being a hosted domain - this should cause a Register()
    // call.
    ReportHostedDomainStatus(true);
  
    // Should have no more outstanding requests.
    ASSERT_FALSE(IsRequestActive());
    Mock::VerifyAndClearExpectations(this);
    ASSERT_TRUE(register_request);
    EXPECT_FALSE(register_completed_);
  
    em::DeviceManagementResponse registration_blob;
    std::string expected_dm_token = "dm_token";
    registration_blob.mutable_register_response()->set_device_management_token(
        expected_dm_token);
    registration_blob.mutable_register_response()->set_enrollment_type(
        em::DeviceRegisterResponse::ENTERPRISE);
    register_request->SendResponse(DM_STATUS_SUCCESS, registration_blob);
    Mock::VerifyAndClearExpectations(this);
    EXPECT_TRUE(register_completed_);
    EXPECT_EQ(dm_token_, expected_dm_token);
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());
  }
  
  TEST_F(UserPolicySigninServiceTest, FetchPolicyFailed) {
    // Initiate a policy fetch request.
    MockDeviceManagementJob* fetch_request = NULL;
    EXPECT_CALL(device_management_service_,
                CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, _))
        .WillOnce(device_management_service_.CreateAsyncJob(&fetch_request));
    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
        .Times(1);
    UserPolicySigninService* signin_service =
        UserPolicySigninServiceFactory::GetForProfile(profile_.get());
    signin_service->FetchPolicyForSignedInUser(
        kTestUser,
        "mock_dm_token",
        "mock_client_id",
        profile_->GetRequestContext(),
        base::Bind(&UserPolicySigninServiceTest::OnPolicyRefresh,
                   base::Unretained(this)));
    ASSERT_TRUE(fetch_request);
  
    // Make the policy fetch fail.
    EXPECT_CALL(*this, OnPolicyRefresh(false)).Times(1);
    fetch_request->SendResponse(DM_STATUS_REQUEST_FAILED,
                                em::DeviceManagementResponse());
  
    // UserCloudPolicyManager should be initialized.
    EXPECT_EQ(mock_store_->signin_username_, kTestUser);
    ASSERT_TRUE(manager_->core()->service());
  }
  
  TEST_F(UserPolicySigninServiceTest, FetchPolicySuccess) {
    ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
  }
  
  TEST_F(UserPolicySigninServiceTest, SignOutThenSignInAgain) {
    ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
  
    EXPECT_CALL(*mock_store_, Clear());
    signin_manager_->ForceSignOut();
    ASSERT_FALSE(manager_->core()->service());
  
    // Now sign in again.
    ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
  }
  
  TEST_F(UserPolicySigninServiceTest, PolicyFetchFailureTemporary) {
    ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
  
    ASSERT_TRUE(manager_->IsClientRegistered());
  
    // Kick off another policy fetch.
    MockDeviceManagementJob* fetch_request = NULL;
    EXPECT_CALL(device_management_service_,
                CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, _))
        .WillOnce(device_management_service_.CreateAsyncJob(&fetch_request));
    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
        .Times(1);
    manager_->RefreshPolicies();
    Mock::VerifyAndClearExpectations(this);
  
    // Now, fake a transient error from the server on this policy fetch. This
    // should have no impact on the cached policy.
    fetch_request->SendResponse(DM_STATUS_REQUEST_FAILED,
                                em::DeviceManagementResponse());
    base::RunLoop().RunUntilIdle();
    ASSERT_TRUE(manager_->IsClientRegistered());
  }
  
  TEST_F(UserPolicySigninServiceTest, PolicyFetchFailureDisableManagement) {
    ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin());
  
    EXPECT_TRUE(manager_->IsClientRegistered());
  #if !defined(OS_ANDROID)
    EXPECT_TRUE(signin_manager_->IsSignoutProhibited());
  #endif
  
    // Kick off another policy fetch.
    MockDeviceManagementJob* fetch_request = NULL;
    EXPECT_CALL(device_management_service_,
                CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, _))
        .WillOnce(device_management_service_.CreateAsyncJob(&fetch_request));
    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _))
        .Times(1);
    manager_->RefreshPolicies();
    Mock::VerifyAndClearExpectations(this);
  
    // Now, fake a SC_FORBIDDEN error from the server on this policy fetch. This
    // indicates that chrome management is disabled and will result in the cached
    // policy being removed and the manager shut down.
    EXPECT_CALL(*mock_store_, Clear());
    fetch_request->SendResponse(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED,
                                em::DeviceManagementResponse());
    base::RunLoop().RunUntilIdle();
    EXPECT_FALSE(manager_->IsClientRegistered());
  #if !defined(OS_ANDROID)
    EXPECT_FALSE(signin_manager_->IsSignoutProhibited());
  #endif
  }
  
  }  // namespace
  
  }  // namespace policy
  