// 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 "chrome/browser/policy/device_token_fetcher.h" #include "base/files/scoped_temp_dir.h" #include "base/message_loop.h" #include "chrome/browser/policy/cloud_policy_data_store.h" #include "chrome/browser/policy/logging_work_scheduler.h" #include "chrome/browser/policy/mock_cloud_policy_data_store.h" #include "chrome/browser/policy/mock_device_management_service.h" #include "chrome/browser/policy/policy_notifier.h" #include "chrome/browser/policy/user_policy_cache.h" #include "content/public/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace em = enterprise_management; namespace policy { const char kTestToken[] = "device_token_fetcher_test_auth_token"; using content::BrowserThread; using testing::AnyNumber; using testing::Mock; using testing::_; ACTION_P(VerifyRegisterRequest, known_machine_id) { ASSERT_TRUE(arg6.has_register_request()); const em::DeviceRegisterRequest& request = arg6.register_request(); if (known_machine_id) { EXPECT_TRUE(request.has_auto_enrolled()); EXPECT_TRUE(request.auto_enrolled()); } else { EXPECT_FALSE(request.has_auto_enrolled()); } } class DeviceTokenFetcherTest : public testing::Test { protected: DeviceTokenFetcherTest() : ui_thread_(BrowserThread::UI, &loop_), file_thread_(BrowserThread::FILE, &loop_) { EXPECT_TRUE(temp_user_data_dir_.CreateUniqueTempDir()); successful_registration_response_.mutable_register_response()-> set_device_management_token("fake_token"); successful_registration_response_.mutable_register_response()-> set_enrollment_type(em::DeviceRegisterResponse::ENTERPRISE); } virtual void SetUp() { cache_.reset(new UserPolicyCache( temp_user_data_dir_.path().AppendASCII("DeviceTokenFetcherTest"), false /* wait_for_policy_fetch */)); EXPECT_CALL(service_, StartJob(_, _, _, _, _, _, _)).Times(AnyNumber()); data_store_.reset(CloudPolicyDataStore::CreateForUserPolicies()); data_store_->AddObserver(&observer_); } virtual void TearDown() { loop_.RunUntilIdle(); data_store_->RemoveObserver(&observer_); } void FetchToken(DeviceTokenFetcher* fetcher, CloudPolicyDataStore* store) { store->SetupForTesting("", "fake_device_id", "fake_user_name", "fake_auth_token", true); fetcher->FetchToken(); } void CreateNewWaitingCache() { cache_.reset(new UserPolicyCache( temp_user_data_dir_.path().AppendASCII("DeviceTokenFetcherTest"), true /* wait_for_policy_fetch */)); // Make this cache's disk cache ready, but have it still waiting for a // policy fetch. cache_->Load(); loop_.RunUntilIdle(); ASSERT_TRUE(cache_->last_policy_refresh_time().is_null()); ASSERT_FALSE(cache_->IsReady()); } void SetUpSuccessfulRegistrationExpectation(bool known_machine_id) { EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.SucceedJob(successful_registration_response_)); EXPECT_CALL(service_, StartJob(_, _, _, _, _, _, _)) .WillOnce(VerifyRegisterRequest(known_machine_id)); } MessageLoop loop_; MockDeviceManagementService service_; scoped_ptr cache_; scoped_ptr data_store_; MockCloudPolicyDataStoreObserver observer_; PolicyNotifier notifier_; base::ScopedTempDir temp_user_data_dir_; em::DeviceManagementResponse successful_registration_response_; private: content::TestBrowserThread ui_thread_; content::TestBrowserThread file_thread_; }; TEST_F(DeviceTokenFetcherTest, FetchToken) { testing::InSequence s; SetUpSuccessfulRegistrationExpectation(false); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); EXPECT_CALL(observer_, OnDeviceTokenChanged()); EXPECT_EQ("", data_store_->device_token()); EXPECT_EQ(DEVICE_MODE_PENDING, data_store_->device_mode()); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); std::string token = data_store_->device_token(); EXPECT_NE("", token); // User policy registration should not set enrollment mode. EXPECT_EQ(DEVICE_MODE_PENDING, data_store_->device_mode()); // Calling FetchToken() again should result in a new token being fetched. successful_registration_response_.mutable_register_response()-> set_device_management_token("new_fake_token"); EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.SucceedJob(successful_registration_response_)); EXPECT_CALL(observer_, OnDeviceTokenChanged()); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); std::string token2 = data_store_->device_token(); EXPECT_NE("", token2); EXPECT_NE(token, token2); } TEST_F(DeviceTokenFetcherTest, FetchDeviceToken) { testing::InSequence s; scoped_ptr data_store( CloudPolicyDataStore::CreateForDevicePolicies()); SetUpSuccessfulRegistrationExpectation(false); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store.get(), ¬ifier_); EXPECT_EQ("", data_store->device_token()); EXPECT_EQ(DEVICE_MODE_PENDING, data_store->device_mode()); FetchToken(&fetcher, data_store.get()); loop_.RunUntilIdle(); EXPECT_NE("", data_store->device_token()); // For device registrations, the fetcher needs to determine device mode. EXPECT_EQ(DEVICE_MODE_ENTERPRISE, data_store->device_mode()); } TEST_F(DeviceTokenFetcherTest, FetchDeviceTokenMissingMode) { testing::InSequence s; scoped_ptr data_store( CloudPolicyDataStore::CreateForDevicePolicies()); SetUpSuccessfulRegistrationExpectation(false); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store.get(), ¬ifier_); EXPECT_EQ("", data_store->device_token()); EXPECT_EQ(DEVICE_MODE_PENDING, data_store->device_mode()); successful_registration_response_.mutable_register_response()-> clear_enrollment_type(); FetchToken(&fetcher, data_store.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); EXPECT_NE("", data_store->device_token()); EXPECT_EQ(DEVICE_MODE_ENTERPRISE, data_store->device_mode()); } TEST_F(DeviceTokenFetcherTest, RetryOnError) { testing::InSequence s; EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.FailJob(DM_STATUS_REQUEST_FAILED)) .WillOnce(service_.SucceedJob(successful_registration_response_)); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_, new DummyWorkScheduler); EXPECT_CALL(observer_, OnDeviceTokenChanged()); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); EXPECT_NE("", data_store_->device_token()); } TEST_F(DeviceTokenFetcherTest, UnmanagedDevice) { EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.FailJob(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED)); EXPECT_FALSE(cache_->is_unmanaged()); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); EXPECT_CALL(observer_, OnDeviceTokenChanged()).Times(0); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); EXPECT_EQ("", data_store_->device_token()); EXPECT_TRUE(cache_->is_unmanaged()); } TEST_F(DeviceTokenFetcherTest, DontSetFetchingDone) { CreateNewWaitingCache(); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); EXPECT_FALSE(cache_->IsReady()); } TEST_F(DeviceTokenFetcherTest, DontSetFetchingDoneWithoutPolicyFetch) { CreateNewWaitingCache(); EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.SucceedJob(successful_registration_response_)); EXPECT_CALL(observer_, OnDeviceTokenChanged()); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); // On successful token fetching the cache isn't set to ready, since the next // step is to fetch policy. Only failures to fetch the token should make // the cache ready. EXPECT_FALSE(cache_->IsReady()); } TEST_F(DeviceTokenFetcherTest, SetFetchingDoneWhenUnmanaged) { CreateNewWaitingCache(); cache_->SetUnmanaged(); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); EXPECT_TRUE(cache_->IsReady()); } TEST_F(DeviceTokenFetcherTest, SetFetchingDoneOnFailures) { CreateNewWaitingCache(); EXPECT_CALL(service_, CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)) .WillOnce(service_.FailJob(DM_STATUS_REQUEST_FAILED)); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); // This is the opposite case of DontSetFetchingDone1. EXPECT_TRUE(cache_->IsReady()); } TEST_F(DeviceTokenFetcherTest, SetKnownMachineId) { SetUpSuccessfulRegistrationExpectation(true); DeviceTokenFetcher fetcher(&service_, cache_.get(), data_store_.get(), ¬ifier_); EXPECT_CALL(observer_, OnDeviceTokenChanged()); EXPECT_EQ("", data_store_->device_token()); data_store_->set_known_machine_id(true); FetchToken(&fetcher, data_store_.get()); loop_.RunUntilIdle(); Mock::VerifyAndClearExpectations(&observer_); std::string token = data_store_->device_token(); EXPECT_NE("", token); } } // namespace policy