Make policy errors available to display in about:policy.

This is the continuation of http://codereview.chromium.org/7972013/

BUG=99178
TEST=Everything works as before, no visible changes yet


Review URL: http://codereview.chromium.org/8139029

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107115 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 84ea4ce..7353f09 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4384,6 +4384,49 @@
       <message name="IDS_POLICY_STATUS_SERIAL_ERROR" desc="Indicates that a policy fetch failed because the serial number was invalid.">
         Invalid serial number
       </message>
+      <message name="IDS_POLICY_TYPE_ERROR" desc="The text displayed in the status column when a policy value has the wrong type.">
+        Expected <ph name="VALUE_TYPE">$1<ex>boolean</ex></ph> value.
+      </message>
+      <message name="IDS_POLICY_OUT_OF_RANGE_ERROR" desc="The text displayed in the status column when a policy value is out of range.">
+        Value is out of range <ph name="VALUE">$1<ex>10</ex></ph>.
+      </message>
+     <message name="IDS_POLICY_DEFAULT_SEARCH_DISABLED" desc="The text displayed in the status column when a policy value has been ignored because default search has been disabled.">
+        Ignored because default search is disabled by policy.
+      </message>
+      <message name="IDS_POLICY_NOT_SPECIFIED_ERROR" desc="The text displayed in the status column when a policy value should have been specified but wasn't.">
+        Must be specified.
+      </message>
+      <message name="IDS_POLICY_INVALID_SEARCH_URL_ERROR" desc="The text displayed in the status column when a the URL given for DefaultSearchProviderSearchURL is invalid.">
+        Invalid search URL.
+      </message>
+      <message name="IDS_POLICY_INVALID_PROXY_MODE_ERROR" desc="The text displayed in the status column when the value for ProxyMode is invalid.">
+        Invalid proxy mode.
+      </message>
+      <message name="IDS_POLICY_PROXY_MODE_DISABLED_ERROR" desc="The text displayed in the status column when use of a proxy is disabled but a proxy configuration is given.">
+        Use of a proxy is disabled but an explicit proxy configuration is specified.
+      </message>
+      <message name="IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR" desc="The text displayed in the status column when the proxy is set to auto configured but a proxy configuration is given.">
+        Proxy is set to auto configured.
+      </message>
+      <message name="IDS_POLICY_PROXY_MODE_PAC_URL_ERROR" desc="The text displayed in the status column when the proxy configuration is set to use a .pac script URL but policies only for fixed proxy servers are also specified.">
+        Proxy configuration is set to use a .pac script URL, not fixed proxy servers.
+      </message>
+      <message name="IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR" desc="The text displayed in the status column when the proxy configuration is set to use fixed proxy servers but an alternate configuration is given.">
+        Proxy is set to use fixed proxy servers, not a .pac script URL.
+      </message>
+      <message name="IDS_POLICY_PROXY_MODE_SYSTEM_ERROR" desc="The text displayed in the status column when the proxy configuration is set to use system settings but an alternate configuration is given.">
+        System proxy settings are set to be used but an explicit proxy configuration is also specified.
+      </message>
+      <message name="IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR" desc="The text displayed in the status column when both fixed proxy servers and .pac url are specified.">
+        Both fixed proxy servers and a .pac script URL are specified.
+      </message>
+      <message name="IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR" desc="The text displayed in the status column when neither a fixed proxy servers or a .pac url are specified.">
+        Neither fixed proxy servers nor a .pac script URL are specified.
+      </message>
+      <message name="IDS_POLICY_OVERRIDDEN" desc="The text displayed in the status column when the corresponding policy is being ignored because another policy is overriding it.">
+        Ignored because it was overridden by <ph name="POLICY_NAME">$1<ex>ProxyMode</ex></ph>.
+      </message>
+
       <!-- about:flags -->
       <message name="IDS_FLAGS_LONG_TITLE" desc="Long version of the title for the about:flags page.">
         Careful, these experiments may bite
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 6c7d1bf..3930466 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/file_path.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "chrome/browser/net/gaia/token_service.h"
 #include "chrome/browser/policy/cloud_policy_provider.h"
 #include "chrome/browser/policy/cloud_policy_provider_impl.h"
@@ -97,6 +98,8 @@
   user_cloud_policy_subsystem_.reset();
   user_policy_token_cache_.reset();
   user_data_store_.reset();
+
+  STLDeleteElements(policy_handlers_.get());
 }
 
 ConfigurationPolicyProvider*
@@ -308,6 +311,11 @@
   return user_data_store_.get();
 }
 
+const ConfigurationPolicyHandler::HandlerList*
+    BrowserPolicyConnector::GetConfigurationPolicyHandlerList() const {
+  return policy_handlers_.get();
+}
+
 BrowserPolicyConnector::BrowserPolicyConnector()
     : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
   managed_platform_provider_.reset(CreateManagedPlatformProvider());
@@ -323,6 +331,7 @@
 #if defined(OS_CHROMEOS)
   InitializeDevicePolicy();
 #endif
+  policy_handlers_.reset(ConfigurationPolicyHandler::CreateHandlerList());
 }
 
 BrowserPolicyConnector::BrowserPolicyConnector(
@@ -334,7 +343,9 @@
       recommended_platform_provider_(recommended_platform_provider),
       managed_cloud_provider_(managed_cloud_provider),
       recommended_cloud_provider_(recommended_cloud_provider),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {}
+      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+  policy_handlers_.reset(ConfigurationPolicyHandler::CreateHandlerList());
+}
 
 void BrowserPolicyConnector::Observe(
     int type,
diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h
index 4f63910e..0100ae1 100644
--- a/chrome/browser/policy/browser_policy_connector.h
+++ b/chrome/browser/policy/browser_policy_connector.h
@@ -12,6 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/policy/cloud_policy_data_store.h"
+#include "chrome/browser/policy/configuration_policy_handler.h"
 #include "chrome/browser/policy/enterprise_install_attributes.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -108,6 +109,9 @@
   const CloudPolicyDataStore* GetDeviceCloudPolicyDataStore() const;
   const CloudPolicyDataStore* GetUserCloudPolicyDataStore() const;
 
+  const ConfigurationPolicyHandler::HandlerList*
+      GetConfigurationPolicyHandlerList() const;
+
  private:
   friend class ::TestingBrowserProcess;
 
@@ -170,6 +174,9 @@
   // policy authentication tokens.
   TokenService* token_service_;
 
+  // List of all available handlers derived from ConfigurationPolicyHandler.
+  scoped_ptr<ConfigurationPolicyHandler::HandlerList> policy_handlers_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserPolicyConnector);
 };
 
diff --git a/chrome/browser/policy/config_dir_policy_provider_unittest.cc b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
index 4663991..c53496f 100644
--- a/chrome/browser/policy/config_dir_policy_provider_unittest.cc
+++ b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
@@ -192,16 +192,6 @@
   EXPECT_TRUE(policy_map.empty());
 }
 
