host_content_settings_map.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h" 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <utility> 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/basictypes.h" 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/command_line.h" 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/prefs/pref_service.h" 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/stl_util.h" 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_util.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/time/clock.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_custom_extension_provider.h" 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_default_provider.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_details.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_internal_extension_provider.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_observable_provider.h" 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_policy_provider.h" 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_pref_provider.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h" 257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "chrome/browser/content_settings/content_settings_rule.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/content_settings/content_settings_utils.h" 27c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "chrome/browser/extensions/api/content_settings/content_settings_service.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/common/content_settings_pattern.h" 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/common/pref_names.h" 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/common/url_constants.h" 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/notification_service.h" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/notification_source.h" 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/common/content_switches.h" 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/browser/extension_prefs.h" 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/common/constants.h" 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "net/base/net_errors.h" 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "net/base/static_cookie_policy.h" 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "url/gurl.h" 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using base::UserMetricsAction; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using content::BrowserThread; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace { 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef std::vector<content_settings::Rule> Rules; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef std::pair<std::string, std::string> StringPair; 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// TODO(bauerb): Expose constants. 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* kProviderNames[] = { 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "platform_app", 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "policy", 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "extension", 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "preference", 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "default" 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)content_settings::SettingSource kProviderSourceMap[] = { 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content_settings::SETTING_SOURCE_EXTENSION, 65e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) content_settings::SETTING_SOURCE_POLICY, 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content_settings::SETTING_SOURCE_EXTENSION, 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) content_settings::SETTING_SOURCE_USER, 68 content_settings::SETTING_SOURCE_USER, 69}; 70COMPILE_ASSERT(arraysize(kProviderSourceMap) == 71 HostContentSettingsMap::NUM_PROVIDER_TYPES, 72 kProviderSourceMap_has_incorrect_size); 73 74// Returns true if the |content_type| supports a resource identifier. 75// Resource identifiers are supported (but not required) for plug-ins. 76bool SupportsResourceIdentifier(ContentSettingsType content_type) { 77 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 78} 79 80} // namespace 81 82HostContentSettingsMap::HostContentSettingsMap( 83 PrefService* prefs, 84 bool incognito) : 85#ifndef NDEBUG 86 used_from_thread_id_(base::PlatformThread::CurrentId()), 87#endif 88 prefs_(prefs), 89 is_off_the_record_(incognito) { 90 content_settings::ObservableProvider* policy_provider = 91 new content_settings::PolicyProvider(prefs_); 92 policy_provider->AddObserver(this); 93 content_settings_providers_[POLICY_PROVIDER] = policy_provider; 94 95 content_settings::ObservableProvider* pref_provider = 96 new content_settings::PrefProvider(prefs_, is_off_the_record_); 97 pref_provider->AddObserver(this); 98 content_settings_providers_[PREF_PROVIDER] = pref_provider; 99 100 content_settings::ObservableProvider* default_provider = 101 new content_settings::DefaultProvider(prefs_, is_off_the_record_); 102 default_provider->AddObserver(this); 103 content_settings_providers_[DEFAULT_PROVIDER] = default_provider; 104 105 if (!is_off_the_record_) { 106 // Migrate obsolete preferences. 107 MigrateObsoleteClearOnExitPref(); 108 } 109} 110 111#if defined(ENABLE_EXTENSIONS) 112void HostContentSettingsMap::RegisterExtensionService( 113 ExtensionService* extension_service) { 114 DCHECK(extension_service); 115 DCHECK(!content_settings_providers_[INTERNAL_EXTENSION_PROVIDER]); 116 DCHECK(!content_settings_providers_[CUSTOM_EXTENSION_PROVIDER]); 117 118 content_settings::InternalExtensionProvider* internal_extension_provider = 119 new content_settings::InternalExtensionProvider(extension_service); 120 internal_extension_provider->AddObserver(this); 121 content_settings_providers_[INTERNAL_EXTENSION_PROVIDER] = 122 internal_extension_provider; 123 124 content_settings::ObservableProvider* custom_extension_provider = 125 new content_settings::CustomExtensionProvider( 126 extensions::ContentSettingsService::Get( 127 extension_service->GetBrowserContext())->content_settings_store(), 128 is_off_the_record_); 129 custom_extension_provider->AddObserver(this); 130 content_settings_providers_[CUSTOM_EXTENSION_PROVIDER] = 131 custom_extension_provider; 132 133#ifndef NDEBUG 134 DCHECK(used_from_thread_id_ != base::kInvalidThreadId) 135 << "Used from multiple threads before initialization complete."; 136#endif 137 138 OnContentSettingChanged(ContentSettingsPattern(), 139 ContentSettingsPattern(), 140 CONTENT_SETTINGS_TYPE_DEFAULT, 141 std::string()); 142} 143#endif 144 145// static 146void HostContentSettingsMap::RegisterProfilePrefs( 147 user_prefs::PrefRegistrySyncable* registry) { 148 registry->RegisterIntegerPref( 149 prefs::kContentSettingsWindowLastTabIndex, 150 0, 151 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 152 registry->RegisterIntegerPref( 153 prefs::kContentSettingsDefaultWhitelistVersion, 154 0, 155 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 156 registry->RegisterBooleanPref( 157 prefs::kContentSettingsClearOnExitMigrated, 158 false, 159 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 160 161 // Register the prefs for the content settings providers. 162 content_settings::DefaultProvider::RegisterProfilePrefs(registry); 163 content_settings::PrefProvider::RegisterProfilePrefs(registry); 164 content_settings::PolicyProvider::RegisterProfilePrefs(registry); 165} 166 167ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider( 168 ContentSettingsType content_type, 169 content_settings::ProviderInterface* provider) const { 170 scoped_ptr<content_settings::RuleIterator> rule_iterator( 171 provider->GetRuleIterator(content_type, std::string(), false)); 172 173 ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); 174 while (rule_iterator->HasNext()) { 175 content_settings::Rule rule = rule_iterator->Next(); 176 if (rule.primary_pattern == wildcard && 177 rule.secondary_pattern == wildcard) { 178 return content_settings::ValueToContentSetting(rule.value.get()); 179 } 180 } 181 return CONTENT_SETTING_DEFAULT; 182} 183 184ContentSetting HostContentSettingsMap::GetDefaultContentSetting( 185 ContentSettingsType content_type, 186 std::string* provider_id) const { 187 UsedContentSettingsProviders(); 188 189 // Iterate through the list of providers and return the first non-NULL value 190 // that matches |primary_url| and |secondary_url|. 191 for (ConstProviderIterator provider = content_settings_providers_.begin(); 192 provider != content_settings_providers_.end(); 193 ++provider) { 194 if (provider->first == PREF_PROVIDER) 195 continue; 196 ContentSetting default_setting = 197 GetDefaultContentSettingFromProvider(content_type, provider->second); 198 if (default_setting != CONTENT_SETTING_DEFAULT) { 199 if (provider_id) 200 *provider_id = kProviderNames[provider->first]; 201 return default_setting; 202 } 203 } 204 205 // The method GetDefaultContentSetting always has to return an explicit 206 // value that is to be used as default. We here rely on the 207 // DefaultProvider to always provide a value. 208 NOTREACHED(); 209 return CONTENT_SETTING_DEFAULT; 210} 211 212ContentSetting HostContentSettingsMap::GetContentSetting( 213 const GURL& primary_url, 214 const GURL& secondary_url, 215 ContentSettingsType content_type, 216 const std::string& resource_identifier) const { 217 DCHECK(!ContentTypeHasCompoundValue(content_type)); 218 scoped_ptr<base::Value> value(GetWebsiteSetting( 219 primary_url, secondary_url, content_type, resource_identifier, NULL)); 220 return content_settings::ValueToContentSetting(value.get()); 221} 222 223void HostContentSettingsMap::GetSettingsForOneType( 224 ContentSettingsType content_type, 225 const std::string& resource_identifier, 226 ContentSettingsForOneType* settings) const { 227 DCHECK(SupportsResourceIdentifier(content_type) || 228 resource_identifier.empty()); 229 DCHECK(settings); 230 UsedContentSettingsProviders(); 231 232 settings->clear(); 233 for (ConstProviderIterator provider = content_settings_providers_.begin(); 234 provider != content_settings_providers_.end(); 235 ++provider) { 236 // For each provider, iterate first the incognito-specific rules, then the 237 // normal rules. 238 if (is_off_the_record_) { 239 AddSettingsForOneType(provider->second, 240 provider->first, 241 content_type, 242 resource_identifier, 243 settings, 244 true); 245 } 246 AddSettingsForOneType(provider->second, 247 provider->first, 248 content_type, 249 resource_identifier, 250 settings, 251 false); 252 } 253} 254 255void HostContentSettingsMap::SetDefaultContentSetting( 256 ContentSettingsType content_type, 257 ContentSetting setting) { 258 DCHECK(IsSettingAllowedForType(prefs_, setting, content_type)); 259 260 base::Value* value = NULL; 261 if (setting != CONTENT_SETTING_DEFAULT) 262 value = new base::FundamentalValue(setting); 263 SetWebsiteSetting( 264 ContentSettingsPattern::Wildcard(), 265 ContentSettingsPattern::Wildcard(), 266 content_type, 267 std::string(), 268 value); 269} 270 271void HostContentSettingsMap::SetWebsiteSetting( 272 const ContentSettingsPattern& primary_pattern, 273 const ContentSettingsPattern& secondary_pattern, 274 ContentSettingsType content_type, 275 const std::string& resource_identifier, 276 base::Value* value) { 277 DCHECK(IsValueAllowedForType(prefs_, value, content_type)); 278 DCHECK(SupportsResourceIdentifier(content_type) || 279 resource_identifier.empty()); 280 UsedContentSettingsProviders(); 281 282 for (ProviderIterator provider = content_settings_providers_.begin(); 283 provider != content_settings_providers_.end(); 284 ++provider) { 285 if (provider->second->SetWebsiteSetting(primary_pattern, 286 secondary_pattern, 287 content_type, 288 resource_identifier, 289 value)) { 290 return; 291 } 292 } 293 NOTREACHED(); 294} 295 296void HostContentSettingsMap::SetNarrowestWebsiteSetting( 297 const ContentSettingsPattern& primary_pattern, 298 const ContentSettingsPattern& secondary_pattern, 299 ContentSettingsType content_type, 300 const std::string& resource_identifier, 301 ContentSetting setting, 302 content_settings::SettingInfo existing_info) { 303 ContentSettingsPattern narrow_primary = primary_pattern; 304 ContentSettingsPattern narrow_secondary = secondary_pattern; 305 306 DCHECK_EQ(content_settings::SETTING_SOURCE_USER, existing_info.source); 307 ContentSettingsPattern::Relation r1 = 308 existing_info.primary_pattern.Compare(primary_pattern); 309 if (r1 == ContentSettingsPattern::PREDECESSOR) { 310 narrow_primary = existing_info.primary_pattern; 311 } else if (r1 == ContentSettingsPattern::IDENTITY) { 312 ContentSettingsPattern::Relation r2 = 313 existing_info.secondary_pattern.Compare(secondary_pattern); 314 DCHECK(r2 != ContentSettingsPattern::DISJOINT_ORDER_POST && 315 r2 != ContentSettingsPattern::DISJOINT_ORDER_PRE); 316 if (r2 == ContentSettingsPattern::PREDECESSOR) 317 narrow_secondary = existing_info.secondary_pattern; 318 } 319 320 SetContentSetting( 321 narrow_primary, narrow_secondary, content_type, std::string(), setting); 322} 323 324void HostContentSettingsMap::SetContentSetting( 325 const ContentSettingsPattern& primary_pattern, 326 const ContentSettingsPattern& secondary_pattern, 327 ContentSettingsType content_type, 328 const std::string& resource_identifier, 329 ContentSetting setting) { 330 DCHECK(!ContentTypeHasCompoundValue(content_type)); 331 332 if (setting == CONTENT_SETTING_ALLOW && 333 (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 334 content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)) { 335 UpdateLastUsageByPattern(primary_pattern, secondary_pattern, content_type); 336 } 337 338 base::Value* value = NULL; 339 if (setting != CONTENT_SETTING_DEFAULT) 340 value = new base::FundamentalValue(setting); 341 SetWebsiteSetting(primary_pattern, 342 secondary_pattern, 343 content_type, 344 resource_identifier, 345 value); 346} 347 348ContentSetting HostContentSettingsMap::GetContentSettingAndMaybeUpdateLastUsage( 349 const GURL& primary_url, 350 const GURL& secondary_url, 351 ContentSettingsType content_type, 352 const std::string& resource_identifier) { 353 DCHECK_CURRENTLY_ON(BrowserThread::UI); 354 355 ContentSetting setting = GetContentSetting( 356 primary_url, secondary_url, content_type, resource_identifier); 357 if (setting == CONTENT_SETTING_ALLOW) { 358 UpdateLastUsageByPattern( 359 ContentSettingsPattern::FromURLNoWildcard(primary_url), 360 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 361 content_type); 362 } 363 return setting; 364} 365 366void HostContentSettingsMap::UpdateLastUsage(const GURL& primary_url, 367 const GURL& secondary_url, 368 ContentSettingsType content_type) { 369 UpdateLastUsageByPattern( 370 ContentSettingsPattern::FromURLNoWildcard(primary_url), 371 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 372 content_type); 373} 374 375void HostContentSettingsMap::UpdateLastUsageByPattern( 376 const ContentSettingsPattern& primary_pattern, 377 const ContentSettingsPattern& secondary_pattern, 378 ContentSettingsType content_type) { 379 UsedContentSettingsProviders(); 380 381 GetPrefProvider()->UpdateLastUsage( 382 primary_pattern, secondary_pattern, content_type); 383} 384 385base::Time HostContentSettingsMap::GetLastUsage( 386 const GURL& primary_url, 387 const GURL& secondary_url, 388 ContentSettingsType content_type) { 389 return GetLastUsageByPattern( 390 ContentSettingsPattern::FromURLNoWildcard(primary_url), 391 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 392 content_type); 393} 394 395base::Time HostContentSettingsMap::GetLastUsageByPattern( 396 const ContentSettingsPattern& primary_pattern, 397 const ContentSettingsPattern& secondary_pattern, 398 ContentSettingsType content_type) { 399 UsedContentSettingsProviders(); 400 401 return GetPrefProvider()->GetLastUsage( 402 primary_pattern, secondary_pattern, content_type); 403} 404 405void HostContentSettingsMap::AddObserver(content_settings::Observer* observer) { 406 observers_.AddObserver(observer); 407} 408 409void HostContentSettingsMap::RemoveObserver( 410 content_settings::Observer* observer) { 411 observers_.RemoveObserver(observer); 412} 413 414void HostContentSettingsMap::SetPrefClockForTesting( 415 scoped_ptr<base::Clock> clock) { 416 UsedContentSettingsProviders(); 417 418 GetPrefProvider()->SetClockForTesting(clock.Pass()); 419} 420 421void HostContentSettingsMap::AddExceptionForURL( 422 const GURL& primary_url, 423 const GURL& secondary_url, 424 ContentSettingsType content_type, 425 ContentSetting setting) { 426 // TODO(markusheintz): Until the UI supports pattern pairs, both urls must 427 // match. 428 DCHECK(primary_url == secondary_url); 429 DCHECK(!ContentTypeHasCompoundValue(content_type)); 430 431 // Make sure there is no entry that would override the pattern we are about 432 // to insert for exactly this URL. 433 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url), 434 ContentSettingsPattern::Wildcard(), 435 content_type, 436 std::string(), 437 CONTENT_SETTING_DEFAULT); 438 439 SetContentSetting(ContentSettingsPattern::FromURL(primary_url), 440 ContentSettingsPattern::Wildcard(), 441 content_type, 442 std::string(), 443 setting); 444} 445 446void HostContentSettingsMap::ClearSettingsForOneType( 447 ContentSettingsType content_type) { 448 UsedContentSettingsProviders(); 449 for (ProviderIterator provider = content_settings_providers_.begin(); 450 provider != content_settings_providers_.end(); 451 ++provider) { 452 provider->second->ClearAllContentSettingsRules(content_type); 453 } 454} 455 456bool HostContentSettingsMap::IsValueAllowedForType( 457 PrefService* prefs, const base::Value* value, ContentSettingsType type) { 458 return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType( 459 prefs, content_settings::ValueToContentSetting(value), type); 460} 461 462// static 463bool HostContentSettingsMap::IsSettingAllowedForType( 464 PrefService* prefs, 465 ContentSetting setting, 466 ContentSettingsType content_type) { 467 // We don't yet support stored content settings for mixed scripting. 468 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) 469 return false; 470 471 // BLOCK semantics are not implemented for fullscreen. 472 if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN && 473 setting == CONTENT_SETTING_BLOCK) { 474 return false; 475 } 476 477 // We don't support ALLOW for media default setting. 478 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM && 479 setting == CONTENT_SETTING_ALLOW) { 480 return false; 481 } 482 483#if defined(OS_ANDROID) 484 // App banners store a dictionary. 485 if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER) 486 return false; 487#endif 488 489 // DEFAULT, ALLOW and BLOCK are always allowed. 490 if (setting == CONTENT_SETTING_DEFAULT || 491 setting == CONTENT_SETTING_ALLOW || 492 setting == CONTENT_SETTING_BLOCK) { 493 return true; 494 } 495 switch (content_type) { 496 case CONTENT_SETTINGS_TYPE_COOKIES: 497 return setting == CONTENT_SETTING_SESSION_ONLY; 498 case CONTENT_SETTINGS_TYPE_PLUGINS: 499 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 500 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 501 case CONTENT_SETTINGS_TYPE_MOUSELOCK: 502 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 503 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 504 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 505 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: 506 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: 507 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 508 return setting == CONTENT_SETTING_ASK; 509 default: 510 return false; 511 } 512} 513 514// static 515bool HostContentSettingsMap::ContentTypeHasCompoundValue( 516 ContentSettingsType type) { 517 // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 518 // CONTENT_SETTINGS_TYPE_MEDIASTREAM, and 519 // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS are of type dictionary/map. 520 // Compound types like dictionaries can't be mapped to the type 521 // |ContentSetting|. 522#if defined(OS_ANDROID) 523 if (type == CONTENT_SETTINGS_TYPE_APP_BANNER) 524 return true; 525#endif 526 527 return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE || 528 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM || 529 type == CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); 530} 531 532void HostContentSettingsMap::OnContentSettingChanged( 533 const ContentSettingsPattern& primary_pattern, 534 const ContentSettingsPattern& secondary_pattern, 535 ContentSettingsType content_type, 536 std::string resource_identifier) { 537 FOR_EACH_OBSERVER(content_settings::Observer, 538 observers_, 539 OnContentSettingChanged(primary_pattern, 540 secondary_pattern, 541 content_type, 542 resource_identifier)); 543} 544 545HostContentSettingsMap::~HostContentSettingsMap() { 546 DCHECK(!prefs_); 547 STLDeleteValues(&content_settings_providers_); 548} 549 550void HostContentSettingsMap::ShutdownOnUIThread() { 551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 552 DCHECK(prefs_); 553 prefs_ = NULL; 554 for (ProviderIterator it = content_settings_providers_.begin(); 555 it != content_settings_providers_.end(); 556 ++it) { 557 it->second->ShutdownOnUIThread(); 558 } 559} 560 561void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() { 562 // Don't migrate more than once. 563 if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) && 564 prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) { 565 return; 566 } 567 568 if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) { 569 // Nothing to be done 570 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 571 return; 572 } 573 574 // Change the default cookie settings: 575 // old new 576 // ---------------- ---------------- 577 // ALLOW SESSION_ONLY 578 // SESSION_ONLY SESSION_ONLY 579 // BLOCK BLOCK 580 ContentSetting default_setting = GetDefaultContentSettingFromProvider( 581 CONTENT_SETTINGS_TYPE_COOKIES, 582 content_settings_providers_[DEFAULT_PROVIDER]); 583 if (default_setting == CONTENT_SETTING_ALLOW) { 584 SetDefaultContentSetting( 585 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY); 586 } 587 588 // Change the exceptions using the same rules. 589 ContentSettingsForOneType exceptions; 590 AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER], 591 PREF_PROVIDER, 592 CONTENT_SETTINGS_TYPE_COOKIES, 593 std::string(), 594 &exceptions, 595 false); 596 for (ContentSettingsForOneType::iterator it = exceptions.begin(); 597 it != exceptions.end(); ++it) { 598 if (it->setting != CONTENT_SETTING_ALLOW) 599 continue; 600 SetWebsiteSetting(it->primary_pattern, 601 it->secondary_pattern, 602 CONTENT_SETTINGS_TYPE_COOKIES, 603 std::string(), 604 new base::FundamentalValue(CONTENT_SETTING_SESSION_ONLY)); 605 } 606 607 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 608} 609 610void HostContentSettingsMap::AddSettingsForOneType( 611 const content_settings::ProviderInterface* provider, 612 ProviderType provider_type, 613 ContentSettingsType content_type, 614 const std::string& resource_identifier, 615 ContentSettingsForOneType* settings, 616 bool incognito) const { 617 scoped_ptr<content_settings::RuleIterator> rule_iterator( 618 provider->GetRuleIterator(content_type, 619 resource_identifier, 620 incognito)); 621 while (rule_iterator->HasNext()) { 622 const content_settings::Rule& rule = rule_iterator->Next(); 623 ContentSetting setting_value = CONTENT_SETTING_DEFAULT; 624 // TODO(bauerb): Return rules as a list of values, not content settings. 625 // Handle the case using compound values for its exceptions and arbitrary 626 // values for its default setting. Here we assume all the exceptions 627 // are granted as |CONTENT_SETTING_ALLOW|. 628 if (ContentTypeHasCompoundValue(content_type) && 629 rule.value.get() && 630 rule.primary_pattern != ContentSettingsPattern::Wildcard()) { 631 setting_value = CONTENT_SETTING_ALLOW; 632 } else { 633 setting_value = content_settings::ValueToContentSetting(rule.value.get()); 634 } 635 settings->push_back(ContentSettingPatternSource( 636 rule.primary_pattern, rule.secondary_pattern, 637 setting_value, 638 kProviderNames[provider_type], 639 incognito)); 640 } 641} 642 643void HostContentSettingsMap::UsedContentSettingsProviders() const { 644#ifndef NDEBUG 645 if (used_from_thread_id_ == base::kInvalidThreadId) 646 return; 647 648 if (base::PlatformThread::CurrentId() != used_from_thread_id_) 649 used_from_thread_id_ = base::kInvalidThreadId; 650#endif 651} 652 653bool HostContentSettingsMap::ShouldAllowAllContent( 654 const GURL& primary_url, 655 const GURL& secondary_url, 656 ContentSettingsType content_type) { 657 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS || 658 content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 659 content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 660 return false; 661 } 662#if defined(OS_ANDROID) || defined(OS_CHROMEOS) 663 if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { 664 return false; 665 } 666#endif 667 if (secondary_url.SchemeIs(content::kChromeUIScheme) && 668 content_type == CONTENT_SETTINGS_TYPE_COOKIES && 669 primary_url.SchemeIsSecure()) { 670 return true; 671 } 672 if (primary_url.SchemeIs(extensions::kExtensionScheme)) { 673 switch (content_type) { 674 case CONTENT_SETTINGS_TYPE_PLUGINS: 675 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 676 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 677 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 678 return false; 679 case CONTENT_SETTINGS_TYPE_COOKIES: 680 return secondary_url.SchemeIs(extensions::kExtensionScheme); 681 default: 682 return true; 683 } 684 } 685 return primary_url.SchemeIs(content::kChromeDevToolsScheme) || 686 primary_url.SchemeIs(content::kChromeUIScheme); 687} 688 689base::Value* HostContentSettingsMap::GetWebsiteSetting( 690 const GURL& primary_url, 691 const GURL& secondary_url, 692 ContentSettingsType content_type, 693 const std::string& resource_identifier, 694 content_settings::SettingInfo* info) const { 695 DCHECK(SupportsResourceIdentifier(content_type) || 696 resource_identifier.empty()); 697 698 // Check if the scheme of the requesting url is whitelisted. 699 if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) { 700 if (info) { 701 info->source = content_settings::SETTING_SOURCE_WHITELIST; 702 info->primary_pattern = ContentSettingsPattern::Wildcard(); 703 info->secondary_pattern = ContentSettingsPattern::Wildcard(); 704 } 705 return new base::FundamentalValue(CONTENT_SETTING_ALLOW); 706 } 707 708 ContentSettingsPattern* primary_pattern = NULL; 709 ContentSettingsPattern* secondary_pattern = NULL; 710 if (info) { 711 primary_pattern = &info->primary_pattern; 712 secondary_pattern = &info->secondary_pattern; 713 } 714 715 // The list of |content_settings_providers_| is ordered according to their 716 // precedence. 717 for (ConstProviderIterator provider = content_settings_providers_.begin(); 718 provider != content_settings_providers_.end(); 719 ++provider) { 720 base::Value* value = content_settings::GetContentSettingValueAndPatterns( 721 provider->second, primary_url, secondary_url, content_type, 722 resource_identifier, is_off_the_record_, 723 primary_pattern, secondary_pattern); 724 if (value) { 725 if (info) 726 info->source = kProviderSourceMap[provider->first]; 727 return value; 728 } 729 } 730 731 if (info) { 732 info->source = content_settings::SETTING_SOURCE_NONE; 733 info->primary_pattern = ContentSettingsPattern(); 734 info->secondary_pattern = ContentSettingsPattern(); 735 } 736 return NULL; 737} 738 739// static 740HostContentSettingsMap::ProviderType 741 HostContentSettingsMap::GetProviderTypeFromSource( 742 const std::string& source) { 743 for (size_t i = 0; i < arraysize(kProviderNames); ++i) { 744 if (source == kProviderNames[i]) 745 return static_cast<ProviderType>(i); 746 } 747 748 NOTREACHED(); 749 return DEFAULT_PROVIDER; 750} 751 752content_settings::PrefProvider* HostContentSettingsMap::GetPrefProvider() { 753 return static_cast<content_settings::PrefProvider*>( 754 content_settings_providers_[PREF_PROVIDER]); 755} 756