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/browser_policy_connector.h"
22#include "chrome/browser/policy/configuration_policy_provider.h"
23#include "chrome/browser/policy/policy_path_parser.h"
24#include "chrome/browser/policy/profile_policy_connector.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/pref_names.h"
31#include "content/common/notification_service.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,
46                                 const Value** result) const;
47
48  // Compute the set of preference names that are different in |keeper|. This
49  // includes preferences that are missing in either one.
50  void GetDifferingPrefPaths(const ConfigurationPolicyPrefKeeper* other,
51                             std::vector<std::string>* differing_prefs) const;
52
53 private:
54  // ConfigurationPolicyStore methods:
55  virtual void Apply(ConfigurationPolicyType setting, Value* value);
56
57  // Policies that map to a single preference are handled
58  // by an automated converter. Each one of these policies
59  // has an entry in |simple_policy_map_| with the following type.
60  struct PolicyToPreferenceMapEntry {
61    Value::ValueType value_type;
62    ConfigurationPolicyType policy_type;
63    const char* preference_path;  // A DictionaryValue path, not a file path.
64  };
65
66  // Remove the preferences found in the map from |prefs_|. Returns true if any
67  // such preferences were found and removed.
68  bool RemovePreferencesOfMap(const PolicyToPreferenceMapEntry* map,
69                              int table_size);
70
71  bool ApplyPolicyFromMap(ConfigurationPolicyType policy,
72                          Value* value,
73                          const PolicyToPreferenceMapEntry* map,
74                          int size);
75
76  // Processes proxy-specific policies. Returns true if the specified policy
77  // is a proxy-related policy. ApplyProxyPolicy assumes the ownership
78  // of |value| in the case that the policy is proxy-specific.
79  bool ApplyProxyPolicy(ConfigurationPolicyType policy, Value* value);
80
81  // Handles sync-related policies. Returns true if the policy was handled.
82  // Assumes ownership of |value| in that case.
83  bool ApplySyncPolicy(ConfigurationPolicyType policy, Value* value);
84
85  // Handles policies that affect Autofill. Returns true if the policy was
86  // handled and assumes ownership of |value| in that case.
87  bool ApplyAutofillPolicy(ConfigurationPolicyType policy, Value* value);
88
89  // Processes download directory policy. Returns true if the specified policy
90  // is the download directory policy. ApplyDownloadDirPolicy assumes the
91  // ownership of |value| in the case that the policy is recognized.
92  bool ApplyDownloadDirPolicy(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  PrefValueMap prefs_;
125
126  static const PolicyToPreferenceMapEntry kSimplePolicyMap[];
127  static const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[];
128
129  DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyPrefKeeper);
130};
131
132const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
133    ConfigurationPolicyPrefKeeper::kSimplePolicyMap[] = {
134  { Value::TYPE_STRING, kPolicyHomepageLocation,  prefs::kHomePage },
135  { Value::TYPE_BOOLEAN, kPolicyHomepageIsNewTabPage,
136    prefs::kHomePageIsNewTabPage },
137  { Value::TYPE_INTEGER, kPolicyRestoreOnStartup,
138    prefs::kRestoreOnStartup},
139  { Value::TYPE_LIST, kPolicyRestoreOnStartupURLs,
140    prefs::kURLsToRestoreOnStartup },
141  { Value::TYPE_BOOLEAN, kPolicyAlternateErrorPagesEnabled,
142    prefs::kAlternateErrorPagesEnabled },
143  { Value::TYPE_BOOLEAN, kPolicySearchSuggestEnabled,
144    prefs::kSearchSuggestEnabled },
145  { Value::TYPE_BOOLEAN, kPolicyDnsPrefetchingEnabled,
146    prefs::kNetworkPredictionEnabled },
147  { Value::TYPE_BOOLEAN, kPolicyDisableSpdy,
148    prefs::kDisableSpdy },
149  { Value::TYPE_LIST, kPolicyDisabledSchemes,
150    prefs::kDisabledSchemes },
151  { Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
152    prefs::kSafeBrowsingEnabled },
153  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
154    prefs::kPasswordManagerEnabled },
155  { Value::TYPE_BOOLEAN, kPolicyPasswordManagerAllowShowPasswords,
156    prefs::kPasswordManagerAllowShowPasswords },
157  { Value::TYPE_BOOLEAN, kPolicyPrintingEnabled,
158    prefs::kPrintingEnabled },
159  { Value::TYPE_BOOLEAN, kPolicyMetricsReportingEnabled,
160    prefs::kMetricsReportingEnabled },
161  { Value::TYPE_STRING, kPolicyApplicationLocaleValue,
162    prefs::kApplicationLocale},
163  { Value::TYPE_LIST, kPolicyExtensionInstallWhitelist,
164    prefs::kExtensionInstallAllowList},
165  { Value::TYPE_LIST, kPolicyExtensionInstallBlacklist,
166    prefs::kExtensionInstallDenyList},
167  { Value::TYPE_LIST, kPolicyExtensionInstallForcelist,
168    prefs::kExtensionInstallForceList},
169  { Value::TYPE_LIST, kPolicyDisabledPlugins,
170    prefs::kPluginsDisabledPlugins},
171  { Value::TYPE_LIST, kPolicyDisabledPluginsExceptions,
172    prefs::kPluginsDisabledPluginsExceptions},
173  { Value::TYPE_LIST, kPolicyEnabledPlugins,
174    prefs::kPluginsEnabledPlugins},
175  { Value::TYPE_BOOLEAN, kPolicyShowHomeButton,
176    prefs::kShowHomeButton },
177  { Value::TYPE_BOOLEAN, kPolicyJavascriptEnabled,
178    prefs::kWebKitJavascriptEnabled },
179  { Value::TYPE_BOOLEAN, kPolicyIncognitoEnabled,
180    prefs::kIncognitoEnabled },
181  { Value::TYPE_BOOLEAN, kPolicySavingBrowserHistoryDisabled,
182    prefs::kSavingBrowserHistoryDisabled },
183  { Value::TYPE_BOOLEAN, kPolicyClearSiteDataOnExit,
184    prefs::kClearSiteDataOnExit },
185  { Value::TYPE_BOOLEAN, kPolicyDeveloperToolsDisabled,
186    prefs::kDevToolsDisabled },
187  { Value::TYPE_BOOLEAN, kPolicyBlockThirdPartyCookies,
188    prefs::kBlockThirdPartyCookies },
189  { Value::TYPE_INTEGER, kPolicyDefaultCookiesSetting,
190    prefs::kManagedDefaultCookiesSetting },
191  { Value::TYPE_INTEGER, kPolicyDefaultImagesSetting,
192    prefs::kManagedDefaultImagesSetting },
193  { Value::TYPE_INTEGER, kPolicyDefaultJavaScriptSetting,
194    prefs::kManagedDefaultJavaScriptSetting },
195  { Value::TYPE_INTEGER, kPolicyDefaultPluginsSetting,
196    prefs::kManagedDefaultPluginsSetting },
197  { Value::TYPE_INTEGER, kPolicyDefaultPopupsSetting,
198    prefs::kManagedDefaultPopupsSetting },
199  { Value::TYPE_LIST, kPolicyCookiesAllowedForUrls,
200    prefs::kManagedCookiesAllowedForUrls },
201  { Value::TYPE_LIST, kPolicyCookiesBlockedForUrls,
202    prefs::kManagedCookiesBlockedForUrls },
203  { Value::TYPE_LIST, kPolicyCookiesSessionOnlyForUrls,
204    prefs::kManagedCookiesSessionOnlyForUrls },
205  { Value::TYPE_LIST, kPolicyImagesAllowedForUrls,
206    prefs::kManagedImagesAllowedForUrls },
207  { Value::TYPE_LIST, kPolicyImagesBlockedForUrls,
208    prefs::kManagedImagesBlockedForUrls },
209  { Value::TYPE_LIST, kPolicyJavaScriptAllowedForUrls,
210    prefs::kManagedJavaScriptAllowedForUrls },
211  { Value::TYPE_LIST, kPolicyJavaScriptBlockedForUrls,
212    prefs::kManagedJavaScriptBlockedForUrls },
213  { Value::TYPE_LIST, kPolicyPluginsAllowedForUrls,
214    prefs::kManagedPluginsAllowedForUrls },
215  { Value::TYPE_LIST, kPolicyPluginsBlockedForUrls,
216    prefs::kManagedPluginsBlockedForUrls },
217  { Value::TYPE_LIST, kPolicyPopupsAllowedForUrls,
218    prefs::kManagedPopupsAllowedForUrls },
219  { Value::TYPE_LIST, kPolicyPopupsBlockedForUrls,
220    prefs::kManagedPopupsBlockedForUrls },
221  { Value::TYPE_INTEGER, kPolicyDefaultNotificationSetting,
222    prefs::kDesktopNotificationDefaultContentSetting },
223  { Value::TYPE_INTEGER, kPolicyDefaultGeolocationSetting,
224    prefs::kGeolocationDefaultContentSetting },
225  { Value::TYPE_STRING, kPolicyAuthSchemes,
226    prefs::kAuthSchemes },
227  { Value::TYPE_BOOLEAN, kPolicyDisableAuthNegotiateCnameLookup,
228    prefs::kDisableAuthNegotiateCnameLookup },
229  { Value::TYPE_BOOLEAN, kPolicyEnableAuthNegotiatePort,
230    prefs::kEnableAuthNegotiatePort },
231  { Value::TYPE_STRING, kPolicyAuthServerWhitelist,
232    prefs::kAuthServerWhitelist },
233  { Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist,
234    prefs::kAuthNegotiateDelegateWhitelist },
235  { Value::TYPE_STRING, kPolicyGSSAPILibraryName,
236    prefs::kGSSAPILibraryName },
237  { Value::TYPE_BOOLEAN, kPolicyDisable3DAPIs,
238    prefs::kDisable3DAPIs },
239  { Value::TYPE_BOOLEAN, kPolicyDisablePluginFinder,
240    prefs::kDisablePluginFinder },
241  { Value::TYPE_INTEGER, kPolicyPolicyRefreshRate,
242    prefs::kPolicyRefreshRate },
243  { Value::TYPE_BOOLEAN, kPolicyInstantEnabled, prefs::kInstantEnabled },
244  { Value::TYPE_BOOLEAN, kPolicyDefaultBrowserSettingEnabled,
245    prefs::kDefaultBrowserSettingEnabled },
246  { Value::TYPE_BOOLEAN, kPolicyCloudPrintProxyEnabled,
247    prefs::kCloudPrintProxyEnabled },
248  { Value::TYPE_BOOLEAN, kPolicyTranslateEnabled, prefs::kEnableTranslate },
249  { Value::TYPE_BOOLEAN, kPolicyBookmarkBarEnabled, prefs::kEnableBookmarkBar },
250  { Value::TYPE_BOOLEAN, kPolicyAllowOutdatedPlugins,
251    prefs::kPluginsAllowOutdated },
252  { Value::TYPE_BOOLEAN, kPolicyEditBookmarksEnabled,
253    prefs::kEditBookmarksEnabled },
254  { Value::TYPE_BOOLEAN, kPolicyAllowFileSelectionDialogs,
255    prefs::kAllowFileSelectionDialogs },
256
257#if defined(OS_CHROMEOS)
258  { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
259    prefs::kEnableScreenLock },
260#endif
261};
262
263const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
264    ConfigurationPolicyPrefKeeper::kDefaultSearchPolicyMap[] = {
265  { Value::TYPE_BOOLEAN, kPolicyDefaultSearchProviderEnabled,
266    prefs::kDefaultSearchProviderEnabled },
267  { Value::TYPE_STRING, kPolicyDefaultSearchProviderName,
268    prefs::kDefaultSearchProviderName },
269  { Value::TYPE_STRING, kPolicyDefaultSearchProviderKeyword,
270    prefs::kDefaultSearchProviderKeyword },
271  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSearchURL,
272    prefs::kDefaultSearchProviderSearchURL },
273  { Value::TYPE_STRING, kPolicyDefaultSearchProviderSuggestURL,
274    prefs::kDefaultSearchProviderSuggestURL },
275  { Value::TYPE_STRING, kPolicyDefaultSearchProviderIconURL,
276    prefs::kDefaultSearchProviderIconURL },
277  { Value::TYPE_STRING, kPolicyDefaultSearchProviderEncodings,
278    prefs::kDefaultSearchProviderEncodings },
279};
280
281ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper(
282    ConfigurationPolicyProvider* provider) {
283  if (!provider->Provide(this))
284    LOG(WARNING) << "Failed to get policy from provider.";
285  FinalizeProxyPolicySettings();
286  FinalizeDefaultSearchPolicySettings();
287}
288
289ConfigurationPolicyPrefKeeper::~ConfigurationPolicyPrefKeeper() {
290  DCHECK(proxy_policies_.empty());
291}
292
293PrefStore::ReadResult
294ConfigurationPolicyPrefKeeper::GetValue(const std::string& key,
295                                        const Value** result) const {
296  const Value* stored_value = NULL;
297  if (!prefs_.GetValue(key, &stored_value))
298    return PrefStore::READ_NO_VALUE;
299
300  // Check whether there's a default value, which indicates READ_USE_DEFAULT
301  // should be returned.
302  if (stored_value->IsType(Value::TYPE_NULL))
303    return PrefStore::READ_USE_DEFAULT;
304
305  *result = stored_value;
306  return PrefStore::READ_OK;
307}
308
309void ConfigurationPolicyPrefKeeper::GetDifferingPrefPaths(
310    const ConfigurationPolicyPrefKeeper* other,
311    std::vector<std::string>* differing_prefs) const {
312  prefs_.GetDifferingKeys(&other->prefs_, differing_prefs);
313}
314
315void ConfigurationPolicyPrefKeeper::Apply(ConfigurationPolicyType policy,
316                                          Value* value) {
317  if (ApplyProxyPolicy(policy, value))
318    return;
319
320  if (ApplySyncPolicy(policy, value))
321    return;
322
323  if (ApplyAutofillPolicy(policy, value))
324    return;
325
326  if (ApplyDownloadDirPolicy(policy, value))
327    return;
328
329  if (ApplyPolicyFromMap(policy, value, kDefaultSearchPolicyMap,
330                         arraysize(kDefaultSearchPolicyMap)))
331    return;
332
333  if (ApplyPolicyFromMap(policy, value, kSimplePolicyMap,
334                         arraysize(kSimplePolicyMap)))
335    return;
336
337  // Other policy implementations go here.
338  NOTIMPLEMENTED();
339  delete value;
340}
341
342bool ConfigurationPolicyPrefKeeper::RemovePreferencesOfMap(
343    const PolicyToPreferenceMapEntry* map, int table_size) {
344  bool found_any = false;
345  for (int i = 0; i < table_size; ++i) {
346    if (prefs_.RemoveValue(map[i].preference_path))
347      found_any = true;
348  }
349  return found_any;
350}
351
352bool ConfigurationPolicyPrefKeeper::ApplyPolicyFromMap(
353    ConfigurationPolicyType policy,
354    Value* value,
355    const PolicyToPreferenceMapEntry* map,
356    int size) {
357  for (int current = 0; current < size; ++current) {
358    if (map[current].policy_type == policy) {
359      DCHECK_EQ(map[current].value_type, value->GetType())
360          << "mismatch in provided and expected policy value for preferences"
361          << map[current].preference_path << ". expected = "
362          << map[current].value_type << ", actual = "<< value->GetType();
363      prefs_.SetValue(map[current].preference_path, value);
364      return true;
365    }
366  }
367  return false;
368}
369
370bool ConfigurationPolicyPrefKeeper::ApplyProxyPolicy(
371    ConfigurationPolicyType policy,
372    Value* value) {
373  // We only collect the values until we have sufficient information when
374  // FinalizeProxyPolicySettings() is called to determine whether the presented
375  // values were correct and apply them in that case.
376  if (policy == kPolicyProxyMode ||
377      policy == kPolicyProxyServerMode ||
378      policy == kPolicyProxyServer ||
379      policy == kPolicyProxyPacUrl ||
380      policy == kPolicyProxyBypassList) {
381    delete proxy_policies_[policy];
382    proxy_policies_[policy] = value;
383    return true;
384  }
385  // We are not interested in this policy.
386  return false;
387}
388
389bool ConfigurationPolicyPrefKeeper::ApplySyncPolicy(
390    ConfigurationPolicyType policy, Value* value) {
391  if (policy == kPolicySyncDisabled) {
392    bool disable_sync;
393    if (value->GetAsBoolean(&disable_sync) && disable_sync)
394      prefs_.SetValue(prefs::kSyncManaged, value);
395    else
396      delete value;
397    return true;
398  }
399  return false;
400}
401
402bool ConfigurationPolicyPrefKeeper::ApplyAutofillPolicy(
403    ConfigurationPolicyType policy, Value* value) {
404  if (policy == kPolicyAutoFillEnabled) {
405    bool auto_fill_enabled;
406    if (value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled)
407      prefs_.SetValue(prefs::kAutofillEnabled,
408                       Value::CreateBooleanValue(false));
409    delete value;
410    return true;
411  }
412  return false;
413}
414
415bool ConfigurationPolicyPrefKeeper::ApplyDownloadDirPolicy(
416    ConfigurationPolicyType policy,
417    Value* value) {
418  // Replace the policy string which might contain some user variables to an
419  // expanded string.
420  if (policy == kPolicyDownloadDirectory) {
421    FilePath::StringType string_value;
422    bool result = value->GetAsString(&string_value);
423    DCHECK(result);
424    FilePath::StringType expanded_value =
425        policy::path_parser::ExpandPathVariables(string_value);
426    prefs_.SetValue(prefs::kDownloadDefaultDirectory,
427                    Value::CreateStringValue(expanded_value));
428    prefs_.SetValue(prefs::kPromptForDownload,
429                    Value::CreateBooleanValue(false));
430    delete value;
431    return true;
432  }
433  // We are not interested in this policy.
434  return false;
435}
436
437void ConfigurationPolicyPrefKeeper::EnsureStringPrefExists(
438    const std::string& path) {
439  std::string value;
440  if (!prefs_.GetString(path, &value))
441    prefs_.SetString(path, value);
442}
443
444namespace {
445
446// Implementation of SearchTermsData just for validation.
447class SearchTermsDataForValidation : public SearchTermsData {
448 public:
449  SearchTermsDataForValidation() {}
450
451  // Implementation of SearchTermsData.
452  virtual std::string GoogleBaseURLValue() const {
453    return "http://www.google.com/";
454  }
455  virtual std::string GetApplicationLocale() const {
456    return "en";
457  }
458#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
459  virtual string16 GetRlzParameterValue() const {
460    return string16();
461  }
462#endif
463 private:
464  DISALLOW_COPY_AND_ASSIGN(SearchTermsDataForValidation);
465};
466
467}  // namespace
468
469void ConfigurationPolicyPrefKeeper::FinalizeDefaultSearchPolicySettings() {
470  bool enabled = true;
471  if (prefs_.GetBoolean(prefs::kDefaultSearchProviderEnabled, &enabled) &&
472      !enabled) {
473    // If default search is disabled, we ignore the other fields.
474    prefs_.SetString(prefs::kDefaultSearchProviderName, std::string());
475    prefs_.SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
476    prefs_.SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
477    prefs_.SetString(prefs::kDefaultSearchProviderIconURL, std::string());
478    prefs_.SetString(prefs::kDefaultSearchProviderEncodings, std::string());
479    prefs_.SetString(prefs::kDefaultSearchProviderKeyword, std::string());
480    prefs_.SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
481    return;
482  }
483  std::string search_url;
484  // The search URL is required.
485  if (prefs_.GetString(prefs::kDefaultSearchProviderSearchURL, &search_url) &&
486      !search_url.empty()) {
487    SearchTermsDataForValidation search_terms_data;
488    const TemplateURLRef search_url_ref(search_url, 0, 0);
489    // It must support replacement (which implies it is valid).
490    if (search_url_ref.SupportsReplacementUsingTermsData(search_terms_data)) {
491      // The other entries are optional.  Just make sure that they are all
492      // specified via policy, so that we don't use regular prefs.
493      EnsureStringPrefExists(prefs::kDefaultSearchProviderSuggestURL);
494      EnsureStringPrefExists(prefs::kDefaultSearchProviderIconURL);
495      EnsureStringPrefExists(prefs::kDefaultSearchProviderEncodings);
496      EnsureStringPrefExists(prefs::kDefaultSearchProviderKeyword);
497      EnsureStringPrefExists(prefs::kDefaultSearchProviderInstantURL);
498
499      // For the name, default to the host if not specified.
500      std::string name;
501      if (!prefs_.GetString(prefs::kDefaultSearchProviderName, &name) ||
502          name.empty())
503        prefs_.SetString(prefs::kDefaultSearchProviderName,
504                          GURL(search_url).host());
505
506      // And clear the IDs since these are not specified via policy.
507      prefs_.SetString(prefs::kDefaultSearchProviderID, std::string());
508      prefs_.SetString(prefs::kDefaultSearchProviderPrepopulateID,
509                        std::string());
510      return;
511    }
512  }
513  // Required entries are not there.  Remove any related entries.
514  RemovePreferencesOfMap(kDefaultSearchPolicyMap,
515                         arraysize(kDefaultSearchPolicyMap));
516}
517
518void ConfigurationPolicyPrefKeeper::FinalizeProxyPolicySettings() {
519  if (CheckProxySettings())
520    ApplyProxySettings();
521
522  STLDeleteContainerPairSecondPointers(proxy_policies_.begin(),
523                                       proxy_policies_.end());
524  proxy_policies_.clear();
525}
526
527bool ConfigurationPolicyPrefKeeper::CheckProxySettings() {
528  bool mode = HasProxyPolicy(kPolicyProxyMode);
529  bool server_mode = HasProxyPolicy(kPolicyProxyServerMode);  // deprecated
530  bool server = HasProxyPolicy(kPolicyProxyServer);
531  bool pac_url = HasProxyPolicy(kPolicyProxyPacUrl);
532  bool bypass_list = HasProxyPolicy(kPolicyProxyBypassList);
533
534  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
535    LOG(WARNING) << "A centrally-administered policy defines proxy setting"
536                 << " details without setting a proxy mode.";
537    return false;
538  }
539
540  // If there's a server mode, convert it into a mode.
541  std::string mode_value;
542  if (mode) {
543    if (server_mode)
544      LOG(WARNING) << "Both ProxyMode and ProxyServerMode policies defined, "
545                   << "ignoring ProxyMode.";
546    if (!proxy_policies_[kPolicyProxyMode]->GetAsString(&mode_value)) {
547      LOG(WARNING) << "Invalid ProxyMode value.";
548      return false;
549    }
550  } else if (server_mode) {
551    int server_mode_value;
552    if (!proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(
553        &server_mode_value)) {
554      LOG(WARNING) << "Invalid ProxyServerMode value.";
555      return false;
556    }
557
558    switch (server_mode_value) {
559      case kPolicyNoProxyServerMode:
560        mode_value = ProxyPrefs::kDirectProxyModeName;
561        break;
562      case kPolicyAutoDetectProxyServerMode:
563        mode_value = ProxyPrefs::kAutoDetectProxyModeName;
564        break;
565      case kPolicyManuallyConfiguredProxyServerMode:
566        if (server && pac_url) {
567          LOG(WARNING) << "A centrally-administered policy dictates that"
568                       << " both fixed proxy servers and a .pac url. should"
569                       << " be used for proxy configuration.";
570          return false;
571        }
572        if (!server && !pac_url) {
573          LOG(WARNING) << "A centrally-administered policy dictates that the"
574                       << " proxy settings should use either fixed proxy"
575                       << " servers or a .pac url, but specifies neither.";
576          return false;
577        }
578        if (pac_url)
579          mode_value = ProxyPrefs::kPacScriptProxyModeName;
580        else
581          mode_value = ProxyPrefs::kFixedServersProxyModeName;
582        break;
583      case kPolicyUseSystemProxyServerMode:
584        mode_value = ProxyPrefs::kSystemProxyModeName;
585        break;
586      default:
587        LOG(WARNING) << "Invalid proxy mode " << server_mode_value;
588        return false;
589    }
590  }
591
592  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
593  // empty and the proxy shouldn't be configured at all.
594  if (mode_value.empty())
595    return true;
596
597  if (mode_value == ProxyPrefs::kDirectProxyModeName) {
598    if (server || pac_url || bypass_list) {
599      LOG(WARNING) << "A centrally-administered policy disables the use of"
600                   << " a proxy but also specifies an explicit proxy"
601                   << " configuration.";
602      return false;
603    }
604  } else if (mode_value == ProxyPrefs::kAutoDetectProxyModeName) {
605    if (server || bypass_list || pac_url) {
606      LOG(WARNING) << "A centrally-administered policy dictates that a proxy"
607                   << " shall be auto configured but specifies fixed proxy"
608                   << " servers, a by-pass list or a .pac script URL.";
609      return false;
610    }
611  } else if (mode_value == ProxyPrefs::kPacScriptProxyModeName) {
612    if (server || bypass_list) {
613      LOG(WARNING) << "A centrally-administered policy dictates that a .pac"
614                   << " script URL should be used for proxy configuration but"
615                   << " also specifies policies required only for fixed"
616                   << " proxy servers.";
617      return false;
618    }
619  } else if (mode_value == ProxyPrefs::kFixedServersProxyModeName) {
620    if (pac_url) {
621      LOG(WARNING) << "A centrally-administered policy dictates that"
622                   << " fixed proxy servers should be used but also"
623                   << " specifies a .pac script URL.";
624      return false;
625    }
626  } else if (mode_value == ProxyPrefs::kSystemProxyModeName) {
627    if (server || pac_url || bypass_list) {
628      LOG(WARNING) << "A centrally-administered policy dictates that the"
629                   << " system proxy settings should be used but also "
630                   << " specifies an explicit proxy configuration.";
631      return false;
632    }
633  } else {
634    LOG(WARNING) << "Invalid proxy mode " << mode_value;
635    return false;
636  }
637  return true;
638}
639
640void ConfigurationPolicyPrefKeeper::ApplyProxySettings() {
641  ProxyPrefs::ProxyMode mode;
642  if (HasProxyPolicy(kPolicyProxyMode)) {
643    std::string string_mode;
644    CHECK(proxy_policies_[kPolicyProxyMode]->GetAsString(&string_mode));
645    if (!ProxyPrefs::StringToProxyMode(string_mode, &mode)) {
646      LOG(WARNING) << "A centrally-administered policy specifies a value for"
647                   << "the ProxyMode policy that isn't recognized.";
648      return;
649    }
650  } else if (HasProxyPolicy(kPolicyProxyServerMode)) {
651    int int_mode = 0;
652    CHECK(proxy_policies_[kPolicyProxyServerMode]->GetAsInteger(&int_mode));
653    switch (int_mode) {
654      case kPolicyNoProxyServerMode:
655        mode = ProxyPrefs::MODE_DIRECT;
656        break;
657      case kPolicyAutoDetectProxyServerMode:
658        mode = ProxyPrefs::MODE_AUTO_DETECT;
659        break;
660      case kPolicyManuallyConfiguredProxyServerMode:
661        mode = ProxyPrefs::MODE_FIXED_SERVERS;
662        if (HasProxyPolicy(kPolicyProxyPacUrl))
663          mode = ProxyPrefs::MODE_PAC_SCRIPT;
664        break;
665      case kPolicyUseSystemProxyServerMode:
666        mode = ProxyPrefs::MODE_SYSTEM;
667        break;
668      default:
669        mode = ProxyPrefs::MODE_DIRECT;
670        NOTREACHED();
671    }
672  } else {
673    return;
674  }
675  switch (mode) {
676    case ProxyPrefs::MODE_DIRECT:
677      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
678      break;
679    case ProxyPrefs::MODE_AUTO_DETECT:
680      prefs_.SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
681      break;
682    case ProxyPrefs::MODE_PAC_SCRIPT: {
683      if (!HasProxyPolicy(kPolicyProxyPacUrl)) {
684        LOG(WARNING) << "A centrally-administered policy specifies to use a "
685                     << "PAC script, but doesn't supply the PAC script URL.";
686        return;
687      }
688      std::string pac_url;
689      proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url);
690      prefs_.SetValue(prefs::kProxy,
691                      ProxyConfigDictionary::CreatePacScript(pac_url));
692      break;
693    }
694    case ProxyPrefs::MODE_FIXED_SERVERS: {
695      if (!HasProxyPolicy(kPolicyProxyServer)) {
696        LOG(WARNING) << "A centrally-administered policy specifies to use a "
697                     << "fixed server, but doesn't supply the server address.";
698        return;
699      }
700      std::string proxy_server;
701      proxy_policies_[kPolicyProxyServer]->GetAsString(&proxy_server);
702      std::string bypass_list;
703      if (HasProxyPolicy(kPolicyProxyBypassList))
704        proxy_policies_[kPolicyProxyBypassList]->GetAsString(&bypass_list);
705      prefs_.SetValue(prefs::kProxy,
706                      ProxyConfigDictionary::CreateFixedServers(proxy_server,
707                                                                bypass_list));
708      break;
709    }
710    case ProxyPrefs::MODE_SYSTEM:
711      prefs_.SetValue(prefs::kProxy,
712                      ProxyConfigDictionary::CreateSystem());
713      break;
714    case ProxyPrefs::kModeCount:
715      NOTREACHED();
716  }
717}
718
719bool ConfigurationPolicyPrefKeeper::HasProxyPolicy(
720    ConfigurationPolicyType policy) const {
721  std::map<ConfigurationPolicyType, Value*>::const_iterator iter;
722  iter = proxy_policies_.find(policy);
723  std::string tmp;
724  if (iter == proxy_policies_.end() ||
725      !iter->second ||
726      iter->second->IsType(Value::TYPE_NULL) ||
727      (iter->second->IsType(Value::TYPE_STRING) &&
728       iter->second->GetAsString(&tmp) &&
729       tmp.empty())) {
730    return false;
731  }
732  return true;
733}
734
735ConfigurationPolicyPrefStore::ConfigurationPolicyPrefStore(
736    ConfigurationPolicyProvider* provider)
737    : provider_(provider),
738      initialization_complete_(false) {
739  if (provider_) {
740    // Read initial policy.
741    policy_keeper_.reset(new ConfigurationPolicyPrefKeeper(provider));
742    registrar_.Init(provider_, this);
743    initialization_complete_ = provider->IsInitializationComplete();
744  } else {
745    initialization_complete_ = true;
746  }
747}
748
749ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() {
750}
751
752void ConfigurationPolicyPrefStore::AddObserver(PrefStore::Observer* observer) {
753  observers_.AddObserver(observer);
754}
755
756void ConfigurationPolicyPrefStore::RemoveObserver(
757    PrefStore::Observer* observer) {
758  observers_.RemoveObserver(observer);
759}
760
761bool ConfigurationPolicyPrefStore::IsInitializationComplete() const {
762  return initialization_complete_;
763}
764
765PrefStore::ReadResult
766ConfigurationPolicyPrefStore::GetValue(const std::string& key,
767                                       const Value** value) const {
768  if (policy_keeper_.get())
769    return policy_keeper_->GetValue(key, value);
770
771  return PrefStore::READ_NO_VALUE;
772}
773
774void ConfigurationPolicyPrefStore::OnUpdatePolicy() {
775  Refresh();
776}
777
778void ConfigurationPolicyPrefStore::OnProviderGoingAway() {
779  provider_ = NULL;
780}
781
782// static
783ConfigurationPolicyPrefStore*
784ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() {
785  BrowserPolicyConnector* connector =
786      g_browser_process->browser_policy_connector();
787  return new ConfigurationPolicyPrefStore(
788      connector->GetManagedPlatformProvider());
789}
790
791// static
792ConfigurationPolicyPrefStore*
793ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(
794    Profile* profile) {
795  ConfigurationPolicyProvider* provider = NULL;
796  if (profile) {
797    // For user policy, return the profile's policy provider.
798    provider = profile->GetPolicyConnector()->GetManagedCloudProvider();
799  } else {
800    // For device policy, return the provider of the browser process.
801    BrowserPolicyConnector* connector =
802        g_browser_process->browser_policy_connector();
803    provider = connector->GetManagedCloudProvider();
804  }
805  return new ConfigurationPolicyPrefStore(provider);
806}
807
808// static
809ConfigurationPolicyPrefStore*
810ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() {
811  BrowserPolicyConnector* connector =
812      g_browser_process->browser_policy_connector();
813  return new ConfigurationPolicyPrefStore(
814      connector->GetRecommendedPlatformProvider());
815}
816
817// static
818ConfigurationPolicyPrefStore*
819ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
820    Profile* profile) {
821  ConfigurationPolicyProvider* provider = NULL;
822  if (profile) {
823    // For user policy, return the profile's policy provider.
824    provider = profile->GetPolicyConnector()->GetRecommendedCloudProvider();
825  } else {
826    // For device policy, return the provider of the browser process.
827    BrowserPolicyConnector* connector =
828        g_browser_process->browser_policy_connector();
829    provider = connector->GetRecommendedCloudProvider();
830  }
831  return new ConfigurationPolicyPrefStore(provider);
832}
833
834/* static */
835const ConfigurationPolicyProvider::PolicyDefinitionList*
836ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() {
837  static ConfigurationPolicyProvider::PolicyDefinitionList::Entry entries[] = {
838    { kPolicyHomepageLocation, Value::TYPE_STRING, key::kHomepageLocation },
839    { kPolicyHomepageIsNewTabPage, Value::TYPE_BOOLEAN,
840      key::kHomepageIsNewTabPage },
841    { kPolicyRestoreOnStartup, Value::TYPE_INTEGER, key::kRestoreOnStartup },
842    { kPolicyRestoreOnStartupURLs, Value::TYPE_LIST,
843      key::kRestoreOnStartupURLs },
844    { kPolicyDefaultSearchProviderEnabled, Value::TYPE_BOOLEAN,
845      key::kDefaultSearchProviderEnabled },
846    { kPolicyDefaultSearchProviderName, Value::TYPE_STRING,
847      key::kDefaultSearchProviderName },
848    { kPolicyDefaultSearchProviderKeyword, Value::TYPE_STRING,
849      key::kDefaultSearchProviderKeyword },
850    { kPolicyDefaultSearchProviderSearchURL, Value::TYPE_STRING,
851      key::kDefaultSearchProviderSearchURL },
852    { kPolicyDefaultSearchProviderSuggestURL, Value::TYPE_STRING,
853      key::kDefaultSearchProviderSuggestURL },
854    { kPolicyDefaultSearchProviderInstantURL, Value::TYPE_STRING,
855      key::kDefaultSearchProviderInstantURL },
856    { kPolicyDefaultSearchProviderIconURL, Value::TYPE_STRING,
857      key::kDefaultSearchProviderIconURL },
858    { kPolicyDefaultSearchProviderEncodings, Value::TYPE_STRING,
859      key::kDefaultSearchProviderEncodings },
860    { kPolicyProxyMode, Value::TYPE_STRING, key::kProxyMode },
861    { kPolicyProxyServerMode, Value::TYPE_INTEGER, key::kProxyServerMode },
862    { kPolicyProxyServer, Value::TYPE_STRING, key::kProxyServer },
863    { kPolicyProxyPacUrl, Value::TYPE_STRING, key::kProxyPacUrl },
864    { kPolicyProxyBypassList, Value::TYPE_STRING, key::kProxyBypassList },
865    { kPolicyAlternateErrorPagesEnabled, Value::TYPE_BOOLEAN,
866      key::kAlternateErrorPagesEnabled },
867    { kPolicySearchSuggestEnabled, Value::TYPE_BOOLEAN,
868      key::kSearchSuggestEnabled },
869    { kPolicyDnsPrefetchingEnabled, Value::TYPE_BOOLEAN,
870      key::kDnsPrefetchingEnabled },
871    { kPolicyDisableSpdy, Value::TYPE_BOOLEAN, key::kDisableSpdy },
872    { kPolicyDisabledSchemes, Value::TYPE_LIST, key::kDisabledSchemes },
873    { kPolicySafeBrowsingEnabled, Value::TYPE_BOOLEAN,
874      key::kSafeBrowsingEnabled },
875    { kPolicyMetricsReportingEnabled, Value::TYPE_BOOLEAN,
876      key::kMetricsReportingEnabled },
877    { kPolicyPasswordManagerEnabled, Value::TYPE_BOOLEAN,
878      key::kPasswordManagerEnabled },
879    { kPolicyPasswordManagerAllowShowPasswords, Value::TYPE_BOOLEAN,
880      key::kPasswordManagerAllowShowPasswords },
881    { kPolicyAutoFillEnabled, Value::TYPE_BOOLEAN, key::kAutoFillEnabled },
882    { kPolicyDisabledPlugins, Value::TYPE_LIST, key::kDisabledPlugins },
883    { kPolicyDisabledPluginsExceptions, Value::TYPE_LIST,
884      key::kDisabledPluginsExceptions },
885    { kPolicyEnabledPlugins, Value::TYPE_LIST, key::kEnabledPlugins },
886    { kPolicyApplicationLocaleValue, Value::TYPE_STRING,
887      key::kApplicationLocaleValue },
888    { kPolicySyncDisabled, Value::TYPE_BOOLEAN, key::kSyncDisabled },
889    { kPolicyExtensionInstallWhitelist, Value::TYPE_LIST,
890      key::kExtensionInstallWhitelist },
891    { kPolicyExtensionInstallBlacklist, Value::TYPE_LIST,
892      key::kExtensionInstallBlacklist },
893    { kPolicyExtensionInstallForcelist, Value::TYPE_LIST,
894      key::kExtensionInstallForcelist },
895    { kPolicyShowHomeButton, Value::TYPE_BOOLEAN, key::kShowHomeButton },
896    { kPolicyPrintingEnabled, Value::TYPE_BOOLEAN, key::kPrintingEnabled },
897    { kPolicyJavascriptEnabled, Value::TYPE_BOOLEAN, key::kJavascriptEnabled },
898    { kPolicyIncognitoEnabled, Value::TYPE_BOOLEAN, key::kIncognitoEnabled },
899    { kPolicySavingBrowserHistoryDisabled, Value::TYPE_BOOLEAN,
900      key::kSavingBrowserHistoryDisabled },
901    { kPolicyClearSiteDataOnExit, Value::TYPE_BOOLEAN,
902      key::kClearSiteDataOnExit },
903    { kPolicyDeveloperToolsDisabled, Value::TYPE_BOOLEAN,
904      key::kDeveloperToolsDisabled },
905    { kPolicyBlockThirdPartyCookies, Value::TYPE_BOOLEAN,
906      key::kBlockThirdPartyCookies },
907    { kPolicyDefaultCookiesSetting, Value::TYPE_INTEGER,
908      key::kDefaultCookiesSetting },
909    { kPolicyDefaultImagesSetting, Value::TYPE_INTEGER,
910      key::kDefaultImagesSetting },
911    { kPolicyDefaultJavaScriptSetting, Value::TYPE_INTEGER,
912      key::kDefaultJavaScriptSetting },
913    { kPolicyDefaultPluginsSetting, Value::TYPE_INTEGER,
914      key::kDefaultPluginsSetting },
915    { kPolicyDefaultPopupsSetting, Value::TYPE_INTEGER,
916      key::kDefaultPopupsSetting },
917    { kPolicyDefaultNotificationSetting, Value::TYPE_INTEGER,
918      key::kDefaultNotificationSetting },
919    { kPolicyDefaultGeolocationSetting, Value::TYPE_INTEGER,
920      key::kDefaultGeolocationSetting },
921    { kPolicyCookiesAllowedForUrls, Value::TYPE_LIST,
922      key::kCookiesAllowedForUrls },
923    { kPolicyCookiesBlockedForUrls, Value::TYPE_LIST,
924      key::kCookiesBlockedForUrls },
925    { kPolicyCookiesSessionOnlyForUrls, Value::TYPE_LIST,
926      key::kCookiesSessionOnlyForUrls },
927    { kPolicyImagesAllowedForUrls, Value::TYPE_LIST,
928      key::kImagesAllowedForUrls },
929    { kPolicyImagesBlockedForUrls, Value::TYPE_LIST,
930      key::kImagesBlockedForUrls },
931    { kPolicyJavaScriptAllowedForUrls, Value::TYPE_LIST,
932      key::kJavaScriptAllowedForUrls },
933    { kPolicyJavaScriptBlockedForUrls, Value::TYPE_LIST,
934      key::kJavaScriptBlockedForUrls },
935    { kPolicyPluginsAllowedForUrls, Value::TYPE_LIST,
936      key::kPluginsAllowedForUrls },
937    { kPolicyPluginsBlockedForUrls, Value::TYPE_LIST,
938      key::kPluginsBlockedForUrls },
939    { kPolicyPopupsAllowedForUrls, Value::TYPE_LIST,
940      key::kPopupsAllowedForUrls },
941    { kPolicyPopupsBlockedForUrls, Value::TYPE_LIST,
942      key::kPopupsBlockedForUrls },
943    { kPolicyAuthSchemes, Value::TYPE_STRING, key::kAuthSchemes },
944    { kPolicyDisableAuthNegotiateCnameLookup, Value::TYPE_BOOLEAN,
945      key::kDisableAuthNegotiateCnameLookup },
946    { kPolicyEnableAuthNegotiatePort, Value::TYPE_BOOLEAN,
947      key::kEnableAuthNegotiatePort },
948    { kPolicyAuthServerWhitelist, Value::TYPE_STRING,
949      key::kAuthServerWhitelist },
950    { kPolicyAuthNegotiateDelegateWhitelist, Value::TYPE_STRING,
951      key::kAuthNegotiateDelegateWhitelist },
952    { kPolicyGSSAPILibraryName, Value::TYPE_STRING,
953      key::kGSSAPILibraryName },
954    { kPolicyDisable3DAPIs, Value::TYPE_BOOLEAN,
955      key::kDisable3DAPIs },
956    { kPolicyDisablePluginFinder, Value::TYPE_BOOLEAN,
957      key::kDisablePluginFinder },
958    { kPolicyPolicyRefreshRate, Value::TYPE_INTEGER,
959      key::kPolicyRefreshRate },
960    { kPolicyInstantEnabled, Value::TYPE_BOOLEAN, key::kInstantEnabled },
961    { kPolicyDefaultBrowserSettingEnabled, Value::TYPE_BOOLEAN,
962      key::kDefaultBrowserSettingEnabled },
963    { kPolicyCloudPrintProxyEnabled, Value::TYPE_BOOLEAN,
964      key::kCloudPrintProxyEnabled },
965    { kPolicyDownloadDirectory, Value::TYPE_STRING,
966      key::kDownloadDirectory },
967    { kPolicyTranslateEnabled, Value::TYPE_BOOLEAN, key::kTranslateEnabled },
968    { kPolicyAllowOutdatedPlugins, Value::TYPE_BOOLEAN,
969      key::kAllowOutdatedPlugins },
970    { kPolicyBookmarkBarEnabled, Value::TYPE_BOOLEAN,
971      key::kBookmarkBarEnabled },
972    { kPolicyEditBookmarksEnabled, Value::TYPE_BOOLEAN,
973      key::kEditBookmarksEnabled },
974    { kPolicyAllowFileSelectionDialogs, Value::TYPE_BOOLEAN,
975      key::kAllowFileSelectionDialogs },
976
977#if defined(OS_CHROMEOS)
978    { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN,
979      key::kChromeOsLockOnIdleSuspend },
980#endif
981  };
982
983  static ConfigurationPolicyProvider::PolicyDefinitionList policy_list = {
984    entries,
985    entries + arraysize(entries),
986  };
987  return &policy_list;
988}
989
990void ConfigurationPolicyPrefStore::Refresh() {
991  if (!provider_)
992    return;
993
994  // Construct a new keeper, determine what changed and swap the keeper in.
995  scoped_ptr<ConfigurationPolicyPrefKeeper> new_keeper(
996      new ConfigurationPolicyPrefKeeper(provider_));
997  std::vector<std::string> changed_prefs;
998  new_keeper->GetDifferingPrefPaths(policy_keeper_.get(), &changed_prefs);
999  policy_keeper_.reset(new_keeper.release());
1000
1001  // Send out change notifications.
1002  for (std::vector<std::string>::const_iterator pref(changed_prefs.begin());
1003       pref != changed_prefs.end();
1004       ++pref) {
1005    FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
1006                      OnPrefValueChanged(*pref));
1007  }
1008
1009  // Update the initialization flag.
1010  if (!initialization_complete_ &&
1011      provider_->IsInitializationComplete()) {
1012    initialization_complete_ = true;
1013    FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
1014                      OnInitializationCompleted());
1015  }
1016}
1017
1018}  // namespace policy
1019