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