diff options
18 files changed, 1721 insertions, 976 deletions
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 @@ Keep your key file in a safe place. You will need it to create new versions of y <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 @@ BrowserPolicyConnector::~BrowserPolicyConnector() { user_cloud_policy_subsystem_.reset(); user_policy_token_cache_.reset(); user_data_store_.reset(); + + STLDeleteElements(policy_handlers_.get()); } ConfigurationPolicyProvider* @@ -308,6 +311,11 @@ const CloudPolicyDataStore* 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 @@ BrowserPolicyConnector::BrowserPolicyConnector() #if defined(OS_CHROMEOS) InitializeDevicePolicy(); #endif + policy_handlers_.reset(ConfigurationPolicyHandler::CreateHandlerList()); } BrowserPolicyConnector::BrowserPolicyConnector( @@ -334,7 +343,9 @@ BrowserPolicyConnector::BrowserPolicyConnector( 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 4f63910..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 @@ class BrowserPolicyConnector : public content::NotificationObserver { const CloudPolicyDataStore* GetDeviceCloudPolicyDataStore() const; const CloudPolicyDataStore* GetUserCloudPolicyDataStore() const; + const ConfigurationPolicyHandler::HandlerList* + GetConfigurationPolicyHandlerList() const; + private: friend class ::TestingBrowserProcess; @@ -170,6 +174,9 @@ class BrowserPolicyConnector : public content::NotificationObserver { // 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 @@ TEST_P(ConfigDirPolicyProviderValueTest, Default) { 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..797da3e --- /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 3616e6d..ee8f280 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.cc +++ b/chrome/browser/policy/configuration_policy_pref_store.cc @@ -4,963 +4,38 @@ #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/"; - } - 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; +// 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; } - 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; -} +} // namespace ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( ConfigurationPolicyProvider* provider) @@ -968,7 +43,7 @@ ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( 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 @@ bool ConfigurationPolicyPrefStore::IsInitializationComplete() const { 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 @@ void ConfigurationPolicyPrefStore::OnProviderGoingAway() { // 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 @@ ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore() { // 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 @@ ConfigurationPolicyPrefStore::IsProxyPolicy(ConfigurationPolicyType policy) { 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 @@ void ConfigurationPolicyPrefStore::Refresh() { } } +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 4b570b2..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 @@ class ConfigurationPolicyPrefStore 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 @@ class ConfigurationPolicyPrefStore // 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 @@ class ConfigurationPolicyPrefStore 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 0533efc..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 e923701..3e9e4e6 100644 --- a/chrome/browser/policy/policy_map.cc +++ b/chrome/browser/policy/policy_map.cc @@ -53,7 +53,7 @@ void PolicyMap::LoadFrom( 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 02ee163..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 f501263..baec7ab 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 04dd091..e1bcac1 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..07e08eb 100644 --- a/ui/base/resource/resource_bundle.cc +++ b/ui/base/resource/resource_bundle.cc @@ -115,6 +115,11 @@ void ResourceBundle::CleanupSharedInstance() { } /* 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..a56c31f 100644 --- a/ui/base/resource/resource_bundle.h +++ b/ui/base/resource/resource_bundle.h @@ -104,6 +104,9 @@ class UI_EXPORT ResourceBundle { // 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(); |