diff options
Diffstat (limited to 'chrome/browser/configuration_policy_pref_store.cc')
-rw-r--r-- | chrome/browser/configuration_policy_pref_store.cc | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/chrome/browser/configuration_policy_pref_store.cc b/chrome/browser/configuration_policy_pref_store.cc new file mode 100644 index 0000000..dc12e63 --- /dev/null +++ b/chrome/browser/configuration_policy_pref_store.cc @@ -0,0 +1,312 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/configuration_policy_pref_store.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/string16.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/browser/configuration_policy_provider.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" + +const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry + ConfigurationPolicyPrefStore::simple_policy_map_[] = { + { Value::TYPE_STRING, kPolicyHomePage, prefs::kHomePage }, + { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage, + prefs::kHomePageIsNewTabPage }, + { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled, + prefs::kAlternateErrorPagesEnabled }, + { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled, + prefs::kSearchSuggestEnabled }, + { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled, + prefs::kDnsPrefetchingEnabled }, + { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled, + prefs::kSafeBrowsingEnabled }, + { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled, + prefs::kPasswordManagerEnabled }, + { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled, + prefs::kMetricsReportingEnabled }, + { Value::TYPE_STRING, kPolicyApplicationLocale,
+ prefs::kApplicationLocale}, +}; + +const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry + ConfigurationPolicyPrefStore::proxy_policy_map_[] = { + { Value::TYPE_STRING, kPolicyProxyServer, prefs::kProxyServer }, + { Value::TYPE_STRING, kPolicyProxyPacUrl, prefs::kProxyPacUrl }, + { Value::TYPE_STRING, kPolicyProxyBypassList, prefs::kProxyBypassList } +}; + +ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore( + const CommandLine* command_line, + ConfigurationPolicyProvider* provider) + : command_line_(command_line), + provider_(provider), + prefs_(new DictionaryValue()), + command_line_proxy_settings_cleared_(false), + proxy_disabled_(false), + proxy_configuration_specified_(false), + use_system_proxy_(false) { +} + +void ConfigurationPolicyPrefStore::ApplyProxySwitches() { + bool proxy_disabled = command_line_->HasSwitch(switches::kNoProxyServer); + if (proxy_disabled) { + prefs_->Set(prefs::kNoProxyServer, Value::CreateBooleanValue(true)); + } + bool has_explicit_proxy_config = false; + if (command_line_->HasSwitch(switches::kProxyAutoDetect)) { + has_explicit_proxy_config = true; + prefs_->Set(prefs::kProxyAutoDetect, Value::CreateBooleanValue(true)); + } + if (command_line_->HasSwitch(switches::kProxyServer)) { + has_explicit_proxy_config = true; + prefs_->Set(prefs::kProxyServer, Value::CreateStringValue( + command_line_->GetSwitchValue(switches::kProxyServer))); + } + if (command_line_->HasSwitch(switches::kProxyPacUrl)) { + has_explicit_proxy_config = true; + prefs_->Set(prefs::kProxyPacUrl, Value::CreateStringValue( + command_line_->GetSwitchValue(switches::kProxyPacUrl))); + } + if (command_line_->HasSwitch(switches::kProxyBypassList)) { + has_explicit_proxy_config = true; + prefs_->Set(prefs::kProxyBypassList, Value::CreateStringValue( + command_line_->GetSwitchValue(switches::kProxyBypassList))); + } + + // Warn about all the other proxy config switches we get if + // the --no-proxy-server command-line argument is present. + if (proxy_disabled && has_explicit_proxy_config) { + LOG(WARNING) << "Additional command-line proxy switches specified when --" + << switches::kNoProxyServer << " was also specified."; + } +} + +PrefStore::PrefReadError ConfigurationPolicyPrefStore::ReadPrefs() { + // Initialize proxy preference values from command-line switches. This is done + // before calling Provide to allow the provider to overwrite proxy-related + // preferences that are specified by line settings. + ApplyProxySwitches(); + + proxy_disabled_ = false; + proxy_configuration_specified_ = false; + command_line_proxy_settings_cleared_ = false; + + return (provider_.get() == NULL || provider_->Provide(this)) ? + PrefStore::PREF_READ_ERROR_NONE : PrefStore::PREF_READ_ERROR_OTHER; +} + +bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy, + Value* value) { + bool result = false; + bool warn_about_proxy_disable_config = false; + bool warn_about_proxy_system_config = false; + + const PolicyToPreferenceMapEntry* match_entry_ = NULL; + for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_; + current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current) { + if (current->policy_type == policy) { + match_entry_ = current; + } + } + + // When the first proxy-related policy is applied, ALL proxy-related + // preferences that have been set by command-line switches must be + // removed. Otherwise it's possible for a user to interfere with proxy + // policy by using proxy-related switches that are related to, but not + // identical, to the ones set through policy. + if ((match_entry_ || + policy == ConfigurationPolicyPrefStore::kPolicyProxyServerMode) && + !command_line_proxy_settings_cleared_) { + for (const PolicyToPreferenceMapEntry* i = proxy_policy_map_; + i != proxy_policy_map_ + arraysize(proxy_policy_map_); ++i) { + if (prefs_->Get(i->preference_path, NULL)) { + LOG(WARNING) << "proxy configuration options were specified on the" + << " command-line but will be ignored because an" + << " explicit proxy configuration has been specified" + << " through a centrally-administered policy."; + break; + } + } + + // Now actually do the preference removal. + for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_; + current != proxy_policy_map_ + arraysize(proxy_policy_map_); ++current) + prefs_->Remove(current->preference_path, NULL); + prefs_->Remove(prefs::kNoProxyServer, NULL); + prefs_->Remove(prefs::kProxyAutoDetect, NULL); + + command_line_proxy_settings_cleared_ = true; + } + + // Translate the proxy policy into preferences. + if (policy == ConfigurationPolicyStore::kPolicyProxyServerMode) { + int int_value; + bool proxy_auto_detect = false; + if (value->GetAsInteger(&int_value)) { + result = true; + switch (int_value) { + case ConfigurationPolicyStore::kPolicyNoProxyServerMode: + if (!proxy_disabled_) { + if (proxy_configuration_specified_) + warn_about_proxy_disable_config = true; + proxy_disabled_ = true; + } + break; + case ConfigurationPolicyStore::kPolicyAutoDetectProxyMode: + proxy_auto_detect = true; + break; + case ConfigurationPolicyStore::kPolicyManuallyConfiguredProxyMode: + break; + case ConfigurationPolicyStore::kPolicyUseSystemProxyMode: + if (!use_system_proxy_) { + if (proxy_configuration_specified_) + warn_about_proxy_system_config = true; + use_system_proxy_ = true; + } + break; + default: + // Not a valid policy, don't assume ownership of |value| + result = false; + break; + } + + if (int_value != kPolicyUseSystemProxyMode) { + prefs_->Set(prefs::kNoProxyServer, + Value::CreateBooleanValue(proxy_disabled_)); + prefs_->Set(prefs::kProxyAutoDetect, + Value::CreateBooleanValue(proxy_auto_detect)); + } + + // No proxy and system proxy mode should ensure that no other + // proxy preferences are set. + if (int_value == ConfigurationPolicyStore::kPolicyNoProxyServerMode || + int_value == kPolicyUseSystemProxyMode) { + for (const PolicyToPreferenceMapEntry* current = proxy_policy_map_; + current != proxy_policy_map_ + arraysize(proxy_policy_map_); + ++current) + prefs_->Remove(current->preference_path, NULL); + } + } + } else if (match_entry_) { + // Determine if the applied proxy policy settings conflict and issue + // a corresponding warning if they do. + if (!proxy_configuration_specified_) { + if (proxy_disabled_) + warn_about_proxy_disable_config = true; + if (use_system_proxy_) + warn_about_proxy_system_config = true; + proxy_configuration_specified_ = true; + } + if (!use_system_proxy_ && !proxy_disabled_) { + prefs_->Set(match_entry_->preference_path, value); + // The ownership of value has been passed on to |prefs_|, + // don't clean it up later. + value = NULL; + } + result = true; + } + + if (warn_about_proxy_disable_config) { + LOG(WARNING) << "A centrally-administered policy disables the use of" + << " a proxy but also specifies an explicit proxy" + << " configuration."; + } + + if (warn_about_proxy_system_config) { + LOG(WARNING) << "A centrally-administered policy dictates that the" + << " system proxy settings should be used but also specifies" + << " an explicit proxy configuration."; + } + + // If the policy was a proxy policy, cleanup |value|. + if (result && value) + delete value; + return result; +} + +bool ConfigurationPolicyPrefStore::ApplyPluginPolicy(PolicyType policy, + Value* value) { + if (policy == kPolicyDisabledPlugins) { + string16 plugin_list; + if (value->GetAsUTF16(&plugin_list)) { + std::vector<string16> plugin_names; + // Change commas into tabs so that we can change escaped + // tabs back into commas, leaving non-escaped commas as tabs + // that can be used for splitting the string. Note that plugin + // names must not contain backslashes, since a trailing backslash + // in a plugin name before a comma would get swallowed during the + // splitting. + std::replace(plugin_list.begin(), plugin_list.end(), L',', L'\t'); + ReplaceSubstringsAfterOffset(&plugin_list, 0, + ASCIIToUTF16("\\\t"), ASCIIToUTF16(",")); + SplitString(plugin_list, L'\t', &plugin_names); + bool added_plugin = false; + scoped_ptr<ListValue> list(new ListValue()); + for (std::vector<string16>::const_iterator i(plugin_names.begin()); + i != plugin_names.end(); ++i) { + if (!i->empty()) { + list->Append(Value::CreateStringValueFromUTF16(*i)); + added_plugin = true; + } + } + if (added_plugin) { + prefs_->Set(prefs::kPluginsPluginsBlacklist, list.release()); + delete value; + return true; + } + } + } + return false; +} + +bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy, + Value* value) { + if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) { + bool disable_sync; + if (value->GetAsBoolean(&disable_sync) && disable_sync) + prefs_->Set(prefs::kSyncManaged, value); + else + delete value; + return true; + } + return false; +} + +bool ConfigurationPolicyPrefStore::ApplyPolicyFromMap(PolicyType policy, + Value* value, const PolicyToPreferenceMapEntry map[], int size) { + const PolicyToPreferenceMapEntry* end = map + size; + for (const PolicyToPreferenceMapEntry* current = map; + current != end; ++current) { + if (current->policy_type == policy) { + DCHECK(current->value_type == value->GetType()); + prefs_->Set(current->preference_path, value); + return true; + } + } + return false; +} + +void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) { + if (ApplyProxyPolicy(policy, value)) + return; + + if (ApplyPluginPolicy(policy, value)) + return; + + if (ApplySyncPolicy(policy, value)) + return; + + if (ApplyPolicyFromMap(policy, value, simple_policy_map_, + arraysize(simple_policy_map_))) + return; + + // Other policy implementations go here. + NOTIMPLEMENTED(); + delete value; +} |