// 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_pref_store.h" #include <map> #include <set> #include <string> #include <vector> #include "base/command_line.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/stl_util-inl.h" #include "base/string16.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/policy/browser_policy_connector.h" #include "chrome/browser/policy/configuration_policy_provider.h" #include "chrome/browser/policy/policy_path_parser.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/prefs/pref_value_map.h" #include "chrome/browser/prefs/proxy_config_dictionary.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/search_terms_data.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/common/pref_names.h" #include "content/common/notification_service.h" #include "policy/policy_constants.h" namespace policy { // Accepts policy settings from a ConfigurationPolicyProvider, converts them // to preferences and caches the result. class ConfigurationPolicyPrefKeeper : private ConfigurationPolicyStoreInterface { 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: // ConfigurationPolicyStore methods: virtual void Apply(ConfigurationPolicyType setting, Value* value); // Policies that map to a single preference are handled // by an automated converter. Each one of these policies // has an entry in |simple_policy_map_| with the following type. struct PolicyToPreferenceMapEntry { Value::ValueType value_type; 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); // 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(); // 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_; 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, kPolicyJavascriptEnabled, prefs::kWebKitJavascriptEnabled }, { Value::TYPE_BOOLEAN, kPolicyIncognitoEnabled, prefs::kIncognitoEnabled }, { 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, kPolicyDefaultJavaScriptSetting, prefs::kManagedDefaultJavaScriptSetting }, { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting, prefs::kManagedDefaultPluginsSetting }, { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting, prefs::kManagedDefaultPopupsSetting }, { 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_INTEGER, kPolicyDefaultNotificationSetting, prefs::kDesktopNotificationDefaultContentSetting }, { Value::TYPE_INTEGER, kPolicyDefaultGeolocationSetting, prefs::kGeolocationDefaultContentSetting }, { 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, kPolicyDisable3DAPIs, prefs::kDisable3DAPIs }, { Value::TYPE_BOOLEAN, kPolicyDisablePluginFinder, prefs::kDisablePluginFinder }, { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate, prefs::kPolicyRefreshRate }, { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled }, { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled, prefs::kDefaultBrowserSettingEnabled }, { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled, prefs::kCloudPrintProxyEnabled }, { Value::TYPE_BOOLEAN, kPolicyTranslateEnabled, prefs::kEnableTranslate }, { Value::TYPE_BOOLEAN, kPolicyBookmarkBarEnabled, prefs::kEnableBookmarkBar }, { Value::TYPE_BOOLEAN, kPolicyAllowOutdatedPlugins, prefs::kPluginsAllowOutdated }, { Value::TYPE_BOOLEAN, kPolicyEditBookmarksEnabled, prefs::kEditBookmarksEnabled }, { Value::TYPE_BOOLEAN, kPolicyAllowFileSelectionDialogs, prefs::kAllowFileSelectionDialogs }, #if defined(OS_CHROMEOS) { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend, prefs::kEnableScreenLock }, #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, kPolicyDefaultSearchProviderIconURL, prefs::kDefaultSearchProviderIconURL }, { Value::TYPE_STRING, kPolicyDefaultSearchProviderEncodings, prefs::kDefaultSearchProviderEncodings }, }; ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper( ConfigurationPolicyProvider* provider) { if (!provider->Provide(this)) LOG(WARNING) << "Failed to get policy from provider."; FinalizeProxyPolicySettings(); FinalizeDefaultSearchPolicySettings(); } 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; *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(ConfigurationPolicyType policy, Value* value) { if (ApplyProxyPolicy(policy, value)) return; if (ApplySyncPolicy(policy, value)) return; if (ApplyAutofillPolicy(policy, value)) return; if (ApplyDownloadDirPolicy(policy, value)) return; if (ApplyPolicyFromMap(policy, value, kDefaultSearchPolicyMap, arraysize(kDefaultSearchPolicyMap))) return; if (ApplyPolicyFromMap(policy, value, kSimplePolicyMap, arraysize(kSimplePolicyMap))) return; // Other policy implementations go here. NOTIMPLEMENTED(); delete value; } 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 (policy == kPolicyProxyMode || policy == kPolicyProxyServerMode || policy == kPolicyProxyServer || policy == kPolicyProxyPacUrl || policy == kPolicyProxyBypassList) { 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) { 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::kDownloadDefaultDirectory, Value::CreateStringValue(expanded_value)); prefs_.SetValue(prefs::kPromptForDownload, Value::CreateBooleanValue(false)); delete value; return true; } // We are not interested in this policy. 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::FinalizeProxyPolicySettings() { if (CheckProxySettings()) ApplyProxySettings(); STLDeleteContainerPairSecondPointers(proxy_policies_.begin(), proxy_policies_.end()); proxy_policies_.clear(); } bool ConfigurationPolicyPrefKeeper::CheckProxySettings() { bool mode = HasProxyPolicy(kPolicyProxyMode); bool server_mode = HasProxyPolicy(kPolicyProxyServerMode); // deprecated bool server = HasProxyPolicy(kPolicyProxyServer); bool pac_url = HasProxyPolicy(kPolicyProxyPacUrl); bool bypass_list = HasProxyPolicy(kPolicyProxyBypassList); if ((server || pac_url || bypass_list) && !(mode || server_mode)) { LOG(WARNING) << "A centrally-administered policy defines proxy setting" << " details without setting a proxy mode."; return false; } // If there's a server mode, convert it into a mode. std::string mode_value; if (mode) { if (server_mode) LOG(WARNING) << "Both ProxyMode and ProxyServerMode policies defined, " << "ignoring ProxyMode."; if (!proxy_policies_[kPolicyProxyMode]->GetAsString(&mode_value)) { LOG(WARNING) << "Invalid ProxyMode value."; return false; } } else if (server_mode) { int server_mode_value; if (!proxy_policies_[kPolicyProxyServerMode]->GetAsInteger( &server_mode_value)) { LOG(WARNING) << "Invalid ProxyServerMode value."; return false; } switch (server_mode_value) { case kPolicyNoProxyServerMode: mode_value = ProxyPrefs::kDirectProxyModeName; break; case kPolicyAutoDetectProxyServerMode: mode_value = ProxyPrefs::kAutoDetectProxyModeName; break; case kPolicyManuallyConfiguredProxyServerMode: if (server && pac_url) { LOG(WARNING) << "A centrally-administered policy dictates that" << " both fixed proxy servers and a .pac url. should" << " be used for proxy configuration."; return false; } if (!server && !pac_url) { LOG(WARNING) << "A centrally-administered policy dictates that the" << " proxy settings should use either fixed proxy" << " servers or a .pac url, but specifies neither."; return false; } if (pac_url) mode_value = ProxyPrefs::kPacScriptProxyModeName; else mode_value = ProxyPrefs::kFixedServersProxyModeName; break; case kPolicyUseSystemProxyServerMode: mode_value = ProxyPrefs::kSystemProxyModeName; break; default: LOG(WARNING) << "Invalid proxy mode " << server_mode_value; return false; } } // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be // empty and the proxy shouldn't be configured at all. if (mode_value.empty()) return true; if (mode_value == ProxyPrefs::kDirectProxyModeName) { if (server || pac_url || bypass_list) { LOG(WARNING) << "A centrally-administered policy disables the use of" << " a proxy but also specifies an explicit proxy" << " configuration."; return false; } } else if (mode_value == ProxyPrefs::kAutoDetectProxyModeName) { if (server || bypass_list || pac_url) { LOG(WARNING) << "A centrally-administered policy dictates that a proxy" << " shall be auto configured but specifies fixed proxy" << " servers, a by-pass list or a .pac script URL."; return false; } } else if (mode_value == ProxyPrefs::kPacScriptProxyModeName) { if (server || bypass_list) { LOG(WARNING) << "A centrally-administered policy dictates that a .pac" << " script URL should be used for proxy configuration but" << " also specifies policies required only for fixed" << " proxy servers."; return false; } } else if (mode_value == ProxyPrefs::kFixedServersProxyModeName) { if (pac_url) { LOG(WARNING) << "A centrally-administered policy dictates that" << " fixed proxy servers should be used but also" << " specifies a .pac script URL."; return false; } } else if (mode_value == ProxyPrefs::kSystemProxyModeName) { if (server || pac_url || bypass_list) { LOG(WARNING) << "A centrally-administered policy dictates that the" << " system proxy settings should be used but also " << " specifies an explicit proxy configuration."; return false; } } else { LOG(WARNING) << "Invalid proxy mode " << mode_value; return false; } return true; } void ConfigurationPolicyPrefKeeper::ApplyProxySettings() { ProxyPrefs::ProxyMode mode; if (HasProxyPolicy(kPolicyProxyMode)) { std::string string_mode; CHECK(proxy_policies_[kPolicyProxyMode]->GetAsString(&string_mode)); if (!ProxyPrefs::StringToProxyMode(string_mode, &mode)) { LOG(WARNING) << "A centrally-administered policy specifies a value for" << "the ProxyMode policy that isn't recognized."; return; } } else if (HasProxyPolicy(kPolicyProxyServerMode)) { int int_mode = 0; CHECK(proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(&int_mode)); switch (int_mode) { case kPolicyNoProxyServerMode: mode = ProxyPrefs::MODE_DIRECT; break; case kPolicyAutoDetectProxyServerMode: mode = ProxyPrefs::MODE_AUTO_DETECT; break; case kPolicyManuallyConfiguredProxyServerMode: mode = ProxyPrefs::MODE_FIXED_SERVERS; if (HasProxyPolicy(kPolicyProxyPacUrl)) mode = ProxyPrefs::MODE_PAC_SCRIPT; break; case kPolicyUseSystemProxyServerMode: mode = ProxyPrefs::MODE_SYSTEM; break; default: mode = ProxyPrefs::MODE_DIRECT; NOTREACHED(); } } else { return; } switch (mode) { case ProxyPrefs::MODE_DIRECT: prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect()); break; case ProxyPrefs::MODE_AUTO_DETECT: prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect()); break; case ProxyPrefs::MODE_PAC_SCRIPT: { if (!HasProxyPolicy(kPolicyProxyPacUrl)) { LOG(WARNING) << "A centrally-administered policy specifies to use a " << "PAC script, but doesn't supply the PAC script URL."; return; } std::string pac_url; proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url); prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreatePacScript(pac_url)); break; } case ProxyPrefs::MODE_FIXED_SERVERS: { if (!HasProxyPolicy(kPolicyProxyServer)) { LOG(WARNING) << "A centrally-administered policy specifies to use a " << "fixed server, but doesn't supply the server address."; return; } std::string proxy_server; proxy_policies_[kPolicyProxyServer]->GetAsString(&proxy_server); std::string bypass_list; if (HasProxyPolicy(kPolicyProxyBypassList)) proxy_policies_[kPolicyProxyBypassList]->GetAsString(&bypass_list); prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateFixedServers(proxy_server, bypass_list)); break; } case ProxyPrefs::MODE_SYSTEM: prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateSystem()); break; case ProxyPrefs::kModeCount: NOTREACHED(); } } bool ConfigurationPolicyPrefKeeper::HasProxyPolicy( ConfigurationPolicyType policy) const { std::map<ConfigurationPolicyType, Value*>::const_iterator iter; iter = proxy_policies_.find(policy); std::string tmp; if (iter == proxy_policies_.end() || !iter->second || iter->second->IsType(Value::TYPE_NULL) || (iter->second->IsType(Value::TYPE_STRING) && iter->second->GetAsString(&tmp) && tmp.empty())) { return false; } return true; } ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( ConfigurationPolicyProvider* provider) : provider_(provider), initialization_complete_(false) { if (provider_) { // Read initial policy. policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider)); registrar_.Init(provider_, this); initialization_complete_ = provider->IsInitializationComplete(); } else { initialization_complete_ = true; } } ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() { } void ConfigurationPolicyPrefStore::AddObserver(PrefStore::Observer* observer) { observers_.AddObserver(observer); } void ConfigurationPolicyPrefStore::RemoveObserver( PrefStore::Observer* observer) { observers_.RemoveObserver(observer); } bool ConfigurationPolicyPrefStore::IsInitializationComplete() const { return initialization_complete_; } PrefStore::ReadResult ConfigurationPolicyPrefStore::GetValue(const std::string& key, const Value** value) const { if (policy_keeper_.get()) return policy_keeper_->GetValue(key, value); return PrefStore::READ_NO_VALUE; } void ConfigurationPolicyPrefStore::OnUpdatePolicy() { Refresh(); } void ConfigurationPolicyPrefStore::OnProviderGoingAway() { provider_ = NULL; } // static ConfigurationPolicyPrefStore* ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() { BrowserPolicyConnector* connector = g_browser_process->browser_policy_connector(); return new ConfigurationPolicyPrefStore( connector->GetManagedPlatformProvider()); } // static ConfigurationPolicyPrefStore* ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore( Profile* profile) { ConfigurationPolicyProvider* provider = NULL; if (profile) { // For user policy, return the profile's policy provider. provider = profile->GetPolicyConnector()->GetManagedCloudProvider(); } else { // For device policy, return the provider of the browser process. BrowserPolicyConnector* connector = g_browser_process->browser_policy_connector(); provider = connector->GetManagedCloudProvider(); } return new ConfigurationPolicyPrefStore(provider); } // static ConfigurationPolicyPrefStore* ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() { BrowserPolicyConnector* connector = g_browser_process->browser_policy_connector(); return new ConfigurationPolicyPrefStore( connector->GetRecommendedPlatformProvider()); } // static ConfigurationPolicyPrefStore* ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore( Profile* profile) { ConfigurationPolicyProvider* provider = NULL; if (profile) { // For user policy, return the profile's policy provider. provider = profile->GetPolicyConnector()->GetRecommendedCloudProvider(); } else { // For device policy, return the provider of the browser process. BrowserPolicyConnector* connector = g_browser_process->browser_policy_connector(); provider = connector->GetRecommendedCloudProvider(); } return new ConfigurationPolicyPrefStore(provider); } /* static */ const ConfigurationPolicyProvider::PolicyDefinitionList* ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() { static ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[] = { { kPolicyHomepageLocation, Value::TYPE_STRING, key::kHomepageLocation }, { kPolicyHomepageIsNewTabPage, Value::TYPE_BOOLEAN, key::kHomepageIsNewTabPage }, { kPolicyRestoreOnStartup, Value::TYPE_INTEGER, key::kRestoreOnStartup }, { kPolicyRestoreOnStartupURLs, Value::TYPE_LIST, key::kRestoreOnStartupURLs }, { kPolicyDefaultSearchProviderEnabled, Value::TYPE_BOOLEAN, key::kDefaultSearchProviderEnabled }, { kPolicyDefaultSearchProviderName, Value::TYPE_STRING, key::kDefaultSearchProviderName }, { kPolicyDefaultSearchProviderKeyword, Value::TYPE_STRING, key::kDefaultSearchProviderKeyword }, { kPolicyDefaultSearchProviderSearchURL, Value::TYPE_STRING, key::kDefaultSearchProviderSearchURL }, { kPolicyDefaultSearchProviderSuggestURL, Value::TYPE_STRING, key::kDefaultSearchProviderSuggestURL }, { kPolicyDefaultSearchProviderInstantURL, Value::TYPE_STRING, key::kDefaultSearchProviderInstantURL }, { kPolicyDefaultSearchProviderIconURL, Value::TYPE_STRING, key::kDefaultSearchProviderIconURL }, { kPolicyDefaultSearchProviderEncodings, Value::TYPE_STRING, key::kDefaultSearchProviderEncodings }, { kPolicyProxyMode, Value::TYPE_STRING, key::kProxyMode }, { kPolicyProxyServerMode, Value::TYPE_INTEGER, key::kProxyServerMode }, { kPolicyProxyServer, Value::TYPE_STRING, key::kProxyServer }, { kPolicyProxyPacUrl, Value::TYPE_STRING, key::kProxyPacUrl }, { kPolicyProxyBypassList, Value::TYPE_STRING, key::kProxyBypassList }, { kPolicyAlternateErrorPagesEnabled, Value::TYPE_BOOLEAN, key::kAlternateErrorPagesEnabled }, { kPolicySearchSuggestEnabled, Value::TYPE_BOOLEAN, key::kSearchSuggestEnabled }, { kPolicyDnsPrefetchingEnabled, Value::TYPE_BOOLEAN, key::kDnsPrefetchingEnabled }, { kPolicyDisableSpdy, Value::TYPE_BOOLEAN, key::kDisableSpdy }, { kPolicyDisabledSchemes, Value::TYPE_LIST, key::kDisabledSchemes }, { kPolicySafeBrowsingEnabled, Value::TYPE_BOOLEAN, key::kSafeBrowsingEnabled }, { kPolicyMetricsReportingEnabled, Value::TYPE_BOOLEAN, key::kMetricsReportingEnabled }, { kPolicyPasswordManagerEnabled, Value::TYPE_BOOLEAN, key::kPasswordManagerEnabled }, { kPolicyPasswordManagerAllowShowPasswords, Value::TYPE_BOOLEAN, key::kPasswordManagerAllowShowPasswords }, { kPolicyAutoFillEnabled, Value::TYPE_BOOLEAN, key::kAutoFillEnabled }, { kPolicyDisabledPlugins, Value::TYPE_LIST, key::kDisabledPlugins }, { kPolicyDisabledPluginsExceptions, Value::TYPE_LIST, key::kDisabledPluginsExceptions }, { kPolicyEnabledPlugins, Value::TYPE_LIST, key::kEnabledPlugins }, { kPolicyApplicationLocaleValue, Value::TYPE_STRING, key::kApplicationLocaleValue }, { kPolicySyncDisabled, Value::TYPE_BOOLEAN, key::kSyncDisabled }, { kPolicyExtensionInstallWhitelist, Value::TYPE_LIST, key::kExtensionInstallWhitelist }, { kPolicyExtensionInstallBlacklist, Value::TYPE_LIST, key::kExtensionInstallBlacklist }, { kPolicyExtensionInstallForcelist, Value::TYPE_LIST, key::kExtensionInstallForcelist }, { kPolicyShowHomeButton, Value::TYPE_BOOLEAN, key::kShowHomeButton }, { kPolicyPrintingEnabled, Value::TYPE_BOOLEAN, key::kPrintingEnabled }, { kPolicyJavascriptEnabled, Value::TYPE_BOOLEAN, key::kJavascriptEnabled }, { kPolicyIncognitoEnabled, Value::TYPE_BOOLEAN, key::kIncognitoEnabled }, { kPolicySavingBrowserHistoryDisabled, Value::TYPE_BOOLEAN, key::kSavingBrowserHistoryDisabled }, { kPolicyClearSiteDataOnExit, Value::TYPE_BOOLEAN, key::kClearSiteDataOnExit }, { kPolicyDeveloperToolsDisabled, Value::TYPE_BOOLEAN, key::kDeveloperToolsDisabled }, { kPolicyBlockThirdPartyCookies, Value::TYPE_BOOLEAN, key::kBlockThirdPartyCookies }, { kPolicyDefaultCookiesSetting, Value::TYPE_INTEGER, key::kDefaultCookiesSetting }, { kPolicyDefaultImagesSetting, Value::TYPE_INTEGER, key::kDefaultImagesSetting }, { kPolicyDefaultJavaScriptSetting, Value::TYPE_INTEGER, key::kDefaultJavaScriptSetting }, { kPolicyDefaultPluginsSetting, Value::TYPE_INTEGER, key::kDefaultPluginsSetting }, { kPolicyDefaultPopupsSetting, Value::TYPE_INTEGER, key::kDefaultPopupsSetting }, { kPolicyDefaultNotificationSetting, Value::TYPE_INTEGER, key::kDefaultNotificationSetting }, { kPolicyDefaultGeolocationSetting, Value::TYPE_INTEGER, key::kDefaultGeolocationSetting }, { kPolicyCookiesAllowedForUrls, Value::TYPE_LIST, key::kCookiesAllowedForUrls }, { kPolicyCookiesBlockedForUrls, Value::TYPE_LIST, key::kCookiesBlockedForUrls }, { kPolicyCookiesSessionOnlyForUrls, Value::TYPE_LIST, key::kCookiesSessionOnlyForUrls }, { kPolicyImagesAllowedForUrls, Value::TYPE_LIST, key::kImagesAllowedForUrls }, { kPolicyImagesBlockedForUrls, Value::TYPE_LIST, key::kImagesBlockedForUrls }, { kPolicyJavaScriptAllowedForUrls, Value::TYPE_LIST, key::kJavaScriptAllowedForUrls }, { kPolicyJavaScriptBlockedForUrls, Value::TYPE_LIST, key::kJavaScriptBlockedForUrls }, { kPolicyPluginsAllowedForUrls, Value::TYPE_LIST, key::kPluginsAllowedForUrls }, { kPolicyPluginsBlockedForUrls, Value::TYPE_LIST, key::kPluginsBlockedForUrls }, { kPolicyPopupsAllowedForUrls, Value::TYPE_LIST, key::kPopupsAllowedForUrls }, { kPolicyPopupsBlockedForUrls, Value::TYPE_LIST, key::kPopupsBlockedForUrls }, { kPolicyAuthSchemes, Value::TYPE_STRING, key::kAuthSchemes }, { kPolicyDisableAuthNegotiateCnameLookup, Value::TYPE_BOOLEAN, key::kDisableAuthNegotiateCnameLookup }, { kPolicyEnableAuthNegotiatePort, Value::TYPE_BOOLEAN, key::kEnableAuthNegotiatePort }, { kPolicyAuthServerWhitelist, Value::TYPE_STRING, key::kAuthServerWhitelist }, { kPolicyAuthNegotiateDelegateWhitelist, Value::TYPE_STRING, key::kAuthNegotiateDelegateWhitelist }, { kPolicyGSSAPILibraryName, Value::TYPE_STRING, key::kGSSAPILibraryName }, { kPolicyDisable3DAPIs, Value::TYPE_BOOLEAN, key::kDisable3DAPIs }, { kPolicyDisablePluginFinder, Value::TYPE_BOOLEAN, key::kDisablePluginFinder }, { kPolicyPolicyRefreshRate, Value::TYPE_INTEGER, key::kPolicyRefreshRate }, { kPolicyInstantEnabled, Value::TYPE_BOOLEAN, key::kInstantEnabled }, { kPolicyDefaultBrowserSettingEnabled, Value::TYPE_BOOLEAN, key::kDefaultBrowserSettingEnabled }, { kPolicyCloudPrintProxyEnabled, Value::TYPE_BOOLEAN, key::kCloudPrintProxyEnabled }, { kPolicyDownloadDirectory, Value::TYPE_STRING, key::kDownloadDirectory }, { kPolicyTranslateEnabled, Value::TYPE_BOOLEAN, key::kTranslateEnabled }, { kPolicyAllowOutdatedPlugins, Value::TYPE_BOOLEAN, key::kAllowOutdatedPlugins }, { kPolicyBookmarkBarEnabled, Value::TYPE_BOOLEAN, key::kBookmarkBarEnabled }, { kPolicyEditBookmarksEnabled, Value::TYPE_BOOLEAN, key::kEditBookmarksEnabled }, { kPolicyAllowFileSelectionDialogs, Value::TYPE_BOOLEAN, key::kAllowFileSelectionDialogs }, #if defined(OS_CHROMEOS) { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN, key::kChromeOsLockOnIdleSuspend }, #endif }; static ConfigurationPolicyProvider::PolicyDefinitionList policy_list = { entries, entries + arraysize(entries), }; return &policy_list; } 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_)); std::vector<std::string> changed_prefs; new_keeper->GetDifferingPrefPaths(policy_keeper_.get(), &changed_prefs); policy_keeper_.reset(new_keeper.release()); // Send out change notifications. for (std::vector<std::string>::const_iterator pref(changed_prefs.begin()); pref != changed_prefs.end(); ++pref) { FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(*pref)); } // Update the initialization flag. if (!initialization_complete_ && provider_->IsInitializationComplete()) { initialization_complete_ = true; FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnInitializationCompleted()); } } } // namespace policy