diff options
author | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-05 16:31:38 +0000 |
---|---|---|
committer | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-05 16:31:38 +0000 |
commit | 03692031cf235aee54219d339a09c5e690c1650e (patch) | |
tree | e620d30b5213f6f714db167956a600072908c0f9 | |
parent | 8358c7a868410c5806649572a32d5b420cc5dfef (diff) | |
download | chromium_src-03692031cf235aee54219d339a09c5e690c1650e.zip chromium_src-03692031cf235aee54219d339a09c5e690c1650e.tar.gz chromium_src-03692031cf235aee54219d339a09c5e690c1650e.tar.bz2 |
Implement device management policy cache.
This decodes the device management policy information and keeps a local cache of the policy information on disk.
BUG=62036
TEST=unit tests
Review URL: http://codereview.chromium.org/4338004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65208 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/policy/device_management_policy_cache.cc | 222 | ||||
-rw-r--r-- | chrome/browser/policy/device_management_policy_cache.h | 76 | ||||
-rw-r--r-- | chrome/browser/policy/device_management_policy_cache_unittest.cc | 294 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
5 files changed, 595 insertions, 0 deletions
diff --git a/chrome/browser/policy/device_management_policy_cache.cc b/chrome/browser/policy/device_management_policy_cache.cc new file mode 100644 index 0000000..b70ced4 --- /dev/null +++ b/chrome/browser/policy/device_management_policy_cache.cc @@ -0,0 +1,222 @@ +// Copyright (c) 2010 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_management_policy_cache.h" + +#include <limits> +#include <string> + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/values.h" +#include "chrome/browser/browser_thread.h" + +using google::protobuf::RepeatedField; +using google::protobuf::RepeatedPtrField; + +namespace policy { + +// A task implementation that saves policy information to a file. +class PersistPolicyTask : public Task { + public: + PersistPolicyTask(const FilePath& path, + const em::DevicePolicyResponse* policy); + + private: + // Task override. + virtual void Run(); + + const FilePath path_; + scoped_ptr<const em::DevicePolicyResponse> policy_; +}; + +PersistPolicyTask::PersistPolicyTask(const FilePath& path, + const em::DevicePolicyResponse* policy) + : path_(path), + policy_(policy) { +} + +void PersistPolicyTask::Run() { + std::string data; + if (!policy_->SerializeToString(&data)) { + LOG(WARNING) << "Failed to serialize policy data"; + return; + } + + int size = data.size(); + if (file_util::WriteFile(path_, data.c_str(), size) != size) { + LOG(WARNING) << "Failed to write " << path_.value(); + return; + } +} + +DeviceManagementPolicyCache::DeviceManagementPolicyCache( + const FilePath& backing_file_path) + : backing_file_path_(backing_file_path), + policy_(new DictionaryValue), + fresh_policy_(false) { +} + +void DeviceManagementPolicyCache::LoadPolicyFromFile() { + if (!file_util::PathExists(backing_file_path_) || fresh_policy_) + return; + + // Read the protobuf from the file. + std::string data; + if (!file_util::ReadFileToString(backing_file_path_, &data)) { + LOG(WARNING) << "Failed to read policy data from " + << backing_file_path_.value(); + return; + } + + em::DevicePolicyResponse policy; + if (!policy.ParseFromArray(data.c_str(), data.size())) { + LOG(WARNING) << "Failed to parse policy data read from " + << backing_file_path_.value(); + return; + } + + // Decode and swap in the new policy information. + scoped_ptr<DictionaryValue> value(DecodePolicy(policy)); + { + AutoLock lock(lock_); + if (!fresh_policy_) + policy_.reset(value.release()); + } +} + +void DeviceManagementPolicyCache::SetPolicy( + const em::DevicePolicyResponse& policy) { + DictionaryValue* value = DeviceManagementPolicyCache::DecodePolicy(policy); + { + AutoLock lock(lock_); + policy_.reset(value); + fresh_policy_ = true; + } + + em::DevicePolicyResponse* policy_copy = new em::DevicePolicyResponse; + policy_copy->CopyFrom(policy); + BrowserThread::PostTask( + BrowserThread::FILE, + FROM_HERE, + new PersistPolicyTask(backing_file_path_, policy_copy)); +} + +DictionaryValue* DeviceManagementPolicyCache::GetPolicy() { + AutoLock lock(lock_); + return static_cast<DictionaryValue*>(policy_->DeepCopy()); +} + +// static +Value* DeviceManagementPolicyCache::DecodeIntegerValue( + google::protobuf::int64 value) { + if (value < std::numeric_limits<int>::min() || + value > std::numeric_limits<int>::max()) { + LOG(WARNING) << "Integer value " << value + << " out of numeric limits, ignoring."; + return NULL; + } + + return Value::CreateIntegerValue(static_cast<int>(value)); +} + +// static +Value* DeviceManagementPolicyCache::DecodeValue(const em::GenericValue& value) { + if (!value.has_value_type()) + return NULL; + + switch (value.value_type()) { + case em::GenericValue::VALUE_TYPE_BOOL: + if (value.has_bool_value()) + return Value::CreateBooleanValue(value.bool_value()); + return NULL; + case em::GenericValue::VALUE_TYPE_INT64: + if (value.has_int64_value()) + return DecodeIntegerValue(value.int64_value()); + return NULL; + case em::GenericValue::VALUE_TYPE_STRING: + if (value.has_string_value()) + return Value::CreateStringValue(value.string_value()); + return NULL; + case em::GenericValue::VALUE_TYPE_DOUBLE: + if (value.has_double_value()) + return Value::CreateRealValue(value.double_value()); + return NULL; + case em::GenericValue::VALUE_TYPE_BYTES: + if (value.has_bytes_value()) { + std::string bytes = value.bytes_value(); + return BinaryValue::CreateWithCopiedBuffer(bytes.c_str(), bytes.size()); + } + return NULL; + case em::GenericValue::VALUE_TYPE_BOOL_ARRAY: { + ListValue* list = new ListValue; + RepeatedField<bool>::const_iterator i; + for (i = value.bool_array().begin(); i != value.bool_array().end(); ++i) + list->Append(Value::CreateBooleanValue(*i)); + return list; + } + case em::GenericValue::VALUE_TYPE_INT64_ARRAY_: { + ListValue* list = new ListValue; + RepeatedField<google::protobuf::int64>::const_iterator i; + for (i = value.int64_array().begin(); + i != value.int64_array().end(); ++i) { + Value* int_value = DecodeIntegerValue(*i); + if (int_value) + list->Append(int_value); + } + return list; + } + case em::GenericValue::VALUE_TYPE_STRING_ARRAY: { + ListValue* list = new ListValue; + RepeatedPtrField<std::string>::const_iterator i; + for (i = value.string_array().begin(); + i != value.string_array().end(); ++i) + list->Append(Value::CreateStringValue(*i)); + return list; + } + case em::GenericValue::VALUE_TYPE_DOUBLE_ARRAY: { + ListValue* list = new ListValue; + RepeatedField<double>::const_iterator i; + for (i = value.double_array().begin(); + i != value.double_array().end(); ++i) + list->Append(Value::CreateRealValue(*i)); + return list; + } + default: + NOTREACHED() << "Unhandled value type"; + } + + return NULL; +} + +// static +DictionaryValue* DeviceManagementPolicyCache::DecodePolicy( + const em::DevicePolicyResponse& policy) { + DictionaryValue* result = new DictionaryValue; + RepeatedPtrField<em::DevicePolicySetting>::const_iterator setting; + for (setting = policy.setting().begin(); + setting != policy.setting().end(); + ++setting) { + // No policy value? Skip. + if (!setting->has_policy_value()) + continue; + + // Iterate through all the name-value pairs wrapped in |setting|. + const em::GenericSetting& policy_value(setting->policy_value()); + RepeatedPtrField<em::GenericNamedValue>::const_iterator named_value; + for (named_value = policy_value.named_value().begin(); + named_value != policy_value.named_value().end(); + ++named_value) { + if (named_value->has_value()) { + Value* decoded_value = + DeviceManagementPolicyCache::DecodeValue(named_value->value()); + if (decoded_value) + result->Set(named_value->name(), decoded_value); + } + } + } + return result; +} + +} // namespace policy diff --git a/chrome/browser/policy/device_management_policy_cache.h b/chrome/browser/policy/device_management_policy_cache.h new file mode 100644 index 0000000..a50402f --- /dev/null +++ b/chrome/browser/policy/device_management_policy_cache.h @@ -0,0 +1,76 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_CACHE_H_ +#define CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_CACHE_H_ + +#include "base/file_path.h" +#include "base/gtest_prod_util.h" +#include "base/lock.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/policy/proto/device_management_backend.pb.h" + +class DictionaryValue; +class Value; + +namespace policy { + +namespace em = enterprise_management; + +// Keeps the authoritative copy of cloud policy information as read from the +// persistence file or determined by the policy backend. The cache doesn't talk +// to the service directly, but receives updated policy information through +// SetPolicy() calls, which is then persisted and decoded into the internal +// Value representation chrome uses. +class DeviceManagementPolicyCache { + public: + explicit DeviceManagementPolicyCache(const FilePath& backing_file_path); + + // Loads policy information from the backing file. Non-existing or erroneous + // cache files are ignored. + void LoadPolicyFromFile(); + + // Resets the policy information. + void SetPolicy(const em::DevicePolicyResponse& policy); + + // Gets the policy information. Ownership of the return value is transferred + // to the caller. + DictionaryValue* GetPolicy(); + + private: + friend class DeviceManagementPolicyCacheDecodeTest; + FRIEND_TEST_ALL_PREFIXES(DeviceManagementPolicyCacheDecodeTest, DecodePolicy); + + // Decodes an int64 value. Checks whether the passed value fits the numeric + // limits of the value representation. Returns a value (ownership is + // transferred to the caller) on success, NULL on failure. + static Value* DecodeIntegerValue(google::protobuf::int64 value); + + // Decode a GenericValue message to the Value representation used internally. + // Returns NULL if |value| is invalid (i.e. contains no actual value). + static Value* DecodeValue(const em::GenericValue& value); + + // Decodes a policy message and returns it in Value representation. Ownership + // of the returned dictionary is transferred to the caller. + static DictionaryValue* DecodePolicy( + const em::DevicePolicyResponse& response); + + // The file in which we store a cached version of the policy information. + const FilePath backing_file_path_; + + // Protects |policy_|. + Lock lock_; + + // Policy key-value information. + scoped_ptr<DictionaryValue> policy_; + + // Tracks whether the store received a SetPolicy() call, which overrides any + // information loaded from the file. + bool fresh_policy_; +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_POLICY_CACHE_H_ diff --git a/chrome/browser/policy/device_management_policy_cache_unittest.cc b/chrome/browser/policy/device_management_policy_cache_unittest.cc new file mode 100644 index 0000000..3f9ba42 --- /dev/null +++ b/chrome/browser/policy/device_management_policy_cache_unittest.cc @@ -0,0 +1,294 @@ +// Copyright (c) 2010 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_management_policy_cache.h" + +#include <limits> + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/scoped_temp_dir.h" +#include "base/values.h" +#include "chrome/browser/browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +// Wraps base functionaly for the test cases. +class DeviceManagementPolicyCacheTestBase : public testing::Test { + protected: + // Add a string policy setting to a policy response message. + void AddStringPolicy(em::DevicePolicyResponse* policy, + const std::string& name, + const std::string& value) { + em::DevicePolicySetting* setting = policy->add_setting(); + setting->set_policy_key("test"); + em::GenericSetting* policy_value = setting->mutable_policy_value(); + em::GenericNamedValue* named_value = policy_value->add_named_value(); + named_value->set_name(name); + em::GenericValue* value_container = named_value->mutable_value(); + value_container->set_value_type(em::GenericValue::VALUE_TYPE_STRING); + value_container->set_string_value(value); + } +}; + +// Tests the device management policy cache. +class DeviceManagementPolicyCacheTest + : public DeviceManagementPolicyCacheTestBase { + protected: + DeviceManagementPolicyCacheTest() + : loop_(MessageLoop::TYPE_UI), + ui_thread_(BrowserThread::UI, &loop_), + file_thread_(BrowserThread::FILE, &loop_) {} + + void SetUp() { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + } + + void TearDown() { + loop_.RunAllPending(); + } + + void WritePolicy(const em::DevicePolicyResponse& policy) { + std::string data; + EXPECT_TRUE(policy.SerializeToString(&data)); + EXPECT_EQ(static_cast<int>(data.size()), + file_util::WriteFile(test_file(), data.c_str(), data.size())); + } + + FilePath test_file() { + return temp_dir_.path().AppendASCII("DeviceManagementPolicyCacheTest"); + } + + protected: + MessageLoop loop_; + + private: + ScopedTempDir temp_dir_; + BrowserThread ui_thread_; + BrowserThread file_thread_; +}; + +TEST_F(DeviceManagementPolicyCacheTest, Empty) { + DeviceManagementPolicyCache cache(test_file()); + DictionaryValue empty; + scoped_ptr<Value> policy(cache.GetPolicy()); + EXPECT_TRUE(empty.Equals(policy.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, LoadNoFile) { + DeviceManagementPolicyCache cache(test_file()); + cache.LoadPolicyFromFile(); + DictionaryValue empty; + scoped_ptr<Value> policy(cache.GetPolicy()); + EXPECT_TRUE(empty.Equals(policy.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, LoadWithFile) { + WritePolicy(em::DevicePolicyResponse()); + DeviceManagementPolicyCache cache(test_file()); + cache.LoadPolicyFromFile(); + DictionaryValue empty; + scoped_ptr<Value> policy(cache.GetPolicy()); + EXPECT_TRUE(empty.Equals(policy.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, LoadWithData) { + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + WritePolicy(policy); + DeviceManagementPolicyCache cache(test_file()); + cache.LoadPolicyFromFile(); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.example.com")); + scoped_ptr<Value> policy_value(cache.GetPolicy()); + EXPECT_TRUE(expected.Equals(policy_value.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, SetPolicy) { + DeviceManagementPolicyCache cache(test_file()); + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + cache.SetPolicy(policy); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.example.com")); + scoped_ptr<Value> policy_value(cache.GetPolicy()); + EXPECT_TRUE(expected.Equals(policy_value.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, ResetPolicy) { + DeviceManagementPolicyCache cache(test_file()); + + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + cache.SetPolicy(policy); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.example.com")); + scoped_ptr<Value> policy_value(cache.GetPolicy()); + EXPECT_TRUE(expected.Equals(policy_value.get())); + + cache.SetPolicy(em::DevicePolicyResponse()); + policy_value.reset(cache.GetPolicy()); + DictionaryValue empty; + EXPECT_TRUE(empty.Equals(policy_value.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, PersistPolicy) { + { + DeviceManagementPolicyCache cache(test_file()); + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + cache.SetPolicy(policy); + } + + loop_.RunAllPending(); + + EXPECT_TRUE(file_util::PathExists(test_file())); + DeviceManagementPolicyCache cache(test_file()); + cache.LoadPolicyFromFile(); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.example.com")); + scoped_ptr<Value> policy_value(cache.GetPolicy()); + EXPECT_TRUE(expected.Equals(policy_value.get())); +} + +TEST_F(DeviceManagementPolicyCacheTest, FreshPolicyOverride) { + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + WritePolicy(policy); + + DeviceManagementPolicyCache cache(test_file()); + em::DevicePolicyResponse updated_policy; + AddStringPolicy(&updated_policy, "HomepageLocation", + "http://www.chromium.org"); + cache.SetPolicy(updated_policy); + + cache.LoadPolicyFromFile(); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.chromium.org")); + scoped_ptr<Value> policy_value(cache.GetPolicy()); + EXPECT_TRUE(expected.Equals(policy_value.get())); +} + +// Tests proper decoding of policy values. +class DeviceManagementPolicyCacheDecodeTest + : public DeviceManagementPolicyCacheTestBase { + protected: + void DecodeAndCheck(Value* expected_value_ptr) { + scoped_ptr<Value> expected_value(expected_value_ptr); + scoped_ptr<Value> decoded_value( + DeviceManagementPolicyCache::DecodeValue(value_)); + if (expected_value_ptr) { + ASSERT_TRUE(decoded_value.get()); + EXPECT_TRUE(decoded_value->Equals(expected_value.get())); + } else { + ASSERT_FALSE(decoded_value.get()); + } + } + + em::GenericValue value_; +}; + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Bool) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_BOOL); + value_.set_bool_value(true); + DecodeAndCheck(Value::CreateBooleanValue(true)); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Int64) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_INT64); + value_.set_int64_value(42); + DecodeAndCheck(Value::CreateIntegerValue(42)); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Int64Overflow) { + const int min = std::numeric_limits<int>::min(); + const int max = std::numeric_limits<int>::max(); + value_.set_value_type(em::GenericValue::VALUE_TYPE_INT64); + value_.set_int64_value(min - 1LL); + DecodeAndCheck(NULL); + value_.set_int64_value(max + 1LL); + DecodeAndCheck(NULL); + value_.set_int64_value(min); + DecodeAndCheck(Value::CreateIntegerValue(min)); + value_.set_int64_value(max); + DecodeAndCheck(Value::CreateIntegerValue(max)); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, String) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_STRING); + value_.set_string_value("ponies!"); + DecodeAndCheck(Value::CreateStringValue("ponies!")); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Double) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_DOUBLE); + value_.set_double_value(0.42L); + DecodeAndCheck(Value::CreateRealValue(0.42L)); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Bytes) { + std::string data("binary ponies."); + value_.set_value_type(em::GenericValue::VALUE_TYPE_BYTES); + value_.set_bytes_value(data); + DecodeAndCheck( + BinaryValue::CreateWithCopiedBuffer(data.c_str(), data.size())); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, BoolArray) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_BOOL_ARRAY); + value_.add_bool_array(false); + value_.add_bool_array(true); + ListValue* list = new ListValue; + list->Append(Value::CreateBooleanValue(false)); + list->Append(Value::CreateBooleanValue(true)); + DecodeAndCheck(list); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, Int64Array) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_INT64_ARRAY_); + value_.add_int64_array(42); + value_.add_int64_array(17); + ListValue* list = new ListValue; + list->Append(Value::CreateIntegerValue(42)); + list->Append(Value::CreateIntegerValue(17)); + DecodeAndCheck(list); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, StringArray) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_STRING_ARRAY); + value_.add_string_array("ponies"); + value_.add_string_array("more ponies"); + ListValue* list = new ListValue; + list->Append(Value::CreateStringValue("ponies")); + list->Append(Value::CreateStringValue("more ponies")); + DecodeAndCheck(list); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, DoubleArray) { + value_.set_value_type(em::GenericValue::VALUE_TYPE_DOUBLE_ARRAY); + value_.add_double_array(0.42L); + value_.add_double_array(0.17L); + ListValue* list = new ListValue; + list->Append(Value::CreateRealValue(0.42L)); + list->Append(Value::CreateRealValue(0.17L)); + DecodeAndCheck(list); +} + +TEST_F(DeviceManagementPolicyCacheDecodeTest, DecodePolicy) { + em::DevicePolicyResponse policy; + AddStringPolicy(&policy, "HomepageLocation", "http://www.example.com"); + scoped_ptr<Value> decoded(DeviceManagementPolicyCache::DecodePolicy(policy)); + DictionaryValue expected; + expected.Set("HomepageLocation", + Value::CreateStringValue("http://www.example.com")); + EXPECT_TRUE(expected.Equals(decoded.get())); +} + +} // namespace policy diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 78c83cb..2288438 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2412,6 +2412,8 @@ 'browser/policy/device_management_backend.h', 'browser/policy/device_management_backend_impl.cc', 'browser/policy/device_management_backend_impl.h', + 'browser/policy/device_management_policy_cache.cc', + 'browser/policy/device_management_policy_cache.h', 'browser/policy/device_token_fetcher.cc', 'browser/policy/device_token_fetcher.h', 'browser/policy/dummy_configuration_policy_provider.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 810655d..75eaf21 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1392,6 +1392,7 @@ 'browser/policy/file_based_policy_provider_unittest.cc', 'browser/policy/device_management_backend_impl_mock.h', 'browser/policy/device_management_backend_impl_unittest.cc', + 'browser/policy/device_management_policy_cache_unittest.cc', 'browser/policy/managed_prefs_banner_base_unittest.cc', 'browser/policy/mock_configuration_policy_provider.cc', 'browser/policy/mock_configuration_policy_provider.h', |