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