content_settings_policy_provider.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
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 NULL, // No policy for default value of MIDI system exclusive requests 47#if defined(OS_WIN) 48 NULL, // No policy for default value of "switch to desktop" 49#endif 50}; 51COMPILE_ASSERT(arraysize(kPrefToManageType) == CONTENT_SETTINGS_NUM_TYPES, 52 managed_content_settings_pref_names_array_size_incorrect); 53 54struct PrefsForManagedContentSettingsMapEntry { 55 const char* pref_name; 56 ContentSettingsType content_type; 57 ContentSetting setting; 58}; 59 60const PrefsForManagedContentSettingsMapEntry 61 kPrefsForManagedContentSettingsMap[] = { 62 { 63 prefs::kManagedCookiesAllowedForUrls, 64 CONTENT_SETTINGS_TYPE_COOKIES, 65 CONTENT_SETTING_ALLOW 66 }, { 67 prefs::kManagedCookiesSessionOnlyForUrls, 68 CONTENT_SETTINGS_TYPE_COOKIES, 69 CONTENT_SETTING_SESSION_ONLY 70 }, { 71 prefs::kManagedCookiesBlockedForUrls, 72 CONTENT_SETTINGS_TYPE_COOKIES, 73 CONTENT_SETTING_BLOCK 74 }, { 75 prefs::kManagedImagesAllowedForUrls, 76 CONTENT_SETTINGS_TYPE_IMAGES, 77 CONTENT_SETTING_ALLOW 78 }, { 79 prefs::kManagedImagesBlockedForUrls, 80 CONTENT_SETTINGS_TYPE_IMAGES, 81 CONTENT_SETTING_BLOCK 82 }, { 83 prefs::kManagedJavaScriptAllowedForUrls, 84 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 85 CONTENT_SETTING_ALLOW 86 }, { 87 prefs::kManagedJavaScriptBlockedForUrls, 88 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 89 CONTENT_SETTING_BLOCK 90 }, { 91 prefs::kManagedPluginsAllowedForUrls, 92 CONTENT_SETTINGS_TYPE_PLUGINS, 93 CONTENT_SETTING_ALLOW 94 }, { 95 prefs::kManagedPluginsBlockedForUrls, 96 CONTENT_SETTINGS_TYPE_PLUGINS, 97 CONTENT_SETTING_BLOCK 98 }, { 99 prefs::kManagedPopupsAllowedForUrls, 100 CONTENT_SETTINGS_TYPE_POPUPS, 101 CONTENT_SETTING_ALLOW 102 }, { 103 prefs::kManagedPopupsBlockedForUrls, 104 CONTENT_SETTINGS_TYPE_POPUPS, 105 CONTENT_SETTING_BLOCK 106 }, { 107 prefs::kManagedNotificationsAllowedForUrls, 108 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 109 CONTENT_SETTING_ALLOW 110 }, { 111 prefs::kManagedNotificationsBlockedForUrls, 112 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 113 CONTENT_SETTING_BLOCK 114 } 115}; 116 117} // namespace 118 119namespace content_settings { 120 121// static 122void PolicyProvider::RegisterProfilePrefs( 123 user_prefs::PrefRegistrySyncable* registry) { 124 registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls, 125 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 126 registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls, 127 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 128 registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls, 129 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 130 registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls, 131 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 132 registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls, 133 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 134 registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls, 135 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 136 registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls, 137 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 138 registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls, 139 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 140 registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls, 141 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 142 registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls, 143 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 144 registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls, 145 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 146 registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls, 147 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 148 registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls, 149 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 150 registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls, 151 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 152 // Preferences for default content setting policies. If a policy is not set of 153 // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. 154 registry->RegisterIntegerPref( 155 prefs::kManagedDefaultCookiesSetting, 156 CONTENT_SETTING_DEFAULT, 157 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 158 registry->RegisterIntegerPref( 159 prefs::kManagedDefaultImagesSetting, 160 CONTENT_SETTING_DEFAULT, 161 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 162 registry->RegisterIntegerPref( 163 prefs::kManagedDefaultJavaScriptSetting, 164 CONTENT_SETTING_DEFAULT, 165 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 166 registry->RegisterIntegerPref( 167 prefs::kManagedDefaultPluginsSetting, 168 CONTENT_SETTING_DEFAULT, 169 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 170 registry->RegisterIntegerPref( 171 prefs::kManagedDefaultPopupsSetting, 172 CONTENT_SETTING_DEFAULT, 173 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 174 registry->RegisterIntegerPref( 175 prefs::kManagedDefaultGeolocationSetting, 176 CONTENT_SETTING_DEFAULT, 177 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 178 registry->RegisterIntegerPref( 179 prefs::kManagedDefaultNotificationsSetting, 180 CONTENT_SETTING_DEFAULT, 181 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 182 registry->RegisterIntegerPref( 183 prefs::kManagedDefaultMediaStreamSetting, 184 CONTENT_SETTING_DEFAULT, 185 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 186} 187 188PolicyProvider::PolicyProvider(PrefService* prefs) : prefs_(prefs) { 189 ReadManagedDefaultSettings(); 190 ReadManagedContentSettings(false); 191 192 pref_change_registrar_.Init(prefs_); 193 PrefChangeRegistrar::NamedChangeCallback callback = 194 base::Bind(&PolicyProvider::OnPreferenceChanged, base::Unretained(this)); 195 pref_change_registrar_.Add( 196 prefs::kManagedAutoSelectCertificateForUrls, callback); 197 pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, callback); 198 pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, callback); 199 pref_change_registrar_.Add( 200 prefs::kManagedCookiesSessionOnlyForUrls, callback); 201 pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, callback); 202 pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, callback); 203 pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, callback); 204 pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, callback); 205 pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, callback); 206 pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, callback); 207 pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, callback); 208 pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, callback); 209 pref_change_registrar_.Add( 210 prefs::kManagedNotificationsAllowedForUrls, callback); 211 pref_change_registrar_.Add( 212 prefs::kManagedNotificationsBlockedForUrls, callback); 213 // The following preferences are only used to indicate if a 214 // default content setting is managed and to hold the managed default setting 215 // value. If the value for any of the following perferences is set then the 216 // corresponding default content setting is managed. These preferences exist 217 // in parallel to the preference default content settings. If a 218 // default content settings type is managed any user defined excpetions 219 // (patterns) for this type are ignored. 220 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, callback); 221 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, callback); 222 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, callback); 223 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, callback); 224 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, callback); 225 pref_change_registrar_.Add( 226 prefs::kManagedDefaultGeolocationSetting, callback); 227 pref_change_registrar_.Add( 228 prefs::kManagedDefaultNotificationsSetting, callback); 229 pref_change_registrar_.Add( 230 prefs::kManagedDefaultMediaStreamSetting, callback); 231} 232 233PolicyProvider::~PolicyProvider() { 234 DCHECK(!prefs_); 235} 236 237RuleIterator* PolicyProvider::GetRuleIterator( 238 ContentSettingsType content_type, 239 const ResourceIdentifier& resource_identifier, 240 bool incognito) const { 241 return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); 242} 243 244void PolicyProvider::GetContentSettingsFromPreferences( 245 OriginIdentifierValueMap* value_map) { 246 for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) { 247 const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name; 248 // Skip unset policies. 249 if (!prefs_->HasPrefPath(pref_name)) { 250 VLOG(2) << "Skipping unset preference: " << pref_name; 251 continue; 252 } 253 254 const PrefService::Preference* pref = prefs_->FindPreference(pref_name); 255 DCHECK(pref); 256 DCHECK(pref->IsManaged()); 257 258 const base::ListValue* pattern_str_list = NULL; 259 if (!pref->GetValue()->GetAsList(&pattern_str_list)) { 260 NOTREACHED(); 261 return; 262 } 263 264 for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { 265 std::string original_pattern_str; 266 if (!pattern_str_list->GetString(j, &original_pattern_str)) { 267 NOTREACHED(); 268 continue; 269 } 270 271 PatternPair pattern_pair = ParsePatternString(original_pattern_str); 272 // Ignore invalid patterns. 273 if (!pattern_pair.first.IsValid()) { 274 VLOG(1) << "Ignoring invalid content settings pattern: " << 275 original_pattern_str; 276 continue; 277 } 278 279 ContentSettingsType content_type = 280 kPrefsForManagedContentSettingsMap[i].content_type; 281 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE); 282 // If only one pattern was defined auto expand it to a pattern pair. 283 ContentSettingsPattern secondary_pattern = 284 !pattern_pair.second.IsValid() ? ContentSettingsPattern::Wildcard() 285 : pattern_pair.second; 286 value_map->SetValue( 287 pattern_pair.first, 288 secondary_pattern, 289 content_type, 290 NO_RESOURCE_IDENTIFIER, 291 base::Value::CreateIntegerValue( 292 kPrefsForManagedContentSettingsMap[i].setting)); 293 } 294 } 295} 296 297void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences( 298 OriginIdentifierValueMap* value_map) { 299 const char* pref_name = prefs::kManagedAutoSelectCertificateForUrls; 300 301 if (!prefs_->HasPrefPath(pref_name)) { 302 VLOG(2) << "Skipping unset preference: " << pref_name; 303 return; 304 } 305 306 const PrefService::Preference* pref = prefs_->FindPreference(pref_name); 307 DCHECK(pref); 308 DCHECK(pref->IsManaged()); 309 310 const base::ListValue* pattern_filter_str_list = NULL; 311 if (!pref->GetValue()->GetAsList(&pattern_filter_str_list)) { 312 NOTREACHED(); 313 return; 314 } 315 316 // Parse the list of pattern filter strings. A pattern filter string has 317 // the following JSON format: 318 // 319 // { 320 // "pattern": <content settings pattern string>, 321 // "filter" : <certificate filter in JSON format> 322 // } 323 // 324 // e.g. 325 // { 326 // "pattern": "[*.]example.com", 327 // "filter": { 328 // "ISSUER": { 329 // "CN": "some name" 330 // } 331 // } 332 // } 333 for (size_t j = 0; j < pattern_filter_str_list->GetSize(); ++j) { 334 std::string pattern_filter_json; 335 if (!pattern_filter_str_list->GetString(j, &pattern_filter_json)) { 336 NOTREACHED(); 337 continue; 338 } 339 340 scoped_ptr<base::Value> value(base::JSONReader::Read(pattern_filter_json, 341 base::JSON_ALLOW_TRAILING_COMMAS)); 342 if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) { 343 VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:" 344 " Invalid JSON object: " << pattern_filter_json; 345 continue; 346 } 347 348 scoped_ptr<base::DictionaryValue> pattern_filter_pair( 349 static_cast<base::DictionaryValue*>(value.release())); 350 std::string pattern_str; 351 bool pattern_read = pattern_filter_pair->GetString("pattern", &pattern_str); 352 scoped_ptr<base::Value> cert_filter; 353 bool filter_read = pattern_filter_pair->Remove("filter", &cert_filter); 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