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 34 namespace policy { 35 36 // Accepts policy settings from a ConfigurationPolicyProvider, converts them 37 // to preferences and caches the result. 38 class 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 132 const 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 263 const 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 281 ConfigurationPolicyPrefKeeper::ConfigurationPolicyPrefKeeper( 282 ConfigurationPolicyProvider* provider) { 283 if (!provider->Provide(this)) 284 LOG(WARNING) << "Failed to get policy from provider."; 285 FinalizeProxyPolicySettings(); 286 FinalizeDefaultSearchPolicySettings(); 287 } 288 289 ConfigurationPolicyPrefKeeper::~ConfigurationPolicyPrefKeeper() { 290 DCHECK(proxy_policies_.empty()); 291 } 292 293 PrefStore::ReadResult 294 ConfigurationPolicyPrefKeeper::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 309 void ConfigurationPolicyPrefKeeper::GetDifferingPrefPaths( 310 const ConfigurationPolicyPrefKeeper* other, 311 std::vector<std::string>* differing_prefs) const { 312 prefs_.GetDifferingKeys(&other->prefs_, differing_prefs); 313 } 314 315 void 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 342 bool 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 352 bool 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 370 bool 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 389 bool 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 402 bool 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 415 bool 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 437 void ConfigurationPolicyPrefKeeper::EnsureStringPrefExists( 438 const std::string& path) { 439 std::string value; 440 if (!prefs_.GetString(path, &value)) 441 prefs_.SetString(path, value); 442 } 443 444 namespace { 445 446 // Implementation of SearchTermsData just for validation. 447 class 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 469 void 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 518 void ConfigurationPolicyPrefKeeper::FinalizeProxyPolicySettings() { 519 if (CheckProxySettings()) 520 ApplyProxySettings(); 521 522 STLDeleteContainerPairSecondPointers(proxy_policies_.begin(), 523 proxy_policies_.end()); 524 proxy_policies_.clear(); 525 } 526 527 bool 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 640 void 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 719 bool 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 735 ConfigurationPolicyPrefStore::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 749 ConfigurationPolicyPrefStore::~ConfigurationPolicyPrefStore() { 750 } 751 752 void ConfigurationPolicyPrefStore::AddObserver(PrefStore::Observer* observer) { 753 observers_.AddObserver(observer); 754 } 755 756 void ConfigurationPolicyPrefStore::RemoveObserver( 757 PrefStore::Observer* observer) { 758 observers_.RemoveObserver(observer); 759 } 760 761 bool ConfigurationPolicyPrefStore::IsInitializationComplete() const { 762 return initialization_complete_; 763 } 764 765 PrefStore::ReadResult 766 ConfigurationPolicyPrefStore::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 774 void ConfigurationPolicyPrefStore::OnUpdatePolicy() { 775 Refresh(); 776 } 777 778 void ConfigurationPolicyPrefStore::OnProviderGoingAway() { 779 provider_ = NULL; 780 } 781 782 // static 783 ConfigurationPolicyPrefStore* 784 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore() { 785 BrowserPolicyConnector* connector = 786 g_browser_process->browser_policy_connector(); 787 return new ConfigurationPolicyPrefStore( 788 connector->GetManagedPlatformProvider()); 789 } 790 791 // static 792 ConfigurationPolicyPrefStore* 793 ConfigurationPolicyPrefStore::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 809 ConfigurationPolicyPrefStore* 810 ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore() { 811 BrowserPolicyConnector* connector = 812 g_browser_process->browser_policy_connector(); 813 return new ConfigurationPolicyPrefStore( 814 connector->GetRecommendedPlatformProvider()); 815 } 816 817 // static 818 ConfigurationPolicyPrefStore* 819 ConfigurationPolicyPrefStore::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 */ 835 const ConfigurationPolicyProvider::PolicyDefinitionList* 836 ConfigurationPolicyPrefStore::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 990 void 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