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