-TEST_P(ConfigDirPolicyProviderValueTest, NullValue) {
-  DictionaryValue dict;
-  dict.Set(GetParam().policy_key(), Value::CreateNullValue());
-  WriteConfigFile(dict, "empty");
-  ConfigDirPolicyProvider provider(GetChromePolicyDefinitionList(), test_dir());
-  PolicyMap policy_map;
-  EXPECT_TRUE(provider.Provide(&policy_map));
-  EXPECT_TRUE(policy_map.empty());
-}
-
 TEST_P(ConfigDirPolicyProviderValueTest, TestValue) {
   DictionaryValue dict;
   dict.Set(GetParam().policy_key(), GetParam().test_value()->DeepCopy());
diff --git a/chrome/browser/policy/configuration_policy_handler.cc b/chrome/browser/policy/configuration_policy_handler.cc
new file mode 100644
index 0000000..38f9e69
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_handler.cc
@@ -0,0 +1,1328 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/configuration_policy_handler.h"
+
+#include <string>
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/policy_error_map.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/policy/policy_path_parser.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
+#include "chrome/browser/prefs/proxy_prefs.h"
+#include "chrome/browser/search_engines/search_terms_data.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "policy/configuration_policy_type.h"
+#include "policy/policy_constants.h"
+
+namespace policy {
+
+namespace {
+
+// Implementations of ConfigurationPolicyHandler -------------------------------
+
+// Abstract class derived from ConfigurationPolicyHandler that should be
+// subclassed to handle a single policy (not a combination of policies).
+class TypeCheckingPolicyHandler : public ConfigurationPolicyHandler {
+ public:
+  TypeCheckingPolicyHandler(ConfigurationPolicyType policy_type,
+                            base::Value::Type value_type);
+
+  // ConfigurationPolicyHandler methods:
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) OVERRIDE;
+
+ protected:
+  virtual ~TypeCheckingPolicyHandler();
+
+  ConfigurationPolicyType policy_type() const;
+
+ private:
+  // The ConfigurationPolicyType of the policy.
+  ConfigurationPolicyType policy_type_;
+
+  // The type the value of the policy should have.
+  base::Value::Type value_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(TypeCheckingPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for policies that map directly to a preference.
+class SimplePolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  SimplePolicyHandler(ConfigurationPolicyType policy_type,
+                      base::Value::Type value_type,
+                      const char* pref_path);
+  virtual ~SimplePolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  // The DictionaryValue path of the preference the policy maps to.
+  const char* pref_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimplePolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the SyncDisabled policy.
+class SyncPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  SyncPolicyHandler();
+  virtual ~SyncPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SyncPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the AutofillEnabled policy.
+class AutofillPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  AutofillPolicyHandler();
+  virtual ~AutofillPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutofillPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the DownloadDirectory policy.
+class DownloadDirPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  DownloadDirPolicyHandler();
+  virtual ~DownloadDirPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DownloadDirPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the DiskCacheDir policy.
+class DiskCacheDirPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  explicit DiskCacheDirPolicyHandler();
+  virtual ~DiskCacheDirPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DiskCacheDirPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the FileSelectionDialogsHandler policy.
+class FileSelectionDialogsHandler : public TypeCheckingPolicyHandler {
+ public:
+  FileSelectionDialogsHandler();
+  virtual ~FileSelectionDialogsHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FileSelectionDialogsHandler);
+};
+
+// ConfigurationPolicyHandler for the incognito mode policies.
+class IncognitoModePolicyHandler : public ConfigurationPolicyHandler {
+ public:
+  IncognitoModePolicyHandler();
+  virtual ~IncognitoModePolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) OVERRIDE;
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  IncognitoModePrefs::Availability GetAvailabilityValueAsEnum(
+      const Value* availability);
+
+  DISALLOW_COPY_AND_ASSIGN(IncognitoModePolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the DefaultSearchEncodings policy.
+class DefaultSearchEncodingsPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  DefaultSearchEncodingsPolicyHandler();
+  virtual ~DefaultSearchEncodingsPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultSearchEncodingsPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the default search policies.
+class DefaultSearchPolicyHandler : public ConfigurationPolicyHandler {
+ public:
+  DefaultSearchPolicyHandler();
+  virtual ~DefaultSearchPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) OVERRIDE;
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  // Calls |CheckPolicySettings()| on each of the handlers in |handlers_|
+  // and returns true if all of the calls return true and false otherwise.
+  bool CheckIndividualPolicies(const PolicyMap* policies,
+                               PolicyErrorMap* errors);
+
+  // Returns true if there is a value for |policy_type| in |policies| and false
+  // otherwise.
+  bool HasDefaultSearchPolicy(const PolicyMap* policies,
+                              ConfigurationPolicyType policy_type);
+
+  // Returns true if any default search policies are specified in |policies| and
+  // false otherwise.
+  bool AnyDefaultSearchPoliciesSpecified(const PolicyMap* policies);
+
+  // Returns true if the default search provider is disabled and false
+  // otherwise.
+  bool DefaultSearchProviderIsDisabled(const PolicyMap* policies);
+
+  // Returns true if the default search URL was set and is valid and false
+  // otherwise.
+  bool DefaultSearchURLIsValid(const PolicyMap* policies);
+
+  // Make sure that the |path| if present in |prefs_|.  If not, set it to
+  // a blank string.
+  void EnsureStringPrefExists(PrefValueMap* prefs, const std::string& path);
+
+  // The ConfigurationPolicyHandler handlers for each default search policy.
+  HandlerList handlers_;
+
+  DISALLOW_COPY_AND_ASSIGN(DefaultSearchPolicyHandler);
+};
+
+// ConfigurationPolicyHandler for the proxy policies.
+class ProxyPolicyHandler : public ConfigurationPolicyHandler {
+ public:
+  ProxyPolicyHandler();
+  virtual ~ProxyPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) OVERRIDE;
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  const Value* GetProxyPolicyValue(const PolicyMap* policies,
+                                   ConfigurationPolicyType policy);
+
+  // Converts the deprecated ProxyServerMode policy value to a ProxyMode value
+  // and places the result in |mode_value|. Returns true if the conversion
+  // succeeded and false otherwise.
+  bool CheckProxyModeAndServerMode(const PolicyMap* policies,
+                                   PolicyErrorMap* errors,
+                                   std::string* mode_value);
+
+  DISALLOW_COPY_AND_ASSIGN(ProxyPolicyHandler);
+};
+
+//
+class JavascriptPolicyHandler : public ConfigurationPolicyHandler {
+ public:
+  JavascriptPolicyHandler();
+  virtual ~JavascriptPolicyHandler();
+
+  // ConfigurationPolicyHandler methods:
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) OVERRIDE;
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(JavascriptPolicyHandler);
+};
+
+
+// Helper classes --------------------------------------------------------------
+
+// Implementation of SearchTermsData just for validation.
+class SearchTermsDataForValidation : public SearchTermsData {
+ public:
+  SearchTermsDataForValidation() {}
+
+  // Implementation of SearchTermsData.
+  virtual std::string GoogleBaseURLValue() const {
+    return "http://www.google.com/";
+  }
+  virtual std::string GetApplicationLocale() const {
+    return "en";
+  }
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+  virtual string16 GetRlzParameterValue() const {
+    return string16();
+  }
+#endif
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SearchTermsDataForValidation);
+};
+
+// This is used to check whether for a given ProxyMode value, the ProxyPacUrl,
+// the ProxyBypassList and the ProxyServer policies are allowed to be specified.
+// |error_message_id| is the message id of the localized error message to show
+// when the policies are not specified as allowed. Each value of ProxyMode
+// has a ProxyModeValidationEntry in the |kProxyModeValidationMap| below.
+struct ProxyModeValidationEntry {
+  const char* mode_value;
+  bool pac_url_allowed;
+  bool bypass_list_allowed;
+  bool server_allowed;
+  int error_message_id;
+};
+
+// Maps a policy type to a preference path, and to the expected value type.
+// This is the entry type of |kSimplePolicyMap| below.
+struct PolicyToPreferenceMapEntry {
+  base::Value::Type value_type;
+  ConfigurationPolicyType policy_type;
+  const char* preference_path;
+};
+
+
+// Static data -----------------------------------------------------------------
+
+// List of policy types to preference names. This is used for simple policies
+// that directly map to a single preference.
+const PolicyToPreferenceMapEntry kSimplePolicyMap[] = {
+  { Value::TYPE_STRING, kPolicyHomepageLocation,  prefs::kHomePage },
+  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
+    prefs::kHomePageIsNewTabPage },
+  { Value::TYPE_INTEGER, kPolicyRestoreOnStartup,
+    prefs::kRestoreOnStartup},
+  { Value::TYPE_LIST, kPolicyRestoreOnStartupURLs,
+    prefs::kURLsToRestoreOnStartup },
+  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
+    prefs::kAlternateErrorPagesEnabled },
+  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
+    prefs::kSearchSuggestEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
+    prefs::kNetworkPredictionEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyDisableSpdy,
+    prefs::kDisableSpdy },
+  { Value::TYPE_LIST, kPolicyDisabledSchemes,
+    prefs::kDisabledSchemes },
+  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
+    prefs::kSafeBrowsingEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
+    prefs::kPasswordManagerEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerAllowShowPasswords,
+    prefs::kPasswordManagerAllowShowPasswords },
+  { Value::TYPE_BOOLEAN, kPolicyPrintingEnabled,
+    prefs::kPrintingEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
+    prefs::kMetricsReportingEnabled },
+  { Value::TYPE_STRING, kPolicyApplicationLocaleValue,
+    prefs::kApplicationLocale},
+  { Value::TYPE_LIST, kPolicyExtensionInstallWhitelist,
+    prefs::kExtensionInstallAllowList},
+  { Value::TYPE_LIST, kPolicyExtensionInstallBlacklist,
+    prefs::kExtensionInstallDenyList},
+  { Value::TYPE_LIST, kPolicyExtensionInstallForcelist,
+    prefs::kExtensionInstallForceList},
+  { Value::TYPE_LIST, kPolicyDisabledPlugins,
+    prefs::kPluginsDisabledPlugins},
+  { Value::TYPE_LIST, kPolicyDisabledPluginsExceptions,
+    prefs::kPluginsDisabledPluginsExceptions},
+  { Value::TYPE_LIST, kPolicyEnabledPlugins,
+    prefs::kPluginsEnabledPlugins},
+  { Value::TYPE_BOOLEAN, kPolicyShowHomeButton,
+    prefs::kShowHomeButton },
+  { Value::TYPE_BOOLEAN, kPolicySavingBrowserHistoryDisabled,
+    prefs::kSavingBrowserHistoryDisabled },
+  { Value::TYPE_BOOLEAN, kPolicyClearSiteDataOnExit,
+    prefs::kClearSiteDataOnExit },
+  { Value::TYPE_BOOLEAN, kPolicyDeveloperToolsDisabled,
+    prefs::kDevToolsDisabled },
+  { Value::TYPE_BOOLEAN, kPolicyBlockThirdPartyCookies,
+    prefs::kBlockThirdPartyCookies },
+  { Value::TYPE_INTEGER, kPolicyDefaultCookiesSetting,
+    prefs::kManagedDefaultCookiesSetting },
+  { Value::TYPE_INTEGER, kPolicyDefaultImagesSetting,
+    prefs::kManagedDefaultImagesSetting },
+  { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting,
+    prefs::kManagedDefaultPluginsSetting },
+  { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting,
+    prefs::kManagedDefaultPopupsSetting },
+  { Value::TYPE_LIST, kPolicyAutoSelectCertificateForUrls,
+    prefs::kManagedAutoSelectCertificateForUrls},
+  { Value::TYPE_LIST, kPolicyCookiesAllowedForUrls,
+    prefs::kManagedCookiesAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyCookiesBlockedForUrls,
+    prefs::kManagedCookiesBlockedForUrls },
+  { Value::TYPE_LIST, kPolicyCookiesSessionOnlyForUrls,
+    prefs::kManagedCookiesSessionOnlyForUrls },
+  { Value::TYPE_LIST, kPolicyImagesAllowedForUrls,
+    prefs::kManagedImagesAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyImagesBlockedForUrls,
+    prefs::kManagedImagesBlockedForUrls },
+  { Value::TYPE_LIST, kPolicyJavaScriptAllowedForUrls,
+    prefs::kManagedJavaScriptAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyJavaScriptBlockedForUrls,
+    prefs::kManagedJavaScriptBlockedForUrls },
+  { Value::TYPE_LIST, kPolicyPluginsAllowedForUrls,
+    prefs::kManagedPluginsAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyPluginsBlockedForUrls,
+    prefs::kManagedPluginsBlockedForUrls },
+  { Value::TYPE_LIST, kPolicyPopupsAllowedForUrls,
+    prefs::kManagedPopupsAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyPopupsBlockedForUrls,
+    prefs::kManagedPopupsBlockedForUrls },
+  { Value::TYPE_LIST, kPolicyNotificationsAllowedForUrls,
+    prefs::kManagedNotificationsAllowedForUrls },
+  { Value::TYPE_LIST, kPolicyNotificationsBlockedForUrls,
+    prefs::kManagedNotificationsBlockedForUrls },
+  { Value::TYPE_INTEGER, kPolicyDefaultNotificationsSetting,
+    prefs::kManagedDefaultNotificationsSetting },
+  { Value::TYPE_INTEGER, kPolicyDefaultGeolocationSetting,
+    prefs::kManagedDefaultGeolocationSetting },
+  { Value::TYPE_STRING, kPolicyAuthSchemes,
+    prefs::kAuthSchemes },
+  { Value::TYPE_BOOLEAN, kPolicyDisableAuthNegotiateCnameLookup,
+    prefs::kDisableAuthNegotiateCnameLookup },
+  { Value::TYPE_BOOLEAN, kPolicyEnableAuthNegotiatePort,
+    prefs::kEnableAuthNegotiatePort },
+  { Value::TYPE_STRING, kPolicyAuthServerWhitelist,
+    prefs::kAuthServerWhitelist },
+  { Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist,
+    prefs::kAuthNegotiateDelegateWhitelist },
+  { Value::TYPE_STRING, kPolicyGSSAPILibraryName,
+    prefs::kGSSAPILibraryName },
+  { Value::TYPE_BOOLEAN, kPolicyAllowCrossOriginAuthPrompt,
+    prefs::kAllowCrossOriginAuthPrompt },
+  { Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
+    prefs::kDisable3DAPIs },
+  { Value::TYPE_BOOLEAN, kPolicyDisablePluginFinder,
+    prefs::kDisablePluginFinder },
+  { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
+    prefs::kUserPolicyRefreshRate },
+  { Value::TYPE_INTEGER, kPolicyDevicePolicyRefreshRate,
+    prefs::kDevicePolicyRefreshRate },
+  { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
+    prefs::kDefaultBrowserSettingEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyRemoteAccessHostFirewallTraversal,
+    prefs::kRemoteAccessHostFirewallTraversal },
+  { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled,
+    prefs::kCloudPrintProxyEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyTranslateEnabled, prefs::kEnableTranslate },
+  { Value::TYPE_BOOLEAN, kPolicyAllowOutdatedPlugins,
+    prefs::kPluginsAllowOutdated },
+  { Value::TYPE_BOOLEAN, kPolicyAlwaysAuthorizePlugins,
+    prefs::kPluginsAlwaysAuthorize },
+  { Value::TYPE_BOOLEAN, kPolicyBookmarkBarEnabled,
+    prefs::kShowBookmarkBar },
+  { Value::TYPE_BOOLEAN, kPolicyEditBookmarksEnabled,
+    prefs::kEditBookmarksEnabled },
+  { Value::TYPE_BOOLEAN, kPolicyAllowFileSelectionDialogs,
+    prefs::kAllowFileSelectionDialogs },
+  { Value::TYPE_BOOLEAN, kPolicyImportBookmarks,
+    prefs::kImportBookmarks},
+  { Value::TYPE_BOOLEAN, kPolicyImportHistory,
+    prefs::kImportHistory},
+  { Value::TYPE_BOOLEAN, kPolicyImportHomepage,
+    prefs::kImportHomepage},
+  { Value::TYPE_BOOLEAN, kPolicyImportSearchEngine,
+    prefs::kImportSearchEngine },
+  { Value::TYPE_BOOLEAN, kPolicyImportSavedPasswords,
+    prefs::kImportSavedPasswords },
+  { Value::TYPE_INTEGER, kPolicyMaxConnectionsPerProxy,
+    prefs::kMaxConnectionsPerProxy },
+  { Value::TYPE_BOOLEAN, kPolicyHideWebStorePromo,
+    prefs::kNTPHideWebStorePromo },
+  { Value::TYPE_LIST, kPolicyURLBlacklist,
+    prefs::kUrlBlacklist },
+  { Value::TYPE_LIST, kPolicyURLWhitelist,
+    prefs::kUrlWhitelist },
+
+#if defined(OS_CHROMEOS)
+  { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
+    prefs::kEnableScreenLock },
+  { Value::TYPE_STRING, kPolicyChromeOsReleaseChannel,
+    prefs::kChromeOsReleaseChannel },
+#endif
+};
+
+// List of policy types to preference names, for policies affecting the default
+// search provider.
+const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[] = {
+  { Value::TYPE_BOOLEAN, kPolicyDefaultSearchProviderEnabled,
+    prefs::kDefaultSearchProviderEnabled },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderName,
+    prefs::kDefaultSearchProviderName },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderKeyword,
+    prefs::kDefaultSearchProviderKeyword },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSearchURL,
+    prefs::kDefaultSearchProviderSearchURL },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSuggestURL,
+    prefs::kDefaultSearchProviderSuggestURL },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderInstantURL,
+    prefs::kDefaultSearchProviderInstantURL },
+  { Value::TYPE_STRING, kPolicyDefaultSearchProviderIconURL,
+    prefs::kDefaultSearchProviderIconURL },
+  { Value::TYPE_LIST, kPolicyDefaultSearchProviderEncodings,
+    prefs::kDefaultSearchProviderEncodings },
+};
+
+// List of entries determining which proxy policies can be specified, depending
+// on the ProxyMode.
+const ProxyModeValidationEntry kProxyModeValidationMap[] = {
+  { ProxyPrefs::kDirectProxyModeName,
+    false, false, false, IDS_POLICY_PROXY_MODE_DISABLED_ERROR },
+  { ProxyPrefs::kAutoDetectProxyModeName,
+    false, false, false, IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR },
+  { ProxyPrefs::kPacScriptProxyModeName,
+    true, false, false, IDS_POLICY_PROXY_MODE_PAC_URL_ERROR },
+  { ProxyPrefs::kFixedServersProxyModeName,
+    false, true, true, IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR },
+  { ProxyPrefs::kSystemProxyModeName,
+    false, false, false, IDS_POLICY_PROXY_MODE_SYSTEM_ERROR },
+};
+
+
+// Helper functions ------------------------------------------------------------
+
+std::string ValueTypeToString(Value::Type type) {
+  static const char* strings[] = {
+    "null",
+    "boolean",
+    "integer",
+    "double",
+    "string",
+    "binary",
+    "dictionary",
+    "list"
+  };
+  DCHECK(static_cast<size_t>(type) < arraysize(strings));
+  return std::string(strings[type]);
+}
+
+
+// TypeCheckingPolicyHandler implementation ------------------------------------
+
+TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
+    ConfigurationPolicyType policy_type,
+    Value::Type value_type)
+    : policy_type_(policy_type),
+      value_type_(value_type) {
+}
+
+TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
+}
+
+ConfigurationPolicyType TypeCheckingPolicyHandler::policy_type() const {
+  return policy_type_;
+}
+
+bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap* policies,
+                                                    PolicyErrorMap* errors) {
+  const Value* value = policies->Get(policy_type_);
+  if (value && value_type_ != value->GetType()) {
+    errors->AddError(policy_type_,
+                     IDS_POLICY_TYPE_ERROR,
+                     ValueTypeToString(value_type_));
+    return false;
+  }
+  return true;
+}
+
+
+// SimplePolicyHandler implementation ------------------------------------------
+
+SimplePolicyHandler::SimplePolicyHandler(
+    ConfigurationPolicyType policy_type,
+    Value::Type value_type,
+    const char* pref_path)
+    : TypeCheckingPolicyHandler(policy_type, value_type),
+      pref_path_(pref_path) {
+}
+
+SimplePolicyHandler::~SimplePolicyHandler() {
+}
+
+void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                              PrefValueMap* prefs) {
+  const Value* value = policies->Get(policy_type());
+  if (value)
+    prefs->SetValue(pref_path_, value->DeepCopy());
+}
+
+
+// SyncPolicyHandler implementation --------------------------------------------
+
+SyncPolicyHandler::SyncPolicyHandler()
+    : TypeCheckingPolicyHandler(kPolicySyncDisabled,
+                                Value::TYPE_BOOLEAN) {
+}
+
+SyncPolicyHandler::~SyncPolicyHandler() {
+}
+
+void SyncPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                            PrefValueMap* prefs) {
+  const Value* value = policies->Get(policy_type());
+  bool disable_sync;
+  if (value && value->GetAsBoolean(&disable_sync) && disable_sync)
+    prefs->SetValue(prefs::kSyncManaged, value->DeepCopy());
+}
+
+
+// AutofillPolicyHandler implementation ----------------------------------------
+
+AutofillPolicyHandler::AutofillPolicyHandler()
+    : TypeCheckingPolicyHandler(kPolicyAutoFillEnabled,
+                                Value::TYPE_BOOLEAN) {
+}
+
+AutofillPolicyHandler::~AutofillPolicyHandler() {
+}
+
+void AutofillPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                PrefValueMap* prefs) {
+  const Value* value = policies->Get(policy_type());
+  bool auto_fill_enabled;
+  if (value && value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled) {
+    prefs->SetValue(prefs::kAutofillEnabled,
+                    Value::CreateBooleanValue(false));
+  }
+}
+
+
+// DownloadDirPolicyHandler implementation -------------------------------------
+
+DownloadDirPolicyHandler::DownloadDirPolicyHandler()
+    : TypeCheckingPolicyHandler(kPolicyDownloadDirectory,
+                                Value::TYPE_STRING) {
+}
+
+DownloadDirPolicyHandler::~DownloadDirPolicyHandler() {
+}
+
+void DownloadDirPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                   PrefValueMap* prefs) {
+  const Value* value = policies->Get(policy_type());
+  FilePath::StringType string_value;
+  if (!value || !value->GetAsString(&string_value))
+    return;
+
+  FilePath::StringType expanded_value =
+      policy::path_parser::ExpandPathVariables(string_value);
+  // Make sure the path isn't empty, since that will point to an undefined
+  // location; the default location is used instead in that case.
+  // This is checked after path expansion because a non-empty policy value can
+  // lead to an empty path value after expansion (e.g. "\"\"").
+  if (expanded_value.empty())
+    expanded_value = download_util::GetDefaultDownloadDirectory().value();
+  prefs->SetValue(prefs::kDownloadDefaultDirectory,
+                  Value::CreateStringValue(expanded_value));
+  prefs->SetValue(prefs::kPromptForDownload,
+                  Value::CreateBooleanValue(false));
+}
+
+
+// DiskCacheDirPolicyHandler implementation ------------------------------------
+
+DiskCacheDirPolicyHandler::DiskCacheDirPolicyHandler()
+    : TypeCheckingPolicyHandler(kPolicyDiskCacheDir,
+                                Value::TYPE_STRING) {
+}
+
+DiskCacheDirPolicyHandler::~DiskCacheDirPolicyHandler() {
+}
+
+void DiskCacheDirPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                    PrefValueMap* prefs) {
+  const Value* value = policies->Get(policy_type());
+  FilePath::StringType string_value;
+  if (value && value->GetAsString(&string_value)) {
+    FilePath::StringType expanded_value =
+        policy::path_parser::ExpandPathVariables(string_value);
+    prefs->SetValue(prefs::kDiskCacheDir,
+                    Value::CreateStringValue(expanded_value));
+  }
+}
+
+
+// FileSelectionDialogsHandler implementation ----------------------------------
+
+FileSelectionDialogsHandler::FileSelectionDialogsHandler()
+    : TypeCheckingPolicyHandler(kPolicyAllowFileSelectionDialogs,
+                                Value::TYPE_BOOLEAN) {
+}
+
+FileSelectionDialogsHandler::~FileSelectionDialogsHandler() {
+}
+
+void FileSelectionDialogsHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                      PrefValueMap* prefs) {
+  bool allow_dialogs;
+  const Value* value = policies->Get(policy_type());
+  if (value && value->GetAsBoolean(&allow_dialogs)) {
+    prefs->SetValue(prefs::kAllowFileSelectionDialogs,
+                    Value::CreateBooleanValue(allow_dialogs));
+    // Disallow selecting the download location if file dialogs are disabled.
+    if (!allow_dialogs) {
+      prefs->SetValue(prefs::kPromptForDownload,
+                      Value::CreateBooleanValue(false));
+    }
+  }
+}
+
+
+// IncognitoModePolicyHandler implementation -----------------------------------
+
+IncognitoModePolicyHandler::IncognitoModePolicyHandler() {
+}
+
+IncognitoModePolicyHandler::~IncognitoModePolicyHandler() {
+}
+
+bool IncognitoModePolicyHandler::CheckPolicySettings(const PolicyMap* policies,
+                                                     PolicyErrorMap* errors) {
+  int int_value = IncognitoModePrefs::ENABLED;
+  const Value* availability = policies->Get(kPolicyIncognitoModeAvailability);
+
+  if (availability) {
+    if (availability->GetAsInteger(&int_value)) {
+      IncognitoModePrefs::Availability availability_enum_value;
+      if (!IncognitoModePrefs::IntToAvailability(int_value,
+                                                 &availability_enum_value)) {
+        errors->AddError(kPolicyIncognitoModeAvailability,
+                         IDS_POLICY_OUT_OF_RANGE_ERROR,
+                         base::IntToString(int_value));
+        return false;
+      }
+    } else {
+      errors->AddError(kPolicyIncognitoModeAvailability,
+                       IDS_POLICY_TYPE_ERROR,
+                       ValueTypeToString(Value::TYPE_INTEGER));
+      return false;
+    }
+  } else {
+    const Value* deprecated_enabled = policies->Get(kPolicyIncognitoEnabled);
+    if (deprecated_enabled &&
+        !deprecated_enabled->IsType(Value::TYPE_BOOLEAN)) {
+      errors->AddError(kPolicyIncognitoEnabled,
+                       IDS_POLICY_TYPE_ERROR,
+                       ValueTypeToString(Value::TYPE_BOOLEAN));
+      return false;
+    }
+  }
+  return true;
+}
+
+void IncognitoModePolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                     PrefValueMap* prefs) {
+  const Value* availability = policies->Get(kPolicyIncognitoModeAvailability);
+  const Value* deprecated_enabled = policies->Get(kPolicyIncognitoEnabled);
+  if (availability) {
+    int int_value = IncognitoModePrefs::ENABLED;
+    IncognitoModePrefs::Availability availability_enum_value;
+    if (availability->GetAsInteger(&int_value) &&
+        IncognitoModePrefs::IntToAvailability(int_value,
+                                              &availability_enum_value)) {
+      prefs->SetValue(prefs::kIncognitoModeAvailability,
+                      Value::CreateIntegerValue(availability_enum_value));
+    } else {
+      NOTREACHED();
+    }
+  } else if (deprecated_enabled) {
+    // If kPolicyIncognitoModeAvailability is not specified, check the obsolete
+    // kPolicyIncognitoEnabled.
+    bool enabled = true;
+    if (deprecated_enabled->GetAsBoolean(&enabled)) {
+      prefs->SetInteger(prefs::kIncognitoModeAvailability,
+                        enabled ? IncognitoModePrefs::ENABLED :
+                                  IncognitoModePrefs::DISABLED);
+    } else {
+      NOTREACHED();
+    }
+  }
+}
+
+
+// DefaultSearchEncodingsPolicyHandler implementation --------------------------
+
+DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
+    : TypeCheckingPolicyHandler(kPolicyDefaultSearchProviderEncodings,
+                                Value::TYPE_LIST) {
+}
+
+DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
+}
+
+void DefaultSearchEncodingsPolicyHandler::ApplyPolicySettings(
+    const PolicyMap* policies, PrefValueMap* prefs) {
+  // The DefaultSearchProviderEncodings policy has type list, but the related
+  // preference has type string. Convert one into the other here, using
+  // ';' as a separator.
+  const Value* value = policies->Get(policy_type());
+  const ListValue* list;
+  if (!value || !value->GetAsList(&list))
+    return;
+
+  ListValue::const_iterator iter(list->begin());
+  ListValue::const_iterator end(list->end());
+  std::vector<std::string> string_parts;
+  for (; iter != end; ++iter) {
+    std::string s;
+    if ((*iter)->GetAsString(&s)) {
+      string_parts.push_back(s);
+    }
+  }
+  std::string encodings = JoinString(string_parts, ';');
+  prefs->SetValue(prefs::kDefaultSearchProviderEncodings,
+                  Value::CreateStringValue(encodings));
+}
+
+
+// DefaultSearchPolicyHandler implementation -----------------------------------
+
+DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
+  for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
+    ConfigurationPolicyType policy_type =
+        kDefaultSearchPolicyMap[i].policy_type;
+    if (policy_type == kPolicyDefaultSearchProviderEncodings) {
+      handlers_.push_back(new DefaultSearchEncodingsPolicyHandler());
+    } else {
+      handlers_.push_back(
+          new SimplePolicyHandler(policy_type,
+                                  kDefaultSearchPolicyMap[i].value_type,
+                                  kDefaultSearchPolicyMap[i].preference_path));
+    }
+  }
+}
+
+DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
+  STLDeleteElements(&handlers_);
+}
+
+bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap* policies,
+                                                     PolicyErrorMap* errors) {
+  if (!CheckIndividualPolicies(policies, errors))
+    return false;
+
+  if (DefaultSearchProviderIsDisabled(policies)) {
+    // Add an error for all specified default search policies except
+    // DefaultSearchProviderEnabled.
+    for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
+      ConfigurationPolicyType policy_type =
+          kDefaultSearchPolicyMap[i].policy_type;
+      if (policy_type != kPolicyDefaultSearchProviderEnabled &&
+          HasDefaultSearchPolicy(policies, policy_type)) {
+        errors->AddError(policy_type, IDS_POLICY_DEFAULT_SEARCH_DISABLED);
+      }
+    }
+    return true;
+  }
+
+  const Value* search_url =
+      policies->Get(kPolicyDefaultSearchProviderSearchURL);
+  if (!search_url && AnyDefaultSearchPoliciesSpecified(policies)) {
+    errors->AddError(kPolicyDefaultSearchProviderSearchURL,
+                     IDS_POLICY_NOT_SPECIFIED_ERROR);
+    return false;
+  }
+
+  if (search_url && !DefaultSearchURLIsValid(policies)) {
+    errors->AddError(kPolicyDefaultSearchProviderSearchURL,
+                     IDS_POLICY_INVALID_SEARCH_URL_ERROR);
+    return false;
+  }
+  return true;
+}
+
+void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                     PrefValueMap* prefs) {
+  if (DefaultSearchProviderIsDisabled(policies)) {
+    // If default search is disabled, the other fields are ignored.
+    prefs->SetString(prefs::kDefaultSearchProviderName, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderIconURL, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderEncodings, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderKeyword, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
+    return;
+  }
+
+  const Value* search_url =
+      policies->Get(kPolicyDefaultSearchProviderSearchURL);
+  // The search URL is required.
+  if (!search_url)
+    return;
+
+  // The other entries are optional.  Just make sure that they are all
+  // specified via policy, so that the regular prefs aren't used.
+  if (DefaultSearchURLIsValid(policies)) {
+    HandlerList::const_iterator handler = handlers_.begin();
+    for ( ; handler != handlers_.end(); ++handler)
+      (*handler)->ApplyPolicySettings(policies, prefs);
+
+    EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderSuggestURL);
+    EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderIconURL);
+    EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderEncodings);
+    EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderKeyword);
+    EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderInstantURL);
+
+    // For the name, default to the host if not specified.
+    std::string name;
+    if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
+        name.empty()) {
+      std::string search_url_string;
+      if (search_url->GetAsString(&search_url_string)) {
+        prefs->SetString(prefs::kDefaultSearchProviderName,
+                         GURL(search_url_string).host());
+      }
+    }
+
+    // And clear the IDs since these are not specified via policy.
+    prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
+    prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
+                     std::string());
+  }
+}
+
+bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
+    const PolicyMap* policies,
+    PolicyErrorMap* errors) {
+  HandlerList::const_iterator handler = handlers_.begin();
+  for ( ; handler != handlers_.end(); ++handler) {
+    if (!(*handler)->CheckPolicySettings(policies, errors))
+      return false;
+  }
+  return true;
+}
+
+bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
+    const PolicyMap* policies,
+    ConfigurationPolicyType policy_type) {
+  return policies->Get(policy_type) != NULL;
+}
+
+bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
+    const PolicyMap* policies) {
+  for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
+    if (policies->Get(kDefaultSearchPolicyMap[i].policy_type))
+      return true;
+  }
+  return false;
+}
+
+bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
+    const PolicyMap* policies) {
+  const Value* provider_enabled =
+      policies->Get(kPolicyDefaultSearchProviderEnabled);
+  bool enabled = true;
+  return provider_enabled &&
+         provider_enabled->GetAsBoolean(&enabled) &&
+         !enabled;
+}
+
+bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
+    const PolicyMap* policies) {
+  const Value* search_url =
+      policies->Get(kPolicyDefaultSearchProviderSearchURL);
+  if (!search_url)
+    return false;
+
+  std::string search_url_string;
+  if (search_url->GetAsString(&search_url_string)) {
+    SearchTermsDataForValidation search_terms_data;
+    const TemplateURLRef search_url_ref(search_url_string, 0, 0);
+    // It must support replacement (which implies it is valid).
+    return search_url_ref.SupportsReplacementUsingTermsData(search_terms_data);
+  }
+  return false;
+}
+
+void DefaultSearchPolicyHandler::EnsureStringPrefExists(
+    PrefValueMap* prefs,
+    const std::string& path) {
+  std::string value;
+  if (!prefs->GetString(path, &value))
+    prefs->SetString(path, value);
+}
+
+
+// ProxyPolicyHandler implementation -------------------------------------------
+
+ProxyPolicyHandler::ProxyPolicyHandler() {
+}
+
+ProxyPolicyHandler::~ProxyPolicyHandler() {
+}
+
+bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap* policies,
+                                             PolicyErrorMap* errors) {
+  const Value* mode = GetProxyPolicyValue(policies, kPolicyProxyMode);
+  const Value* server = GetProxyPolicyValue(policies, kPolicyProxyServer);
+  const Value* server_mode =
+      GetProxyPolicyValue(policies, kPolicyProxyServerMode);
+  const Value* pac_url = GetProxyPolicyValue(policies, kPolicyProxyPacUrl);
+  const Value* bypass_list =
+      GetProxyPolicyValue(policies, kPolicyProxyBypassList);
+
+  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
+    errors->AddError(kPolicyProxyMode,
+                     IDS_POLICY_NOT_SPECIFIED_ERROR);
+    return false;
+  }
+
+  std::string mode_value;
+  if (!CheckProxyModeAndServerMode(policies, errors, &mode_value))
+    return false;
+
+  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
+  // empty and the proxy shouldn't be configured at all.
+  if (mode_value.empty())
+    return true;
+
+  bool is_valid_mode = false;
+  for (size_t i = 0; i != arraysize(kProxyModeValidationMap); ++i) {
+    const ProxyModeValidationEntry& entry = kProxyModeValidationMap[i];
+    if (entry.mode_value != mode_value)
+      continue;
+
+    is_valid_mode = true;
+
+    if (!entry.pac_url_allowed && pac_url)
+      errors->AddError(kPolicyProxyPacUrl, entry.error_message_id);
+    if (!entry.bypass_list_allowed && bypass_list)
+      errors->AddError(kPolicyProxyPacUrl, entry.error_message_id);
+    if (!entry.server_allowed && server)
+      errors->AddError(kPolicyProxyPacUrl, entry.error_message_id);
+
+    if ((!entry.pac_url_allowed && pac_url) ||
+        (!entry.bypass_list_allowed && bypass_list) ||
+        (!entry.server_allowed && server)) {
+      return false;
+    }
+  }
+
+  if (!is_valid_mode) {
+    errors->AddError(mode ? kPolicyProxyMode : kPolicyProxyServerMode,
+                     IDS_POLICY_OUT_OF_RANGE_ERROR, mode_value);
+    return false;
+  }
+  return true;
+}
+
+void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                             PrefValueMap* prefs) {
+  const Value* mode = GetProxyPolicyValue(policies, kPolicyProxyMode);
+  const Value* server = GetProxyPolicyValue(policies, kPolicyProxyServer);
+  const Value* server_mode =
+      GetProxyPolicyValue(policies, kPolicyProxyServerMode);
+  const Value* pac_url = GetProxyPolicyValue(policies, kPolicyProxyPacUrl);
+  const Value* bypass_list =
+      GetProxyPolicyValue(policies, kPolicyProxyBypassList);
+
+  ProxyPrefs::ProxyMode proxy_mode;
+  if (mode) {
+    std::string string_mode;
+    CHECK(mode->GetAsString(&string_mode));
+    CHECK(ProxyPrefs::StringToProxyMode(string_mode, &proxy_mode));
+  } else if (server_mode) {
+    int int_mode = 0;
+    CHECK(server_mode->GetAsInteger(&int_mode));
+
+    switch (int_mode) {
+      case kPolicyNoProxyServerMode:
+        proxy_mode = ProxyPrefs::MODE_DIRECT;
+        break;
+      case kPolicyAutoDetectProxyServerMode:
+        proxy_mode = ProxyPrefs::MODE_AUTO_DETECT;
+        break;
+      case kPolicyManuallyConfiguredProxyServerMode:
+        proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
+        if (pac_url)
+          proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
+        break;
+      case kPolicyUseSystemProxyServerMode:
+        proxy_mode = ProxyPrefs::MODE_SYSTEM;
+        break;
+      default:
+        proxy_mode = ProxyPrefs::MODE_DIRECT;
+        NOTREACHED();
+    }
+  } else {
+    return;
+  }
+
+  switch (proxy_mode) {
+    case ProxyPrefs::MODE_DIRECT:
+      prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
+      break;
+    case ProxyPrefs::MODE_AUTO_DETECT:
+      prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
+      break;
+    case ProxyPrefs::MODE_PAC_SCRIPT: {
+      std::string pac_url_string;
+      if (pac_url->GetAsString(&pac_url_string)) {
+        prefs->SetValue(prefs::kProxy,
+            ProxyConfigDictionary::CreatePacScript(pac_url_string, false));
+      } else {
+        NOTREACHED();
+      }
+      break;
+    }
+    case ProxyPrefs::MODE_FIXED_SERVERS: {
+      std::string proxy_server;
+      std::string bypass_list_string;
+      if (server->GetAsString(&proxy_server)) {
+        if (bypass_list)
+          bypass_list->GetAsString(&bypass_list_string);
+        prefs->SetValue(prefs::kProxy,
+                        ProxyConfigDictionary::CreateFixedServers(
+                            proxy_server, bypass_list_string));
+      }
+      break;
+    }
+    case ProxyPrefs::MODE_SYSTEM:
+      prefs->SetValue(prefs::kProxy,
+                      ProxyConfigDictionary::CreateSystem());
+      break;
+    case ProxyPrefs::kModeCount:
+      NOTREACHED();
+  }
+}
+
+const Value* ProxyPolicyHandler::GetProxyPolicyValue(
+    const PolicyMap* policies, ConfigurationPolicyType policy) {
+  const Value* value = policies->Get(policy);
+  std::string tmp;
+  if (!value ||
+      value->IsType(Value::TYPE_NULL) ||
+      (value->IsType(Value::TYPE_STRING) &&
+      value->GetAsString(&tmp) &&
+      tmp.empty())) {
+    return NULL;
+  }
+  return value;
+}
+
+bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap* policies,
+                                                     PolicyErrorMap* errors,
+                                                     std::string* mode_value) {
+  const Value* mode = GetProxyPolicyValue(policies, kPolicyProxyMode);
+  const Value* server = GetProxyPolicyValue(policies, kPolicyProxyServer);
+  const Value* server_mode =
+      GetProxyPolicyValue(policies, kPolicyProxyServerMode);
+  const Value* pac_url = GetProxyPolicyValue(policies, kPolicyProxyPacUrl);
+
+  // If there's a server mode, convert it into a mode.
+  // When both are specified, the mode takes precedence.
+  if (mode) {
+    if (server_mode) {
+      errors->AddError(kPolicyProxyServerMode,
+                       IDS_POLICY_OVERRIDDEN,
+                       GetPolicyName(kPolicyProxyMode));
+    }
+    if (!mode->GetAsString(mode_value)) {
+      errors->AddError(kPolicyProxyMode,
+                       IDS_POLICY_TYPE_ERROR,
+                       ValueTypeToString(Value::TYPE_BOOLEAN));
+      return false;
+    }
+
+    ProxyPrefs::ProxyMode mode;
+    if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) {
+      errors->AddError(kPolicyProxyMode, IDS_POLICY_INVALID_PROXY_MODE_ERROR);
+      return false;
+    }
+
+    if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) {
+      errors->AddError(kPolicyProxyPacUrl, IDS_POLICY_NOT_SPECIFIED_ERROR);
+      return false;
+    } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) {
+      errors->AddError(kPolicyProxyServer, IDS_POLICY_NOT_SPECIFIED_ERROR);
+      return false;
+    }
+  } else if (server_mode) {
+    int server_mode_value;
+    if (!server_mode->GetAsInteger(&server_mode_value)) {
+      errors->AddError(kPolicyProxyServerMode,
+                       IDS_POLICY_TYPE_ERROR,
+                       ValueTypeToString(Value::TYPE_INTEGER));
+      return false;
+    }
+
+    switch (server_mode_value) {
+      case kPolicyNoProxyServerMode:
+        *mode_value = ProxyPrefs::kDirectProxyModeName;
+        break;
+      case kPolicyAutoDetectProxyServerMode:
+        *mode_value = ProxyPrefs::kAutoDetectProxyModeName;
+        break;
+      case kPolicyManuallyConfiguredProxyServerMode:
+        if (server && pac_url) {
+          int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR;
+          errors->AddError(kPolicyProxyServer, message_id);
+          errors->AddError(kPolicyProxyPacUrl, message_id);
+          return false;
+        }
+        if (!server && !pac_url) {
+          int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR;
+          errors->AddError(kPolicyProxyServer, message_id);
+          errors->AddError(kPolicyProxyPacUrl, message_id);
+          return false;
+        }
+        if (pac_url)
+          *mode_value = ProxyPrefs::kPacScriptProxyModeName;
+        else
+          *mode_value = ProxyPrefs::kFixedServersProxyModeName;
+        break;
+      case kPolicyUseSystemProxyServerMode:
+        *mode_value = ProxyPrefs::kSystemProxyModeName;
+        break;
+      default:
+        errors->AddError(kPolicyProxyServerMode,
+                         IDS_POLICY_OUT_OF_RANGE_ERROR,
+                         base::IntToString(server_mode_value));
+        return false;
+    }
+  }
+  return true;
+}
+
+
+// JavascriptPolicyHandler implementation --------------------------------------
+
+JavascriptPolicyHandler::JavascriptPolicyHandler() {
+}
+
+JavascriptPolicyHandler::~JavascriptPolicyHandler() {
+}
+
+bool JavascriptPolicyHandler::CheckPolicySettings(const PolicyMap* policies,
+                                                  PolicyErrorMap* errors) {
+  const Value* javascript_enabled = policies->Get(kPolicyJavascriptEnabled);
+  const Value* default_setting = policies->Get(kPolicyDefaultJavaScriptSetting);
+
+  if (javascript_enabled && !javascript_enabled->IsType(Value::TYPE_BOOLEAN)) {
+    errors->AddError(kPolicyJavascriptEnabled,
+                     IDS_POLICY_TYPE_ERROR,
+                     ValueTypeToString(Value::TYPE_BOOLEAN));
+    javascript_enabled = NULL;
+  }
+
+  if (default_setting && !default_setting->IsType(Value::TYPE_INTEGER)) {
+    errors->AddError(kPolicyDefaultJavaScriptSetting,
+                     IDS_POLICY_TYPE_ERROR,
+                     ValueTypeToString(Value::TYPE_INTEGER));
+    default_setting = NULL;
+  }
+
+  bool enabled;
+  int setting;
+  if (javascript_enabled &&
+      default_setting &&
+      javascript_enabled->GetAsBoolean(&enabled) &&
+      default_setting->GetAsInteger(&setting) &&
+      !enabled &&
+      setting != CONTENT_SETTING_BLOCK) {
+    errors->AddError(kPolicyDefaultJavaScriptSetting,
+                     IDS_POLICY_OVERRIDDEN,
+                     GetPolicyName(kPolicyJavascriptEnabled));
+  }
+  return true;
+}
+
+void JavascriptPolicyHandler::ApplyPolicySettings(const PolicyMap* policies,
+                                                  PrefValueMap* prefs) {
+  const Value* javascript_enabled = policies->Get(kPolicyJavascriptEnabled);
+  const Value* default_setting = policies->Get(kPolicyDefaultJavaScriptSetting);
+
+  int setting = CONTENT_SETTING_DEFAULT;
+  if (default_setting)
+    default_setting->GetAsInteger(&setting);
+
+  bool enabled = true;
+  if (javascript_enabled && javascript_enabled->GetAsBoolean(&enabled)) {
+    prefs->SetValue(prefs::kWebKitJavascriptEnabled,
+                    javascript_enabled->DeepCopy());
+    // Force the javascript content setting to BLOCK when this policy disables
+    // javascript globally.
+    if (!enabled)
+      setting = CONTENT_SETTING_BLOCK;
+  }
+
+  if (setting != CONTENT_SETTING_DEFAULT)
+    prefs->SetValue(prefs::kManagedDefaultJavaScriptSetting,
+                    Value::CreateIntegerValue(setting));
+}
+
+
+}  // namespace
+
+
+// ConfigurationPolicyHandler implementation -----------------------------------
+
+// static
+ConfigurationPolicyHandler::HandlerList*
+    ConfigurationPolicyHandler::CreateHandlerList() {
+  HandlerList* list = new HandlerList;
+
+  for (size_t i = 0; i < arraysize(kSimplePolicyMap); ++i) {
+    list->push_back(
+        new SimplePolicyHandler(kSimplePolicyMap[i].policy_type,
+                                kSimplePolicyMap[i].value_type,
+                                kSimplePolicyMap[i].preference_path));
+  }
+
+  list->push_back(new AutofillPolicyHandler());
+  list->push_back(new DefaultSearchPolicyHandler());
+  list->push_back(new DiskCacheDirPolicyHandler());
+  list->push_back(new FileSelectionDialogsHandler());
+  list->push_back(new IncognitoModePolicyHandler());
+  list->push_back(new JavascriptPolicyHandler());
+  list->push_back(new ProxyPolicyHandler());
+  list->push_back(new SyncPolicyHandler());
+
+#if !defined(OS_CHROMEOS)
+  list->push_back(new DownloadDirPolicyHandler());
+#endif  // !defined(OS_CHROME0S)
+
+  return list;
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_handler.h b/chrome/browser/policy/configuration_policy_handler.h
new file mode 100644
index 0000000..797da3ee
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_handler.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_HANDLER_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_HANDLER_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+
+class PrefValueMap;
+
+namespace policy {
+
+class PolicyErrorMap;
+class PolicyMap;
+
+// An abstract super class that subclasses should implement to map policies to
+// their corresponding preferences, and to check whether the policies are valid.
+class ConfigurationPolicyHandler {
+ public:
+  typedef std::vector<ConfigurationPolicyHandler*> HandlerList;
+
+  ConfigurationPolicyHandler() {}
+  virtual ~ConfigurationPolicyHandler() {}
+
+  // Returns true if the policy settings handled by this
+  // ConfigurationPolicyHandler can be applied and false otherwise. Fills
+  // |errors| with error messages or warnings. |errors| may contain error
+  // messages even when |CheckPolicySettings()| returns true.
+  virtual bool CheckPolicySettings(const PolicyMap* policies,
+                                   PolicyErrorMap* errors) = 0;
+
+  // Processes the policies handled by this ConfigurationPolicyHandler and sets
+  // the appropriate preferences in |prefs|.
+  virtual void ApplyPolicySettings(const PolicyMap* policies,
+                                   PrefValueMap* prefs) = 0;
+
+  // Creates a new HandlerList with all the known handlers and returns it.
+  // The new list and its elements are owned by the caller.
+  static HandlerList* CreateHandlerList();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyHandler);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_HANDLER_H_
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index 3616e6d4..ee8f280 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -4,971 +4,46 @@
 
 #include "chrome/browser/policy/configuration_policy_pref_store.h"
 
-#include <map>
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/string16.h"
-#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_util.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/configuration_policy_handler.h"
+#include "chrome/browser/policy/policy_error_map.h"
 #include "chrome/browser/policy/policy_map.h"
-#include "chrome/browser/policy/policy_path_parser.h"
-#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/prefs/pref_value_map.h"
-#include "chrome/browser/prefs/proxy_config_dictionary.h"
-#include "chrome/browser/search_engines/search_terms_data.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/common/content_settings.h"
-#include "chrome/common/pref_names.h"
+#include "content/browser/browser_thread.h"
 #include "policy/policy_constants.h"
 
 namespace policy {
 
-// Accepts policy settings from a ConfigurationPolicyProvider, converts them
-// to preferences and caches the result.
-class ConfigurationPolicyPrefKeeper {
- public:
-  explicit ConfigurationPolicyPrefKeeper(ConfigurationPolicyProvider* provider);
-  virtual ~ConfigurationPolicyPrefKeeper();
-
-  // Get a preference value.
-  PrefStore::ReadResult GetValue(const std::string& key,
-                                 const Value** result) const;
-
-  // Compute the set of preference names that are different in |keeper|. This
-  // includes preferences that are missing in either one.
-  void GetDifferingPrefPaths(const ConfigurationPolicyPrefKeeper* other,
-                             std::vector<std::string>* differing_prefs) const;
-
- private:
-  // Apply the policy settings stored in |policies|.
-  void Apply(PolicyMap* policies);
-
-  // 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 {
-    base::Value::Type value_type;
-    ConfigurationPolicyType policy_type;
-    const char* preference_path;  // A DictionaryValue path, not a file path.
-  };
-
-  // Remove the preferences found in the map from |prefs_|. Returns true if any
-  // such preferences were found and removed.
-  bool RemovePreferencesOfMap(const PolicyToPreferenceMapEntry* map,
-                              int table_size);
-
-  bool ApplyPolicyFromMap(ConfigurationPolicyType 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(ConfigurationPolicyType policy, Value* value);
-
-  // Handles sync-related policies. Returns true if the policy was handled.
-  // Assumes ownership of |value| in that case.
-  bool ApplySyncPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Handles policies that affect Autofill. Returns true if the policy was
-  // handled and assumes ownership of |value| in that case.
-  bool ApplyAutofillPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Processes download directory policy. Returns true if the specified policy
-  // is the download directory policy. ApplyDownloadDirPolicy assumes the
-  // ownership of |value| in the case that the policy is recognized.
-  bool ApplyDownloadDirPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Processes disk cache directory policy. Returns true if the specified policy
-  // is the right one. ApplyDiskCacheDirPolicy assumes the
-  // ownership of |value| in the case that the policy is recognized.
-  bool ApplyDiskCacheDirPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Processes file-selection dialogs policy. Returns true if the specified
-  // policy is the file-selection dialogs policy.
-  // ApplyFileSelectionDialogsPolicy assumes the ownership of |value| in the
-  // case that the policy is recognized.
-  bool ApplyFileSelectionDialogsPolicy(ConfigurationPolicyType policy,
-                                       Value* value);
-
-  // Processes default search provider policies. Returns true if the specified
-  // policy is a default search provider related policy. In that case,
-  // ApplyDefaultSearchPolicy takes ownership of |value|.
-  bool ApplyDefaultSearchPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Processes incognito mode availability related policies. Returns true if the
-  // specified policy is pertinent to incognito mode availability. In that case,
-  // the function takes ownership of |value|.
-  bool ApplyIncognitoModePolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Processes policies that determine whether Javascript can be enabled.
-  // Returns true if the specified policy was processed.
-  bool ApplyJavascriptPolicy(ConfigurationPolicyType policy, Value* value);
-
-  // Make sure that the |path| if present in |prefs_|.  If not, set it to
-  // a blank string.
-  void EnsureStringPrefExists(const std::string& path);
-
-  // If the required entries for default search are specified and valid,
-  // finalizes the policy-specified configuration by initializing the
-  // unspecified map entries.  Otherwise wipes all default search related
-  // map entries from |prefs_|.
-  void FinalizeDefaultSearchPolicySettings();
-
-  // If the required entries for the proxy settings are specified and valid,
-  // finalizes the policy-specified configuration by initializing the
-  // respective values in |prefs_|.
-  void FinalizeProxyPolicySettings();
-
-  // If the required entries for the Incognito mode availability settings
-  // are specified and valid, finalizes the policy-specified configuration
-  // by initializing the respective values in |prefs_|.
-  void FinalizeIncognitoModeSettings();
-
-  // Returns true if the policy values stored in proxy_* represent a valid proxy
-  // configuration, including the case in which there is no configuration at
-  // all.
-  bool CheckProxySettings();
-
-  // Assumes CheckProxySettings returns true and applies the values stored
-  // in proxy_*.
-  void ApplyProxySettings();
-
-  bool HasProxyPolicy(ConfigurationPolicyType policy) const;
-
-  // Temporary cache that stores values until FinalizeProxyPolicySettings()
-  // is called.
-  std::map<ConfigurationPolicyType, Value*> proxy_policies_;
-
-  // Saved state of the deprecated kPolicyIncognitoEnabled. It is still used for
-  // backward compatibility to set the new kIncognitoAvailabilityMode pref in
-  // case the corresponding policy for the latter is not specified.
-  scoped_ptr<Value> deprecated_incognito_enabled_;
-
-  PrefValueMap prefs_;
-
-  static const PolicyToPreferenceMapEntry kSimplePolicyMap[];
-  static const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[];
-
-  DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyPrefKeeper);
-};
-
-const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
-    ConfigurationPolicyPrefKeeper::kSimplePolicyMap[] = {
-  { Value::TYPE_STRING, kPolicyHomepageLocation,  prefs::kHomePage },
-  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
-    prefs::kHomePageIsNewTabPage },
-  { Value::TYPE_INTEGER, kPolicyRestoreOnStartup,
-    prefs::kRestoreOnStartup},
-  { Value::TYPE_LIST, kPolicyRestoreOnStartupURLs,
-    prefs::kURLsToRestoreOnStartup },
-  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
-    prefs::kAlternateErrorPagesEnabled },
-  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
-    prefs::kSearchSuggestEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
-    prefs::kNetworkPredictionEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyDisableSpdy,
-    prefs::kDisableSpdy },
-  { Value::TYPE_LIST, kPolicyDisabledSchemes,
-    prefs::kDisabledSchemes },
-  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
-    prefs::kSafeBrowsingEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
-    prefs::kPasswordManagerEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerAllowShowPasswords,
-    prefs::kPasswordManagerAllowShowPasswords },
-  { Value::TYPE_BOOLEAN, kPolicyPrintingEnabled,
-    prefs::kPrintingEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
-    prefs::kMetricsReportingEnabled },
-  { Value::TYPE_STRING, kPolicyApplicationLocaleValue,
-    prefs::kApplicationLocale},
-  { Value::TYPE_LIST, kPolicyExtensionInstallWhitelist,
-    prefs::kExtensionInstallAllowList},
-  { Value::TYPE_LIST, kPolicyExtensionInstallBlacklist,
-    prefs::kExtensionInstallDenyList},
-  { Value::TYPE_LIST, kPolicyExtensionInstallForcelist,
-    prefs::kExtensionInstallForceList},
-  { Value::TYPE_LIST, kPolicyDisabledPlugins,
-    prefs::kPluginsDisabledPlugins},
-  { Value::TYPE_LIST, kPolicyDisabledPluginsExceptions,
-    prefs::kPluginsDisabledPluginsExceptions},
-  { Value::TYPE_LIST, kPolicyEnabledPlugins,
-    prefs::kPluginsEnabledPlugins},
-  { Value::TYPE_BOOLEAN, kPolicyShowHomeButton,
-    prefs::kShowHomeButton },
-  { Value::TYPE_BOOLEAN, kPolicySavingBrowserHistoryDisabled,
-    prefs::kSavingBrowserHistoryDisabled },
-  { Value::TYPE_BOOLEAN, kPolicyClearSiteDataOnExit,
-    prefs::kClearSiteDataOnExit },
-  { Value::TYPE_BOOLEAN, kPolicyDeveloperToolsDisabled,
-    prefs::kDevToolsDisabled },
-  { Value::TYPE_BOOLEAN, kPolicyBlockThirdPartyCookies,
-    prefs::kBlockThirdPartyCookies },
-  { Value::TYPE_INTEGER, kPolicyDefaultCookiesSetting,
-    prefs::kManagedDefaultCookiesSetting },
-  { Value::TYPE_INTEGER, kPolicyDefaultImagesSetting,
-    prefs::kManagedDefaultImagesSetting },
-  { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting,
-    prefs::kManagedDefaultPluginsSetting },
-  { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting,
-    prefs::kManagedDefaultPopupsSetting },
-  { Value::TYPE_LIST, kPolicyAutoSelectCertificateForUrls,
-    prefs::kManagedAutoSelectCertificateForUrls},
-  { Value::TYPE_LIST, kPolicyCookiesAllowedForUrls,
-    prefs::kManagedCookiesAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyCookiesBlockedForUrls,
-    prefs::kManagedCookiesBlockedForUrls },
-  { Value::TYPE_LIST, kPolicyCookiesSessionOnlyForUrls,
-    prefs::kManagedCookiesSessionOnlyForUrls },
-  { Value::TYPE_LIST, kPolicyImagesAllowedForUrls,
-    prefs::kManagedImagesAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyImagesBlockedForUrls,
-    prefs::kManagedImagesBlockedForUrls },
-  { Value::TYPE_LIST, kPolicyJavaScriptAllowedForUrls,
-    prefs::kManagedJavaScriptAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyJavaScriptBlockedForUrls,
-    prefs::kManagedJavaScriptBlockedForUrls },
-  { Value::TYPE_LIST, kPolicyPluginsAllowedForUrls,
-    prefs::kManagedPluginsAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyPluginsBlockedForUrls,
-    prefs::kManagedPluginsBlockedForUrls },
-  { Value::TYPE_LIST, kPolicyPopupsAllowedForUrls,
-    prefs::kManagedPopupsAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyPopupsBlockedForUrls,
-    prefs::kManagedPopupsBlockedForUrls },
-  { Value::TYPE_LIST, kPolicyNotificationsAllowedForUrls,
-    prefs::kManagedNotificationsAllowedForUrls },
-  { Value::TYPE_LIST, kPolicyNotificationsBlockedForUrls,
-    prefs::kManagedNotificationsBlockedForUrls },
-  { Value::TYPE_INTEGER, kPolicyDefaultNotificationsSetting,
-    prefs::kManagedDefaultNotificationsSetting },
-  { Value::TYPE_INTEGER, kPolicyDefaultGeolocationSetting,
-    prefs::kManagedDefaultGeolocationSetting },
-  { Value::TYPE_STRING, kPolicyAuthSchemes,
-    prefs::kAuthSchemes },
-  { Value::TYPE_BOOLEAN, kPolicyDisableAuthNegotiateCnameLookup,
-    prefs::kDisableAuthNegotiateCnameLookup },
-  { Value::TYPE_BOOLEAN, kPolicyEnableAuthNegotiatePort,
-    prefs::kEnableAuthNegotiatePort },
-  { Value::TYPE_STRING, kPolicyAuthServerWhitelist,
-    prefs::kAuthServerWhitelist },
-  { Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist,
-    prefs::kAuthNegotiateDelegateWhitelist },
-  { Value::TYPE_STRING, kPolicyGSSAPILibraryName,
-    prefs::kGSSAPILibraryName },
-  { Value::TYPE_BOOLEAN, kPolicyAllowCrossOriginAuthPrompt,
-    prefs::kAllowCrossOriginAuthPrompt },
-  { Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
-    prefs::kDisable3DAPIs },
-  { Value::TYPE_BOOLEAN, kPolicyDisablePluginFinder,
-    prefs::kDisablePluginFinder },
-  { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
-    prefs::kUserPolicyRefreshRate },
-  { Value::TYPE_INTEGER, kPolicyDevicePolicyRefreshRate,
-    prefs::kDevicePolicyRefreshRate },
-  { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
-    prefs::kDefaultBrowserSettingEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyRemoteAccessHostFirewallTraversal,
-    prefs::kRemoteAccessHostFirewallTraversal },
-  { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled,
-    prefs::kCloudPrintProxyEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyTranslateEnabled, prefs::kEnableTranslate },
-  { Value::TYPE_BOOLEAN, kPolicyAllowOutdatedPlugins,
-    prefs::kPluginsAllowOutdated },
-  { Value::TYPE_BOOLEAN, kPolicyAlwaysAuthorizePlugins,
-    prefs::kPluginsAlwaysAuthorize },
-  { Value::TYPE_BOOLEAN, kPolicyBookmarkBarEnabled,
-    prefs::kShowBookmarkBar },
-  { Value::TYPE_BOOLEAN, kPolicyEditBookmarksEnabled,
-    prefs::kEditBookmarksEnabled },
-  { Value::TYPE_BOOLEAN, kPolicyAllowFileSelectionDialogs,
-    prefs::kAllowFileSelectionDialogs },
-  { Value::TYPE_BOOLEAN, kPolicyImportBookmarks,
-    prefs::kImportBookmarks},
-  { Value::TYPE_BOOLEAN, kPolicyImportHistory,
-    prefs::kImportHistory},
-  { Value::TYPE_BOOLEAN, kPolicyImportHomepage,
-    prefs::kImportHomepage},
-  { Value::TYPE_BOOLEAN, kPolicyImportSearchEngine,
-    prefs::kImportSearchEngine },
-  { Value::TYPE_BOOLEAN, kPolicyImportSavedPasswords,
-    prefs::kImportSavedPasswords },
-  { Value::TYPE_INTEGER, kPolicyMaxConnectionsPerProxy,
-    prefs::kMaxConnectionsPerProxy },
-  { Value::TYPE_BOOLEAN, kPolicyHideWebStorePromo,
-    prefs::kNTPHideWebStorePromo },
-  { Value::TYPE_LIST, kPolicyURLBlacklist,
-    prefs::kUrlBlacklist },
-  { Value::TYPE_LIST, kPolicyURLWhitelist,
-    prefs::kUrlWhitelist },
-
-#if defined(OS_CHROMEOS)
-  { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
-    prefs::kEnableScreenLock },
-  { Value::TYPE_STRING, kPolicyChromeOsReleaseChannel,
-    prefs::kChromeOsReleaseChannel },
-#endif
-};
-
-const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
-    ConfigurationPolicyPrefKeeper::kDefaultSearchPolicyMap[] = {
-  { Value::TYPE_BOOLEAN, kPolicyDefaultSearchProviderEnabled,
-    prefs::kDefaultSearchProviderEnabled },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderName,
-    prefs::kDefaultSearchProviderName },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderKeyword,
-    prefs::kDefaultSearchProviderKeyword },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSearchURL,
-    prefs::kDefaultSearchProviderSearchURL },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSuggestURL,
-    prefs::kDefaultSearchProviderSuggestURL },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderInstantURL,
-    prefs::kDefaultSearchProviderInstantURL },
-  { Value::TYPE_STRING, kPolicyDefaultSearchProviderIconURL,
-    prefs::kDefaultSearchProviderIconURL },
-  { Value::TYPE_LIST, kPolicyDefaultSearchProviderEncodings,
-    prefs::kDefaultSearchProviderEncodings },
-};
-
-ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper(
-    ConfigurationPolicyProvider* provider) {
-  scoped_ptr<PolicyMap> policies(new PolicyMap());
-  if (!provider->Provide(policies.get()))
-    LOG(WARNING) << "Failed to get policy from provider.";
-
-  Apply(policies.get());
-  FinalizeProxyPolicySettings();
-  FinalizeDefaultSearchPolicySettings();
-  FinalizeIncognitoModeSettings();
-}
-
-ConfigurationPolicyPrefKeeper::~ConfigurationPolicyPrefKeeper() {
-  DCHECK(proxy_policies_.empty());
-}
-
-PrefStore::ReadResult
-ConfigurationPolicyPrefKeeper::GetValue(const std::string& key,
-                                        const Value** result) const {
-  const Value* stored_value = NULL;
-  if (!prefs_.GetValue(key, &stored_value))
-    return PrefStore::READ_NO_VALUE;
-
-  // Check whether there's a default value, which indicates READ_USE_DEFAULT
-  // should be returned.
-  if (stored_value->IsType(Value::TYPE_NULL))
-    return PrefStore::READ_USE_DEFAULT;
-
-  if (result)
-    *result = stored_value;
-  return PrefStore::READ_OK;
-}
-
-void ConfigurationPolicyPrefKeeper::GetDifferingPrefPaths(
-    const ConfigurationPolicyPrefKeeper* other,
-    std::vector<std::string>* differing_prefs) const {
-  prefs_.GetDifferingKeys(&other->prefs_, differing_prefs);
-}
-
-void ConfigurationPolicyPrefKeeper::Apply(PolicyMap* policies) {
-  PolicyMap::const_iterator current = policies->begin();
-  for ( ; current != policies->end(); ++current) {
-    // TODO(simo) Use a separate ConfigurationPolicyHandler class to apply
-    // policy settings.
-    Value* value = current->second->DeepCopy();
-    if (ApplyProxyPolicy(current->first, value) ||
-        ApplySyncPolicy(current->first, value) ||
-        ApplyAutofillPolicy(current->first, value) ||
-        ApplyDownloadDirPolicy(current->first, value) ||
-        ApplyDiskCacheDirPolicy(current->first, value) ||
-        ApplyFileSelectionDialogsPolicy(current->first, value) ||
-        ApplyDefaultSearchPolicy(current->first, value) ||
-        ApplyIncognitoModePolicy(current->first, value) ||
-        ApplyJavascriptPolicy(current->first, value) ||
-        ApplyPolicyFromMap(current->first, value,
-                           kSimplePolicyMap, arraysize(kSimplePolicyMap))) {
-      continue;
-    }
-    delete value;
-
-    // Other policy implementations should go into the conditional above.
-    NOTIMPLEMENTED();
-  }
-}
-
-bool ConfigurationPolicyPrefKeeper::RemovePreferencesOfMap(
-    const PolicyToPreferenceMapEntry* map, int table_size) {
-  bool found_any = false;
-  for (int i = 0; i < table_size; ++i) {
-    if (prefs_.RemoveValue(map[i].preference_path))
-      found_any = true;
-  }
-  return found_any;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyPolicyFromMap(
-    ConfigurationPolicyType policy,
-    Value* value,
-    const PolicyToPreferenceMapEntry* map,
-    int size) {
-  for (int current = 0; current < size; ++current) {
-    if (map[current].policy_type == policy) {
-      DCHECK_EQ(map[current].value_type, value->GetType())
-          << "mismatch in provided and expected policy value for preferences "
-          << map[current].preference_path << ". expected = "
-          << map[current].value_type << ", actual = "<< value->GetType();
-      prefs_.SetValue(map[current].preference_path, value);
-      return true;
-    }
-  }
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyProxyPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  // We only collect the values until we have sufficient information when
-  // FinalizeProxyPolicySettings() is called to determine whether the presented
-  // values were correct and apply them in that case.
-  if (ConfigurationPolicyPrefStore::IsProxyPolicy(policy)) {
-    delete proxy_policies_[policy];
-    proxy_policies_[policy] = value;
-    return true;
-  }
-  // We are not interested in this policy.
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplySyncPolicy(
-    ConfigurationPolicyType policy, Value* value) {
-  if (policy == kPolicySyncDisabled) {
-    bool disable_sync;
-    if (value->GetAsBoolean(&disable_sync) && disable_sync)
-      prefs_.SetValue(prefs::kSyncManaged, value);
-    else
-      delete value;
-    return true;
-  }
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyAutofillPolicy(
-    ConfigurationPolicyType policy, Value* value) {
-  if (policy == kPolicyAutoFillEnabled) {
-    bool auto_fill_enabled;
-    if (value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled)
-      prefs_.SetValue(prefs::kAutofillEnabled,
-                       Value::CreateBooleanValue(false));
-    delete value;
-    return true;
-  }
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyDownloadDirPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  // Replace the policy string which might contain some user variables to an
-  // expanded string.
-  if (policy == kPolicyDownloadDirectory) {
-    // This policy is ignored on ChromeOS because the download path there is
-    // fixed and can not be configured by the user.
-#if !defined(OS_CHROMEOS)
-    FilePath::StringType string_value;
-    bool result = value->GetAsString(&string_value);
-    DCHECK(result);
-    FilePath::StringType expanded_value =
-        policy::path_parser::ExpandPathVariables(string_value);
-    // Leaving the policy empty would revert to the default download location
-    // else we would point in an undefined location. We do this after the
-    // path expansion because it might lead to an empty string(e.g. for "\"\"").
-    if (expanded_value.empty())
-      expanded_value = download_util::GetDefaultDownloadDirectory().value();
-    prefs_.SetValue(prefs::kDownloadDefaultDirectory,
-                    Value::CreateStringValue(expanded_value));
-    prefs_.SetValue(prefs::kPromptForDownload,
-                    Value::CreateBooleanValue(false));
-#endif  // !defined(OS_CHROMEOS)
-    delete value;
-    return true;
-  }
-  // We are not interested in this policy.
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyDiskCacheDirPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  // Replace the policy string which might contain some user variables to an
-  // expanded string.
-  if (policy == kPolicyDiskCacheDir) {
-    FilePath::StringType string_value;
-    bool result = value->GetAsString(&string_value);
-    DCHECK(result);
-    FilePath::StringType expanded_value =
-        policy::path_parser::ExpandPathVariables(string_value);
-    prefs_.SetValue(prefs::kDiskCacheDir,
-                    Value::CreateStringValue(expanded_value));
-    delete value;
-    return true;
-  }
-  // We are not interested in this policy.
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyFileSelectionDialogsPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  if (policy == kPolicyAllowFileSelectionDialogs) {
-    prefs_.SetValue(prefs::kAllowFileSelectionDialogs, value);
-    // If file-selection dialogs are not allowed we forbid the user to be
-    // prompted for the download location, since this would end up in an Infobar
-    // explaining that file-selection dialogs are forbidden anyways.
-    bool allow_file_selection_dialogs = true;
-    bool result = value->GetAsBoolean(&allow_file_selection_dialogs);
-    DCHECK(result);
-    if (!allow_file_selection_dialogs) {
-      prefs_.SetValue(prefs::kPromptForDownload,
-                      Value::CreateBooleanValue(false));
-    }
-    return true;
-  }
-  // We are not interested in this policy.
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyDefaultSearchPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  // The DefaultSearchProviderEncodings policy has type list, but the related
-  // preference has type string. Convert one into the other here, using
-  // ';' as a separator.
-  if (policy == kPolicyDefaultSearchProviderEncodings) {
-    ListValue* list;
-    if (!value->GetAsList(&list)) {
-      NOTREACHED()
-          << "mismatch in provided and expected policy value for preferences "
-          << prefs::kDefaultSearchProviderEncodings << ". expected = "
-          << Value::TYPE_LIST << ", actual = "<< value->GetType();
-      return false;
-    }
-    ListValue::const_iterator iter(list->begin());
-    ListValue::const_iterator end(list->end());
-    std::string encodings;
-    for (; iter != end; ++iter) {
-      std::string s;
-      if ((*iter)->GetAsString(&s)) {
-        if (!encodings.empty())
-          encodings.push_back(';');
-        encodings.append(s);
-      } else {
-        NOTREACHED();
-      }
-    }
-    // We own |value|.
-    delete value;
-    prefs_.SetValue(prefs::kDefaultSearchProviderEncodings,
-                    Value::CreateStringValue(encodings));
-    return true;
-  }
-
-  if (ApplyPolicyFromMap(policy, value, kDefaultSearchPolicyMap,
-                         arraysize(kDefaultSearchPolicyMap))) {
-    return true;
-  }
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyIncognitoModePolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  if (policy == kPolicyIncognitoModeAvailability) {
-    int availability = IncognitoModePrefs::ENABLED;
-    bool result = value->GetAsInteger(&availability);
-    delete value;
-    if (result) {
-      IncognitoModePrefs::Availability availability_enum_value;
-      if (IncognitoModePrefs::IntToAvailability(availability,
-                                                &availability_enum_value)) {
-        prefs_.SetValue(prefs::kIncognitoModeAvailability,
-                        Value::CreateIntegerValue(availability_enum_value));
-      } else {
-        LOG(WARNING) << "IncognitoModeAvailability policy value is "
-                     << "out of range " << availability;
-      }
-    } else {
-      LOG(WARNING) << "IncognitoModeAvailability policy value could not be "
-                   << "parsed";
-    }
-    return true;
-  }
-  if (policy == kPolicyIncognitoEnabled) {
-    deprecated_incognito_enabled_.reset(value);
-    return true;
-  }
-  // The policy is not relevant to incognito.
-  return false;
-}
-
-bool ConfigurationPolicyPrefKeeper::ApplyJavascriptPolicy(
-    ConfigurationPolicyType policy,
-    Value* value) {
-  if (policy == kPolicyJavascriptEnabled) {
-    bool enabled;
-    if (value->GetAsBoolean(&enabled) && !enabled) {
-      // Force the content setting policy for javascript to BLOCK too.
-      prefs_.SetValue(prefs::kManagedDefaultJavaScriptSetting,
-                      Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
-    }
-    prefs_.SetValue(prefs::kWebKitJavascriptEnabled, value);
-    return true;
-  }
-  if (policy == kPolicyDefaultJavaScriptSetting) {
-    // Ignore this policy if it has been overridden by kPolicyJavascriptEnabled.
-    Value* existing_value;
-    if (prefs_.GetValue(prefs::kManagedDefaultJavaScriptSetting,
-                        &existing_value)) {
-      delete value;
-    } else {
-      prefs_.SetValue(prefs::kManagedDefaultJavaScriptSetting, value);
-    }
-    return true;
-  }
-  return false;
-}
-
-void ConfigurationPolicyPrefKeeper::EnsureStringPrefExists(
-    const std::string& path) {
-  std::string value;
-  if (!prefs_.GetString(path, &value))
-    prefs_.SetString(path, value);
-}
-
 namespace {
 
-// Implementation of SearchTermsData just for validation.
-class SearchTermsDataForValidation : public SearchTermsData {
- public:
-  SearchTermsDataForValidation() {}
-
-  // Implementation of SearchTermsData.
-  virtual std::string GoogleBaseURLValue() const {
-    return "http://www.google.com/";
+// Policies are loaded early on startup, before PolicyErrorMaps are ready to
+// be retrieved. This function is posted to UI to log any errors found on
+// Refresh below.
+void LogErrors(PolicyErrorMap* errors) {
+  PolicyErrorMap::const_iterator iter;
+  for (iter = errors->begin(); iter != errors->end(); ++iter) {
+    string16 policy = ASCIIToUTF16(GetPolicyName(iter->first));
+    DLOG(WARNING) << "Policy " << policy << ": " << iter->second;
   }
-  virtual std::string GetApplicationLocale() const {
-    return "en";
-  }
-#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
-  virtual string16 GetRlzParameterValue() const {
-    return string16();
-  }
-#endif
- private:
-  DISALLOW_COPY_AND_ASSIGN(SearchTermsDataForValidation);
-};
+}
 
 }  // namespace
 
-void ConfigurationPolicyPrefKeeper::FinalizeDefaultSearchPolicySettings() {
-  bool enabled = true;
-  if (prefs_.GetBoolean(prefs::kDefaultSearchProviderEnabled, &enabled) &&
-      !enabled) {
-    // If default search is disabled, we ignore the other fields.
-    prefs_.SetString(prefs::kDefaultSearchProviderName, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderIconURL, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderEncodings, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderKeyword, std::string());
-    prefs_.SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
-    return;
-  }
-  std::string search_url;
-  // The search URL is required.
-  if (prefs_.GetString(prefs::kDefaultSearchProviderSearchURL, &search_url) &&
-      !search_url.empty()) {
-    SearchTermsDataForValidation search_terms_data;
-    const TemplateURLRef search_url_ref(search_url, 0, 0);
-    // It must support replacement (which implies it is valid).
-    if (search_url_ref.SupportsReplacementUsingTermsData(search_terms_data)) {
-      // The other entries are optional.  Just make sure that they are all
-      // specified via policy, so that we don't use regular prefs.
-      EnsureStringPrefExists(prefs::kDefaultSearchProviderSuggestURL);
-      EnsureStringPrefExists(prefs::kDefaultSearchProviderIconURL);
-      EnsureStringPrefExists(prefs::kDefaultSearchProviderEncodings);
-      EnsureStringPrefExists(prefs::kDefaultSearchProviderKeyword);
-      EnsureStringPrefExists(prefs::kDefaultSearchProviderInstantURL);
-
-      // For the name, default to the host if not specified.
-      std::string name;
-      if (!prefs_.GetString(prefs::kDefaultSearchProviderName, &name) ||
-          name.empty())
-        prefs_.SetString(prefs::kDefaultSearchProviderName,
-                          GURL(search_url).host());
-
-      // And clear the IDs since these are not specified via policy.
-      prefs_.SetString(prefs::kDefaultSearchProviderID, std::string());
-      prefs_.SetString(prefs::kDefaultSearchProviderPrepopulateID,
-                        std::string());
-      return;
-    }
-  }
-  // Required entries are not there.  Remove any related entries.
-  RemovePreferencesOfMap(kDefaultSearchPolicyMap,
-                         arraysize(kDefaultSearchPolicyMap));
-}
-
-void ConfigurationPolicyPrefKeeper::FinalizeIncognitoModeSettings() {
-  int int_value;
-  if (!prefs_.GetInteger(prefs::kIncognitoModeAvailability, &int_value)) {
-    // If kPolicyIncognitoModeAvailability is not specified, check the obsolete
-    // kPolicyIncognitoEnabled.
-    if (deprecated_incognito_enabled_.get()) {
-      bool enabled = true;
-      if (deprecated_incognito_enabled_->GetAsBoolean(&enabled)) {
-        prefs_.SetInteger(
-            prefs::kIncognitoModeAvailability,
-            enabled ? IncognitoModePrefs::ENABLED :
-                      IncognitoModePrefs::DISABLED);
-      } else {
-        LOG(WARNING) << "IncognitoEnabled policy value could not be parsed";
-      }
-    }
-  }
-}
-
-void ConfigurationPolicyPrefKeeper::FinalizeProxyPolicySettings() {
-  if (CheckProxySettings())
-    ApplyProxySettings();
-
-  STLDeleteContainerPairSecondPointers(proxy_policies_.begin(),
-                                       proxy_policies_.end());
-  proxy_policies_.clear();
-}
-
-bool ConfigurationPolicyPrefKeeper::CheckProxySettings() {
-  bool mode = HasProxyPolicy(kPolicyProxyMode);
-  bool server_mode = HasProxyPolicy(kPolicyProxyServerMode);  // deprecated
-  bool server = HasProxyPolicy(kPolicyProxyServer);
-  bool pac_url = HasProxyPolicy(kPolicyProxyPacUrl);
-  bool bypass_list = HasProxyPolicy(kPolicyProxyBypassList);
-
-  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
-    LOG(WARNING) << "A centrally-administered policy defines proxy setting"
-                 << " details without setting a proxy mode.";
-    return false;
-  }
-
-  // If there's a server mode, convert it into a mode.
-  std::string mode_value;
-  if (mode) {
-    if (server_mode)
-      LOG(WARNING) << "Both ProxyMode and ProxyServerMode policies defined, "
-                   << "ignoring ProxyMode.";
-    if (!proxy_policies_[kPolicyProxyMode]->GetAsString(&mode_value)) {
-      LOG(WARNING) << "Invalid ProxyMode value.";
-      return false;
-    }
-  } else if (server_mode) {
-    int server_mode_value;
-    if (!proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(
-        &server_mode_value)) {
-      LOG(WARNING) << "Invalid ProxyServerMode value.";
-      return false;
-    }
-
-    switch (server_mode_value) {
-      case kPolicyNoProxyServerMode:
-        mode_value = ProxyPrefs::kDirectProxyModeName;
-        break;
-      case kPolicyAutoDetectProxyServerMode:
-        mode_value = ProxyPrefs::kAutoDetectProxyModeName;
-        break;
-      case kPolicyManuallyConfiguredProxyServerMode:
-        if (server && pac_url) {
-          LOG(WARNING) << "A centrally-administered policy dictates that"
-                       << " both fixed proxy servers and a .pac url. should"
-                       << " be used for proxy configuration.";
-          return false;
-        }
-        if (!server && !pac_url) {
-          LOG(WARNING) << "A centrally-administered policy dictates that the"
-                       << " proxy settings should use either fixed proxy"
-                       << " servers or a .pac url, but specifies neither.";
-          return false;
-        }
-        if (pac_url)
-          mode_value = ProxyPrefs::kPacScriptProxyModeName;
-        else
-          mode_value = ProxyPrefs::kFixedServersProxyModeName;
-        break;
-      case kPolicyUseSystemProxyServerMode:
-        mode_value = ProxyPrefs::kSystemProxyModeName;
-        break;
-      default:
-        LOG(WARNING) << "Invalid proxy mode " << server_mode_value;
-        return false;
-    }
-  }
-
-  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
-  // empty and the proxy shouldn't be configured at all.
-  if (mode_value.empty())
-    return true;
-
-  if (mode_value == ProxyPrefs::kDirectProxyModeName) {
-    if (server || pac_url || bypass_list) {
-      LOG(WARNING) << "A centrally-administered policy disables the use of"
-                   << " a proxy but also specifies an explicit proxy"
-                   << " configuration.";
-      return false;
-    }
-  } else if (mode_value == ProxyPrefs::kAutoDetectProxyModeName) {
-    if (server || bypass_list || pac_url) {
-      LOG(WARNING) << "A centrally-administered policy dictates that a proxy"
-                   << " shall be auto configured but specifies fixed proxy"
-                   << " servers, a by-pass list or a .pac script URL.";
-      return false;
-    }
-  } else if (mode_value == ProxyPrefs::kPacScriptProxyModeName) {
-    if (server || bypass_list) {
-      LOG(WARNING) << "A centrally-administered policy dictates that a .pac"
-                   << " script URL should be used for proxy configuration but"
-                   << " also specifies policies required only for fixed"
-                   << " proxy servers.";
-      return false;
-    }
-  } else if (mode_value == ProxyPrefs::kFixedServersProxyModeName) {
-    if (pac_url) {
-      LOG(WARNING) << "A centrally-administered policy dictates that"
-                   << " fixed proxy servers should be used but also"
-                   << " specifies a .pac script URL.";
-      return false;
-    }
-  } else if (mode_value == ProxyPrefs::kSystemProxyModeName) {
-    if (server || pac_url || bypass_list) {
-      LOG(WARNING) << "A centrally-administered policy dictates that the"
-                   << " system proxy settings should be used but also "
-                   << " specifies an explicit proxy configuration.";
-      return false;
-    }
-  } else {
-    LOG(WARNING) << "Invalid proxy mode " << mode_value;
-    return false;
-  }
-  return true;
-}
-
-void ConfigurationPolicyPrefKeeper::ApplyProxySettings() {
-  ProxyPrefs::ProxyMode mode;
-  if (HasProxyPolicy(kPolicyProxyMode)) {
-    std::string string_mode;
-    CHECK(proxy_policies_[kPolicyProxyMode]->GetAsString(&string_mode));
-    if (!ProxyPrefs::StringToProxyMode(string_mode, &mode)) {
-      LOG(WARNING) << "A centrally-administered policy specifies a value for "
-                   << "the ProxyMode policy that isn't recognized.";
-      return;
-    }
-  } else if (HasProxyPolicy(kPolicyProxyServerMode)) {
-    int int_mode = 0;
-    CHECK(proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(&int_mode));
-    switch (int_mode) {
-      case kPolicyNoProxyServerMode:
-        mode = ProxyPrefs::MODE_DIRECT;
-        break;
-      case kPolicyAutoDetectProxyServerMode:
-        mode = ProxyPrefs::MODE_AUTO_DETECT;
-        break;
-      case kPolicyManuallyConfiguredProxyServerMode:
-        mode = ProxyPrefs::MODE_FIXED_SERVERS;
-        if (HasProxyPolicy(kPolicyProxyPacUrl))
-          mode = ProxyPrefs::MODE_PAC_SCRIPT;
-        break;
-      case kPolicyUseSystemProxyServerMode:
-        mode = ProxyPrefs::MODE_SYSTEM;
-        break;
-      default:
-        mode = ProxyPrefs::MODE_DIRECT;
-        NOTREACHED();
-    }
-  } else {
-    return;
-  }
-  switch (mode) {
-    case ProxyPrefs::MODE_DIRECT:
-      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
-      break;
-    case ProxyPrefs::MODE_AUTO_DETECT:
-      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
-      break;
-    case ProxyPrefs::MODE_PAC_SCRIPT: {
-      if (!HasProxyPolicy(kPolicyProxyPacUrl)) {
-        LOG(WARNING) << "A centrally-administered policy specifies to use a "
-                     << "PAC script, but doesn't supply the PAC script URL.";
-        return;
-      }
-      std::string pac_url;
-      proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url);
-      prefs_.SetValue(prefs::kProxy,
-                      ProxyConfigDictionary::CreatePacScript(pac_url, false));
-      break;
-    }
-    case ProxyPrefs::MODE_FIXED_SERVERS: {
-      if (!HasProxyPolicy(kPolicyProxyServer)) {
-        LOG(WARNING) << "A centrally-administered policy specifies to use a "
-                     << "fixed server, but doesn't supply the server address.";
-        return;
-      }
-      std::string proxy_server;
-      proxy_policies_[kPolicyProxyServer]->GetAsString(&proxy_server);
-      std::string bypass_list;
-      if (HasProxyPolicy(kPolicyProxyBypassList))
-        proxy_policies_[kPolicyProxyBypassList]->GetAsString(&bypass_list);
-      prefs_.SetValue(prefs::kProxy,
-                      ProxyConfigDictionary::CreateFixedServers(proxy_server,
-                                                                bypass_list));
-      break;
-    }
-    case ProxyPrefs::MODE_SYSTEM:
-      prefs_.SetValue(prefs::kProxy,
-                      ProxyConfigDictionary::CreateSystem());
-      break;
-    case ProxyPrefs::kModeCount:
-      NOTREACHED();
-  }
-}
-
-bool ConfigurationPolicyPrefKeeper::HasProxyPolicy(
-    ConfigurationPolicyType policy) const {
-  std::map<ConfigurationPolicyType, Value*>::const_iterator iter;
-  iter = proxy_policies_.find(policy);
-  std::string tmp;
-  if (iter == proxy_policies_.end() ||
-      !iter->second ||
-      iter->second->IsType(Value::TYPE_NULL) ||
-      (iter->second->IsType(Value::TYPE_STRING) &&
-       iter->second->GetAsString(&tmp) &&
-       tmp.empty())) {
-    return false;
-  }
-  return true;
-}
-
 ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
     ConfigurationPolicyProvider* provider)
     : provider_(provider),
       initialization_complete_(false) {
   if (provider_) {
     // Read initial policy.
-    policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider_));
+    prefs_.reset(CreatePreferencesFromPolicies());
     registrar_.Init(provider_, this);
     initialization_complete_ = provider_->IsInitializationComplete();
   } else {
@@ -995,10 +70,13 @@
 PrefStore::ReadResult
 ConfigurationPolicyPrefStore::GetValue(const std::string& key,
                                        const Value** value) const {
-  if (policy_keeper_.get())
-    return policy_keeper_->GetValue(key, value);
+  const Value* stored_value = NULL;
+  if (!prefs_.get() || !prefs_->GetValue(key, &stored_value))
+    return PrefStore::READ_NO_VALUE;
 
-  return PrefStore::READ_NO_VALUE;
+  if (value)
+    *value = stored_value;
+  return PrefStore::READ_OK;
 }
 
 void ConfigurationPolicyPrefStore::OnUpdatePolicy() {
@@ -1012,10 +90,9 @@
 // static
 ConfigurationPolicyPrefStore*
 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() {
-  BrowserPolicyConnector* connector =
-      g_browser_process->browser_policy_connector();
   return new ConfigurationPolicyPrefStore(
-      connector->GetManagedPlatformProvider());
+      g_browser_process->browser_policy_connector()->
+          GetManagedPlatformProvider());
 }
 
 // static
@@ -1028,10 +105,9 @@
 // static
 ConfigurationPolicyPrefStore*
 ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() {
-  BrowserPolicyConnector* connector =
-      g_browser_process->browser_policy_connector();
   return new ConfigurationPolicyPrefStore(
-      connector->GetRecommendedPlatformProvider());
+      g_browser_process->browser_policy_connector()->
+          GetRecommendedPlatformProvider());
 }
 
 // static
@@ -1054,13 +130,10 @@
 void ConfigurationPolicyPrefStore::Refresh() {
   if (!provider_)
     return;
-
-  // Construct a new keeper, determine what changed and swap the keeper in.
-  scoped_ptr<ConfigurationPolicyPrefKeeper> new_keeper(
-      new ConfigurationPolicyPrefKeeper(provider_));
+  scoped_ptr<PrefValueMap> new_prefs(CreatePreferencesFromPolicies());
   std::vector<std::string> changed_prefs;
-  new_keeper->GetDifferingPrefPaths(policy_keeper_.get(), &changed_prefs);
-  policy_keeper_.swap(new_keeper);
+  new_prefs->GetDifferingKeys(prefs_.get(), &changed_prefs);
+  prefs_.swap(new_prefs);
 
   // Send out change notifications.
   for (std::vector<std::string>::const_iterator pref(changed_prefs.begin());
@@ -1079,4 +152,32 @@
   }
 }
 
+PrefValueMap* ConfigurationPolicyPrefStore::CreatePreferencesFromPolicies() {
+  scoped_ptr<PrefValueMap> prefs(new PrefValueMap);
+
+  PolicyMap policies;
+  if (!provider_->Provide(&policies))
+    DLOG(WARNING) << "Failed to get policy from provider.";
+
+  const ConfigurationPolicyHandler::HandlerList* handlers =
+      g_browser_process->browser_policy_connector()->
+          GetConfigurationPolicyHandlerList();
+
+  scoped_ptr<PolicyErrorMap> errors(new PolicyErrorMap);
+  ConfigurationPolicyHandler::HandlerList::const_iterator handler;
+  for (handler = handlers->begin(); handler != handlers->end(); ++handler) {
+    if ((*handler)->CheckPolicySettings(&policies, errors.get()))
+      (*handler)->ApplyPolicySettings(&policies, prefs.get());
+  }
+
+  // Retrieve and log the errors once the UI loop is ready. This is only an
+  // issue during startup.
+  BrowserThread::PostTask(BrowserThread::UI,
+                          FROM_HERE,
+                          base::Bind(&LogErrors,
+                                     base::Owned(errors.release())));
+
+  return prefs.release();
+}
+
 }  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h
