// Copyright (c) 2011 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_policy_cache.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/policy/device_policy_identity_strategy.h"
#include "chrome/browser/policy/enterprise_install_attributes.h"
#include "policy/configuration_policy_type.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
namespace {
// Test registration user name.
const char kTestUser[] = "test@example.com";
using ::chromeos::SignedSettings;
using ::chromeos::SignedSettingsHelper;
using ::testing::_;
using ::testing::InSequence;
class MockSignedSettingsHelper : public SignedSettingsHelper {
public:
MockSignedSettingsHelper() {}
virtual ~MockSignedSettingsHelper() {}
MOCK_METHOD2(StartStorePolicyOp, void(const em::PolicyFetchResponse&,
SignedSettingsHelper::Callback*));
MOCK_METHOD1(StartRetrievePolicyOp, void(SignedSettingsHelper::Callback*));
MOCK_METHOD1(CancelCallback, void(SignedSettingsHelper::Callback*));
// This test doesn't need these methods, but since they're pure virtual in
// SignedSettingsHelper, they must be implemented:
MOCK_METHOD2(StartCheckWhitelistOp, void(const std::string&,
SignedSettingsHelper::Callback*));
MOCK_METHOD3(StartWhitelistOp, void(const std::string&, bool,
SignedSettingsHelper::Callback*));
MOCK_METHOD3(StartStorePropertyOp, void(const std::string&,
const std::string&,
SignedSettingsHelper::Callback*));
MOCK_METHOD2(StartRetrieveProperty, void(const std::string&,
SignedSettingsHelper::Callback*));
private:
DISALLOW_COPY_AND_ASSIGN(MockSignedSettingsHelper);
};
ACTION_P(MockSignedSettingsHelperStorePolicy, status_code) {
arg1->OnStorePolicyCompleted(status_code);
}
ACTION_P2(MockSignedSettingsHelperRetrievePolicy, status_code, policy) {
arg0->OnRetrievePolicyCompleted(status_code, policy);
}
void CreateRefreshRatePolicy(em::PolicyFetchResponse* policy,
const std::string& user,
int refresh_rate) {
// This method omits a few fields which currently aren't needed by tests:
// timestamp, machine_name, policy_type, public key info.
em::PolicyData signed_response;
em::ChromeDeviceSettingsProto settings;
settings.mutable_policy_refresh_rate()->set_policy_refresh_rate(refresh_rate);
signed_response.set_username(user);
signed_response.set_request_token("dmtoken");
signed_response.set_device_id("deviceid");
EXPECT_TRUE(
settings.SerializeToString(signed_response.mutable_policy_value()));
std::string serialized_signed_response;
EXPECT_TRUE(signed_response.SerializeToString(&serialized_signed_response));
policy->set_policy_data(serialized_signed_response);
}
void CreateProxyPolicy(em::PolicyFetchResponse* policy,
const std::string& user,
const std::string& proxy_mode,
const std::string& proxy_server,
const std::string& proxy_pac_url,
const std::string& proxy_bypass_list) {
em::PolicyData signed_response;
em::ChromeDeviceSettingsProto settings;
em::DeviceProxySettingsProto* proxy_settings =
settings.mutable_device_proxy_settings();
proxy_settings->set_proxy_mode(proxy_mode);
proxy_settings->set_proxy_server(proxy_server);
proxy_settings->set_proxy_pac_url(proxy_pac_url);
proxy_settings->set_proxy_bypass_list(proxy_bypass_list);
signed_response.set_username(user);
signed_response.set_request_token("dmtoken");
signed_response.set_device_id("deviceid");
EXPECT_TRUE(
settings.SerializeToString(signed_response.mutable_policy_value()));
std::string serialized_signed_response;
EXPECT_TRUE(signed_response.SerializeToString(&serialized_signed_response));
policy->set_policy_data(serialized_signed_response);
}
} // namespace
class DevicePolicyCacheTest : public testing::Test {
protected:
DevicePolicyCacheTest()
: cryptohome_(chromeos::CryptohomeLibrary::GetImpl(true)),
install_attributes_(cryptohome_.get()) {}
virtual void SetUp() {
cache_.reset(new DevicePolicyCache(&identity_strategy_,
&install_attributes_,
&signed_settings_helper_));
}
virtual void TearDown() {
EXPECT_CALL(signed_settings_helper_, CancelCallback(_));
cache_.reset();
}
void MakeEnterpriseDevice(const char* registration_user) {
ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
install_attributes_.LockDevice(registration_user));
}
const Value* GetMandatoryPolicy(ConfigurationPolicyType policy) {
return cache_->mandatory_policy_.Get(policy);
}
const Value* GetRecommendedPolicy(ConfigurationPolicyType policy) {
return cache_->recommended_policy_.Get(policy);
}
scoped_ptr<chromeos::CryptohomeLibrary> cryptohome_;
EnterpriseInstallAttributes install_attributes_;
DevicePolicyIdentityStrategy identity_strategy_;
MockSignedSettingsHelper signed_settings_helper_;
scoped_ptr<DevicePolicyCache> cache_;
private:
DISALLOW_COPY_AND_ASSIGN(DevicePolicyCacheTest);
};
TEST_F(DevicePolicyCacheTest, Startup) {
em::PolicyFetchResponse policy;
CreateRefreshRatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
policy));
cache_->Load();
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
FundamentalValue expected(120);
EXPECT_TRUE(Value::Equals(&expected,
GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
TEST_F(DevicePolicyCacheTest, SetPolicy) {
InSequence s;
MakeEnterpriseDevice(kTestUser);
// Startup.
em::PolicyFetchResponse policy;
CreateRefreshRatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
policy));
cache_->Load();
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
FundamentalValue expected(120);
EXPECT_TRUE(Value::Equals(&expected,
GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
// Set new policy information.
em::PolicyFetchResponse new_policy;
CreateRefreshRatePolicy(&new_policy, kTestUser, 300);
EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).WillOnce(
MockSignedSettingsHelperStorePolicy(chromeos::SignedSettings::SUCCESS));
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
new_policy));
cache_->SetPolicy(new_policy);
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
FundamentalValue updated_expected(300);
EXPECT_TRUE(Value::Equals(&updated_expected,
GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
TEST_F(DevicePolicyCacheTest, SetPolicyWrongUser) {
InSequence s;
MakeEnterpriseDevice(kTestUser);
// Startup.
em::PolicyFetchResponse policy;
CreateRefreshRatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
policy));
cache_->Load();
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
// Set new policy information. This should fail due to invalid user.
em::PolicyFetchResponse new_policy;
CreateRefreshRatePolicy(&new_policy, "foreign_user@example.com", 300);
EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).Times(0);
cache_->SetPolicy(new_policy);
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
FundamentalValue expected(120);
EXPECT_TRUE(Value::Equals(&expected,
GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
TEST_F(DevicePolicyCacheTest, SetPolicyNonEnterpriseDevice) {
InSequence s;
// Startup.
em::PolicyFetchResponse policy;
CreateRefreshRatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
policy));
cache_->Load();
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
// Set new policy information. This should fail due to invalid user.
em::PolicyFetchResponse new_policy;
CreateRefreshRatePolicy(&new_policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).Times(0);
cache_->SetPolicy(new_policy);
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
FundamentalValue expected(120);
EXPECT_TRUE(Value::Equals(&expected,
GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
TEST_F(DevicePolicyCacheTest, SetProxyPolicy) {
InSequence s;
MakeEnterpriseDevice(kTestUser);
// Startup.
em::PolicyFetchResponse policy;
CreateProxyPolicy(&policy, kTestUser, "direct", "http://proxy:8080",
"http://proxy:8080/pac.js", "127.0.0.1,example.com");
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
policy));
cache_->Load();
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
StringValue expected_proxy_mode("direct");
StringValue expected_proxy_server("http://proxy:8080");
StringValue expected_proxy_pac_url("http://proxy:8080/pac.js");
StringValue expected_proxy_bypass_list("127.0.0.1,example.com");
EXPECT_TRUE(Value::Equals(&expected_proxy_mode,
GetRecommendedPolicy(kPolicyProxyMode)));
EXPECT_TRUE(Value::Equals(&expected_proxy_server,
GetRecommendedPolicy(kPolicyProxyServer)));
EXPECT_TRUE(Value::Equals(&expected_proxy_pac_url,
GetRecommendedPolicy(kPolicyProxyPacUrl)));
EXPECT_TRUE(Value::Equals(&expected_proxy_bypass_list,
GetRecommendedPolicy(kPolicyProxyBypassList)));
}
} // namespace policy