summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-09 23:36:04 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-09 23:36:04 +0000
commit99178111dddd6c8770cc021870f2bca48b218565 (patch)
tree7bf0089e70dedfb3afbf49b8a0a6762d0ab8cce3 /chrome/browser/policy
parent537436d7d0ef6690f31de8854886597dddfa1117 (diff)
downloadchromium_src-99178111dddd6c8770cc021870f2bca48b218565.zip
chromium_src-99178111dddd6c8770cc021870f2bca48b218565.tar.gz
chromium_src-99178111dddd6c8770cc021870f2bca48b218565.tar.bz2
Move a bunch of chrome/browser/ files into a policy/ subdir.
BUG=50548 TEST=compiles Review URL: http://codereview.chromium.org/3110002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55503 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/policy')
-rw-r--r--chrome/browser/policy/config_dir_policy_provider.cc75
-rw-r--r--chrome/browser/policy/config_dir_policy_provider.h43
-rw-r--r--chrome/browser/policy/config_dir_policy_provider_unittest.cc115
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store.cc365
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store.h107
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.cc470
-rw-r--r--chrome/browser/policy/configuration_policy_provider.cc81
-rw-r--r--chrome/browser/policy/configuration_policy_provider.h54
-rw-r--r--chrome/browser/policy/configuration_policy_provider_mac.cc78
-rw-r--r--chrome/browser/policy/configuration_policy_provider_mac.h31
-rw-r--r--chrome/browser/policy/configuration_policy_provider_mac_unittest.cc119
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win.cc166
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win.h62
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win_unittest.cc316
-rw-r--r--chrome/browser/policy/configuration_policy_store.h57
-rw-r--r--chrome/browser/policy/dummy_configuration_policy_provider.h26
-rw-r--r--chrome/browser/policy/mock_configuration_policy_provider.h43
-rw-r--r--chrome/browser/policy/mock_configuration_policy_store.h35
18 files changed, 2243 insertions, 0 deletions
diff --git a/chrome/browser/policy/config_dir_policy_provider.cc b/chrome/browser/policy/config_dir_policy_provider.cc
new file mode 100644
index 0000000..92e9714
--- /dev/null
+++ b/chrome/browser/policy/config_dir_policy_provider.cc
@@ -0,0 +1,75 @@
+// 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/config_dir_policy_provider.h"
+
+#include <set>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/json_value_serializer.h"
+
+ConfigDirPolicyProvider::ConfigDirPolicyProvider(const FilePath& config_dir)
+ : config_dir_(config_dir) {
+}
+
+bool ConfigDirPolicyProvider::Provide(ConfigurationPolicyStore* store) {
+ scoped_ptr<DictionaryValue> policy(ReadPolicies());
+ DecodePolicyValueTree(policy.get(), store);
+ return true;
+}
+
+DictionaryValue* ConfigDirPolicyProvider::ReadPolicies() {
+ // Enumerate the files and sort them lexicographically.
+ std::set<FilePath> files;
+ file_util::FileEnumerator file_enumerator(config_dir_, false,
+ file_util::FileEnumerator::FILES);
+ for (FilePath config_file_path = file_enumerator.Next();
+ !config_file_path.empty(); config_file_path = file_enumerator.Next())
+ files.insert(config_file_path);
+
+ // Start with an empty dictionary and merge the files' contents.
+ DictionaryValue* policy = new DictionaryValue;
+ for (std::set<FilePath>::iterator config_file_iter = files.begin();
+ config_file_iter != files.end(); ++config_file_iter) {
+ JSONFileValueSerializer deserializer(*config_file_iter);
+ int error_code = 0;
+ std::string error_msg;
+ scoped_ptr<Value> value(deserializer.Deserialize(&error_code, &error_msg));
+ if (!value.get()) {
+ LOG(WARNING) << "Failed to read configuration file "
+ << config_file_iter->value() << ": " << error_msg;
+ continue;
+ }
+ if (!value->IsType(Value::TYPE_DICTIONARY)) {
+ LOG(WARNING) << "Expected JSON dictionary in configuration file "
+ << config_file_iter->value();
+ continue;
+ }
+ policy->MergeDictionary(static_cast<DictionaryValue*>(value.get()));
+ }
+
+ return policy;
+}
+
+void ConfigDirPolicyProvider::DecodePolicyValueTree(
+ DictionaryValue* policies,
+ ConfigurationPolicyStore* store) {
+ const PolicyValueMap* mapping = PolicyValueMapping();
+ for (PolicyValueMap::const_iterator i = mapping->begin();
+ i != mapping->end(); ++i) {
+ const PolicyValueMapEntry& entry(*i);
+ Value* value;
+ if (policies->Get(UTF8ToWide(entry.name), &value) &&
+ value->IsType(entry.value_type))
+ store->Apply(entry.policy_type, value->DeepCopy());
+ }
+
+ // TODO(mnissler): Handle preference overrides once |ConfigurationPolicyStore|
+ // supports it.
+}
+
diff --git a/chrome/browser/policy/config_dir_policy_provider.h b/chrome/browser/policy/config_dir_policy_provider.h
new file mode 100644
index 0000000..9412ff2
--- /dev/null
+++ b/chrome/browser/policy/config_dir_policy_provider.h
@@ -0,0 +1,43 @@
+// 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_CONFIG_DIR_POLICY_PROVIDER_H_
+#define CHROME_BROWSER_POLICY_CONFIG_DIR_POLICY_PROVIDER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+
+class DictionaryValue;
+
+// A policy provider implementation backed by a set of files in a given
+// directory. The files should contain JSON-formatted policy settings. They are
+// merged together and the result is returned via the
+// ConfigurationPolicyProvider interface. The files are consulted in
+// lexicographic file name order, so the last value read takes precedence in
+// case of preference key collisions.
+class ConfigDirPolicyProvider : public ConfigurationPolicyProvider {
+ public:
+ explicit ConfigDirPolicyProvider(const FilePath& config_dir);
+ virtual ~ConfigDirPolicyProvider() { }
+
+ // ConfigurationPolicyProvider implementation.
+ virtual bool Provide(ConfigurationPolicyStore* store);
+
+ private:
+ // Read and merge the files from the configuration directory.
+ DictionaryValue* ReadPolicies();
+
+ // Decodes the value tree and writes the configuration to the given |store|.
+ void DecodePolicyValueTree(DictionaryValue* policies,
+ ConfigurationPolicyStore* store);
+
+ // The directory in which we look for configuration files.
+ const FilePath config_dir_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigDirPolicyProvider);
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIG_DIR_POLICY_PROVIDER_H_
diff --git a/chrome/browser/policy/config_dir_policy_provider_unittest.cc b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
new file mode 100644
index 0000000..987a50b
--- /dev/null
+++ b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
@@ -0,0 +1,115 @@
+// 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 "base/file_util.h"
+#include "base/path_service.h"
+#include "base/string_number_conversions.h"
+#include "chrome/browser/policy/config_dir_policy_provider.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+#include "chrome/common/json_value_serializer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class ConfigDirPolicyProviderTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Determine the directory to use for testing.
+ ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
+ test_dir_ =
+ test_dir_.Append(FILE_PATH_LITERAL("ConfigDirPolicyProviderTest"));
+
+ // Make sure the directory is fresh.
+ file_util::Delete(test_dir_, true);
+ file_util::CreateDirectory(test_dir_);
+ ASSERT_TRUE(file_util::DirectoryExists(test_dir_));
+
+ // Create a fresh policy store mock.
+ policy_store_.reset(new MockConfigurationPolicyStore());
+ }
+
+ virtual void TearDown() {
+ // Clean up test directory.
+ ASSERT_TRUE(file_util::Delete(test_dir_, true));
+ ASSERT_FALSE(file_util::PathExists(test_dir_));
+ }
+
+ // JSON-encode a dictionary and write it to a file.
+ void WriteConfigFile(const DictionaryValue& dict,
+ const std::string& file_name) {
+ std::string data;
+ JSONStringValueSerializer serializer(&data);
+ serializer.Serialize(dict);
+ FilePath file_path(test_dir_.AppendASCII(file_name));
+ file_util::WriteFile(file_path, data.c_str(), data.size());
+ }
+
+ FilePath test_dir_;
+ scoped_ptr<MockConfigurationPolicyStore> policy_store_;
+};
+
+// The preferences dictionary is expected to be empty when there are no files to
+// load.
+TEST_F(ConfigDirPolicyProviderTest, ReadPrefsEmpty) {
+ ConfigDirPolicyProvider provider(test_dir_);
+ EXPECT_TRUE(provider.Provide(policy_store_.get()));
+ EXPECT_TRUE(policy_store_->policy_map().empty());
+}
+
+// Reading from a non-existent directory should result in an empty preferences
+// dictionary.
+TEST_F(ConfigDirPolicyProviderTest, ReadPrefsNonExistentDirectory) {
+ FilePath non_existent_dir(test_dir_.Append(FILE_PATH_LITERAL("not_there")));
+ ConfigDirPolicyProvider provider(non_existent_dir);
+ EXPECT_TRUE(provider.Provide(policy_store_.get()));
+ EXPECT_TRUE(policy_store_->policy_map().empty());
+}
+
+// Test reading back a single preference value.
+TEST_F(ConfigDirPolicyProviderTest, ReadPrefsSinglePref) {
+ DictionaryValue test_dict;
+ test_dict.SetString(L"HomepageLocation", L"http://www.google.com");
+ WriteConfigFile(test_dict, "config_file");
+ ConfigDirPolicyProvider provider(test_dir_);
+
+ EXPECT_TRUE(provider.Provide(policy_store_.get()));
+ const MockConfigurationPolicyStore::PolicyMap& policy_map(
+ policy_store_->policy_map());
+ EXPECT_EQ(1U, policy_map.size());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator entry =
+ policy_map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(entry != policy_map.end());
+
+ std::wstring str_value;
+ EXPECT_TRUE(entry->second->GetAsString(&str_value));
+ EXPECT_EQ(L"http://www.google.com", str_value);
+}
+
+// Test merging values from different files.
+TEST_F(ConfigDirPolicyProviderTest, ReadPrefsMergePrefs) {
+ // Write a bunch of data files in order to increase the chance to detect the
+ // provider not respecting lexicographic ordering when reading them. Since the
+ // filesystem may return files in arbitrary order, there is no way to be sure,
+ // but this is better than nothing.
+ DictionaryValue test_dict_bar;
+ test_dict_bar.SetString(L"HomepageLocation", L"http://bar.com");
+ for (unsigned int i = 1; i <= 4; ++i)
+ WriteConfigFile(test_dict_bar, base::IntToString(i));
+ DictionaryValue test_dict_foo;
+ test_dict_foo.SetString(L"HomepageLocation", L"http://foo.com");
+ WriteConfigFile(test_dict_foo, "9");
+ for (unsigned int i = 5; i <= 8; ++i)
+ WriteConfigFile(test_dict_bar, base::IntToString(i));
+ ConfigDirPolicyProvider provider(test_dir_);
+
+ EXPECT_TRUE(provider.Provide(policy_store_.get()));
+ const MockConfigurationPolicyStore::PolicyMap& policy_map(
+ policy_store_->policy_map());
+ EXPECT_EQ(1U, policy_map.size());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator entry =
+ policy_map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(entry != policy_map.end());
+
+ std::wstring str_value;
+ EXPECT_TRUE(entry->second->GetAsString(&str_value));
+ EXPECT_EQ(L"http://foo.com", str_value);
+}
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
new file mode 100644
index 0000000..b6fd1e6
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -0,0 +1,365 @@
+// 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/configuration_policy_pref_store.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/string16.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#if defined(OS_WIN)
+#include "chrome/browser/policy/configuration_policy_provider_win.h"
+#elif defined(OS_MACOSX)
+#include "chrome/browser/policy/configuration_policy_provider_mac.h"
+#elif defined(OS_POSIX)
+#include "chrome/browser/policy/config_dir_policy_provider.h"
+#endif
+#include "chrome/browser/policy/dummy_configuration_policy_provider.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+
+const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
+ ConfigurationPolicyPrefStore::simple_policy_map_[] = {
+ { Value::TYPE_STRING, kPolicyHomePage, prefs::kHomePage },
+ { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
+ prefs::kHomePageIsNewTabPage },
+ { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
+ prefs::kAlternateErrorPagesEnabled },
+ { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
+ prefs::kSearchSuggestEnabled },
+ { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
+ prefs::kDnsPrefetchingEnabled },
+ { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
+ prefs::kSafeBrowsingEnabled },
+ { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
+ prefs::kPasswordManagerEnabled },
+ { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
+ prefs::kMetricsReportingEnabled },
+ { Value::TYPE_STRING, kPolicyApplicationLocale,
+ prefs::kApplicationLocale},
+};
+
+const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
+ ConfigurationPolicyPrefStore::proxy_policy_map_[] = {
+ { Value::TYPE_STRING, kPolicyProxyServer, prefs::kProxyServer },
+ { Value::TYPE_STRING, kPolicyProxyPacUrl, prefs::kProxyPacUrl },
+ { Value::TYPE_STRING, kPolicyProxyBypassList, prefs::kProxyBypassList }
+};
+
+ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
+ const CommandLine* command_line,
+ ConfigurationPolicyProvider* provider)
+ : command_line_(command_line),
+ provider_(provider),
+ prefs_(new DictionaryValue()),
+ command_line_proxy_settings_cleared_(false),
+ proxy_disabled_(false),
+ proxy_configuration_specified_(false),
+ use_system_proxy_(false) {
+}
+
+void ConfigurationPolicyPrefStore::ApplyProxySwitches() {
+ bool proxy_disabled = command_line_->HasSwitch(switches::kNoProxyServer);
+ if (proxy_disabled) {
+ prefs_->Set(prefs::kNoProxyServer, Value::CreateBooleanValue(true));
+ }
+ bool has_explicit_proxy_config = false;
+ if (command_line_->HasSwitch(switches::kProxyAutoDetect)) {
+ has_explicit_proxy_config = true;
+ prefs_->Set(prefs::kProxyAutoDetect, Value::CreateBooleanValue(true));
+ }
+ if (command_line_->HasSwitch(switches::kProxyServer)) {
+ has_explicit_proxy_config = true;
+ prefs_->Set(prefs::kProxyServer, Value::CreateStringValue(
+ command_line_->GetSwitchValueASCII(switches::kProxyServer)));
+ }
+ if (command_line_->HasSwitch(switches::kProxyPacUrl)) {
+ has_explicit_proxy_config = true;
+ prefs_->Set(prefs::kProxyPacUrl, Value::CreateStringValue(
+ command_line_->GetSwitchValueASCII(switches::kProxyPacUrl)));
+ }
+ if (command_line_->HasSwitch(switches::kProxyBypassList)) {
+ has_explicit_proxy_config = true;
+ prefs_->Set(prefs::kProxyBypassList, Value::CreateStringValue(
+ command_line_->GetSwitchValueASCII(switches::kProxyBypassList)));
+ }
+
+ // Warn about all the other proxy config switches we get if
+ // the --no-proxy-server command-line argument is present.
+ if (proxy_disabled && has_explicit_proxy_config) {
+ LOG(WARNING) << "Additional command-line proxy switches specified when --"
+ << switches::kNoProxyServer << " was also specified.";
+ }
+}
+
+PrefStore::PrefReadError ConfigurationPolicyPrefStore::ReadPrefs() {
+ // Initialize proxy preference values from command-line switches. This is done
+ // before calling Provide to allow the provider to overwrite proxy-related
+ // preferences that are specified by line settings.
+ ApplyProxySwitches();
+
+ proxy_disabled_ = false;
+ proxy_configuration_specified_ = false;
+ command_line_proxy_settings_cleared_ = false;
+
+ return (provider_.get() == NULL || provider_->Provide(this)) ?
+ PrefStore::PREF_READ_ERROR_NONE : PrefStore::PREF_READ_ERROR_OTHER;
+}
+
+// static
+ConfigurationPolicyPrefStore*
+ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore() {
+ ConfigurationPolicyProvider* provider;
+#if defined(OS_WIN)
+ provider = new ConfigurationPolicyProviderWin();
+#elif defined(OS_MACOSX)
+ provider = new ConfigurationPolicyProviderMac();
+#elif defined(OS_POSIX)
+ FilePath config_dir_path;
+ if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
+ provider = new ConfigDirPolicyProvider(
+ config_dir_path.Append(FILE_PATH_LITERAL("managed")));
+ else
+ provider = new DummyConfigurationPolicyProvider();
+#else
+ provider = new DummyConfigurationPolicyProvider();
+#endif
+
+ return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
+ provider);
+}
+
+// static
+ConfigurationPolicyPrefStore*
+ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore() {
+ ConfigurationPolicyProvider* provider;
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ FilePath config_dir_path;
+ if (PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path))
+ provider = new ConfigDirPolicyProvider(
+ config_dir_path.Append(FILE_PATH_LITERAL("recommended")));
+ else
+ provider = new DummyConfigurationPolicyProvider();
+#else
+ provider = new DummyConfigurationPolicyProvider();
+#endif
+
+ return new ConfigurationPolicyPrefStore(CommandLine::ForCurrentProcess(),
+ provider);
+}
+
+bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy,
+ Value* value) {
+ bool result = false;
+ bool warn_about_proxy_disable_config = false;
+ bool warn_about_proxy_system_config = false;
+
+ const PolicyToPreferenceMapEntry* match_entry_ = NULL;
+ for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
+ current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current) {
+ if (current->policy_type == policy) {
+ match_entry_ = current;
+ }
+ }
+
+ // When the first proxy-related policy is applied, ALL proxy-related
+ // preferences that have been set by command-line switches must be
+ // removed. Otherwise it's possible for a user to interfere with proxy
+ // policy by using proxy-related switches that are related to, but not
+ // identical, to the ones set through policy.
+ if ((match_entry_ ||
+ policy == ConfigurationPolicyPrefStore::kPolicyProxyServerMode) &&
+ !command_line_proxy_settings_cleared_) {
+ for (const PolicyToPreferenceMapEntry* i = proxy_policy_map_;
+ i != proxy_policy_map_ + arraysize(proxy_policy_map_); ++i) {
+ if (prefs_->Get(i->preference_path, NULL)) {
+ LOG(WARNING) << "proxy configuration options were specified on the"
+ << " command-line but will be ignored because an"
+ << " explicit proxy configuration has been specified"
+ << " through a centrally-administered policy.";
+ break;
+ }
+ }
+
+ // Now actually do the preference removal.
+ for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
+ current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current)
+ prefs_->Remove(current->preference_path, NULL);
+ prefs_->Remove(prefs::kNoProxyServer, NULL);
+ prefs_->Remove(prefs::kProxyAutoDetect, NULL);
+
+ command_line_proxy_settings_cleared_ = true;
+ }
+
+ // Translate the proxy policy into preferences.
+ if (policy == ConfigurationPolicyStore::kPolicyProxyServerMode) {
+ int int_value;
+ bool proxy_auto_detect = false;
+ if (value->GetAsInteger(&int_value)) {
+ result = true;
+ switch (int_value) {
+ case ConfigurationPolicyStore::kPolicyNoProxyServerMode:
+ if (!proxy_disabled_) {
+ if (proxy_configuration_specified_)
+ warn_about_proxy_disable_config = true;
+ proxy_disabled_ = true;
+ }
+ break;
+ case ConfigurationPolicyStore::kPolicyAutoDetectProxyMode:
+ proxy_auto_detect = true;
+ break;
+ case ConfigurationPolicyStore::kPolicyManuallyConfiguredProxyMode:
+ break;
+ case ConfigurationPolicyStore::kPolicyUseSystemProxyMode:
+ if (!use_system_proxy_) {
+ if (proxy_configuration_specified_)
+ warn_about_proxy_system_config = true;
+ use_system_proxy_ = true;
+ }
+ break;
+ default:
+ // Not a valid policy, don't assume ownership of |value|
+ result = false;
+ break;
+ }
+
+ if (int_value != kPolicyUseSystemProxyMode) {
+ prefs_->Set(prefs::kNoProxyServer,
+ Value::CreateBooleanValue(proxy_disabled_));
+ prefs_->Set(prefs::kProxyAutoDetect,
+ Value::CreateBooleanValue(proxy_auto_detect));
+ }
+
+ // No proxy and system proxy mode should ensure that no other
+ // proxy preferences are set.
+ if (int_value == ConfigurationPolicyStore::kPolicyNoProxyServerMode ||
+ int_value == kPolicyUseSystemProxyMode) {
+ for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_;
+ current != proxy_policy_map_ + arraysize(proxy_policy_map_);
+ ++current)
+ prefs_->Remove(current->preference_path, NULL);
+ }
+ }
+ } else if (match_entry_) {
+ // Determine if the applied proxy policy settings conflict and issue
+ // a corresponding warning if they do.
+ if (!proxy_configuration_specified_) {
+ if (proxy_disabled_)
+ warn_about_proxy_disable_config = true;
+ if (use_system_proxy_)
+ warn_about_proxy_system_config = true;
+ proxy_configuration_specified_ = true;
+ }
+ if (!use_system_proxy_ && !proxy_disabled_) {
+ prefs_->Set(match_entry_->preference_path, value);
+ // The ownership of value has been passed on to |prefs_|,
+ // don't clean it up later.
+ value = NULL;
+ }
+ result = true;
+ }
+
+ if (warn_about_proxy_disable_config) {
+ LOG(WARNING) << "A centrally-administered policy disables the use of"
+ << " a proxy but also specifies an explicit proxy"
+ << " configuration.";
+ }
+
+ if (warn_about_proxy_system_config) {
+ LOG(WARNING) << "A centrally-administered policy dictates that the"
+ << " system proxy settings should be used but also specifies"
+ << " an explicit proxy configuration.";
+ }
+
+ // If the policy was a proxy policy, cleanup |value|.
+ if (result && value)
+ delete value;
+ return result;
+}
+
+bool ConfigurationPolicyPrefStore::ApplyPluginPolicy(PolicyType policy,
+ Value* value) {
+ if (policy == kPolicyDisabledPlugins) {
+ string16 plugin_list;
+ if (value->GetAsString(&plugin_list)) {
+ std::vector<string16> plugin_names;
+ // Change commas into tabs so that we can change escaped
+ // tabs back into commas, leaving non-escaped commas as tabs
+ // that can be used for splitting the string. Note that plugin
+ // names must not contain backslashes, since a trailing backslash
+ // in a plugin name before a comma would get swallowed during the
+ // splitting.
+ std::replace(plugin_list.begin(), plugin_list.end(), L',', L'\t');
+ ReplaceSubstringsAfterOffset(&plugin_list, 0,
+ ASCIIToUTF16("\\\t"), ASCIIToUTF16(","));
+ SplitString(plugin_list, L'\t', &plugin_names);
+ bool added_plugin = false;
+ scoped_ptr<ListValue> list(new ListValue());
+ for (std::vector<string16>::const_iterator i(plugin_names.begin());
+ i != plugin_names.end(); ++i) {
+ if (!i->empty()) {
+ list->Append(Value::CreateStringValue(*i));
+ added_plugin = true;
+ }
+ }
+ if (added_plugin) {
+ prefs_->Set(prefs::kPluginsPluginsBlacklist, list.release());
+ delete value;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy,
+ Value* value) {
+ if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) {
+ bool disable_sync;
+ if (value->GetAsBoolean(&disable_sync) && disable_sync)
+ prefs_->Set(prefs::kSyncManaged, value);
+ else
+ delete value;
+ return true;
+ }
+ return false;
+}
+
+bool ConfigurationPolicyPrefStore::ApplyPolicyFromMap(PolicyType policy,
+ Value* value, const PolicyToPreferenceMapEntry map[], int size) {
+ const PolicyToPreferenceMapEntry* end = map + size;
+ for (const PolicyToPreferenceMapEntry* current = map;
+ current != end; ++current) {
+ if (current->policy_type == policy) {
+ DCHECK(current->value_type == value->GetType());
+ prefs_->Set(current->preference_path, value);
+ return true;
+ }
+ }
+ return false;
+}
+
+void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) {
+ if (ApplyProxyPolicy(policy, value))
+ return;
+
+ if (ApplyPluginPolicy(policy, value))
+ return;
+
+ if (ApplySyncPolicy(policy, value))
+ return;
+
+ if (ApplyPolicyFromMap(policy, value, simple_policy_map_,
+ arraysize(simple_policy_map_)))
+ return;
+
+ // Other policy implementations go here.
+ NOTIMPLEMENTED();
+ delete value;
+}
diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h
new file mode 100644
index 0000000..df35238
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_pref_store.h
@@ -0,0 +1,107 @@
+// 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_CONFIGURATION_POLICY_PREF_STORE_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PREF_STORE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/configuration_policy_store.h"
+#include "chrome/common/pref_store.h"
+
+class CommandLine;
+
+// An implementation of the |PrefStore| that holds a Dictionary
+// created through applied policy.
+class ConfigurationPolicyPrefStore : public PrefStore,
+ public ConfigurationPolicyStore {
+ public:
+ // The ConfigurationPolicyPrefStore takes the ownership of the passed
+ // |provider|.
+ ConfigurationPolicyPrefStore(const CommandLine* command_line,
+ ConfigurationPolicyProvider* provider);
+ virtual ~ConfigurationPolicyPrefStore() { }
+
+ // PrefStore methods:
+ virtual PrefReadError ReadPrefs();
+ virtual DictionaryValue* prefs() { return prefs_.get(); }
+
+ // Creates a ConfigurationPolicyPrefStore that reads managed policy.
+ static ConfigurationPolicyPrefStore* CreateManagedPolicyPrefStore();
+
+ // Creates a ConfigurationPolicyPrefStore that reads recommended policy.
+ static ConfigurationPolicyPrefStore* CreateRecommendedPolicyPrefStore();
+
+ private:
+ // For unit tests.
+ friend class ConfigurationPolicyPrefStoreTest;
+
+ // Policies that map to a single preference are handled
+ // by an automated converter. Each one of these policies
+ // has an entry in |simple_policy_map_| with the following type.
+ struct PolicyToPreferenceMapEntry {
+ Value::ValueType value_type;
+ PolicyType policy_type;
+ const wchar_t* preference_path; // A DictionaryValue path, not a file path.
+ };
+
+ static const PolicyToPreferenceMapEntry simple_policy_map_[];
+ static const PolicyToPreferenceMapEntry proxy_policy_map_[];
+
+ const CommandLine* command_line_;
+ scoped_ptr<ConfigurationPolicyProvider> provider_;
+ scoped_ptr<DictionaryValue> prefs_;
+
+ // Set to false until the first proxy-relevant policy is applied. Allows
+ // the Apply method to erase all switch-specified proxy configuration before
+ // applying proxy policy configuration;
+ bool command_line_proxy_settings_cleared_;
+
+ // The following are used to track what proxy-relevant policy has been applied
+ // accross calls to Apply to provide a warning if a policy specifies a
+ // contradictory proxy configuration. |proxy_disabled_| is set to true if and
+ // only if the kPolicyNoProxyServer has been applied,
+ // |proxy_configuration_specified_| is set to true if and only if any other
+ // proxy policy other than kPolicyNoProxyServer has been applied.
+ bool proxy_disabled_;
+ bool proxy_configuration_specified_;
+
+ // Set to true if a the proxy mode policy has been set to force Chrome
+ // to use the system proxy.
+ bool use_system_proxy_;
+
+ // ConfigurationPolicyStore methods:
+ virtual void Apply(PolicyType setting, Value* value);
+
+ // Initializes default preference values from proxy-related command-line
+ // switches in |command_line_|.
+ void ApplyProxySwitches();
+
+ bool ApplyPolicyFromMap(PolicyType policy, Value* value,
+ const PolicyToPreferenceMapEntry map[], int size);
+
+ // Processes proxy-specific policies. Returns true if the specified policy
+ // is a proxy-related policy. ApplyProxyPolicy assumes the ownership
+ // of |value| in the case that the policy is proxy-specific.
+ bool ApplyProxyPolicy(PolicyType policy, Value* value);
+
+ // Processes plugin policies. Returns true if the specified policy
+ // is a plugin-related policy. ApplyPluginPolicy assumes the ownership
+ // of |value| in the case that the policy is plugin-specific.
+ bool ApplyPluginPolicy(PolicyType policy, Value* value);
+
+ // Handles sync-related policies. Returns true if the policy was handled.
+ // Assumes ownership of |value| in that case.
+ bool ApplySyncPolicy(PolicyType policy, Value* value);
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyPrefStore);
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PREF_STORE_H_
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
new file mode 100644
index 0000000..fa63845
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -0,0 +1,470 @@
+// 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 <gtest/gtest.h>
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/chrome_switches.h"
+
+class ConfigurationPolicyPrefStoreTest : public testing::Test {
+ public:
+ // Applies a policy that has a string value.
+ void ApplyStringPolicyValue(
+ ConfigurationPolicyPrefStore* store,
+ ConfigurationPolicyStore::PolicyType type,
+ const wchar_t* policy_value);
+
+ // The following three methods test a policy which controls a string
+ // preference.
+ // Checks that by default, it's an empty string.
+ void TestStringPolicyGetDefault(const wchar_t* pref_name);
+ // Checks that values can be set.
+ void TestStringPolicySetValue(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+ // A wrapper that calls the above two methods.
+ void TestStringPolicy(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+
+ // The following three methods test a policy which controls a boolean
+ // preference.
+ // Checks that there's no deafult.
+ void TestBooleanPolicyGetDefault(const wchar_t* pref_name);
+ // Checks that values can be set.
+ void TestBooleanPolicySetValue(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+ // A wrapper that calls the above two methods.
+ void TestBooleanPolicy(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+
+ // The following three methods test a policy which controls an integer
+ // preference.
+ // Checks that by default, it's 0.
+ void TestIntegerPolicyGetDefault(const wchar_t* pref_name);
+ // Checks that values can be set.
+ void TestIntegerPolicySetValue(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+ // A wrapper that calls the above two methods.
+ void TestIntegerPolicy(const wchar_t* pref_name,
+ ConfigurationPolicyStore::PolicyType type);
+};
+
+void ConfigurationPolicyPrefStoreTest::ApplyStringPolicyValue(
+ ConfigurationPolicyPrefStore* store,
+ ConfigurationPolicyStore::PolicyType type,
+ const wchar_t* policy_value) {
+ store->Apply(type, Value::CreateStringValue(policy_value));
+}
+
+void ConfigurationPolicyPrefStoreTest::TestStringPolicyGetDefault(
+ const wchar_t* pref_name) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ std::wstring result;
+ store.prefs()->GetString(pref_name, &result);
+ EXPECT_EQ(result, L"");
+}
+
+void ConfigurationPolicyPrefStoreTest::TestStringPolicySetValue(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ ApplyStringPolicyValue(&store, type, L"http://chromium.org");
+ std::wstring result;
+ store.prefs()->GetString(pref_name, &result);
+ EXPECT_EQ(result, L"http://chromium.org");
+}
+
+void ConfigurationPolicyPrefStoreTest::TestStringPolicy(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ TestStringPolicyGetDefault(pref_name);
+ TestStringPolicySetValue(pref_name, type);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestBooleanPolicyGetDefault(
+ const wchar_t* pref_name) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ bool result = false;
+ store.prefs()->GetBoolean(pref_name, &result);
+ EXPECT_FALSE(result);
+ result = true;
+ store.prefs()->GetBoolean(pref_name, &result);
+ EXPECT_TRUE(result);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestBooleanPolicySetValue(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ store.Apply(type, Value::CreateBooleanValue(false));
+ bool result = true;
+ store.prefs()->GetBoolean(pref_name, &result);
+ EXPECT_FALSE(result);
+
+ store.Apply(type, Value::CreateBooleanValue(true));
+ result = false;
+ store.prefs()->GetBoolean(pref_name, &result);
+ EXPECT_TRUE(result);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestBooleanPolicy(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ TestBooleanPolicyGetDefault(pref_name);
+ TestBooleanPolicySetValue(pref_name, type);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestIntegerPolicyGetDefault(
+ const wchar_t* pref_name) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ int result = 0;
+ store.prefs()->GetInteger(pref_name, &result);
+ EXPECT_EQ(result, 0);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestIntegerPolicySetValue(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ ConfigurationPolicyPrefStore store(NULL, NULL);
+ store.Apply(type, Value::CreateIntegerValue(2));
+ int result = 0;
+ store.prefs()->GetInteger(pref_name, &result);
+ EXPECT_EQ(result, 2);
+}
+
+void ConfigurationPolicyPrefStoreTest::TestIntegerPolicy(
+ const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) {
+ TestIntegerPolicyGetDefault(pref_name);
+ TestIntegerPolicySetValue(pref_name, type);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestSettingHomePageDefault) {
+ TestStringPolicy(prefs::kHomePage,
+ ConfigurationPolicyPrefStore::kPolicyHomePage);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyHomepageIsNewTabPage) {
+ TestBooleanPolicy(prefs::kHomePageIsNewTabPage,
+ ConfigurationPolicyPrefStore::kPolicyHomepageIsNewTabPage);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyAlternateErrorPagesEnabled) {
+ TestBooleanPolicy(prefs::kAlternateErrorPagesEnabled,
+ ConfigurationPolicyStore::kPolicyAlternateErrorPagesEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicySearchSuggestEnabled) {
+ TestBooleanPolicy(prefs::kSearchSuggestEnabled,
+ ConfigurationPolicyStore::kPolicySearchSuggestEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyDnsPrefetchingEnabled) {
+ TestBooleanPolicy(prefs::kDnsPrefetchingEnabled,
+ ConfigurationPolicyStore::kPolicyDnsPrefetchingEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicySafeBrowsingEnabled) {
+ TestBooleanPolicy(prefs::kSafeBrowsingEnabled,
+ ConfigurationPolicyStore::kPolicySafeBrowsingEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyMetricsReportingEnabled) {
+ TestBooleanPolicy(prefs::kMetricsReportingEnabled,
+ ConfigurationPolicyStore::kPolicyMetricsReportingEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyPasswordManagerEnabled) {
+ TestBooleanPolicy(prefs::kPasswordManagerEnabled,
+ ConfigurationPolicyStore::kPolicyPasswordManagerEnabled);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestSettingProxyServer) {
+ TestStringPolicy(prefs::kProxyServer,
+ ConfigurationPolicyPrefStore::kPolicyProxyServer);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestSettingProxyPacUrl) {
+ TestStringPolicy(prefs::kProxyPacUrl,
+ ConfigurationPolicyPrefStore::kPolicyProxyPacUrl);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestSettingProxyBypassList) {
+ TestStringPolicy(prefs::kProxyBypassList,
+ ConfigurationPolicyPrefStore::kPolicyProxyBypassList);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestSettingsProxyConfig) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ command_line.AppendSwitch(switches::kNoProxyServer);
+ command_line.AppendSwitch(switches::kProxyAutoDetect);
+ command_line.AppendSwitchASCII(switches::kProxyPacUrl,
+ "http://chromium.org/test.pac");
+ command_line.AppendSwitchASCII(switches::kProxyServer,
+ "http://chromium2.org");
+ command_line.AppendSwitchASCII(switches::kProxyBypassList,
+ "http://chromium3.org");
+
+ ConfigurationPolicyPrefStore store(&command_line, NULL);
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ // Ensure that all traces of the command-line specified proxy
+ // switches have been overriden.
+ std::wstring string_result;
+ EXPECT_TRUE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+ EXPECT_EQ(string_result, L"http://chromium3.org");
+
+ EXPECT_TRUE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_EQ(string_result, L"http://chromium.org/test.pac");
+ EXPECT_TRUE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ EXPECT_EQ(string_result, L"http://chromium2.org");
+ bool bool_result;
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_TRUE(bool_result);
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+ EXPECT_TRUE(bool_result);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyProxyConfigManualOverride) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ command_line.AppendSwitch(switches::kNoProxyServer);
+ command_line.AppendSwitch(switches::kProxyAutoDetect);
+ command_line.AppendSwitchASCII(switches::kProxyPacUrl,
+ "http://chromium.org/test.pac");
+ command_line.AppendSwitchASCII(switches::kProxyServer,
+ "http://chromium.org");
+ command_line.AppendSwitchASCII(switches::kProxyBypassList,
+ "http://chromium.org");
+
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyManuallyConfiguredProxyMode));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+
+ ConfigurationPolicyPrefStore store(&command_line,
+ provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ // Ensure that all traces of the command-line specified proxy
+ // switches have been overriden.
+ std::wstring string_result;
+ EXPECT_TRUE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+ EXPECT_EQ(string_result, L"http://chromium.org/override");
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_FALSE(bool_result);
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+ EXPECT_FALSE(bool_result);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyProxyConfigNoProxy) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyNoProxyServerMode));
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ std::wstring string_result;
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_TRUE(bool_result);
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+ EXPECT_FALSE(bool_result);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest,
+ TestPolicyProxyConfigNoProxyReversedApplyOrder) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyNoProxyServerMode));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ std::wstring string_result;
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_TRUE(bool_result);
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+ EXPECT_FALSE(bool_result);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyProxyConfigAutoDetect) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyAutoDetectProxyMode));
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ // Ensure that all traces of the command-line specified proxy
+ // switches have been overriden.
+ std::wstring string_result;
+ EXPECT_TRUE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+ EXPECT_EQ(string_result, L"http://chromium.org/override");
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_FALSE(bool_result);
+ EXPECT_TRUE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+ EXPECT_TRUE(bool_result);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest, TestPolicyProxyConfiguseSystem) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyUseSystemProxyMode));
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ std::wstring string_result;
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+ EXPECT_EQ(string_result, L"");
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_FALSE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_FALSE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest,
+ TestPolicyProxyConfiguseSystemReversedApplyOrder) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::CreateIntegerValue(
+ ConfigurationPolicyStore::kPolicyUseSystemProxyMode));
+ provider->AddPolicy(ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::CreateStringValue(L"http://chromium.org/override"));
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ std::wstring string_result;
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyBypassList,
+ &string_result));
+ EXPECT_EQ(string_result, L"");
+
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyPacUrl, &string_result));
+ EXPECT_FALSE(store.prefs()->GetString(prefs::kProxyServer, &string_result));
+ bool bool_result;
+ EXPECT_FALSE(store.prefs()->GetBoolean(prefs::kNoProxyServer, &bool_result));
+ EXPECT_FALSE(store.prefs()->GetBoolean(prefs::kProxyAutoDetect,
+ &bool_result));
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest,
+ TestPolicyProxyDisabledPlugin) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ ApplyStringPolicyValue(&store,
+ ConfigurationPolicyStore::kPolicyDisabledPlugins,
+ L"plugin1");
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ ListValue* plugin_blacklist = NULL;
+ EXPECT_TRUE(store.prefs()->GetList(prefs::kPluginsPluginsBlacklist,
+ &plugin_blacklist));
+
+ ListValue::const_iterator current(plugin_blacklist->begin());
+ ListValue::const_iterator end(plugin_blacklist->end());
+
+ ASSERT_TRUE(current != end);
+ std::string plugin_name;
+ (*current)->GetAsString(&plugin_name);
+ EXPECT_EQ("plugin1", plugin_name);
+ ++current;
+ EXPECT_TRUE(current == end);
+}
+
+TEST_F(ConfigurationPolicyPrefStoreTest,
+ TestPolicyProxyDisabledPluginEscapedComma) {
+ FilePath unused_path(FILE_PATH_LITERAL("foo.exe"));
+ CommandLine command_line(unused_path);
+ scoped_ptr<MockConfigurationPolicyProvider> provider(
+ new MockConfigurationPolicyProvider());
+
+ ConfigurationPolicyPrefStore store(&command_line, provider.release());
+ ApplyStringPolicyValue(&store,
+ ConfigurationPolicyStore::kPolicyDisabledPlugins,
+ L"plugin1,plugin2\\,");
+ EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE);
+
+ ListValue* plugin_blacklist = NULL;
+ EXPECT_TRUE(store.prefs()->GetList(prefs::kPluginsPluginsBlacklist,
+ &plugin_blacklist));
+ ListValue::const_iterator current(plugin_blacklist->begin());
+ ListValue::const_iterator end(plugin_blacklist->end());
+ ASSERT_TRUE(current != end);
+ std::string plugin_name;
+ (*current)->GetAsString(&plugin_name);
+ EXPECT_EQ("plugin1", plugin_name);
+ ++current;
+ ASSERT_TRUE(current != end);
+ (*current)->GetAsString(&plugin_name);
+ EXPECT_EQ("plugin2,", plugin_name);
+ ++current;
+ EXPECT_TRUE(current == end);
+}
+
diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc
new file mode 100644
index 0000000..99c61cf
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider.cc
@@ -0,0 +1,81 @@
+// 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/configuration_policy_provider.h"
+
+#include "base/values.h"
+#include "chrome/common/policy_constants.h"
+#include "chrome/common/notification_service.h"
+
+namespace {
+
+// TODO(avi): Use this mapping to auto-generate MCX manifests and Windows
+// ADM/ADMX files. http://crbug.com/49316
+
+struct InternalPolicyValueMapEntry {
+ ConfigurationPolicyStore::PolicyType policy_type;
+ Value::ValueType value_type;
+ const char* name;
+};
+
+const InternalPolicyValueMapEntry kPolicyValueMap[] = {
+ { ConfigurationPolicyStore::kPolicyHomePage,
+ Value::TYPE_STRING, policy::key::kHomepageLocation },
+ { ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage,
+ Value::TYPE_BOOLEAN, policy::key::kHomepageIsNewTabPage },
+ { ConfigurationPolicyStore::kPolicyProxyServerMode,
+ Value::TYPE_INTEGER, policy::key::kProxyServerMode },
+ { ConfigurationPolicyStore::kPolicyProxyServer,
+ Value::TYPE_STRING, policy::key::kProxyServer },
+ { ConfigurationPolicyStore::kPolicyProxyPacUrl,
+ Value::TYPE_STRING, policy::key::kProxyPacUrl },
+ { ConfigurationPolicyStore::kPolicyProxyBypassList,
+ Value::TYPE_STRING, policy::key::kProxyBypassList },
+ { ConfigurationPolicyStore::kPolicyAlternateErrorPagesEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kAlternateErrorPagesEnabled },
+ { ConfigurationPolicyStore::kPolicySearchSuggestEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kSearchSuggestEnabled },
+ { ConfigurationPolicyStore::kPolicyDnsPrefetchingEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kDnsPrefetchingEnabled },
+ { ConfigurationPolicyStore::kPolicySafeBrowsingEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kSafeBrowsingEnabled },
+ { ConfigurationPolicyStore::kPolicyMetricsReportingEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kMetricsReportingEnabled },
+ { ConfigurationPolicyStore::kPolicyPasswordManagerEnabled,
+ Value::TYPE_BOOLEAN, policy::key::kPasswordManagerEnabled },
+ { ConfigurationPolicyStore::kPolicyDisabledPlugins,
+ Value::TYPE_STRING, policy::key::kDisabledPluginsList },
+ { ConfigurationPolicyStore::kPolicyApplicationLocale,
+ Value::TYPE_STRING, policy::key::kApplicationLocaleValue },
+ { ConfigurationPolicyStore::kPolicySyncDisabled,
+ Value::TYPE_BOOLEAN, policy::key::kSyncDisabled },
+};
+
+} // namespace
+
+/* static */
+const ConfigurationPolicyProvider::PolicyValueMap*
+ ConfigurationPolicyProvider::PolicyValueMapping() {
+ static PolicyValueMap* mapping;
+ if (!mapping) {
+ mapping = new PolicyValueMap();
+ for (size_t i = 0; i < arraysize(kPolicyValueMap); ++i) {
+ const InternalPolicyValueMapEntry& internal_entry = kPolicyValueMap[i];
+ PolicyValueMapEntry entry;
+ entry.policy_type = internal_entry.policy_type;
+ entry.value_type = internal_entry.value_type;
+ entry.name = std::string(internal_entry.name);
+ mapping->push_back(entry);
+ }
+ }
+ return mapping;
+}
+
+void ConfigurationPolicyProvider::NotifyStoreOfPolicyChange() {
+ NotificationService::current()->Notify(
+ NotificationType::POLICY_CHANGED,
+ Source<ConfigurationPolicyProvider>(this),
+ NotificationService::NoDetails());
+}
+
diff --git a/chrome/browser/policy/configuration_policy_provider.h b/chrome/browser/policy/configuration_policy_provider.h
new file mode 100644
index 0000000..a0802e8
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider.h
@@ -0,0 +1,54 @@
+// 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_CONFIGURATION_POLICY_PROVIDER_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/values.h"
+#include "chrome/browser/policy/configuration_policy_store.h"
+
+// A mostly-abstract super class for platform-specific policy providers.
+// Platform-specific policy providers (Windows Group Policy, gconf,
+// etc.) should implement a subclass of this class.
+class ConfigurationPolicyProvider {
+ public:
+ ConfigurationPolicyProvider() {}
+ virtual ~ConfigurationPolicyProvider() {}
+
+ // Must be implemented by provider subclasses to specify the
+ // provider-specific policy decisions. The preference service
+ // invokes this |Provide| method when it needs a policy
+ // provider to specify its policy choices. In |Provide|,
+ // the |ConfigurationPolicyProvider| must make calls to the
+ // |Apply| method of |store| to apply specific policies.
+ // Returns true if the policy could be provided, otherwise false.
+ virtual bool Provide(ConfigurationPolicyStore* store) = 0;
+
+ // Called by the subclass provider at any time to indicate that the currently
+ // applied policy is not longer current. A policy refresh will be initiated as
+ // soon as possible.
+ virtual void NotifyStoreOfPolicyChange();
+
+ protected:
+ // A structure mapping policies to their implementations by providers.
+ struct PolicyValueMapEntry {
+ ConfigurationPolicyStore::PolicyType policy_type;
+ Value::ValueType value_type;
+ std::string name;
+ };
+ typedef std::vector<PolicyValueMapEntry> PolicyValueMap;
+
+ // Returns the mapping from policy values to the actual names used by
+ // implementations.
+ static const PolicyValueMap* PolicyValueMapping();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProvider);
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_H_
diff --git a/chrome/browser/policy/configuration_policy_provider_mac.cc b/chrome/browser/policy/configuration_policy_provider_mac.cc
new file mode 100644
index 0000000..77e3a4c
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_mac.cc
@@ -0,0 +1,78 @@
+// 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/configuration_policy_provider_mac.h"
+
+#include "base/logging.h"
+#include "base/scoped_cftyperef.h"
+#include "base/sys_string_conversions.h"
+
+ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac()
+ : preferences_(new MacPreferences()) {
+}
+
+ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac(
+ MacPreferences* preferences) : preferences_(preferences) {
+}
+
+bool ConfigurationPolicyProviderMac::Provide(ConfigurationPolicyStore* store) {
+ bool success = true;
+ const PolicyValueMap* mapping = PolicyValueMapping();
+
+ for (PolicyValueMap::const_iterator current = mapping->begin();
+ current != mapping->end(); ++current) {
+ scoped_cftyperef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(current->name));
+ scoped_cftyperef<CFPropertyListRef> value(
+ preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication));
+ if (!value.get())
+ continue;
+ if (!preferences_->AppValueIsForced(name, kCFPreferencesCurrentApplication))
+ continue;
+
+ switch (current->value_type) {
+ case Value::TYPE_STRING:
+ if (CFGetTypeID(value) == CFStringGetTypeID()) {
+ std::string string_value =
+ base::SysCFStringRefToUTF8((CFStringRef)value.get());
+ store->Apply(
+ current->policy_type,
+ Value::CreateStringValue(string_value));
+ } else {
+ success = false;
+ }
+ break;
+ case Value::TYPE_BOOLEAN:
+ if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
+ bool bool_value = CFBooleanGetValue((CFBooleanRef)value.get());
+ store->Apply(current->policy_type,
+ Value::CreateBooleanValue(bool_value));
+ } else {
+ success = false;
+ }
+ break;
+ case Value::TYPE_INTEGER:
+ if (CFGetTypeID(value) == CFNumberGetTypeID()) {
+ int int_value;
+ bool cast = CFNumberGetValue((CFNumberRef)value.get(),
+ kCFNumberIntType,
+ &int_value);
+ if (cast)
+ store->Apply(current->policy_type,
+ Value::CreateIntegerValue(int_value));
+ else
+ success = false;
+ } else {
+ success = false;
+ }
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ }
+
+ return success;
+}
+
diff --git a/chrome/browser/policy/configuration_policy_provider_mac.h b/chrome/browser/policy/configuration_policy_provider_mac.h
new file mode 100644
index 0000000..ab24473
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_mac.h
@@ -0,0 +1,31 @@
+// 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_CONFIGURATION_POLICY_PROVIDER_MAC_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_MAC_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/policy/configuration_policy_store.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/preferences_mac.h"
+
+// An implementation of |ConfigurationPolicyProvider| using the mechanism
+// provided by Mac OS X's managed preferences.
+class ConfigurationPolicyProviderMac : public ConfigurationPolicyProvider {
+ public:
+ ConfigurationPolicyProviderMac();
+ // For testing; takes ownership of |preferences|.
+ explicit ConfigurationPolicyProviderMac(MacPreferences* preferences);
+ virtual ~ConfigurationPolicyProviderMac() { }
+
+ // ConfigurationPolicyProvider method overrides:
+ virtual bool Provide(ConfigurationPolicyStore* store);
+
+ protected:
+ scoped_ptr<MacPreferences> preferences_;
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_MAC_H_
+
diff --git a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
new file mode 100644
index 0000000..23f01b7
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
@@ -0,0 +1,119 @@
+// 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 <gtest/gtest.h>
+
+#include "base/stl_util-inl.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/policy/configuration_policy_provider_mac.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+#include "chrome/browser/preferences_mock_mac.h"
+
+// A subclass of |ConfigurationPolicyProviderMac| providing access to various
+// internal things without an orgy of FRIEND_TESTS.
+class TestConfigurationPolicyProviderMac
+ : public ConfigurationPolicyProviderMac {
+ public:
+ TestConfigurationPolicyProviderMac() :
+ ConfigurationPolicyProviderMac(new MockPreferences()) { }
+ virtual ~TestConfigurationPolicyProviderMac() { }
+
+ void AddTestItem(ConfigurationPolicyStore::PolicyType policy,
+ CFPropertyListRef value,
+ bool is_forced);
+
+ typedef std::vector<PolicyValueMapEntry> PolicyValueMap;
+ static const PolicyValueMap* PolicyValueMapping() {
+ return ConfigurationPolicyProvider::PolicyValueMapping();
+ }
+};
+
+void TestConfigurationPolicyProviderMac::AddTestItem(
+ ConfigurationPolicyStore::PolicyType policy,
+ CFPropertyListRef value,
+ bool is_forced) {
+ const PolicyValueMap* mapping = PolicyValueMapping();
+ for (PolicyValueMap::const_iterator current = mapping->begin();
+ current != mapping->end(); ++current) {
+ if (current->policy_type == policy) {
+ scoped_cftyperef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(current->name));
+ static_cast<MockPreferences*>(preferences_.get())->
+ AddTestItem(name, value, is_forced);
+ }
+ }
+}
+
+TEST(ConfigurationPolicyProviderMacTest, TestPolicyDefault) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderMac provider;
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, ConfigurationPolicyStore::kPolicyHomePage));
+}
+
+TEST(ConfigurationPolicyProviderMacTest, TestHomePagePolicy) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderMac provider;
+ provider.AddTestItem(ConfigurationPolicyStore::kPolicyHomePage,
+ CFSTR("http://chromium.org"),
+ true);
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i =
+ map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(i != map.end());
+ std::string value;
+ i->second->GetAsString(&value);
+ EXPECT_EQ("http://chromium.org", value);
+}
+
+TEST(ConfigurationPolicyProviderMacTest, TestHomePagePolicyUnforced) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderMac provider;
+ provider.AddTestItem(ConfigurationPolicyStore::kPolicyHomePage,
+ CFSTR("http://chromium.org"),
+ false);
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, ConfigurationPolicyStore::kPolicyHomePage));
+}
+
+TEST(ConfigurationPolicyProviderMacTest, TestHomePagePolicyWrongType) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderMac provider;
+ provider.AddTestItem(ConfigurationPolicyStore::kPolicyHomePage,
+ kCFBooleanTrue,
+ true);
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, ConfigurationPolicyStore::kPolicyHomePage));
+}
+
+TEST(ConfigurationPolicyProviderMacTest, TestHomepageIsNewTabPagePolicy) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderMac provider;
+ provider.AddTestItem(ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage,
+ kCFBooleanTrue,
+ true);
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i =
+ map.find(ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage);
+ ASSERT_TRUE(i != map.end());
+ bool value = false;
+ i->second->GetAsBoolean(&value);
+ EXPECT_EQ(true, value);
+}
+
diff --git a/chrome/browser/policy/configuration_policy_provider_win.cc b/chrome/browser/policy/configuration_policy_provider_win.cc
new file mode 100644
index 0000000..4085b14
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_win.cc
@@ -0,0 +1,166 @@
+// 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/configuration_policy_provider_win.h"
+
+#include <userenv.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/object_watcher.h"
+#include "base/registry.h"
+#include "base/scoped_ptr.h"
+#include "base/string_piece.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/policy_constants.h"
+
+ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
+ GroupPolicyChangeWatcher(ConfigurationPolicyProvider* provider)
+ : provider_(provider),
+ user_policy_changed_event_(false, false),
+ machine_policy_changed_event_(false, false) {
+ CHECK(RegisterGPNotification(user_policy_changed_event_.handle(), false));
+ CHECK(RegisterGPNotification(machine_policy_changed_event_.handle(), true));
+ user_policy_watcher_.StartWatching(
+ user_policy_changed_event_.handle(),
+ this);
+ machine_policy_watcher_.StartWatching(
+ machine_policy_changed_event_.handle(),
+ this);
+}
+
+void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
+ OnObjectSignaled(HANDLE object) {
+ provider_->NotifyStoreOfPolicyChange();
+ if (object == user_policy_changed_event_.handle()) {
+ user_policy_watcher_.StartWatching(
+ user_policy_changed_event_.handle(),
+ this);
+ } else if (object == machine_policy_changed_event_.handle()) {
+ machine_policy_watcher_.StartWatching(
+ machine_policy_changed_event_.handle(),
+ this);
+ } else {
+ // This method should only be called as a result of signals
+ // to the user- and machine-policy handle watchers.
+ NOTREACHED();
+ }
+}
+
+ConfigurationPolicyProviderWin::ConfigurationPolicyProviderWin() {
+ watcher_.reset(new GroupPolicyChangeWatcher(this));
+}
+
+bool ConfigurationPolicyProviderWin::GetRegistryPolicyString(
+ const wchar_t* value_name, string16* result) {
+ DWORD value_size = 0;
+ DWORD key_type = 0;
+ scoped_array<uint8> buffer;
+ RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey);
+ if (hkcu_policy_key.ReadValue(value_name, 0, &value_size, &key_type)) {
+ if (key_type != REG_SZ)
+ return false;
+ // According to the Microsoft documentation, the string
+ // buffer may not be explicitly 0-terminated. Allocate a
+ // slightly larger buffer and prefill to zeros to guarantee
+ // the 0-termination.
+ buffer.reset(new uint8[value_size + 2]);
+ memset(buffer.get(), 0, value_size + 2);
+ hkcu_policy_key.ReadValue(value_name, buffer.get(), &value_size);
+ } else {
+ RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey);
+ if (hklm_policy_key.ReadValue(value_name, 0, &value_size, &key_type)) {
+ if (key_type != REG_SZ)
+ return false;
+ // According to the Microsoft documentation, the string
+ // buffer may not be explicitly 0-terminated. Allocate a
+ // slightly larger buffer and prefill to zeros to guarantee
+ // the 0-termination.
+ buffer.reset(new uint8[value_size + 2]);
+ memset(buffer.get(), 0, value_size + 2);
+ hklm_policy_key.ReadValue(value_name, buffer.get(), &value_size);
+ } else {
+ return false;
+ }
+ }
+
+ result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
+ return true;
+}
+
+bool ConfigurationPolicyProviderWin::GetRegistryPolicyBoolean(
+ const wchar_t* value_name, bool* result) {
+ DWORD value;
+ RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey);
+ if (hkcu_policy_key.ReadValueDW(value_name, &value)) {
+ *result = value != 0;
+ return true;
+ }
+
+ RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey);
+ if (hklm_policy_key.ReadValueDW(value_name, &value)) {
+ *result = value != 0;
+ return true;
+ }
+ return false;
+}
+
+bool ConfigurationPolicyProviderWin::GetRegistryPolicyInteger(
+ const wchar_t* value_name, uint32* result) {
+ DWORD value;
+ RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey);
+ if (hkcu_policy_key.ReadValueDW(value_name, &value)) {
+ *result = value;
+ return true;
+ }
+
+ RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey);
+ if (hklm_policy_key.ReadValueDW(value_name, &value)) {
+ *result = value;
+ return true;
+ }
+ return false;
+}
+
+bool ConfigurationPolicyProviderWin::Provide(
+ ConfigurationPolicyStore* store) {
+ const PolicyValueMap* mapping = PolicyValueMapping();
+
+ for (PolicyValueMap::const_iterator current = mapping->begin();
+ current != mapping->end(); ++current) {
+ std::wstring name = UTF8ToWide(current->name);
+ std::wstring string_value;
+ uint32 int_value;
+ bool bool_value;
+ switch (current->value_type) {
+ case Value::TYPE_STRING:
+ if (GetRegistryPolicyString(name.c_str(), &string_value)) {
+ store->Apply(
+ current->policy_type,
+ Value::CreateStringValue(string_value));
+ }
+ break;
+ case Value::TYPE_BOOLEAN:
+ if (GetRegistryPolicyBoolean(name.c_str(), &bool_value)) {
+ store->Apply(current->policy_type,
+ Value::CreateBooleanValue(bool_value));
+ }
+ break;
+ case Value::TYPE_INTEGER:
+ if (GetRegistryPolicyInteger(name.c_str(), &int_value)) {
+ store->Apply(current->policy_type,
+ Value::CreateIntegerValue(int_value));
+ }
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/chrome/browser/policy/configuration_policy_provider_win.h b/chrome/browser/policy/configuration_policy_provider_win.h
new file mode 100644
index 0000000..e2ebbdb
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_win.h
@@ -0,0 +1,62 @@
+// 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_CONFIGURATION_POLICY_PROVIDER_WIN_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_WIN_H_
+#pragma once
+
+#include "base/object_watcher.h"
+#include "base/scoped_ptr.h"
+#include "base/waitable_event.h"
+#include "chrome/browser/policy/configuration_policy_store.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+
+// An implementation of |ConfigurationPolicyProvider| using the
+// mechanism provided by Windows Groups Policy. Policy decisions are
+// stored as values in a special section of the Windows Registry.
+// On a managed machine in a domain, this portion of the registry is
+// periodically updated by the Windows Group Policy machinery to contain
+// the latest version of the policy set by administrators.
+class ConfigurationPolicyProviderWin : public ConfigurationPolicyProvider {
+ public:
+ // Keeps watch on Windows Group Policy notification event to trigger
+ // a policy reload when Group Policy changes.
+ class GroupPolicyChangeWatcher : public base::ObjectWatcher::Delegate {
+ public:
+ explicit GroupPolicyChangeWatcher(ConfigurationPolicyProvider* provider);
+ virtual ~GroupPolicyChangeWatcher() {}
+
+ virtual void OnObjectSignaled(HANDLE object);
+
+ private:
+ ConfigurationPolicyProvider* provider_;
+ base::WaitableEvent user_policy_changed_event_;
+ base::WaitableEvent machine_policy_changed_event_;
+ base::ObjectWatcher user_policy_watcher_;
+ base::ObjectWatcher machine_policy_watcher_;
+ };
+
+ ConfigurationPolicyProviderWin();
+ virtual ~ConfigurationPolicyProviderWin() { }
+
+ // ConfigurationPolicyProvider method overrides:
+ virtual bool Provide(ConfigurationPolicyStore* store);
+
+ protected:
+ // The sub key path for Chromium's Group Policy information in the
+ // Windows registry.
+ static const wchar_t kPolicyRegistrySubKey[];
+
+ private:
+ scoped_ptr<GroupPolicyChangeWatcher> watcher_;
+
+ // Methods to perfrom type-specific policy lookups in the registry.
+ // HKLM is checked first, then HKCU.
+ bool GetRegistryPolicyString(const wchar_t* value_name, string16* result);
+ bool GetRegistryPolicyBoolean(const wchar_t* value_name, bool* result);
+ bool GetRegistryPolicyInteger(const wchar_t* value_name, uint32* result);
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_WIN_H_
+
diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
new file mode 100644
index 0000000..221ef83
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
@@ -0,0 +1,316 @@
+// 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 <gtest/gtest.h>
+
+#include <windows.h>
+
+#include "base/logging.h"
+#include "base/registry.h"
+#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
+#include "base/string_piece.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/policy/configuration_policy_provider_win.h"
+#include "chrome/browser/policy/mock_configuration_policy_store.h"
+#include "chrome/common/policy_constants.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+const wchar_t kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests";
+const wchar_t kUnitTestMachineOverrideSubKey[] =
+ L"SOFTWARE\\Chromium Unit Tests\\HKLM Override";
+const wchar_t kUnitTestUserOverrideSubKey[] =
+ L"SOFTWARE\\Chromium Unit Tests\\HKCU Override";
+
+} // namespace
+
+// A subclass of |ConfigurationPolicyProviderWin| providing access to
+// internal protected constants without an orgy of FRIEND_TESTS.
+class TestConfigurationPolicyProviderWin
+ : public ConfigurationPolicyProviderWin {
+ public:
+ TestConfigurationPolicyProviderWin() : ConfigurationPolicyProviderWin() { }
+ virtual ~TestConfigurationPolicyProviderWin() { }
+
+ void SetHomepageRegistryValue(HKEY hive, const wchar_t* value);
+ void SetHomepageRegistryValueWrongType(HKEY hive);
+ void SetBooleanPolicy(ConfigurationPolicyStore::PolicyType type,
+ HKEY hive, bool value);
+ void SetCookiesMode(HKEY hive, uint32 value);
+
+ typedef std::vector<PolicyValueMapEntry> PolicyValueMap;
+ static const PolicyValueMap* PolicyValueMapping() {
+ return ConfigurationPolicyProvider::PolicyValueMapping();
+ }
+};
+
+namespace {
+
+std::wstring NameForPolicy(ConfigurationPolicyStore::PolicyType policy) {
+ const TestConfigurationPolicyProviderWin::PolicyValueMap* mapping =
+ TestConfigurationPolicyProviderWin::PolicyValueMapping();
+ for (TestConfigurationPolicyProviderWin::PolicyValueMap::const_iterator
+ current = mapping->begin(); current != mapping->end(); ++current) {
+ if (current->policy_type == policy)
+ return UTF8ToWide(current->name);
+ }
+ return NULL;
+}
+
+} // namespace
+
+void TestConfigurationPolicyProviderWin::SetHomepageRegistryValue(
+ HKEY hive,
+ const wchar_t* value) {
+ RegKey key(hive, policy::kRegistrySubKey, KEY_ALL_ACCESS);
+ EXPECT_TRUE(key.WriteValue(
+ NameForPolicy(ConfigurationPolicyStore::kPolicyHomePage).c_str(),
+ value));
+}
+
+void TestConfigurationPolicyProviderWin::SetHomepageRegistryValueWrongType(
+ HKEY hive) {
+ RegKey key(hive, policy::kRegistrySubKey, KEY_ALL_ACCESS);
+ EXPECT_TRUE(key.WriteValue(
+ NameForPolicy(ConfigurationPolicyStore::kPolicyHomePage).c_str(),
+ 5));
+}
+
+void TestConfigurationPolicyProviderWin::SetBooleanPolicy(
+ ConfigurationPolicyStore::PolicyType type,
+ HKEY hive,
+ bool value) {
+ RegKey key(hive, policy::kRegistrySubKey, KEY_ALL_ACCESS);
+ EXPECT_TRUE(key.WriteValue(NameForPolicy(type).c_str(), value));
+}
+
+// This test class provides sandboxing and mocking for the parts of the
+// Windows Registry implementing Group Policy. The |SetUp| method prepares
+// two temporary sandbox keys in |kUnitTestRegistrySubKey|, one for HKLM and one
+// for HKCU. A test's calls to the registry are redirected by Windows to these
+// sandboxes, allowing the tests to manipulate and access policy as if it
+// were active, but without actually changing the parts of the Registry that
+// are managed by Group Policy.
+class ConfigurationPolicyProviderWinTest : public testing::Test {
+ public:
+ ConfigurationPolicyProviderWinTest();
+
+ // testing::Test method overrides:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ void ActivateOverrides();
+ void DeactivateOverrides();
+
+ // Deletes the registry key created during the tests.
+ void DeleteRegistrySandbox();
+
+ void TestBooleanPolicyDefault(ConfigurationPolicyStore::PolicyType type);
+ void TestBooleanPolicyHKLM(ConfigurationPolicyStore::PolicyType type);
+ void TestBooleanPolicy(ConfigurationPolicyStore::PolicyType type);
+
+ private:
+ // A message loop must be declared and instantiated for these tests,
+ // because Windows policy provider create WaitableEvents and
+ // ObjectWatchers that require the tests to have a MessageLoop associated
+ // with the thread executing the tests.
+ MessageLoop loop_;
+
+ // Keys are created for the lifetime of a test to contain
+ // the sandboxed HKCU and HKLM hives, respectively.
+ RegKey temp_hkcu_hive_key_;
+ RegKey temp_hklm_hive_key_;
+};
+
+ConfigurationPolicyProviderWinTest::ConfigurationPolicyProviderWinTest()
+ : temp_hklm_hive_key_(HKEY_CURRENT_USER, kUnitTestMachineOverrideSubKey),
+ temp_hkcu_hive_key_(HKEY_CURRENT_USER, kUnitTestUserOverrideSubKey) {
+}
+
+void ConfigurationPolicyProviderWinTest::SetUp() {
+ // Cleanup any remnants of previous tests.
+ DeleteRegistrySandbox();
+
+ // Create the subkeys to hold the overridden HKLM and HKCU
+ // policy settings.
+ temp_hklm_hive_key_.Create(HKEY_CURRENT_USER,
+ kUnitTestMachineOverrideSubKey,
+ KEY_ALL_ACCESS);
+ temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
+ kUnitTestUserOverrideSubKey,
+ KEY_ALL_ACCESS);
+
+ ActivateOverrides();
+}
+
+void ConfigurationPolicyProviderWinTest::ActivateOverrides() {
+ HRESULT result = RegOverridePredefKey(HKEY_LOCAL_MACHINE,
+ temp_hklm_hive_key_.Handle());
+ EXPECT_EQ(ERROR_SUCCESS, result);
+ result = RegOverridePredefKey(HKEY_CURRENT_USER,
+ temp_hkcu_hive_key_.Handle());
+ EXPECT_EQ(ERROR_SUCCESS, result);
+}
+
+void ConfigurationPolicyProviderWinTest::DeactivateOverrides() {
+ uint32 result = RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0);
+ EXPECT_EQ(ERROR_SUCCESS, result);
+ result = RegOverridePredefKey(HKEY_CURRENT_USER, 0);
+ EXPECT_EQ(ERROR_SUCCESS, result);
+}
+
+void ConfigurationPolicyProviderWinTest::TearDown() {
+ DeactivateOverrides();
+ DeleteRegistrySandbox();
+}
+
+void ConfigurationPolicyProviderWinTest::DeleteRegistrySandbox() {
+ temp_hklm_hive_key_.Close();
+ temp_hkcu_hive_key_.Close();
+ RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey, KEY_ALL_ACCESS);
+ key.DeleteKey(L"");
+}
+
+void ConfigurationPolicyProviderWinTest::TestBooleanPolicyDefault(
+ ConfigurationPolicyStore::PolicyType type) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, type));
+}
+
+void ConfigurationPolicyProviderWinTest::TestBooleanPolicyHKLM(
+ ConfigurationPolicyStore::PolicyType type) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.SetBooleanPolicy(type, HKEY_LOCAL_MACHINE, true);
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i = map.find(type);
+ ASSERT_TRUE(i != map.end());
+ bool value = false;
+ i->second->GetAsBoolean(&value);
+ EXPECT_EQ(true, value);
+}
+
+void ConfigurationPolicyProviderWinTest::TestBooleanPolicy(
+ ConfigurationPolicyStore::PolicyType type) {
+ TestBooleanPolicyDefault(type);
+ TestBooleanPolicyHKLM(type);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest, TestHomePagePolicyDefault) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, ConfigurationPolicyStore::kPolicyHomePage));
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest, TestHomePagePolicyHKCU) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.SetHomepageRegistryValue(HKEY_CURRENT_USER,
+ L"http://chromium.org");
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i =
+ map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(i != map.end());
+ string16 value;
+ i->second->GetAsString(&value);
+ EXPECT_EQ(L"http://chromium.org", value);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest, TestHomePagePolicyHKCUWrongType) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.SetHomepageRegistryValueWrongType(HKEY_CURRENT_USER);
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ EXPECT_FALSE(ContainsKey(map, ConfigurationPolicyStore::kPolicyHomePage));
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest, TestHomePagePolicyHKLM) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.SetHomepageRegistryValue(HKEY_LOCAL_MACHINE,
+ L"http://chromium.org");
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i =
+ map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(i != map.end());
+ string16 value;
+ i->second->GetAsString(&value);
+ EXPECT_EQ(L"http://chromium.org", value);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest, TestHomePagePolicyHKLMOverHKCU) {
+ MockConfigurationPolicyStore store;
+ TestConfigurationPolicyProviderWin provider;
+ provider.SetHomepageRegistryValue(HKEY_CURRENT_USER,
+ L"http://chromium.org");
+ provider.SetHomepageRegistryValue(HKEY_LOCAL_MACHINE,
+ L"http://crbug.com");
+
+ provider.Provide(&store);
+
+ const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map());
+ MockConfigurationPolicyStore::PolicyMap::const_iterator i =
+ map.find(ConfigurationPolicyStore::kPolicyHomePage);
+ ASSERT_TRUE(i != map.end());
+ string16 value;
+ i->second->GetAsString(&value);
+ EXPECT_EQ(L"http://crbug.com", value);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestHomepageIsNewTabPagePolicy) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicyAlternateErrorPagesEnabled) {
+ TestBooleanPolicy(
+ ConfigurationPolicyStore::kPolicyAlternateErrorPagesEnabled);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicySearchSuggestEnabled) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicySearchSuggestEnabled);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicyDnsPrefetchingEnabled) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicyDnsPrefetchingEnabled);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicySafeBrowsingEnabled) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicySafeBrowsingEnabled);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicyMetricsReportingEnabled) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicyMetricsReportingEnabled);
+}
+
+TEST_F(ConfigurationPolicyProviderWinTest,
+ TestPolicyPasswordManagerEnabled) {
+ TestBooleanPolicy(ConfigurationPolicyStore::kPolicyPasswordManagerEnabled);
+}
diff --git a/chrome/browser/policy/configuration_policy_store.h b/chrome/browser/policy/configuration_policy_store.h
new file mode 100644
index 0000000..80d9a56
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_store.h
@@ -0,0 +1,57 @@
+// 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_CONFIGURATION_POLICY_STORE_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_STORE_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+class Value;
+
+// An abstract super class for policy stores that provides a method that can be
+// called by a |ConfigurationPolicyProvider| to specify a policy.
+class ConfigurationPolicyStore {
+ public:
+ ConfigurationPolicyStore() {}
+ virtual ~ConfigurationPolicyStore() {}
+
+ enum PolicyType {
+ kPolicyHomePage,
+ kPolicyHomepageIsNewTabPage,
+ kPolicyProxyServerMode,
+ kPolicyProxyServer,
+ kPolicyProxyPacUrl,
+ kPolicyProxyBypassList,
+ kPolicyAlternateErrorPagesEnabled,
+ kPolicySearchSuggestEnabled,
+ kPolicyDnsPrefetchingEnabled,
+ kPolicySafeBrowsingEnabled,
+ kPolicyMetricsReportingEnabled,
+ kPolicyPasswordManagerEnabled,
+ kPolicySyncDisabled,
+ kPolicyApplicationLocale,
+
+ // A policy for allowing administrators to forcibly disable
+ // specific plugins. This policy is a comma-separated list of
+ // plugin names. Plugin names must not include the backslash
+ // character.
+ kPolicyDisabledPlugins
+ };
+
+ static const int kPolicyNoProxyServerMode = 0;
+ static const int kPolicyAutoDetectProxyMode = 1;
+ static const int kPolicyManuallyConfiguredProxyMode = 2;
+ static const int kPolicyUseSystemProxyMode = 3;
+
+ // A |ConfigurationPolicyProvider| specifes the value of a policy setting
+ // through a call to |Apply|.
+ // The configuration policy pref store takes over the ownership of |value|.
+ virtual void Apply(PolicyType policy, Value* value) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyStore);
+};
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_STORE_H_
diff --git a/chrome/browser/policy/dummy_configuration_policy_provider.h b/chrome/browser/policy/dummy_configuration_policy_provider.h
new file mode 100644
index 0000000..9309c00
--- /dev/null
+++ b/chrome/browser/policy/dummy_configuration_policy_provider.h
@@ -0,0 +1,26 @@
+// 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_DUMMY_CONFIGURATION_POLICY_PROVIDER_H_
+#define CHROME_BROWSER_POLICY_DUMMY_CONFIGURATION_POLICY_PROVIDER_H_
+#pragma once
+
+#include "chrome/browser/policy/configuration_policy_store.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+
+class DummyConfigurationPolicyProvider : public ConfigurationPolicyProvider {
+ public:
+ DummyConfigurationPolicyProvider() {}
+ virtual ~DummyConfigurationPolicyProvider() {}
+
+ virtual bool Provide(ConfigurationPolicyStore* store) {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DummyConfigurationPolicyProvider);
+};
+
+#endif // CHROME_BROWSER_POLICY_DUMMY_CONFIGURATION_POLICY_PROVIDER_H_
+
diff --git a/chrome/browser/policy/mock_configuration_policy_provider.h b/chrome/browser/policy/mock_configuration_policy_provider.h
new file mode 100644
index 0000000..2d727467
--- /dev/null
+++ b/chrome/browser/policy/mock_configuration_policy_provider.h
@@ -0,0 +1,43 @@
+// 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_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
+#define CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
+#pragma once
+
+#include <map>
+
+#include "base/stl_util-inl.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+
+// Mock ConfigurationPolicyProvider implementation that supplies canned
+// values for polices.
+class MockConfigurationPolicyProvider : public ConfigurationPolicyProvider {
+ public:
+ MockConfigurationPolicyProvider() {}
+ ~MockConfigurationPolicyProvider() {
+ STLDeleteValues(&policy_map_);
+ }
+
+ typedef std::map<ConfigurationPolicyStore::PolicyType, Value*> PolicyMap;
+
+ void AddPolicy(ConfigurationPolicyStore::PolicyType policy, Value* value) {
+ policy_map_[policy] = value;
+ }
+
+ // ConfigurationPolicyProvider method overrides.
+ virtual bool Provide(ConfigurationPolicyStore* store) {
+ for (PolicyMap::const_iterator current = policy_map_.begin();
+ current != policy_map_.end(); ++current) {
+ store->Apply(current->first, current->second->DeepCopy());
+ }
+ return true;
+ }
+
+ private:
+ PolicyMap policy_map_;
+};
+
+#endif // CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
+
diff --git a/chrome/browser/policy/mock_configuration_policy_store.h b/chrome/browser/policy/mock_configuration_policy_store.h
new file mode 100644
index 0000000..c1ab12d
--- /dev/null
+++ b/chrome/browser/policy/mock_configuration_policy_store.h
@@ -0,0 +1,35 @@
+// 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_MOCK_CONFIGURATION_POLICY_STORE_H_
+#define CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_STORE_H_
+#pragma once
+
+#include <map>
+
+#include "base/stl_util-inl.h"
+#include "chrome/browser/policy/configuration_policy_store.h"
+
+// Mock ConfigurationPolicyStore implementation that records values for policy
+// settings as they get set.
+class MockConfigurationPolicyStore : public ConfigurationPolicyStore {
+ public:
+ MockConfigurationPolicyStore() {}
+ ~MockConfigurationPolicyStore() {
+ STLDeleteValues(&policy_map_);
+ }
+
+ typedef std::map<ConfigurationPolicyStore::PolicyType, Value*> PolicyMap;
+ const PolicyMap& policy_map() { return policy_map_; }
+
+ // ConfigurationPolicyStore implementation.
+ virtual void Apply(PolicyType policy, Value* value) {
+ policy_map_[policy] = value;
+ }
+
+ private:
+ PolicyMap policy_map_;
+};
+
+#endif // CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_STORE_H_