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/host_content_settings_map.h" 6 7 #include "base/command_line.h" 8 #include "base/string_util.h" 9 #include "base/utf_string_conversions.h" 10 #include "chrome/browser/content_settings/content_settings_details.h" 11 #include "chrome/browser/content_settings/content_settings_policy_provider.h" 12 #include "chrome/browser/content_settings/content_settings_pref_provider.h" 13 #include "chrome/browser/content_settings/content_settings_provider.h" 14 #include "chrome/browser/metrics/user_metrics.h" 15 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/prefs/scoped_user_pref_update.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/common/chrome_switches.h" 19 #include "chrome/common/pref_names.h" 20 #include "chrome/common/url_constants.h" 21 #include "content/browser/browser_thread.h" 22 #include "content/common/notification_service.h" 23 #include "content/common/notification_source.h" 24 #include "content/common/notification_type.h" 25 #include "googleurl/src/gurl.h" 26 #include "net/base/net_util.h" 27 #include "net/base/static_cookie_policy.h" 28 29 namespace { 30 31 // Returns true if we should allow all content types for this URL. This is 32 // true for various internal objects like chrome:// URLs, so UI and other 33 // things users think of as "not webpages" don't break. 34 static bool ShouldAllowAllContent(const GURL& url) { 35 return url.SchemeIs(chrome::kChromeDevToolsScheme) || 36 url.SchemeIs(chrome::kChromeInternalScheme) || 37 url.SchemeIs(chrome::kChromeUIScheme) || 38 url.SchemeIs(chrome::kExtensionScheme) || 39 url.SchemeIs(chrome::kUserScriptScheme); 40 } 41 42 typedef linked_ptr<content_settings::DefaultProviderInterface> 43 DefaultContentSettingsProviderPtr; 44 typedef std::vector<DefaultContentSettingsProviderPtr>::iterator 45 DefaultProviderIterator; 46 typedef std::vector<DefaultContentSettingsProviderPtr>::const_iterator 47 ConstDefaultProviderIterator; 48 49 typedef linked_ptr<content_settings::ProviderInterface> ProviderPtr; 50 typedef std::vector<ProviderPtr>::iterator ProviderIterator; 51 typedef std::vector<ProviderPtr>::const_iterator ConstProviderIterator; 52 53 typedef content_settings::ProviderInterface::Rules Rules; 54 typedef content_settings::ProviderInterface::Rules::iterator 55 rules_iterator; 56 typedef content_settings::ProviderInterface::Rules::const_iterator 57 const_rules_iterator; 58 59 } // namespace 60 61 HostContentSettingsMap::HostContentSettingsMap(Profile* profile) 62 : profile_(profile), 63 is_off_the_record_(profile_->IsOffTheRecord()), 64 updating_preferences_(false), 65 block_third_party_cookies_(false), 66 is_block_third_party_cookies_managed_(false) { 67 // The order in which the default content settings providers are created is 68 // critical, as providers that are further down in the list (i.e. added later) 69 // override providers further up. 70 default_content_settings_providers_.push_back( 71 DefaultContentSettingsProviderPtr( 72 new content_settings::PrefDefaultProvider(profile))); 73 default_content_settings_providers_.push_back( 74 DefaultContentSettingsProviderPtr( 75 new content_settings::PolicyDefaultProvider(profile))); 76 77 PrefService* prefs = profile_->GetPrefs(); 78 79 // TODO(markusheintz): Discuss whether it is sensible to move migration code 80 // to PrefContentSettingsProvider. 81 MigrateObsoleteCookiePref(prefs); 82 83 // Read misc. global settings. 84 block_third_party_cookies_ = 85 prefs->GetBoolean(prefs::kBlockThirdPartyCookies); 86 if (block_third_party_cookies_) { 87 UserMetrics::RecordAction( 88 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); 89 } else { 90 UserMetrics::RecordAction( 91 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); 92 } 93 is_block_third_party_cookies_managed_ = 94 prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies); 95 block_nonsandboxed_plugins_ = 96 prefs->GetBoolean(prefs::kBlockNonsandboxedPlugins); 97 98 // User defined non default content settings are provided by the PrefProvider. 99 // The order in which the content settings providers are created is critical, 100 // as providers that are further up in the list (i.e. added earlier) override 101 // providers further down. 102 content_settings_providers_.push_back( 103 make_linked_ptr(new content_settings::PolicyProvider(profile))); 104 content_settings_providers_.push_back( 105 make_linked_ptr(new content_settings::PrefProvider(profile))); 106 107 pref_change_registrar_.Init(prefs); 108 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); 109 pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this); 110 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, 111 Source<Profile>(profile_)); 112 } 113 114 // static 115 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { 116 prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, false); 117 prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false); 118 prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0); 119 120 // Obsolete prefs, for migration: 121 prefs->RegisterIntegerPref(prefs::kCookieBehavior, 122 net::StaticCookiePolicy::ALLOW_ALL_COOKIES); 123 124 // Register the prefs for the content settings providers. 125 content_settings::PrefDefaultProvider::RegisterUserPrefs(prefs); 126 content_settings::PolicyDefaultProvider::RegisterUserPrefs(prefs); 127 content_settings::PrefProvider::RegisterUserPrefs(prefs); 128 content_settings::PolicyProvider::RegisterUserPrefs(prefs); 129 } 130 131 ContentSetting HostContentSettingsMap::GetDefaultContentSetting( 132 ContentSettingsType content_type) const { 133 ContentSetting setting = CONTENT_SETTING_DEFAULT; 134 for (ConstDefaultProviderIterator provider = 135 default_content_settings_providers_.begin(); 136 provider != default_content_settings_providers_.end(); ++provider) { 137 ContentSetting provided_setting = 138 (*provider)->ProvideDefaultSetting(content_type); 139 if (provided_setting != CONTENT_SETTING_DEFAULT) 140 setting = provided_setting; 141 } 142 // The method GetDefaultContentSetting always has to return an explicit 143 // value that is to be used as default. We here rely on the 144 // PrefContentSettingProvider to always provide a value. 145 CHECK_NE(CONTENT_SETTING_DEFAULT, setting); 146 return setting; 147 } 148 149 ContentSetting HostContentSettingsMap::GetContentSetting( 150 const GURL& url, 151 ContentSettingsType content_type, 152 const std::string& resource_identifier) const { 153 ContentSetting setting = GetNonDefaultContentSetting(url, 154 content_type, 155 resource_identifier); 156 if (setting == CONTENT_SETTING_DEFAULT) 157 return GetDefaultContentSetting(content_type); 158 return setting; 159 } 160 161 ContentSetting HostContentSettingsMap::GetNonDefaultContentSetting( 162 const GURL& url, 163 ContentSettingsType content_type, 164 const std::string& resource_identifier) const { 165 if (ShouldAllowAllContent(url)) 166 return CONTENT_SETTING_ALLOW; 167 168 // Iterate through the list of providers and break when the first non default 169 // setting is found. 170 ContentSetting provided_setting(CONTENT_SETTING_DEFAULT); 171 for (ConstProviderIterator provider = content_settings_providers_.begin(); 172 provider != content_settings_providers_.end(); 173 ++provider) { 174 provided_setting = (*provider)->GetContentSetting( 175 url, url, content_type, resource_identifier); 176 bool isManaged = (*provider)->ContentSettingsTypeIsManaged(content_type); 177 if (provided_setting != CONTENT_SETTING_DEFAULT || isManaged) 178 return provided_setting; 179 } 180 return provided_setting; 181 } 182 183 ContentSettings HostContentSettingsMap::GetContentSettings( 184 const GURL& url) const { 185 ContentSettings output = GetNonDefaultContentSettings(url); 186 187 // If we require a resource identifier, set the content settings to default, 188 // otherwise make the defaults explicit. 189 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { 190 // A managed default content setting has the highest priority and hence 191 // will overwrite any previously set value. 192 if (output.settings[j] == CONTENT_SETTING_DEFAULT && 193 j != CONTENT_SETTINGS_TYPE_PLUGINS) { 194 output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j)); 195 } 196 } 197 return output; 198 } 199 200 ContentSettings HostContentSettingsMap::GetNonDefaultContentSettings( 201 const GURL& url) const { 202 if (ShouldAllowAllContent(url)) 203 return ContentSettings(CONTENT_SETTING_ALLOW); 204 205 ContentSettings output(CONTENT_SETTING_DEFAULT); 206 for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) { 207 output.settings[j] = GetNonDefaultContentSetting( 208 url, ContentSettingsType(j) , ""); 209 } 210 return output; 211 } 212 213 void HostContentSettingsMap::GetSettingsForOneType( 214 ContentSettingsType content_type, 215 const std::string& resource_identifier, 216 SettingsForOneType* settings) const { 217 DCHECK(settings); 218 settings->clear(); 219 220 // Collect content_settings::Rules for the given content_type and 221 // resource_identifier from the content settings providers. 222 Rules content_settings_rules; 223 for (ConstProviderIterator provider = content_settings_providers_.begin(); 224 provider != content_settings_providers_.end(); 225 ++provider) { 226 // TODO(markusheintz): Only the rules that are applied should be collected. 227 // Merge rules. 228 // TODO(markusheintz): GetAllContentSettingsRules should maybe not clear the 229 // passed vector in case rule sets are just unified. 230 Rules rules; 231 (*provider)->GetAllContentSettingsRules( 232 content_type, resource_identifier, &rules); 233 content_settings_rules.insert(content_settings_rules.end(), 234 rules.begin(), 235 rules.end()); 236 } 237 238 // convert Rules to SettingsForOneType 239 for (const_rules_iterator rule_iterator = 240 content_settings_rules.begin(); 241 rule_iterator != content_settings_rules.end(); 242 ++rule_iterator) { 243 settings->push_back(std::make_pair(ContentSettingsPattern( 244 rule_iterator->requesting_url_pattern), 245 rule_iterator->content_setting)); 246 } 247 } 248 249 void HostContentSettingsMap::SetDefaultContentSetting( 250 ContentSettingsType content_type, 251 ContentSetting setting) { 252 for (DefaultProviderIterator provider = 253 default_content_settings_providers_.begin(); 254 provider != default_content_settings_providers_.end(); ++provider) { 255 (*provider)->UpdateDefaultSetting(content_type, setting); 256 } 257 } 258 259 void HostContentSettingsMap::SetContentSetting( 260 const ContentSettingsPattern& pattern, 261 ContentSettingsType content_type, 262 const std::string& resource_identifier, 263 ContentSetting setting) { 264 for (ProviderIterator provider = content_settings_providers_.begin(); 265 provider != content_settings_providers_.end(); 266 ++provider) { 267 (*provider)->SetContentSetting( 268 pattern, pattern, content_type, resource_identifier, setting); 269 } 270 } 271 272 void HostContentSettingsMap::AddExceptionForURL( 273 const GURL& url, 274 ContentSettingsType content_type, 275 const std::string& resource_identifier, 276 ContentSetting setting) { 277 // Make sure there is no entry that would override the pattern we are about 278 // to insert for exactly this URL. 279 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(url), 280 content_type, 281 resource_identifier, 282 CONTENT_SETTING_DEFAULT); 283 SetContentSetting(ContentSettingsPattern::FromURL(url), 284 content_type, 285 resource_identifier, 286 setting); 287 } 288 289 void HostContentSettingsMap::ClearSettingsForOneType( 290 ContentSettingsType content_type) { 291 for (ProviderIterator provider = content_settings_providers_.begin(); 292 provider != content_settings_providers_.end(); 293 ++provider) { 294 (*provider)->ClearAllContentSettingsRules(content_type); 295 } 296 } 297 298 void HostContentSettingsMap::SetBlockThirdPartyCookies(bool block) { 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 300 301 // This setting may not be directly modified for OTR sessions. Instead, it 302 // is synced to the main profile's setting. 303 if (is_off_the_record_) { 304 NOTREACHED(); 305 return; 306 } 307 308 PrefService* prefs = profile_->GetPrefs(); 309 // If the preference block-third-party-cookies is managed then do not allow to 310 // change it. 311 if (prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies)) { 312 NOTREACHED(); 313 return; 314 } 315 316 { 317 base::AutoLock auto_lock(lock_); 318 block_third_party_cookies_ = block; 319 } 320 321 if (block) 322 prefs->SetBoolean(prefs::kBlockThirdPartyCookies, true); 323 else 324 prefs->ClearPref(prefs::kBlockThirdPartyCookies); 325 } 326 327 void HostContentSettingsMap::SetBlockNonsandboxedPlugins(bool block) { 328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 329 330 // This setting may not be directly modified for OTR sessions. Instead, it 331 // is synced to the main profile's setting. 332 if (is_off_the_record_) { 333 NOTREACHED(); 334 return; 335 } 336 337 { 338 base::AutoLock auto_lock(lock_); 339 block_nonsandboxed_plugins_ = block; 340 } 341 342 PrefService* prefs = profile_->GetPrefs(); 343 if (block) { 344 UserMetrics::RecordAction( 345 UserMetricsAction("BlockNonsandboxedPlugins_Enable")); 346 prefs->SetBoolean(prefs::kBlockNonsandboxedPlugins, true); 347 } else { 348 UserMetrics::RecordAction( 349 UserMetricsAction("BlockNonsandboxedPlugins_Disable")); 350 prefs->ClearPref(prefs::kBlockNonsandboxedPlugins); 351 } 352 } 353 354 void HostContentSettingsMap::ResetToDefaults() { 355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 356 357 { 358 base::AutoLock auto_lock(lock_); 359 for (DefaultProviderIterator provider = 360 default_content_settings_providers_.begin(); 361 provider != default_content_settings_providers_.end(); ++provider) { 362 (*provider)->ResetToDefaults(); 363 } 364 365 for (ProviderIterator provider = content_settings_providers_.begin(); 366 provider != content_settings_providers_.end(); 367 ++provider) { 368 (*provider)->ResetToDefaults(); 369 } 370 371 // Don't reset block third party cookies if they are managed. 372 if (!IsBlockThirdPartyCookiesManaged()) 373 block_third_party_cookies_ = false; 374 block_nonsandboxed_plugins_ = false; 375 } 376 377 if (!is_off_the_record_) { 378 PrefService* prefs = profile_->GetPrefs(); 379 updating_preferences_ = true; 380 // If the block third party cookies preference is managed we still must 381 // clear it in order to restore the default value for later when the 382 // preference is not managed anymore. 383 prefs->ClearPref(prefs::kBlockThirdPartyCookies); 384 prefs->ClearPref(prefs::kBlockNonsandboxedPlugins); 385 updating_preferences_ = false; 386 NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(), 387 CONTENT_SETTINGS_TYPE_DEFAULT, 388 "")); 389 } 390 } 391 392 void HostContentSettingsMap::Observe(NotificationType type, 393 const NotificationSource& source, 394 const NotificationDetails& details) { 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 396 397 if (type == NotificationType::PREF_CHANGED) { 398 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); 399 if (updating_preferences_) 400 return; 401 402 std::string* name = Details<std::string>(details).ptr(); 403 if (*name == prefs::kBlockThirdPartyCookies) { 404 base::AutoLock auto_lock(lock_); 405 block_third_party_cookies_ = profile_->GetPrefs()->GetBoolean( 406 prefs::kBlockThirdPartyCookies); 407 is_block_third_party_cookies_managed_ = 408 profile_->GetPrefs()->IsManagedPreference( 409 prefs::kBlockThirdPartyCookies); 410 } else if (*name == prefs::kBlockNonsandboxedPlugins) { 411 base::AutoLock auto_lock(lock_); 412 block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean( 413 prefs::kBlockNonsandboxedPlugins); 414 } else { 415 NOTREACHED() << "Unexpected preference observed"; 416 return; 417 } 418 419 if (!is_off_the_record_) { 420 NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(), 421 CONTENT_SETTINGS_TYPE_DEFAULT, 422 "")); 423 } 424 } else if (type == NotificationType::PROFILE_DESTROYED) { 425 DCHECK_EQ(profile_, Source<Profile>(source).ptr()); 426 UnregisterObservers(); 427 } else { 428 NOTREACHED() << "Unexpected notification"; 429 } 430 } 431 432 HostContentSettingsMap::~HostContentSettingsMap() { 433 UnregisterObservers(); 434 } 435 436 bool HostContentSettingsMap::IsDefaultContentSettingManaged( 437 ContentSettingsType content_type) const { 438 for (ConstDefaultProviderIterator provider = 439 default_content_settings_providers_.begin(); 440 provider != default_content_settings_providers_.end(); ++provider) { 441 if ((*provider)->DefaultSettingIsManaged(content_type)) 442 return true; 443 } 444 return false; 445 } 446 447 void HostContentSettingsMap::NotifyObservers( 448 const ContentSettingsDetails& details) { 449 NotificationService::current()->Notify( 450 NotificationType::CONTENT_SETTINGS_CHANGED, 451 Source<HostContentSettingsMap>(this), 452 Details<const ContentSettingsDetails>(&details)); 453 } 454 455 void HostContentSettingsMap::UnregisterObservers() { 456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 457 if (!profile_) 458 return; 459 pref_change_registrar_.RemoveAll(); 460 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, 461 Source<Profile>(profile_)); 462 profile_ = NULL; 463 } 464 465 void HostContentSettingsMap::MigrateObsoleteCookiePref(PrefService* prefs) { 466 if (prefs->HasPrefPath(prefs::kCookieBehavior)) { 467 int cookie_behavior = prefs->GetInteger(prefs::kCookieBehavior); 468 prefs->ClearPref(prefs::kCookieBehavior); 469 if (!prefs->HasPrefPath(prefs::kDefaultContentSettings)) { 470 SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES, 471 (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ? 472 CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW); 473 } 474 if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) { 475 SetBlockThirdPartyCookies(cookie_behavior == 476 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); 477 } 478 } 479 } 480