1 // Copyright (c) 2011 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/command_line.h" 11 #include "chrome/browser/content_settings/content_settings_details.h" 12 #include "chrome/browser/content_settings/content_settings_pattern.h" 13 #include "chrome/browser/prefs/pref_service.h" 14 #include "chrome/browser/prefs/scoped_user_pref_update.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/common/pref_names.h" 17 #include "content/browser/browser_thread.h" 18 #include "content/common/notification_details.h" 19 #include "content/common/notification_service.h" 20 #include "content/common/notification_source.h" 21 #include "webkit/plugins/npapi/plugin_group.h" 22 #include "webkit/plugins/npapi/plugin_list.h" 23 24 namespace { 25 26 // Base pref path of the prefs that contain the managed default content 27 // settings values. 28 const std::string kManagedSettings = 29 "profile.managed_default_content_settings"; 30 31 // The preferences used to manage ContentSettingsTypes. 32 const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = { 33 prefs::kManagedDefaultCookiesSetting, 34 prefs::kManagedDefaultImagesSetting, 35 prefs::kManagedDefaultJavaScriptSetting, 36 prefs::kManagedDefaultPluginsSetting, 37 prefs::kManagedDefaultPopupsSetting, 38 NULL, // Not used for Geolocation 39 NULL, // Not used for Notifications 40 }; 41 42 struct PrefsForManagedContentSettingsMapEntry { 43 const char* pref_name; 44 ContentSettingsType content_type; 45 ContentSetting setting; 46 }; 47 48 const PrefsForManagedContentSettingsMapEntry 49 kPrefsForManagedContentSettingsMap[] = { 50 { 51 prefs::kManagedCookiesAllowedForUrls, 52 CONTENT_SETTINGS_TYPE_COOKIES, 53 CONTENT_SETTING_ALLOW 54 }, { 55 prefs::kManagedCookiesSessionOnlyForUrls, 56 CONTENT_SETTINGS_TYPE_COOKIES, 57 CONTENT_SETTING_SESSION_ONLY 58 }, { 59 prefs::kManagedCookiesBlockedForUrls, 60 CONTENT_SETTINGS_TYPE_COOKIES, 61 CONTENT_SETTING_BLOCK 62 }, { 63 prefs::kManagedImagesAllowedForUrls, 64 CONTENT_SETTINGS_TYPE_IMAGES, 65 CONTENT_SETTING_ALLOW 66 }, { 67 prefs::kManagedImagesBlockedForUrls, 68 CONTENT_SETTINGS_TYPE_IMAGES, 69 CONTENT_SETTING_BLOCK 70 }, { 71 prefs::kManagedJavaScriptAllowedForUrls, 72 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 73 CONTENT_SETTING_ALLOW 74 }, { 75 prefs::kManagedJavaScriptBlockedForUrls, 76 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 77 CONTENT_SETTING_BLOCK 78 }, { 79 prefs::kManagedPluginsAllowedForUrls, 80 CONTENT_SETTINGS_TYPE_PLUGINS, 81 CONTENT_SETTING_ALLOW 82 }, { 83 prefs::kManagedPluginsBlockedForUrls, 84 CONTENT_SETTINGS_TYPE_PLUGINS, 85 CONTENT_SETTING_BLOCK 86 }, { 87 prefs::kManagedPopupsAllowedForUrls, 88 CONTENT_SETTINGS_TYPE_POPUPS, 89 CONTENT_SETTING_ALLOW 90 }, { 91 prefs::kManagedPopupsBlockedForUrls, 92 CONTENT_SETTINGS_TYPE_POPUPS, 93 CONTENT_SETTING_BLOCK 94 } 95 }; 96 97 } // namespace 98 99 namespace content_settings { 100 101 PolicyDefaultProvider::PolicyDefaultProvider(Profile* profile) 102 : profile_(profile), 103 is_off_the_record_(profile_->IsOffTheRecord()) { 104 PrefService* prefs = profile->GetPrefs(); 105 106 // Read global defaults. 107 DCHECK_EQ(arraysize(kPrefToManageType), 108 static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); 109 ReadManagedDefaultSettings(); 110 111 pref_change_registrar_.Init(prefs); 112 // The following preferences are only used to indicate if a 113 // default-content-setting is managed and to hold the managed default-setting 114 // value. If the value for any of the following perferences is set then the 115 // corresponding default-content-setting is managed. These preferences exist 116 // in parallel to the preference default-content-settings. If a 117 // default-content-settings-type is managed any user defined excpetions 118 // (patterns) for this type are ignored. 119 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); 120 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); 121 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); 122 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); 123 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); 124 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, 125 Source<Profile>(profile_)); 126 } 127 128 PolicyDefaultProvider::~PolicyDefaultProvider() { 129 UnregisterObservers(); 130 } 131 132 ContentSetting PolicyDefaultProvider::ProvideDefaultSetting( 133 ContentSettingsType content_type) const { 134 base::AutoLock auto_lock(lock_); 135 return managed_default_content_settings_.settings[content_type]; 136 } 137 138 void PolicyDefaultProvider::UpdateDefaultSetting( 139 ContentSettingsType content_type, 140 ContentSetting setting) { 141 } 142 143 bool PolicyDefaultProvider::DefaultSettingIsManaged( 144 ContentSettingsType content_type) const { 145 base::AutoLock lock(lock_); 146 if (managed_default_content_settings_.settings[content_type] != 147 CONTENT_SETTING_DEFAULT) { 148 return true; 149 } else { 150 return false; 151 } 152 } 153 154 void PolicyDefaultProvider::ResetToDefaults() { 155 } 156 157 void PolicyDefaultProvider::Observe(NotificationType type, 158 const NotificationSource& source, 159 const NotificationDetails& details) { 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 161 162 if (type == NotificationType::PREF_CHANGED) { 163 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); 164 std::string* name = Details<std::string>(details).ptr(); 165 if (*name == prefs::kManagedDefaultCookiesSetting) { 166 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES); 167 } else if (*name == prefs::kManagedDefaultImagesSetting) { 168 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES); 169 } else if (*name == prefs::kManagedDefaultJavaScriptSetting) { 170 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT); 171 } else if (*name == prefs::kManagedDefaultPluginsSetting) { 172 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS); 173 } else if (*name == prefs::kManagedDefaultPopupsSetting) { 174 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS); 175 } else { 176 NOTREACHED() << "Unexpected preference observed"; 177 return; 178 } 179 180 if (!is_off_the_record_) { 181 NotifyObservers(ContentSettingsDetails( 182 ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); 183 } 184 } else if (type == NotificationType::PROFILE_DESTROYED) { 185 DCHECK_EQ(profile_, Source<Profile>(source).ptr()); 186 UnregisterObservers(); 187 } else { 188 NOTREACHED() << "Unexpected notification"; 189 } 190 } 191 192 void PolicyDefaultProvider::UnregisterObservers() { 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 194 if (!profile_) 195 return; 196 pref_change_registrar_.RemoveAll(); 197 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, 198 Source<Profile>(profile_)); 199 profile_ = NULL; 200 } 201 202 203 void PolicyDefaultProvider::NotifyObservers( 204 const ContentSettingsDetails& details) { 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 206 if (profile_ == NULL) 207 return; 208 NotificationService::current()->Notify( 209 NotificationType::CONTENT_SETTINGS_CHANGED, 210 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), 211 Details<const ContentSettingsDetails>(&details)); 212 } 213 214 void PolicyDefaultProvider::ReadManagedDefaultSettings() { 215 for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { 216 if (kPrefToManageType[type] == NULL) { 217 continue; 218 } 219 UpdateManagedDefaultSetting(ContentSettingsType(type)); 220 } 221 } 222 223 void PolicyDefaultProvider::UpdateManagedDefaultSetting( 224 ContentSettingsType type) { 225 // If a pref to manage a default-content-setting was not set (NOTICE: 226 // "HasPrefPath" returns false if no value was set for a registered pref) then 227 // the default value of the preference is used. The default value of a 228 // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT. 229 // This indicates that no managed value is set. If a pref was set, than it 230 // MUST be managed. 231 PrefService* prefs = profile_->GetPrefs(); 232 DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) || 233 prefs->IsManagedPreference(kPrefToManageType[type])); 234 base::AutoLock auto_lock(lock_); 235 managed_default_content_settings_.settings[type] = IntToContentSetting( 236 prefs->GetInteger(kPrefToManageType[type])); 237 } 238 239 // static 240 void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) { 241 // Preferences for default content setting policies. A policy is not set of 242 // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. 243 prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting, 244 CONTENT_SETTING_DEFAULT); 245 prefs->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting, 246 CONTENT_SETTING_DEFAULT); 247 prefs->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting, 248 CONTENT_SETTING_DEFAULT); 249 prefs->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting, 250 CONTENT_SETTING_DEFAULT); 251 prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting, 252 CONTENT_SETTING_DEFAULT); 253 } 254 255 // //////////////////////////////////////////////////////////////////////////// 256 // PolicyProvider 257 258 // static 259 void PolicyProvider::RegisterUserPrefs(PrefService* prefs) { 260 prefs->RegisterListPref(prefs::kManagedCookiesAllowedForUrls); 261 prefs->RegisterListPref(prefs::kManagedCookiesBlockedForUrls); 262 prefs->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls); 263 prefs->RegisterListPref(prefs::kManagedImagesAllowedForUrls); 264 prefs->RegisterListPref(prefs::kManagedImagesBlockedForUrls); 265 prefs->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls); 266 prefs->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls); 267 prefs->RegisterListPref(prefs::kManagedPluginsAllowedForUrls); 268 prefs->RegisterListPref(prefs::kManagedPluginsBlockedForUrls); 269 prefs->RegisterListPref(prefs::kManagedPopupsAllowedForUrls); 270 prefs->RegisterListPref(prefs::kManagedPopupsBlockedForUrls); 271 } 272 273 PolicyProvider::PolicyProvider(Profile* profile) 274 : BaseProvider(profile->IsOffTheRecord()), 275 profile_(profile) { 276 Init(); 277 } 278 279 PolicyProvider::~PolicyProvider() { 280 UnregisterObservers(); 281 } 282 283 void PolicyProvider::ReadManagedContentSettingsTypes( 284 ContentSettingsType content_type) { 285 PrefService* prefs = profile_->GetPrefs(); 286 if (kPrefToManageType[content_type] == NULL) { 287 content_type_is_managed_[content_type] = false; 288 } else { 289 content_type_is_managed_[content_type] = 290 prefs->IsManagedPreference(kPrefToManageType[content_type]); 291 } 292 } 293 294 void PolicyProvider::Init() { 295 PrefService* prefs = profile_->GetPrefs(); 296 297 ReadManagedContentSettings(false); 298 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) 299 ReadManagedContentSettingsTypes(ContentSettingsType(i)); 300 301 pref_change_registrar_.Init(prefs); 302 pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, this); 303 pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, this); 304 pref_change_registrar_.Add(prefs::kManagedCookiesSessionOnlyForUrls, this); 305 pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, this); 306 pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, this); 307 pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, this); 308 pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, this); 309 pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, this); 310 pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, this); 311 pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, this); 312 pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, this); 313 314 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); 315 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); 316 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); 317 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); 318 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); 319 320 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, 321 Source<Profile>(profile_)); 322 } 323 324 bool PolicyProvider::ContentSettingsTypeIsManaged( 325 ContentSettingsType content_type) { 326 return content_type_is_managed_[content_type]; 327 } 328 329 void PolicyProvider::GetContentSettingsFromPreferences( 330 PrefService* prefs, 331 ContentSettingsRules* rules) { 332 for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) { 333 const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name; 334 // Skip unset policies. 335 if (!prefs->HasPrefPath(pref_name)) { 336 VLOG(2) << "Skipping unset preference: " << pref_name; 337 continue; 338 } 339 340 const PrefService::Preference* pref = prefs->FindPreference(pref_name); 341 DCHECK(pref->IsManaged()); 342 DCHECK_EQ(Value::TYPE_LIST, pref->GetType()); 343 344 const ListValue* pattern_str_list = 345 static_cast<const ListValue*>(pref->GetValue()); 346 for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { 347 std::string original_pattern_str; 348 pattern_str_list->GetString(j, &original_pattern_str); 349 ContentSettingsPattern pattern(original_pattern_str); 350 // Ignore invalid patterns. 351 if (!pattern.IsValid()) { 352 VLOG(1) << "Ignoring invalid content settings pattern: " << 353 pattern.AsString(); 354 continue; 355 } 356 rules->push_back(MakeTuple( 357 pattern, 358 pattern, 359 kPrefsForManagedContentSettingsMap[i].content_type, 360 ProviderInterface::ResourceIdentifier(NO_RESOURCE_IDENTIFIER), 361 kPrefsForManagedContentSettingsMap[i].setting)); 362 } 363 } 364 } 365 366 void PolicyProvider::ReadManagedContentSettings(bool overwrite) { 367 ContentSettingsRules rules; 368 PrefService* prefs = profile_->GetPrefs(); 369 GetContentSettingsFromPreferences(prefs, &rules); 370 { 371 base::AutoLock auto_lock(lock()); 372 HostContentSettings* content_settings_map = host_content_settings(); 373 if (overwrite) 374 content_settings_map->clear(); 375 for (ContentSettingsRules::iterator rule = rules.begin(); 376 rule != rules.end(); 377 ++rule) { 378 DispatchToMethod(this, &PolicyProvider::UpdateContentSettingsMap, *rule); 379 } 380 } 381 } 382 383 // Since the PolicyProvider is a read only content settings provider, all 384 // methodes of the ProviderInterface that set or delete any settings do nothing. 385 void PolicyProvider::SetContentSetting( 386 const ContentSettingsPattern& requesting_pattern, 387 const ContentSettingsPattern& embedding_pattern, 388 ContentSettingsType content_type, 389 const ResourceIdentifier& resource_identifier, 390 ContentSetting content_setting) { 391 } 392 393 ContentSetting PolicyProvider::GetContentSetting( 394 const GURL& requesting_url, 395 const GURL& embedding_url, 396 ContentSettingsType content_type, 397 const ResourceIdentifier& resource_identifier) const { 398 return BaseProvider::GetContentSetting( 399 requesting_url, 400 embedding_url, 401 content_type, 402 NO_RESOURCE_IDENTIFIER); 403 } 404 405 void PolicyProvider::ClearAllContentSettingsRules( 406 ContentSettingsType content_type) { 407 } 408 409 void PolicyProvider::ResetToDefaults() { 410 } 411 412 void PolicyProvider::UnregisterObservers() { 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 414 if (!profile_) 415 return; 416 pref_change_registrar_.RemoveAll(); 417 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, 418 Source<Profile>(profile_)); 419 profile_ = NULL; 420 } 421 422 void PolicyProvider::NotifyObservers( 423 const ContentSettingsDetails& details) { 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 425 if (profile_ == NULL) 426 return; 427 NotificationService::current()->Notify( 428 NotificationType::CONTENT_SETTINGS_CHANGED, 429 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), 430 Details<const ContentSettingsDetails>(&details)); 431 } 432 433 void PolicyProvider::Observe(NotificationType type, 434 const NotificationSource& source, 435 const NotificationDetails& details) { 436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 437 438 if (type == NotificationType::PREF_CHANGED) { 439 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); 440 std::string* name = Details<std::string>(details).ptr(); 441 if (*name == prefs::kManagedCookiesAllowedForUrls || 442 *name == prefs::kManagedCookiesBlockedForUrls || 443 *name == prefs::kManagedCookiesSessionOnlyForUrls || 444 *name == prefs::kManagedImagesAllowedForUrls || 445 *name == prefs::kManagedImagesBlockedForUrls || 446 *name == prefs::kManagedJavaScriptAllowedForUrls || 447 *name == prefs::kManagedJavaScriptBlockedForUrls || 448 *name == prefs::kManagedPluginsAllowedForUrls || 449 *name == prefs::kManagedPluginsBlockedForUrls || 450 *name == prefs::kManagedPopupsAllowedForUrls || 451 *name == prefs::kManagedPopupsBlockedForUrls) { 452 ReadManagedContentSettings(true); 453 NotifyObservers(ContentSettingsDetails( 454 ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); 455 // We do not want to sent a notification when managed default content 456 // settings change. The DefaultProvider will take care of that. We are 457 // only a passive observer. 458 // TODO(markusheintz): NOTICE: This is still work in progress and part of 459 // a larger refactoring. The code will change and be much cleaner and 460 // clearer in the end. 461 } else if (*name == prefs::kManagedDefaultCookiesSetting) { 462 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_COOKIES); 463 } else if (*name == prefs::kManagedDefaultImagesSetting) { 464 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_IMAGES); 465 } else if (*name == prefs::kManagedDefaultJavaScriptSetting) { 466 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_JAVASCRIPT); 467 } else if (*name == prefs::kManagedDefaultPluginsSetting) { 468 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_PLUGINS); 469 } else if (*name == prefs::kManagedDefaultPopupsSetting) { 470 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_POPUPS); 471 } 472 } else if (type == NotificationType::PROFILE_DESTROYED) { 473 DCHECK_EQ(profile_, Source<Profile>(source).ptr()); 474 UnregisterObservers(); 475 } else { 476 NOTREACHED() << "Unexpected notification"; 477 } 478 } 479 480 } // namespace content_settings 481