1// Copyright (c) 2012 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/content_settings/content_settings_policy_provider.h" 6 7#include <string> 8#include <vector> 9 10#include "base/json/json_reader.h" 11#include "base/prefs/pref_service.h" 12#include "base/values.h" 13#include "chrome/browser/content_settings/content_settings_utils.h" 14#include "chrome/common/pref_names.h" 15#include "components/content_settings/core/browser/content_settings_rule.h" 16#include "components/content_settings/core/common/content_settings_pattern.h" 17#include "components/pref_registry/pref_registry_syncable.h" 18#include "content/public/browser/browser_thread.h" 19 20using content::BrowserThread; 21 22namespace { 23 24// The preferences used to manage ContentSettingsTypes. 25const char* kPrefToManageType[] = { 26 prefs::kManagedDefaultCookiesSetting, 27 prefs::kManagedDefaultImagesSetting, 28 prefs::kManagedDefaultJavaScriptSetting, 29 prefs::kManagedDefaultPluginsSetting, 30 prefs::kManagedDefaultPopupsSetting, 31 prefs::kManagedDefaultGeolocationSetting, 32 prefs::kManagedDefaultNotificationsSetting, 33 NULL, // No policy for default value of content type auto-select-certificate 34 NULL, // No policy for default value of fullscreen requests 35 NULL, // No policy for default value of mouse lock requests 36 NULL, // No policy for default value of mixed script blocking 37 prefs::kManagedDefaultMediaStreamSetting, 38 NULL, // No policy for default value of media stream mic 39 NULL, // No policy for default value of media stream camera 40 NULL, // No policy for default value of protocol handlers 41 NULL, // No policy for default value of PPAPI broker 42 NULL, // No policy for default value of multiple automatic downloads 43 NULL, // No policy for default value of MIDI system exclusive requests 44 NULL, // No policy for default value of push messaging requests 45 NULL, // No policy for default value of SSL certificate decisions 46#if defined(OS_WIN) 47 NULL, // No policy for default value of "switch to desktop" 48#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) 49 NULL, // No policy for default value of protected media identifier 50#endif 51#if defined(OS_ANDROID) 52 NULL, // No policy for default value of app banners 53#endif 54}; 55COMPILE_ASSERT(arraysize(kPrefToManageType) == CONTENT_SETTINGS_NUM_TYPES, 56 managed_content_settings_pref_names_array_size_incorrect); 57 58struct PrefsForManagedContentSettingsMapEntry { 59 const char* pref_name; 60 ContentSettingsType content_type; 61 ContentSetting setting; 62}; 63 64const PrefsForManagedContentSettingsMapEntry 65 kPrefsForManagedContentSettingsMap[] = { 66 { 67 prefs::kManagedCookiesAllowedForUrls, 68 CONTENT_SETTINGS_TYPE_COOKIES, 69 CONTENT_SETTING_ALLOW 70 }, { 71 prefs::kManagedCookiesSessionOnlyForUrls, 72 CONTENT_SETTINGS_TYPE_COOKIES, 73 CONTENT_SETTING_SESSION_ONLY 74 }, { 75 prefs::kManagedCookiesBlockedForUrls, 76 CONTENT_SETTINGS_TYPE_COOKIES, 77 CONTENT_SETTING_BLOCK 78 }, { 79 prefs::kManagedImagesAllowedForUrls, 80 CONTENT_SETTINGS_TYPE_IMAGES, 81 CONTENT_SETTING_ALLOW 82 }, { 83 prefs::kManagedImagesBlockedForUrls, 84 CONTENT_SETTINGS_TYPE_IMAGES, 85 CONTENT_SETTING_BLOCK 86 }, { 87 prefs::kManagedJavaScriptAllowedForUrls, 88 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 89 CONTENT_SETTING_ALLOW 90 }, { 91 prefs::kManagedJavaScriptBlockedForUrls, 92 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 93 CONTENT_SETTING_BLOCK 94 }, { 95 prefs::kManagedPluginsAllowedForUrls, 96 CONTENT_SETTINGS_TYPE_PLUGINS, 97 CONTENT_SETTING_ALLOW 98 }, { 99 prefs::kManagedPluginsBlockedForUrls, 100 CONTENT_SETTINGS_TYPE_PLUGINS, 101 CONTENT_SETTING_BLOCK 102 }, { 103 prefs::kManagedPopupsAllowedForUrls, 104 CONTENT_SETTINGS_TYPE_POPUPS, 105 CONTENT_SETTING_ALLOW 106 }, { 107 prefs::kManagedPopupsBlockedForUrls, 108 CONTENT_SETTINGS_TYPE_POPUPS, 109 CONTENT_SETTING_BLOCK 110 }, { 111 prefs::kManagedNotificationsAllowedForUrls, 112 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 113 CONTENT_SETTING_ALLOW 114 }, { 115 prefs::kManagedNotificationsBlockedForUrls, 116 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 117 CONTENT_SETTING_BLOCK 118 } 119}; 120 121} // namespace 122 123namespace content_settings { 124 125// static 126void PolicyProvider::RegisterProfilePrefs( 127 user_prefs::PrefRegistrySyncable* registry) { 128 registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls, 129 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 130 registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls, 131 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 132 registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls, 133 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 134 registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls, 135 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 136 registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls, 137 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 138 registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls, 139 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 140 registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls, 141 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 142 registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls, 143 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 144 registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls, 145 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 146 registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls, 147 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 148 registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls, 149 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 150 registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls, 151 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 152 registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls, 153 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 154 registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls, 155 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 156 // Preferences for default content setting policies. If a policy is not set of 157 // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. 158 registry->RegisterIntegerPref( 159 prefs::kManagedDefaultCookiesSetting, 160 CONTENT_SETTING_DEFAULT, 161 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 162 registry->RegisterIntegerPref( 163 prefs::kManagedDefaultImagesSetting, 164 CONTENT_SETTING_DEFAULT, 165 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 166 registry->RegisterIntegerPref( 167 prefs::kManagedDefaultJavaScriptSetting, 168 CONTENT_SETTING_DEFAULT, 169 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 170 registry->RegisterIntegerPref( 171 prefs::kManagedDefaultPluginsSetting, 172 CONTENT_SETTING_DEFAULT, 173 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 174 registry->RegisterIntegerPref( 175 prefs::kManagedDefaultPopupsSetting, 176 CONTENT_SETTING_DEFAULT, 177 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 178 registry->RegisterIntegerPref( 179 prefs::kManagedDefaultGeolocationSetting, 180 CONTENT_SETTING_DEFAULT, 181 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 182 registry->RegisterIntegerPref( 183 prefs::kManagedDefaultNotificationsSetting, 184 CONTENT_SETTING_DEFAULT, 185 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 186 registry->RegisterIntegerPref( 187 prefs::kManagedDefaultMediaStreamSetting, 188 CONTENT_SETTING_DEFAULT, 189 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 190} 191 192PolicyProvider::PolicyProvider(PrefService* prefs) : prefs_(prefs) { 193 ReadManagedDefaultSettings(); 194 ReadManagedContentSettings(false); 195 196 pref_change_registrar_.Init(prefs_); 197 PrefChangeRegistrar::NamedChangeCallback callback = 198 base::Bind(&PolicyProvider::OnPreferenceChanged, base::Unretained(this)); 199 pref_change_registrar_.Add( 200 prefs::kManagedAutoSelectCertificateForUrls, callback); 201 pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, callback); 202 pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, callback); 203 pref_change_registrar_.Add( 204 prefs::kManagedCookiesSessionOnlyForUrls, callback); 205 pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, callback); 206 pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, callback); 207 pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, callback); 208 pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, callback); 209 pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, callback); 210 pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, callback); 211 pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, callback); 212 pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, callback); 213 pref_change_registrar_.Add( 214 prefs::kManagedNotificationsAllowedForUrls, callback); 215 pref_change_registrar_.Add( 216 prefs::kManagedNotificationsBlockedForUrls, callback); 217 // The following preferences are only used to indicate if a default content 218 // setting is managed and to hold the managed default setting value. If the 219 // value for any of the following preferences is set then the corresponding 220 // default content setting is managed. These preferences exist in parallel to 221 // the preference default content settings. If a default content settings type 222 // is managed any user defined exceptions (patterns) for this type are 223 // ignored. 224 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, callback); 225 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, callback); 226 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, callback); 227 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, callback); 228 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, callback); 229 pref_change_registrar_.Add( 230 prefs::kManagedDefaultGeolocationSetting, callback); 231 pref_change_registrar_.Add( 232 prefs::kManagedDefaultNotificationsSetting, callback); 233 pref_change_registrar_.Add( 234 prefs::kManagedDefaultMediaStreamSetting, callback); 235} 236 237PolicyProvider::~PolicyProvider() { 238 DCHECK(!prefs_); 239} 240 241RuleIterator* PolicyProvider::GetRuleIterator( 242 ContentSettingsType content_type, 243 const ResourceIdentifier& resource_identifier, 244 bool incognito) const { 245 return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); 246} 247 248void PolicyProvider::GetContentSettingsFromPreferences( 249 OriginIdentifierValueMap* value_map) { 250 for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) { 251 const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name; 252 // Skip unset policies. 253 if (!prefs_->HasPrefPath(pref_name)) { 254 VLOG(2) << "Skipping unset preference: " << pref_name; 255 continue; 256 } 257 258 const PrefService::Preference* pref = prefs_->FindPreference(pref_name); 259 DCHECK(pref); 260 DCHECK(pref->IsManaged()); 261 262 const base::ListValue* pattern_str_list = NULL; 263 if (!pref->GetValue()->GetAsList(&pattern_str_list)) { 264 NOTREACHED(); 265 return; 266 } 267 268 for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { 269 std::string original_pattern_str; 270 if (!pattern_str_list->GetString(j, &original_pattern_str)) { 271 NOTREACHED(); 272 continue; 273 } 274 275 PatternPair pattern_pair = ParsePatternString(original_pattern_str); 276 // Ignore invalid patterns. 277 if (!pattern_pair.first.IsValid()) { 278 VLOG(1) << "Ignoring invalid content settings pattern: " << 279 original_pattern_str; 280 continue; 281 } 282 283 ContentSettingsType content_type = 284 kPrefsForManagedContentSettingsMap[i].content_type; 285 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE); 286 // If only one pattern was defined auto expand it to a pattern pair. 287 ContentSettingsPattern secondary_pattern = 288 !pattern_pair.second.IsValid() ? ContentSettingsPattern::Wildcard() 289 : pattern_pair.second; 290 value_map->SetValue(pattern_pair.first, 291 secondary_pattern, 292 content_type, 293 NO_RESOURCE_IDENTIFIER, 294 new base::FundamentalValue( 295 kPrefsForManagedContentSettingsMap[i].setting)); 296 } 297 } 298} 299 300void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences( 301 OriginIdentifierValueMap* value_map) { 302 const char* pref_name = prefs::kManagedAutoSelectCertificateForUrls; 303 304 if (!prefs_->HasPrefPath(pref_name)) { 305 VLOG(2) << "Skipping unset preference: " << pref_name; 306 return; 307 } 308 309 const PrefService::Preference* pref = prefs_->FindPreference(pref_name); 310 DCHECK(pref); 311 DCHECK(pref->IsManaged()); 312 313 const base::ListValue* pattern_filter_str_list = NULL; 314 if (!pref->GetValue()->GetAsList(&pattern_filter_str_list)) { 315 NOTREACHED(); 316 return; 317 } 318 319 // Parse the list of pattern filter strings. A pattern filter string has 320 // the following JSON format: 321 // 322 // { 323 // "pattern": <content settings pattern string>, 324 // "filter" : <certificate filter in JSON format> 325 // } 326 // 327 // e.g. 328 // { 329 // "pattern": "[*.]example.com", 330 // "filter": { 331 // "ISSUER": { 332 // "CN": "some name" 333 // } 334 // } 335 // } 336 for (size_t j = 0; j < pattern_filter_str_list->GetSize(); ++j) { 337 std::string pattern_filter_json; 338 if (!pattern_filter_str_list->GetString(j, &pattern_filter_json)) { 339 NOTREACHED(); 340 continue; 341 } 342 343 scoped_ptr<base::Value> value(base::JSONReader::Read(pattern_filter_json, 344 base::JSON_ALLOW_TRAILING_COMMAS)); 345 if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) { 346 VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:" 347 " Invalid JSON object: " << pattern_filter_json; 348 continue; 349 } 350 351 scoped_ptr<base::DictionaryValue> pattern_filter_pair( 352 static_cast<base::DictionaryValue*>(value.release())); 353 std::string pattern_str; 354 bool pattern_read = pattern_filter_pair->GetStringWithoutPathExpansion( 355 "pattern", &pattern_str); 356 base::DictionaryValue* cert_filter = NULL; 357 pattern_filter_pair->GetDictionaryWithoutPathExpansion("filter", 358 &cert_filter); 359 if (!pattern_read || !cert_filter) { 360 VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:" 361 " Missing pattern or filter."; 362 continue; 363 } 364 365 ContentSettingsPattern pattern = 366 ContentSettingsPattern::FromString(pattern_str); 367 // Ignore invalid patterns. 368 if (!pattern.IsValid()) { 369 VLOG(1) << "Ignoring invalid certificate auto select setting:" 370 " Invalid content settings pattern: " << pattern.ToString(); 371 continue; 372 } 373 374 // Don't pass removed values from |value|, because base::Values read with 375 // JSONReader use a shared string buffer. Instead, DeepCopy here. 376 value_map->SetValue(pattern, 377 ContentSettingsPattern::Wildcard(), 378 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 379 std::string(), 380 cert_filter->DeepCopy()); 381 } 382} 383 384void PolicyProvider::ReadManagedDefaultSettings() { 385 for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { 386 if (kPrefToManageType[type] == NULL) { 387 continue; 388 } 389 UpdateManagedDefaultSetting(ContentSettingsType(type)); 390 } 391} 392 393void PolicyProvider::UpdateManagedDefaultSetting( 394 ContentSettingsType content_type) { 395 // If a pref to manage a default-content-setting was not set (NOTICE: 396 // "HasPrefPath" returns false if no value was set for a registered pref) then 397 // the default value of the preference is used. The default value of a 398 // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT. 399 // This indicates that no managed value is set. If a pref was set, than it 400 // MUST be managed. 401 DCHECK(!prefs_->HasPrefPath(kPrefToManageType[content_type]) || 402 prefs_->IsManagedPreference(kPrefToManageType[content_type])); 403 base::AutoLock auto_lock(lock_); 404 405 int setting = prefs_->GetInteger(kPrefToManageType[content_type]); 406 if (setting == CONTENT_SETTING_DEFAULT) { 407 value_map_.DeleteValue( 408 ContentSettingsPattern::Wildcard(), 409 ContentSettingsPattern::Wildcard(), 410 content_type, 411 std::string()); 412 } else { 413 value_map_.SetValue(ContentSettingsPattern::Wildcard(), 414 ContentSettingsPattern::Wildcard(), 415 content_type, 416 std::string(), 417 new base::FundamentalValue(setting)); 418 } 419} 420 421 422void PolicyProvider::ReadManagedContentSettings(bool overwrite) { 423 base::AutoLock auto_lock(lock_); 424 if (overwrite) 425 value_map_.clear(); 426 GetContentSettingsFromPreferences(&value_map_); 427 GetAutoSelectCertificateSettingsFromPreferences(&value_map_); 428} 429 430// Since the PolicyProvider is a read only content settings provider, all 431// methodes of the ProviderInterface that set or delete any settings do nothing. 432bool PolicyProvider::SetWebsiteSetting( 433 const ContentSettingsPattern& primary_pattern, 434 const ContentSettingsPattern& secondary_pattern, 435 ContentSettingsType content_type, 436 const ResourceIdentifier& resource_identifier, 437 base::Value* value) { 438 return false; 439} 440 441void PolicyProvider::ClearAllContentSettingsRules( 442 ContentSettingsType content_type) { 443} 444 445void PolicyProvider::ShutdownOnUIThread() { 446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 447 RemoveAllObservers(); 448 if (!prefs_) 449 return; 450 pref_change_registrar_.RemoveAll(); 451 prefs_ = NULL; 452} 453 454void PolicyProvider::OnPreferenceChanged(const std::string& name) { 455 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 456 457 if (name == prefs::kManagedDefaultCookiesSetting) { 458 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES); 459 } else if (name == prefs::kManagedDefaultImagesSetting) { 460 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES); 461 } else if (name == prefs::kManagedDefaultJavaScriptSetting) { 462 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT); 463 } else if (name == prefs::kManagedDefaultPluginsSetting) { 464 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS); 465 } else if (name == prefs::kManagedDefaultPopupsSetting) { 466 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS); 467 } else if (name == prefs::kManagedDefaultGeolocationSetting) { 468 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_GEOLOCATION); 469 } else if (name == prefs::kManagedDefaultNotificationsSetting) { 470 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 471 } else if (name == prefs::kManagedDefaultMediaStreamSetting) { 472 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM); 473 } else if (name == prefs::kManagedAutoSelectCertificateForUrls || 474 name == prefs::kManagedCookiesAllowedForUrls || 475 name == prefs::kManagedCookiesBlockedForUrls || 476 name == prefs::kManagedCookiesSessionOnlyForUrls || 477 name == prefs::kManagedImagesAllowedForUrls || 478 name == prefs::kManagedImagesBlockedForUrls || 479 name == prefs::kManagedJavaScriptAllowedForUrls || 480 name == prefs::kManagedJavaScriptBlockedForUrls || 481 name == prefs::kManagedPluginsAllowedForUrls || 482 name == prefs::kManagedPluginsBlockedForUrls || 483 name == prefs::kManagedPopupsAllowedForUrls || 484 name == prefs::kManagedPopupsBlockedForUrls || 485 name == prefs::kManagedNotificationsAllowedForUrls || 486 name == prefs::kManagedNotificationsBlockedForUrls) { 487 ReadManagedContentSettings(true); 488 ReadManagedDefaultSettings(); 489 } 490 491 NotifyObservers(ContentSettingsPattern(), 492 ContentSettingsPattern(), 493 CONTENT_SETTINGS_TYPE_DEFAULT, 494 std::string()); 495} 496 497} // namespace content_settings 498