index 4b570b2f..82fc3a1 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.h
+++ b/chrome/browser/policy/configuration_policy_pref_store.h
@@ -13,9 +13,9 @@
 #include "chrome/browser/policy/configuration_policy_provider.h"
 #include "chrome/common/pref_store.h"
 
-namespace policy {
+class PrefValueMap;
 
-class ConfigurationPolicyPrefKeeper;
+namespace policy {
 
 // Constants for the "Proxy Server Mode" defined in the policies.
 // Note that these diverge from internal presentation defined in
@@ -47,15 +47,15 @@
   virtual ~ConfigurationPolicyPrefStore();
 
   // PrefStore methods:
-  virtual void AddObserver(PrefStore::Observer* observer);
-  virtual void RemoveObserver(PrefStore::Observer* observer);
-  virtual bool IsInitializationComplete() const;
+  virtual void AddObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual bool IsInitializationComplete() const OVERRIDE;
   virtual ReadResult GetValue(const std::string& key,
-                              const Value** result) const;
+                              const Value** result) const OVERRIDE;
 
   // ConfigurationPolicyProvider::Observer methods:
-  virtual void OnUpdatePolicy();
-  virtual void OnProviderGoingAway();
+  virtual void OnUpdatePolicy() OVERRIDE;
+  virtual void OnProviderGoingAway() OVERRIDE;
 
   // Creates a ConfigurationPolicyPrefStore that reads managed platform policy.
   static ConfigurationPolicyPrefStore* CreateManagedPlatformPolicyPrefStore();
@@ -79,6 +79,10 @@
   // sending out change notifications as appropriate.
   void Refresh();
 
+  // Returns a new PrefValueMap containing the preference values that correspond
+  // to the policies currently provided by |provider_|.
+  PrefValueMap* CreatePreferencesFromPolicies();
+
   // The policy provider from which policy settings are read.
   ConfigurationPolicyProvider* provider_;
 
@@ -87,7 +91,7 @@
   bool initialization_complete_;
 
   // Current policy preferences.
-  scoped_ptr<ConfigurationPolicyPrefKeeper> policy_keeper_;
+  scoped_ptr<PrefValueMap> prefs_;
 
   ObserverList<PrefStore::Observer, true> observers_;
 
diff --git a/chrome/browser/policy/device_management_backend_mock.h b/chrome/browser/policy/device_management_backend_mock.h
index 0533efca..a3dbcd6 100644
--- a/chrome/browser/policy/device_management_backend_mock.h
+++ b/chrome/browser/policy/device_management_backend_mock.h
@@ -4,6 +4,7 @@
 
 #ifndef CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_BACKEND_MOCK_H_
 #define CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_BACKEND_MOCK_H_
+#pragma once
 
 #include "chrome/browser/policy/device_management_backend.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/policy/policy_error_map.cc b/chrome/browser/policy/policy_error_map.cc
new file mode 100644
index 0000000..bbe6e1c
--- /dev/null
+++ b/chrome/browser/policy/policy_error_map.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/policy_error_map.h"
+
+#include <utility>
+
+#include "base/utf_string_conversions.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace policy {
+
+struct PolicyErrorMap::PendingError {
+  PendingError(ConfigurationPolicyType policy,
+               int message_id,
+               const string16& replacement)
+      : policy(policy),
+        message_id(message_id),
+        has_replacement(true),
+        replacement(replacement) {}
+
+  PendingError(ConfigurationPolicyType policy, int message_id)
+      : policy(policy), message_id(message_id), has_replacement(false) {}
+
+  ConfigurationPolicyType policy;
+  int message_id;
+  bool has_replacement;
+  string16 replacement;
+};
+
+PolicyErrorMap::PolicyErrorMap() {
+}
+
+PolicyErrorMap::~PolicyErrorMap() {
+}
+
+bool PolicyErrorMap::IsReady() const {
+  return ui::ResourceBundle::HasSharedInstance();
+}
+
+void PolicyErrorMap::AddError(ConfigurationPolicyType policy, int message_id) {
+  AddError(PendingError(policy, message_id));
+}
+
+void PolicyErrorMap::AddError(ConfigurationPolicyType policy,
+                              int message_id,
+                              const std::string& replacement) {
+  AddError(PendingError(policy, message_id, ASCIIToUTF16(replacement)));
+}
+
+ListValue* PolicyErrorMap::GetErrors(ConfigurationPolicyType policy) {
+  CheckReadyAndConvert();
+  std::pair<const_iterator, const_iterator> range = map_.equal_range(policy);
+
+  if (range.first == range.second)
+    return NULL;
+
+  ListValue* list = new ListValue();
+  for (const_iterator it = range.first; it != range.second; ++it)
+    list->Append(Value::CreateStringValue(it->second));
+
+  return list;
+}
+
+bool PolicyErrorMap::empty() {
+  CheckReadyAndConvert();
+  return map_.empty();
+}
+
+size_t PolicyErrorMap::size() {
+  CheckReadyAndConvert();
+  return map_.size();
+}
+
+PolicyErrorMap::const_iterator PolicyErrorMap::begin() {
+  CheckReadyAndConvert();
+  return map_.begin();
+}
+
+PolicyErrorMap::const_iterator PolicyErrorMap::end() {
+  CheckReadyAndConvert();
+  return map_.end();
+}
+
+void PolicyErrorMap::Clear() {
+  CheckReadyAndConvert();
+  map_.clear();
+}
+
+void PolicyErrorMap::AddError(const PendingError& error) {
+  if (IsReady()) {
+    Convert(error);
+  } else {
+    pending_.push_back(error);
+  }
+}
+
+void PolicyErrorMap::Convert(const PendingError& error) {
+  string16 message;
+  if (error.has_replacement)
+    message = l10n_util::GetStringFUTF16(error.message_id, error.replacement);
+  else
+    message = l10n_util::GetStringUTF16(error.message_id);
+  map_.insert(std::make_pair(error.policy, message));
+}
+
+void PolicyErrorMap::CheckReadyAndConvert() {
+  DCHECK(IsReady());
+  for (size_t i = 0; i < pending_.size(); ++i) {
+    Convert(pending_[i]);
+  }
+  pending_.clear();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/policy_error_map.h b/chrome/browser/policy/policy_error_map.h
new file mode 100644
index 0000000..b031b22
--- /dev/null
+++ b/chrome/browser/policy/policy_error_map.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_POLICY_ERROR_MAP_H_
+#define CHROME_BROWSER_POLICY_POLICY_ERROR_MAP_H_
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "base/values.h"
+#include "policy/configuration_policy_type.h"
+
+namespace policy {
+
+// Collects error messages and their associated policies.
+class PolicyErrorMap {
+ public:
+  typedef std::multimap<ConfigurationPolicyType, string16> PolicyMapType;
+  typedef PolicyMapType::const_iterator const_iterator;
+
+  PolicyErrorMap();
+  virtual ~PolicyErrorMap();
+
+  // Returns true when the errors logged are ready to be retrieved. It is always
+  // safe to call AddError, but the other methods are only allowed once
+  // IsReady is true. IsReady will be true once the UI message loop has started.
+  bool IsReady() const;
+
+  // Adds an entry with key |policy| and the error message corresponding to
+  // |message_id| in grit/generated_resources.h to the map.
+  void AddError(ConfigurationPolicyType policy, int message_id);
+
+  // Adds an entry with key |policy| and the error message corresponding to
+  // |message_id| in grit/generated_resources.h to the map and replaces the
+  // placeholder within the error message with |replacement_string|.
+  void AddError(ConfigurationPolicyType policy,
+                int message_id,
+                const std::string& replacement_string);
+
+  // Returns a list of all the error messages stored for |policy|. Returns NULL
+  // if there are no error messages for |policy. The caller acquires ownership
+  // of the returned ListValue pointer.
+  ListValue* GetErrors(ConfigurationPolicyType policy);
+
+  bool empty();
+  size_t size();
+
+  const_iterator begin();
+  const_iterator end();
+
+  void Clear();
+
+ private:
+  struct PendingError;
+
+  // Maps the error when ready, otherwise adds it to the pending errors list.
+  void AddError(const PendingError& error);
+
+  // Converts a PendingError into a |map_| entry.
+  void Convert(const PendingError& error);
+
+  // Converts all pending errors to |map_| entries.
+  void CheckReadyAndConvert();
+
+  std::vector<PendingError> pending_;
+  PolicyMapType map_;
+
+  DISALLOW_COPY_AND_ASSIGN(PolicyErrorMap);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_POLICY_ERROR_MAP_H_
diff --git a/chrome/browser/policy/policy_map.cc b/chrome/browser/policy/policy_map.cc
index e923701a..3e9e4e6 100644
--- a/chrome/browser/policy/policy_map.cc
+++ b/chrome/browser/policy/policy_map.cc
@@ -53,7 +53,7 @@
   const PolicyDefinitionList::Entry* entry;
   for (entry = list->begin; entry != list->end; ++entry) {
     Value* value;
-    if (policies->Get(entry->name, &value) && value->IsType(entry->value_type))
+    if (policies->Get(entry->name, &value))
       Set(entry->policy_type, value->DeepCopy());
   }
 }
diff --git a/chrome/browser/policy/policy_map.h b/chrome/browser/policy/policy_map.h
index 02ee1630..ac0872d 100644
--- a/chrome/browser/policy/policy_map.h
+++ b/chrome/browser/policy/policy_map.h
@@ -4,6 +4,7 @@
 
 #ifndef CHROME_BROWSER_POLICY_POLICY_MAP_H_
 #define CHROME_BROWSER_POLICY_POLICY_MAP_H_
+#pragma once
 
 #include <map>
 
diff --git a/chrome/browser/policy/policy_path_parser.h b/chrome/browser/policy/policy_path_parser.h
index f5012632..baec7abf 100644
--- a/chrome/browser/policy/policy_path_parser.h
+++ b/chrome/browser/policy/policy_path_parser.h
@@ -4,6 +4,7 @@
 
 #ifndef CHROME_BROWSER_POLICY_POLICY_PATH_PARSER_H_
 #define CHROME_BROWSER_POLICY_POLICY_PATH_PARSER_H_
+#pragma once
 
 #include <string>
 
diff --git a/chrome/browser/policy/policy_status_info.h b/chrome/browser/policy/policy_status_info.h
index 2eecf19..545c198 100644
--- a/chrome/browser/policy/policy_status_info.h
+++ b/chrome/browser/policy/policy_status_info.h
@@ -4,6 +4,7 @@
 
 #ifndef CHROME_BROWSER_POLICY_POLICY_STATUS_INFO_H_
 #define CHROME_BROWSER_POLICY_POLICY_STATUS_INFO_H_
+#pragma once
 
 #include "base/memory/scoped_ptr.h"
 #include "base/string16.h"
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 04dd091a..e1bcac1b 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1753,6 +1753,8 @@
         'browser/policy/cloud_policy_subsystem.h',
         'browser/policy/config_dir_policy_provider.cc',
         'browser/policy/config_dir_policy_provider.h',
+        'browser/policy/configuration_policy_handler.cc',
+        'browser/policy/configuration_policy_handler.h',
         'browser/policy/configuration_policy_loader_win.cc',
         'browser/policy/configuration_policy_loader_win.h',
         'browser/policy/configuration_policy_pref_store.cc',
@@ -1786,6 +1788,8 @@
         'browser/policy/file_based_policy_loader.h',
         'browser/policy/file_based_policy_provider.cc',
         'browser/policy/file_based_policy_provider.h',
+        'browser/policy/policy_error_map.cc',
+        'browser/policy/policy_error_map.h',
         'browser/policy/policy_notifier.cc',
         'browser/policy/policy_notifier.h',
         'browser/policy/policy_path_parser.h',
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index 0e973f8..07e08ebf 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -115,6 +115,11 @@
 }
 
 /* static */
+bool ResourceBundle::HasSharedInstance() {
+  return g_shared_instance_ != NULL;
+}
+
+/* static */
 ResourceBundle& ResourceBundle::GetSharedInstance() {
   // Must call InitSharedInstance before this function.
   CHECK(g_shared_instance_ != NULL);
diff --git a/ui/base/resource/resource_bundle.h b/ui/base/resource/resource_bundle.h
index e739262..a56c31f4 100644
--- a/ui/base/resource/resource_bundle.h
+++ b/ui/base/resource/resource_bundle.h
@@ -104,6 +104,9 @@
   // Delete the ResourceBundle for this process if it exists.
   static void CleanupSharedInstance();
 
+  // Returns true after the global resource loader instance has been created.
+  static bool HasSharedInstance();
+
   // Return the global resource loader instance.
   static ResourceBundle& GetSharedInstance();