configuration_policy_pref_store.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/policy/configuration_policy_pref_store.h"
6
7#include <map>
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/command_line.h"
13#include "base/lazy_instance.h"
14#include "base/logging.h"
15#include "base/stl_util-inl.h"
16#include "base/string16.h"
17#include "base/string_util.h"
18#include "base/utf_string_conversions.h"
19#include "base/values.h"
20#include "chrome/browser/browser_process.h"
21#include "chrome/browser/policy/configuration_policy_provider.h"
22#include "chrome/browser/policy/configuration_policy_provider_keeper.h"
23#include "chrome/browser/policy/device_management_policy_provider.h"
24#include "chrome/browser/policy/profile_policy_context.h"
25#include "chrome/browser/prefs/pref_value_map.h"
26#include "chrome/browser/prefs/proxy_config_dictionary.h"
27#include "chrome/browser/profiles/profile.h"
28#include "chrome/browser/search_engines/search_terms_data.h"
29#include "chrome/browser/search_engines/template_url.h"
30#include "chrome/common/notification_service.h"
31#include "chrome/common/pref_names.h"
32#include "policy/policy_constants.h"
33
34namespace policy {
35
36// Accepts policy settings from a ConfigurationPolicyProvider, converts them
37// to preferences and caches the result.
38class ConfigurationPolicyPrefKeeper
39    : private ConfigurationPolicyStoreInterface {
40 public:
41  explicit ConfigurationPolicyPrefKeeper(ConfigurationPolicyProvider* provider);
42  virtual ~ConfigurationPolicyPrefKeeper();
43
44  // Get a preference value.
45  PrefStore::ReadResult GetValue(const std::string& key, Value** result) const;
46
47  // Compute the set of preference names that are different in |keeper|. This
48  // includes preferences that are missing in either one.
49  void GetDifferingPrefPaths(const ConfigurationPolicyPrefKeeper* other,
50                             std::vector<std::string>* differing_prefs) const;
51
52 private:
53  // ConfigurationPolicyStore methods:
54  virtual void Apply(ConfigurationPolicyType setting, Value* value);
55
56  // Policies that map to a single preference are handled
57  // by an automated converter. Each one of these policies
58  // has an entry in |simple_policy_map_| with the following type.
59  struct PolicyToPreferenceMapEntry {
60    Value::ValueType value_type;
61    ConfigurationPolicyType policy_type;
62    const char* preference_path;  // A DictionaryValue path, not a file path.
63  };
64
65  // Returns the map entry that corresponds to |policy| in the map.
66  const PolicyToPreferenceMapEntry* FindPolicyInMap(
67      ConfigurationPolicyType policy,
68      const PolicyToPreferenceMapEntry* map,
69      int size) const;
70
71  // Remove the preferences found in the map from |prefs_|. Returns true if any
72  // such preferences were found and removed.
73  bool RemovePreferencesOfMap(const PolicyToPreferenceMapEntry* map,
74                              int table_size);
75
76  bool ApplyPolicyFromMap(ConfigurationPolicyType policy,
77                          Value* value,
78                          const PolicyToPreferenceMapEntry* map,
79                          int size);
80
81  // Processes proxy-specific policies. Returns true if the specified policy
82  // is a proxy-related policy. ApplyProxyPolicy assumes the ownership
83  // of |value| in the case that the policy is proxy-specific.
84  bool ApplyProxyPolicy(ConfigurationPolicyType policy, Value* value);
85
86  // Handles sync-related policies. Returns true if the policy was handled.
87  // Assumes ownership of |value| in that case.
88  bool ApplySyncPolicy(ConfigurationPolicyType policy, Value* value);
89
90  // Handles policies that affect AutoFill. Returns true if the policy was
91  // handled and assumes ownership of |value| in that case.
92  bool ApplyAutoFillPolicy(ConfigurationPolicyType policy, Value* value);
93
94  // Make sure that the |path| if present in |prefs_|.  If not, set it to
95  // a blank string.
96  void EnsureStringPrefExists(const std::string& path);
97
98  // If the required entries for default search are specified and valid,
99  // finalizes the policy-specified configuration by initializing the
100  // unspecified map entries.  Otherwise wipes all default search related
101  // map entries from |prefs_|.
102  void FinalizeDefaultSearchPolicySettings();
103
104  // If the required entries for the proxy settings are specified and valid,
105  // finalizes the policy-specified configuration by initializing the
106  // respective values in |prefs_|.
107  void FinalizeProxyPolicySettings();
108
109  // Returns true if the policy values stored in proxy_* represent a valid proxy
110  // configuration, including the case in which there is no configuration at
111  // all.
112  bool CheckProxySettings();
113
114  // Assumes CheckProxySettings returns true and applies the values stored
115  // in proxy_*.
116  void ApplyProxySettings();
117
118  bool HasProxyPolicy(ConfigurationPolicyType policy) const;
119
120  // Temporary cache that stores values until FinalizeProxyPolicySettings()
121  // is called.
122  std::map<ConfigurationPolicyType, Value*> proxy_policies_;
123
124  // Set to false until the first proxy-relevant policy is applied. At that
125  // time, default values are provided for all proxy-relevant prefs
126  // to override any values set from stores with a lower priority.
127  bool lower_priority_proxy_settings_overridden_;
128
129  // The following are used to track what proxy-relevant policy has been applied
130  // accross calls to Apply to provide a warning if a policy specifies a
131  // contradictory proxy configuration. |proxy_disabled_| is set to true if and
132  // only if the kPolicyNoProxyServer has been applied,
133  // |proxy_configuration_specified_| is set to true if and only if any other
134  // proxy policy other than kPolicyNoProxyServer has been applied.
135  bool proxy_disabled_;
136  bool proxy_configuration_specified_;
137
138  // Set to true if a the proxy mode policy has been set to force Chrome
139  // to use the system proxy.
140  bool use_system_proxy_;
141
142  PrefValueMap prefs_;
143
144  static const PolicyToPreferenceMapEntry kSimplePolicyMap[];
145  static const PolicyToPreferenceMapEntry kProxyPolicyMap[];
146  static const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[];
147
148  DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyPrefKeeper);
149};
150
151const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
152    ConfigurationPolicyPrefKeeper::kSimplePolicyMap[] = {
153  { Value::TYPE_STRING, kPolicyHomepageLocation,  prefs::kHomePage },
154  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
155    prefs::kHomePageIsNewTabPage },
156  { Value::TYPE_INTEGER, kPolicyRestoreOnStartup,
157    prefs::kRestoreOnStartup},
158  { Value::TYPE_LIST, kPolicyRestoreOnStartupURLs,
159    prefs::kURLsToRestoreOnStartup },
160  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
161    prefs::kAlternateErrorPagesEnabled },
162  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
163    prefs::kSearchSuggestEnabled },
164  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
165    prefs::kDnsPrefetchingEnabled },
166  { Value::TYPE_BOOLEAN, kPolicyDisableSpdy,
167    prefs::kDisableSpdy },
168  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
169    prefs::kSafeBrowsingEnabled },
170  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
171    prefs::kPasswordManagerEnabled },
172  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerAllowShowPasswords,
173    prefs::kPasswordManagerAllowShowPasswords },
174  { Value::TYPE_BOOLEAN, kPolicyPrintingEnabled,
175    prefs::kPrintingEnabled },
176  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
177    prefs::kMetricsReportingEnabled },
178  { Value::TYPE_STRING, kPolicyApplicationLocaleValue,
179    prefs::kApplicationLocale},
180  { Value::TYPE_LIST, kPolicyExtensionInstallWhitelist,
181    prefs::kExtensionInstallAllowList},
182  { Value::TYPE_LIST, kPolicyExtensionInstallBlacklist,
183    prefs::kExtensionInstallDenyList},
184  { Value::TYPE_LIST, kPolicyExtensionInstallForcelist,
185    prefs::kExtensionInstallForceList},
186  { Value::TYPE_LIST, kPolicyDisabledPlugins,
187    prefs::kPluginsPluginsBlacklist},
188  { Value::TYPE_BOOLEAN, kPolicyShowHomeButton,
189    prefs::kShowHomeButton },
190  { Value::TYPE_BOOLEAN, kPolicyJavascriptEnabled,
191    prefs::kWebKitJavascriptEnabled },
192  { Value::TYPE_BOOLEAN, kPolicyIncognitoEnabled,
193    prefs::kIncognitoEnabled },
194  { Value::TYPE_BOOLEAN, kPolicySavingBrowserHistoryDisabled,
195    prefs::kSavingBrowserHistoryDisabled },
196  { Value::TYPE_BOOLEAN, kPolicyDeveloperToolsDisabled,
197    prefs::kDevToolsDisabled },
198  { Value::TYPE_BOOLEAN, kPolicyBlockThirdPartyCookies,
199    prefs::kBlockThirdPartyCookies },
200  { Value::TYPE_INTEGER, kPolicyDefaultCookiesSetting,
201    prefs::kManagedDefaultCookiesSetting },
202  { Value::TYPE_INTEGER, kPolicyDefaultImagesSetting,
203    prefs::kManagedDefaultImagesSetting },
204  { Value::TYPE_INTEGER, kPolicyDefaultJavaScriptSetting,
205    prefs::kManagedDefaultJavaScriptSetting },
206  { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting,
207    prefs::kManagedDefaultPluginsSetting },
208  { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting,
209    prefs::kManagedDefaultPopupsSetting },
210  { Value::TYPE_INTEGER, kPolicyDefaultNotificationSetting,
211    prefs::kDesktopNotificationDefaultContentSetting },
212  { Value::TYPE_INTEGER, kPolicyDefaultGeolocationSetting,
213    prefs::kGeolocationDefaultContentSetting },
214  { Value::TYPE_STRING, kPolicyAuthSchemes,
215    prefs::kAuthSchemes },
216  { Value::TYPE_BOOLEAN, kPolicyDisableAuthNegotiateCnameLookup,
217    prefs::kDisableAuthNegotiateCnameLookup },
218  { Value::TYPE_BOOLEAN, kPolicyEnableAuthNegotiatePort,
219    prefs::kEnableAuthNegotiatePort },
220  { Value::TYPE_STRING, kPolicyAuthServerWhitelist,
221    prefs::kAuthServerWhitelist },
222  { Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist,
223    prefs::kAuthNegotiateDelegateWhitelist },
224  { Value::TYPE_STRING, kPolicyGSSAPILibraryName,
225    prefs::kGSSAPILibraryName },
226  { Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
227    prefs::kDisable3DAPIs },
228  { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
229    prefs::kPolicyRefreshRate },
230  { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
231  { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
232    prefs::kDefaultBrowserSettingEnabled },
233  { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled,
234    prefs::kCloudPrintProxyEnabled },
235
236#if defined(OS_CHROMEOS)
237  { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
238    prefs::kEnableScreenLock },
239#endif
240};
241
242const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
243    ConfigurationPolicyPrefKeeper::kDefaultSearchPolicyMap[] = {
244  { Value::TYPE_BOOLEAN, kPolicyDefaultSearchProviderEnabled,
245    prefs::kDefaultSearchProviderEnabled },
246  { Value::TYPE_STRING, kPolicyDefaultSearchProviderName,
247    prefs::kDefaultSearchProviderName },
248  { Value::TYPE_STRING, kPolicyDefaultSearchProviderKeyword,
249    prefs::kDefaultSearchProviderKeyword },
250  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSearchURL,
251    prefs::kDefaultSearchProviderSearchURL },
252  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSuggestURL,
253    prefs::kDefaultSearchProviderSuggestURL },
254  { Value::TYPE_STRING, kPolicyDefaultSearchProviderIconURL,
255    prefs::kDefaultSearchProviderIconURL },
256  { Value::TYPE_STRING, kPolicyDefaultSearchProviderEncodings,
257    prefs::kDefaultSearchProviderEncodings },
258};
259
260ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper(
261    ConfigurationPolicyProvider* provider)
262  : lower_priority_proxy_settings_overridden_(false),
263    proxy_disabled_(false),
264    proxy_configuration_specified_(false),
265    use_system_proxy_(false) {
266  if (!provider->Provide(this))
267    LOG(WARNING) << "Failed to get policy from provider.";
268  FinalizeProxyPolicySettings();
269  FinalizeDefaultSearchPolicySettings();
270}
271
272ConfigurationPolicyPrefKeeper::~ConfigurationPolicyPrefKeeper() {
273  DCHECK(proxy_policies_.empty());
274}
275
276PrefStore::ReadResult
277ConfigurationPolicyPrefKeeper::GetValue(const std::string& key,
278                                        Value** result) const {
279  Value* stored_value = NULL;
280  if (!prefs_.GetValue(key, &stored_value))
281    return PrefStore::READ_NO_VALUE;
282
283  // Check whether there's a default value, which indicates READ_USE_DEFAULT
284  // should be returned.
285  if (stored_value->IsType(Value::TYPE_NULL))
286    return PrefStore::READ_USE_DEFAULT;
287
288  *result = stored_value;
289  return PrefStore::READ_OK;
290}
291
292void ConfigurationPolicyPrefKeeper::GetDifferingPrefPaths(
293    const ConfigurationPolicyPrefKeeper* other,
294    std::vector<std::string>* differing_prefs) const {
295  prefs_.GetDifferingKeys(&other->prefs_, differing_prefs);
296}
297
298void ConfigurationPolicyPrefKeeper::Apply(ConfigurationPolicyType policy,
299                                          Value* value) {
300  if (ApplyProxyPolicy(policy, value))
301    return;
302
303  if (ApplySyncPolicy(policy, value))
304    return;
305
306  if (ApplyAutoFillPolicy(policy, value))
307    return;
308
309  if (ApplyPolicyFromMap(policy, value, kDefaultSearchPolicyMap,
310                         arraysize(kDefaultSearchPolicyMap)))
311    return;
312
313  if (ApplyPolicyFromMap(policy, value, kSimplePolicyMap,
314                         arraysize(kSimplePolicyMap)))
315    return;
316
317  // Other policy implementations go here.
318  NOTIMPLEMENTED();
319  delete value;
320}
321
322const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry*
323ConfigurationPolicyPrefKeeper::FindPolicyInMap(
324    ConfigurationPolicyType policy,
325    const PolicyToPreferenceMapEntry* map,
326    int table_size) const {
327  for (int i = 0; i < table_size; ++i) {
328    if (map[i].policy_type == policy)
329      return map + i;
330  }
331  return NULL;
332}
333
334bool ConfigurationPolicyPrefKeeper::RemovePreferencesOfMap(
335    const PolicyToPreferenceMapEntry* map, int table_size) {
336  bool found_any = false;
337  for (int i = 0; i < table_size; ++i) {
338    if (prefs_.RemoveValue(map[i].preference_path))
339      found_any = true;
340  }
341  return found_any;
342}
343
344bool ConfigurationPolicyPrefKeeper::ApplyPolicyFromMap(
345    ConfigurationPolicyType policy,
346    Value* value,
347    const PolicyToPreferenceMapEntry* map,
348    int size) {
349  for (int current = 0; current < size; ++current) {
350    if (map[current].policy_type == policy) {
351      DCHECK_EQ(map[current].value_type, value->GetType())
352          << "mismatch in provided and expected policy value for preferences"
353          << map[current].preference_path << ". expected = "
354          << map[current].value_type << ", actual = "<< value->GetType();
355      prefs_.SetValue(map[current].preference_path, value);
356      return true;
357    }
358  }
359  return false;
360}
361
362bool ConfigurationPolicyPrefKeeper::ApplyProxyPolicy(
363    ConfigurationPolicyType policy,
364    Value* value) {
365  // We only collect the values until we have sufficient information when
366  // FinalizeProxyPolicySettings() is called to determine whether the presented
367  // values were correct and apply them in that case.
368  if (policy == kPolicyProxyMode ||
369      policy == kPolicyProxyServerMode ||
370      policy == kPolicyProxyServer ||
371      policy == kPolicyProxyPacUrl ||
372      policy == kPolicyProxyBypassList) {
373    delete proxy_policies_[policy];
374    proxy_policies_[policy] = value;
375    return true;
376  }
377  // We are not interested in this policy.
378  return false;
379}
380
381bool ConfigurationPolicyPrefKeeper::ApplySyncPolicy(
382    ConfigurationPolicyType policy, Value* value) {
383  if (policy == kPolicySyncDisabled) {
384    bool disable_sync;
385    if (value->GetAsBoolean(&disable_sync) && disable_sync)
386      prefs_.SetValue(prefs::kSyncManaged, value);
387    else
388      delete value;
389    return true;
390  }
391  return false;
392}
393
394bool ConfigurationPolicyPrefKeeper::ApplyAutoFillPolicy(
395    ConfigurationPolicyType policy, Value* value) {
396  if (policy == kPolicyAutoFillEnabled) {
397    bool auto_fill_enabled;
398    if (value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled)
399      prefs_.SetValue(prefs::kAutoFillEnabled,
400                       Value::CreateBooleanValue(false));
401    delete value;
402    return true;
403  }
404  return false;
405}
406
407void ConfigurationPolicyPrefKeeper::EnsureStringPrefExists(
408    const std::string& path) {
409  std::string value;
410  if (!prefs_.GetString(path, &value))
411    prefs_.SetString(path, value);
412}
413
414namespace {
415
416// Implementation of SearchTermsData just for validation.
417class SearchTermsDataForValidation : public SearchTermsData {
418 public:
419  SearchTermsDataForValidation() {}
420
421  // Implementation of SearchTermsData.
422  virtual std::string GoogleBaseURLValue() const {
423    return "http://www.google.com/";
424  }
425  virtual std::string GetApplicationLocale() const {
426    return "en";
427  }
428#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
429  virtual string16 GetRlzParameterValue() const {
430    return string16();
431  }
432#endif
433 private:
434  DISALLOW_COPY_AND_ASSIGN(SearchTermsDataForValidation);
435};
436
437}  // namespace
438
439void ConfigurationPolicyPrefKeeper::FinalizeDefaultSearchPolicySettings() {
440  bool enabled = true;
441  if (prefs_.GetBoolean(prefs::kDefaultSearchProviderEnabled, &enabled) &&
442      !enabled) {
443    // If default search is disabled, we ignore the other fields.
444    prefs_.SetString(prefs::kDefaultSearchProviderName, std::string());
445    prefs_.SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
446    prefs_.SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
447    prefs_.SetString(prefs::kDefaultSearchProviderIconURL, std::string());
448    prefs_.SetString(prefs::kDefaultSearchProviderEncodings, std::string());
449    prefs_.SetString(prefs::kDefaultSearchProviderKeyword, std::string());
450    prefs_.SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
451    return;
452  }
453  std::string search_url;
454  // The search URL is required.
455  if (prefs_.GetString(prefs::kDefaultSearchProviderSearchURL, &search_url) &&
456      !search_url.empty()) {
457    SearchTermsDataForValidation search_terms_data;
458    const TemplateURLRef search_url_ref(search_url, 0, 0);
459    // It must support replacement (which implies it is valid).
460    if (search_url_ref.SupportsReplacementUsingTermsData(search_terms_data)) {
461      // The other entries are optional.  Just make sure that they are all
462      // specified via policy, so that we don't use regular prefs.
463      EnsureStringPrefExists(prefs::kDefaultSearchProviderSuggestURL);
464      EnsureStringPrefExists(prefs::kDefaultSearchProviderIconURL);
465      EnsureStringPrefExists(prefs::kDefaultSearchProviderEncodings);
466      EnsureStringPrefExists(prefs::kDefaultSearchProviderKeyword);
467      EnsureStringPrefExists(prefs::kDefaultSearchProviderInstantURL);
468
469      // For the name, default to the host if not specified.
470      std::string name;
471      if (!prefs_.GetString(prefs::kDefaultSearchProviderName, &name) ||
472          name.empty())
473        prefs_.SetString(prefs::kDefaultSearchProviderName,
474                          GURL(search_url).host());
475
476      // And clear the IDs since these are not specified via policy.
477      prefs_.SetString(prefs::kDefaultSearchProviderID, std::string());
478      prefs_.SetString(prefs::kDefaultSearchProviderPrepopulateID,
479                        std::string());
480      return;
481    }
482  }
483  // Required entries are not there.  Remove any related entries.
484  RemovePreferencesOfMap(kDefaultSearchPolicyMap,
485                         arraysize(kDefaultSearchPolicyMap));
486}
487
488void ConfigurationPolicyPrefKeeper::FinalizeProxyPolicySettings() {
489  if (CheckProxySettings())
490    ApplyProxySettings();
491
492  STLDeleteContainerPairSecondPointers(proxy_policies_.begin(),
493                                       proxy_policies_.end());
494  proxy_policies_.clear();
495}
496
497bool ConfigurationPolicyPrefKeeper::CheckProxySettings() {
498  bool mode = HasProxyPolicy(kPolicyProxyMode);
499  bool server_mode = HasProxyPolicy(kPolicyProxyServerMode);  // deprecated
500  bool server = HasProxyPolicy(kPolicyProxyServer);
501  bool pac_url = HasProxyPolicy(kPolicyProxyPacUrl);
502  bool bypass_list = HasProxyPolicy(kPolicyProxyBypassList);
503
504  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
505    LOG(WARNING) << "A centrally-administered policy defines proxy setting"
506                 << " details without setting a proxy mode.";
507    return false;
508  }
509
510  // If there's a server mode, convert it into a mode.
511  std::string mode_value;
512  if (mode) {
513    if (server_mode)
514      LOG(WARNING) << "Both ProxyMode and ProxyServerMode policies defined, "
515                   << "ignoring ProxyMode.";
516    if (!proxy_policies_[kPolicyProxyMode]->GetAsString(&mode_value)) {
517      LOG(WARNING) << "Invalid ProxyMode value.";
518      return false;
519    }
520  } else if (server_mode) {
521    int server_mode_value;
522    if (!proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(
523        &server_mode_value)) {
524      LOG(WARNING) << "Invalid ProxyServerMode value.";
525      return false;
526    }
527
528    switch (server_mode_value) {
529      case kPolicyNoProxyServerMode:
530        mode_value = ProxyPrefs::kDirectProxyModeName;
531        break;
532      case kPolicyAutoDetectProxyServerMode:
533        mode_value = ProxyPrefs::kAutoDetectProxyModeName;
534        break;
535      case kPolicyManuallyConfiguredProxyServerMode:
536        if (server && pac_url) {
537          LOG(WARNING) << "A centrally-administered policy dictates that"
538                       << " both fixed proxy servers and a .pac url. should"
539                       << " be used for proxy configuration.";
540          return false;
541        }
542        if (!server && !pac_url) {
543          LOG(WARNING) << "A centrally-administered policy dictates that the"
544                       << " proxy settings should use either fixed proxy"
545                       << " servers or a .pac url, but specifies neither.";
546          return false;
547        }
548        if (pac_url)
549          mode_value = ProxyPrefs::kPacScriptProxyModeName;
550        else
551          mode_value = ProxyPrefs::kFixedServersProxyModeName;
552        break;
553      case kPolicyUseSystemProxyServerMode:
554        mode_value = ProxyPrefs::kSystemProxyModeName;
555        break;
556      default:
557        LOG(WARNING) << "Invalid proxy mode " << server_mode_value;
558        return false;
559    }
560  }
561
562  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
563  // empty and the proxy shouldn't be configured at all.
564  if (mode_value.empty())
565    return true;
566
567  if (mode_value == ProxyPrefs::kDirectProxyModeName) {
568    if (server || pac_url || bypass_list) {
569      LOG(WARNING) << "A centrally-administered policy disables the use of"
570                   << " a proxy but also specifies an explicit proxy"
571                   << " configuration.";
572      return false;
573    }
574  } else if (mode_value == ProxyPrefs::kAutoDetectProxyModeName) {
575    if (server || bypass_list || pac_url) {
576      LOG(WARNING) << "A centrally-administered policy dictates that a proxy"
577                   << " shall be auto configured but specifies fixed proxy"
578                   << " servers, a by-pass list or a .pac script URL.";
579      return false;
580    }
581  } else if (mode_value == ProxyPrefs::kPacScriptProxyModeName) {
582    if (server || bypass_list) {
583      LOG(WARNING) << "A centrally-administered policy dictates that a .pac"
584                   << " script URL should be used for proxy configuration but"
585                   << " also specifies policies required only for fixed"
586                   << " proxy servers.";
587      return false;
588    }
589  } else if (mode_value == ProxyPrefs::kFixedServersProxyModeName) {
590    if (pac_url) {
591      LOG(WARNING) << "A centrally-administered policy dictates that"
592                   << " fixed proxy servers should be used but also"
593                   << " specifies a .pac script URL.";
594      return false;
595    }
596  } else if (mode_value == ProxyPrefs::kSystemProxyModeName) {
597    if (server || pac_url || bypass_list) {
598      LOG(WARNING) << "A centrally-administered policy dictates that the"
599                   << " system proxy settings should be used but also "
600                   << " specifies an explicit proxy configuration.";
601      return false;
602    }
603  } else {
604    LOG(WARNING) << "Invalid proxy mode " << mode_value;
605    return false;
606  }
607  return true;
608}
609
610void ConfigurationPolicyPrefKeeper::ApplyProxySettings() {
611  ProxyPrefs::ProxyMode mode;
612  if (HasProxyPolicy(kPolicyProxyMode)) {
613    std::string string_mode;
614    CHECK(proxy_policies_[kPolicyProxyMode]->GetAsString(&string_mode));
615    if (!ProxyPrefs::StringToProxyMode(string_mode, &mode)) {
616      LOG(WARNING) << "A centrally-administered policy specifies a value for"
617                   << "the ProxyMode policy that isn't recognized.";
618      return;
619    }
620  } else if (HasProxyPolicy(kPolicyProxyServerMode)) {
621    int int_mode = 0;
622    CHECK(proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(&int_mode));
623    switch (int_mode) {
624      case kPolicyNoProxyServerMode:
625        mode = ProxyPrefs::MODE_DIRECT;
626        break;
627      case kPolicyAutoDetectProxyServerMode:
628        mode = ProxyPrefs::MODE_AUTO_DETECT;
629        break;
630      case kPolicyManuallyConfiguredProxyServerMode:
631        mode = ProxyPrefs::MODE_FIXED_SERVERS;
632        if (HasProxyPolicy(kPolicyProxyPacUrl))
633          mode = ProxyPrefs::MODE_PAC_SCRIPT;
634        break;
635      case kPolicyUseSystemProxyServerMode:
636        mode = ProxyPrefs::MODE_SYSTEM;
637        break;
638      default:
639        mode = ProxyPrefs::MODE_DIRECT;
640        NOTREACHED();
641    }
642  } else {
643    return;
644  }
645  switch (mode) {
646    case ProxyPrefs::MODE_DIRECT:
647      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
648      break;
649    case ProxyPrefs::MODE_AUTO_DETECT:
650      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
651      break;
652    case ProxyPrefs::MODE_PAC_SCRIPT: {
653      std::string pac_url;
654      proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url);
655      prefs_.SetValue(prefs::kProxy,
656                      ProxyConfigDictionary::CreatePacScript(pac_url));
657      break;
658    }
659    case ProxyPrefs::MODE_FIXED_SERVERS: {
660      std::string proxy_server;
661      proxy_policies_[kPolicyProxyServer]->GetAsString(&proxy_server);
662      std::string bypass_list;
663      if (HasProxyPolicy(kPolicyProxyBypassList))
664        proxy_policies_[kPolicyProxyBypassList]->GetAsString(&bypass_list);
665      prefs_.SetValue(prefs::kProxy,
666                      ProxyConfigDictionary::CreateFixedServers(proxy_server,
667                                                                bypass_list));
668      break;
669    }
670    case ProxyPrefs::MODE_SYSTEM:
671      prefs_.SetValue(prefs::kProxy,
672                      ProxyConfigDictionary::CreateSystem());
673      break;
674    case ProxyPrefs::kModeCount:
675      NOTREACHED();
676  }
677}
678
679bool ConfigurationPolicyPrefKeeper::HasProxyPolicy(
680    ConfigurationPolicyType policy) const {
681  std::map<ConfigurationPolicyType, Value*>::const_iterator iter;
682  iter = proxy_policies_.find(policy);
683  return iter != proxy_policies_.end() &&
684         iter->second && !iter->second->IsType(Value::TYPE_NULL);
685}
686
687ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
688    ConfigurationPolicyProvider* provider)
689    : provider_(provider),
690      initialization_complete_(false) {
691  if (provider_) {
692    // Read initial policy.
693    policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider));
694    registrar_.Init(provider_, this);
695    initialization_complete_ = provider->IsInitializationComplete();
696  } else {
697    initialization_complete_ = true;
698  }
699}
700
701ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() {
702}
703
704void ConfigurationPolicyPrefStore::AddObserver(PrefStore::Observer* observer) {
705  observers_.AddObserver(observer);
706}
707
708void ConfigurationPolicyPrefStore::RemoveObserver(
709    PrefStore::Observer* observer) {
710  observers_.RemoveObserver(observer);
711}
712
713bool ConfigurationPolicyPrefStore::IsInitializationComplete() const {
714  return initialization_complete_;
715}
716
717PrefStore::ReadResult
718ConfigurationPolicyPrefStore::GetValue(const std::string& key,
719                                       Value** value) const {
720  if (policy_keeper_.get())
721    return policy_keeper_->GetValue(key, value);
722
723  return PrefStore::READ_NO_VALUE;
724}
725
726void ConfigurationPolicyPrefStore::OnUpdatePolicy() {
727  Refresh();
728}
729
730void ConfigurationPolicyPrefStore::OnProviderGoingAway() {
731  provider_ = NULL;
732}
733
734// static
735ConfigurationPolicyPrefStore*
736ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() {
737  ConfigurationPolicyProviderKeeper* keeper =
738      g_browser_process->configuration_policy_provider_keeper();
739  return new ConfigurationPolicyPrefStore(keeper->managed_platform_provider());
740}
741
742// static
743ConfigurationPolicyPrefStore*
744ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(
745    Profile* profile) {
746  if (profile) {
747    return new ConfigurationPolicyPrefStore(
748        profile->GetPolicyContext()->GetDeviceManagementPolicyProvider());
749  }
750  return new ConfigurationPolicyPrefStore(NULL);
751}
752
753// static
754ConfigurationPolicyPrefStore*
755ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() {
756  ConfigurationPolicyProviderKeeper* keeper =
757      g_browser_process->configuration_policy_provider_keeper();
758  return new ConfigurationPolicyPrefStore(keeper->recommended_provider());
759}
760
761// static
762ConfigurationPolicyPrefStore*
763ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
764    Profile* profile) {
765  return new ConfigurationPolicyPrefStore(NULL);
766}
767
768/* static */
769const ConfigurationPolicyProvider::PolicyDefinitionList*
770ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() {
771  static ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[] = {
772    { kPolicyHomepageLocation, Value::TYPE_STRING, key::kHomepageLocation },
773    { kPolicyHomepageIsNewTabPage, Value::TYPE_BOOLEAN,
774      key::kHomepageIsNewTabPage },
775    { kPolicyRestoreOnStartup, Value::TYPE_INTEGER, key::kRestoreOnStartup },
776    { kPolicyRestoreOnStartupURLs, Value::TYPE_LIST,
777      key::kRestoreOnStartupURLs },
778    { kPolicyDefaultSearchProviderEnabled, Value::TYPE_BOOLEAN,
779      key::kDefaultSearchProviderEnabled },
780    { kPolicyDefaultSearchProviderName, Value::TYPE_STRING,
781      key::kDefaultSearchProviderName },
782    { kPolicyDefaultSearchProviderKeyword, Value::TYPE_STRING,
783      key::kDefaultSearchProviderKeyword },
784    { kPolicyDefaultSearchProviderSearchURL, Value::TYPE_STRING,
785      key::kDefaultSearchProviderSearchURL },
786    { kPolicyDefaultSearchProviderSuggestURL, Value::TYPE_STRING,
787      key::kDefaultSearchProviderSuggestURL },
788    { kPolicyDefaultSearchProviderInstantURL, Value::TYPE_STRING,
789      key::kDefaultSearchProviderInstantURL },
790    { kPolicyDefaultSearchProviderIconURL, Value::TYPE_STRING,
791      key::kDefaultSearchProviderIconURL },
792    { kPolicyDefaultSearchProviderEncodings, Value::TYPE_STRING,
793      key::kDefaultSearchProviderEncodings },
794    { kPolicyProxyMode, Value::TYPE_STRING, key::kProxyMode },
795    { kPolicyProxyServerMode, Value::TYPE_INTEGER, key::kProxyServerMode },
796    { kPolicyProxyServer, Value::TYPE_STRING, key::kProxyServer },
797    { kPolicyProxyPacUrl, Value::TYPE_STRING, key::kProxyPacUrl },
798    { kPolicyProxyBypassList, Value::TYPE_STRING, key::kProxyBypassList },
799    { kPolicyAlternateErrorPagesEnabled, Value::TYPE_BOOLEAN,
800      key::kAlternateErrorPagesEnabled },
801    { kPolicySearchSuggestEnabled, Value::TYPE_BOOLEAN,
802      key::kSearchSuggestEnabled },
803    { kPolicyDnsPrefetchingEnabled, Value::TYPE_BOOLEAN,
804      key::kDnsPrefetchingEnabled },
805    { kPolicyDisableSpdy, Value::TYPE_BOOLEAN, key::kDisableSpdy },
806    { kPolicySafeBrowsingEnabled, Value::TYPE_BOOLEAN,
807      key::kSafeBrowsingEnabled },
808    { kPolicyMetricsReportingEnabled, Value::TYPE_BOOLEAN,
809      key::kMetricsReportingEnabled },
810    { kPolicyPasswordManagerEnabled, Value::TYPE_BOOLEAN,
811      key::kPasswordManagerEnabled },
812    { kPolicyPasswordManagerAllowShowPasswords, Value::TYPE_BOOLEAN,
813      key::kPasswordManagerAllowShowPasswords },
814    { kPolicyAutoFillEnabled, Value::TYPE_BOOLEAN, key::kAutoFillEnabled },
815    { kPolicyDisabledPlugins, Value::TYPE_LIST, key::kDisabledPlugins },
816    { kPolicyApplicationLocaleValue, Value::TYPE_STRING,
817      key::kApplicationLocaleValue },
818    { kPolicySyncDisabled, Value::TYPE_BOOLEAN, key::kSyncDisabled },
819    { kPolicyExtensionInstallWhitelist, Value::TYPE_LIST,
820      key::kExtensionInstallWhitelist },
821    { kPolicyExtensionInstallBlacklist, Value::TYPE_LIST,
822      key::kExtensionInstallBlacklist },
823    { kPolicyExtensionInstallForcelist, Value::TYPE_LIST,
824      key::kExtensionInstallForcelist },
825    { kPolicyShowHomeButton, Value::TYPE_BOOLEAN, key::kShowHomeButton },
826    { kPolicyPrintingEnabled, Value::TYPE_BOOLEAN, key::kPrintingEnabled },
827    { kPolicyJavascriptEnabled, Value::TYPE_BOOLEAN, key::kJavascriptEnabled },
828    { kPolicyIncognitoEnabled, Value::TYPE_BOOLEAN, key::kIncognitoEnabled },
829    { kPolicySavingBrowserHistoryDisabled, Value::TYPE_BOOLEAN,
830      key::kSavingBrowserHistoryDisabled },
831    { kPolicyDeveloperToolsDisabled, Value::TYPE_BOOLEAN,
832      key::kDeveloperToolsDisabled },
833    { kPolicyBlockThirdPartyCookies, Value::TYPE_BOOLEAN,
834      key::kBlockThirdPartyCookies },
835    { kPolicyDefaultCookiesSetting, Value::TYPE_INTEGER,
836      key::kDefaultCookiesSetting },
837    { kPolicyDefaultImagesSetting, Value::TYPE_INTEGER,
838      key::kDefaultImagesSetting },
839    { kPolicyDefaultJavaScriptSetting, Value::TYPE_INTEGER,
840      key::kDefaultJavaScriptSetting },
841    { kPolicyDefaultPluginsSetting, Value::TYPE_INTEGER,
842      key::kDefaultPluginsSetting },
843    { kPolicyDefaultPopupsSetting, Value::TYPE_INTEGER,
844      key::kDefaultPopupsSetting },
845    { kPolicyDefaultNotificationSetting, Value::TYPE_INTEGER,
846      key::kDefaultNotificationSetting },
847    { kPolicyDefaultGeolocationSetting, Value::TYPE_INTEGER,
848      key::kDefaultGeolocationSetting },
849    { kPolicyAuthSchemes, Value::TYPE_STRING, key::kAuthSchemes },
850    { kPolicyDisableAuthNegotiateCnameLookup, Value::TYPE_BOOLEAN,
851      key::kDisableAuthNegotiateCnameLookup },
852    { kPolicyEnableAuthNegotiatePort, Value::TYPE_BOOLEAN,
853      key::kEnableAuthNegotiatePort },
854    { kPolicyAuthServerWhitelist, Value::TYPE_STRING,
855      key::kAuthServerWhitelist },
856    { kPolicyAuthNegotiateDelegateWhitelist, Value::TYPE_STRING,
857      key::kAuthNegotiateDelegateWhitelist },
858    { kPolicyGSSAPILibraryName, Value::TYPE_STRING,
859      key::kGSSAPILibraryName },
860    { kPolicyDisable3DAPIs, Value::TYPE_BOOLEAN,
861      key::kDisable3DAPIs },
862    { kPolicyPolicyRefreshRate, Value::TYPE_INTEGER,
863      key::kPolicyRefreshRate },
864    { kPolicyInstantEnabled, Value::TYPE_BOOLEAN, key::kInstantEnabled },
865    { kPolicyDefaultBrowserSettingEnabled, Value::TYPE_BOOLEAN,
866      key::kDefaultBrowserSettingEnabled },
867    { kPolicyCloudPrintProxyEnabled, Value::TYPE_BOOLEAN,
868      key::kCloudPrintProxyEnabled },
869
870#if defined(OS_CHROMEOS)
871    { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN,
872      key::kChromeOsLockOnIdleSuspend },
873#endif
874  };
875
876  static ConfigurationPolicyProvider::PolicyDefinitionList policy_list = {
877    entries,
878    entries + arraysize(entries),
879  };
880  return &policy_list;
881}
882
883void ConfigurationPolicyPrefStore::Refresh() {
884  if (!provider_)
885    return;
886
887  // Construct a new keeper, determine what changed and swap the keeper in.
888  scoped_ptr<ConfigurationPolicyPrefKeeper> new_keeper(
889      new ConfigurationPolicyPrefKeeper(provider_));
890  std::vector<std::string> changed_prefs;
891  new_keeper->GetDifferingPrefPaths(policy_keeper_.get(), &changed_prefs);
892  policy_keeper_.reset(new_keeper.release());
893
894  // Send out change notifications.
895  for (std::vector<std::string>::const_iterator pref(changed_prefs.begin());
896       pref != changed_prefs.end();
897       ++pref) {
898    FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
899                      OnPrefValueChanged(*pref));
900  }
901
902  // Update the initialization flag.
903  if (!initialization_complete_ &&
904      provider_->IsInitializationComplete()) {
905    initialization_complete_ = true;
906    FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
907                      OnInitializationCompleted());
908  }
909}
910
911}  // namespace policy
912