// 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 "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/prefs/pref_service.h"
#include "base/run_loop.h"
#include "base/time/time.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/fake_profile_oauth2_token_service.h"
#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
#include "chrome/browser/signin/fake_signin_manager.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_pref_service_syncable.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/signin/core/browser/signin_manager.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/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 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\""
    "}";

class SigninManagerFake : public FakeSigninManager {
 public:
  explicit SigninManagerFake(Profile* profile)
      : FakeSigninManager(profile) {
    Initialize(NULL);
  }

  void ForceSignOut() {
    // Allow signing out now.
    prohibit_signout_ = false;
    SignOut(signin_metrics::SIGNOUT_TEST);
  }

  static KeyedService* Build(content::BrowserContext* profile) {
    return new SigninManagerFake(static_cast<Profile*>(profile));
  }
};

UserCloudPolicyManager* BuildCloudPolicyManager(
    content::BrowserContext* context) {
  MockUserCloudPolicyStore *store = new MockUserCloudPolicyStore();
  EXPECT_CALL(*store, Load()).Times(AnyNumber());

  return new UserCloudPolicyManager(
      scoped_ptr<UserCloudPolicyStore>(store),
      base::FilePath(),
      scoped_ptr<CloudExternalDataManager>(),
      base::MessageLoopProxy::current(),
      base::MessageLoopProxy::current(),
      base::MessageLoopProxy::current());
}

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()->IssueRefreshTokenForUser(kTestUser,
                                                "oauth2_login_refresh_token");
#endif
    service->RegisterForPolicy(
        kTestUser,
#if !defined(OS_ANDROID)
        "mock_oauth_token",
#endif
        base::Bind(&UserPolicySigninServiceTest::OnRegisterCompleted,
                   base::Unretained(this)));
    ASSERT_TRUE(IsRequestActive());
  }

  virtual 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::MessageLoopProxy::current());
    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.
    scoped_ptr<TestingPrefServiceSyncable> prefs(
        new 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(scoped_ptr<PrefServiceSyncable>(prefs.Pass()));
    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                              SigninManagerFake::Build);
    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
                              BuildFakeProfileOAuth2TokenService);

    profile_ = builder.Build().Pass();
    url_factory_.set_remove_fetcher_on_delete(true);

    signin_manager_ = static_cast<SigninManagerFake*>(
        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_);
  }

  virtual 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->SetBrowserPolicyConnector(NULL);
    base::RunLoop run_loop;
    run_loop.RunUntilIdle();
  }

  virtual void AddProfile() {
    // For this test, the user should not be signed in yet.
    DCHECK(signin_manager_->GetAuthenticatedUsername().empty());

    // 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);
  }

  scoped_ptr<TestingProfile> profile_;
  MockUserCloudPolicyStore* mock_store_;  // Not owned.
  SchemaRegistry schema_registry_;
  scoped_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_;

  SigninManagerFake* 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_;

  scoped_ptr<TestingPrefServiceSimple> local_state_;
  scoped_refptr<net::URLRequestContextGetter> system_request_context_getter_;
};

class UserPolicySigninServiceSignedInTest : public UserPolicySigninServiceTest {
 public:
  virtual void AddProfile() OVERRIDE {
    // UserCloudPolicyManager should not be initialized.
    ASSERT_FALSE(manager_->core()->service());

    // Set the user as signed in.
    SigninManagerFactory::GetForProfile(profile_.get())->
        SetAuthenticatedUsername(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_TRUE(SigninManagerFactory::GetForProfile(profile_.get())->
      GetAuthenticatedUsername().empty());

  // 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()->IssueRefreshTokenForUser(kTestUser,
                                              "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()->IssueRefreshTokenForUser(kTestUser,
                                              "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())->SetAuthenticatedUsername(
      kTestUser);

  // Complete initialization of the store.
  mock_store_->NotifyStoreLoaded();

  // Make oauth token available.
  GetTokenService()->IssueRefreshTokenForUser(kTestUser,
                                              "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())->SetAuthenticatedUsername(
      "non_enterprise_user@gmail.com");

  // Complete initialization of the store.
  mock_store_->NotifyStoreLoaded();

  // Make oauth token available.
  GetTokenService()->IssueRefreshTokenForUser(kTestUser,
                                              "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())->SetAuthenticatedUsername(
      kTestUser);

  // Make oauth token available.
  GetTokenService()->IssueRefreshTokenForUser(kTestUser,
                                              "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())->SetAuthenticatedUsername(
      kTestUser);

  // Make oauth token available.
  GetTokenService()->IssueRefreshTokenForUser(kTestUser,
                                              "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);

  // 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(net::URLRequestStatus::FAILED, -1));
  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
