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