host_content_settings_map.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/host_content_settings_map.h" 6 7#include <utility> 8 9#include "base/basictypes.h" 10#include "base/command_line.h" 11#include "base/prefs/pref_service.h" 12#include "base/stl_util.h" 13#include "base/strings/string_util.h" 14#include "base/strings/utf_string_conversions.h" 15#include "chrome/browser/chrome_notification_types.h" 16#include "chrome/browser/content_settings/content_settings_custom_extension_provider.h" 17#include "chrome/browser/content_settings/content_settings_default_provider.h" 18#include "chrome/browser/content_settings/content_settings_details.h" 19#include "chrome/browser/content_settings/content_settings_internal_extension_provider.h" 20#include "chrome/browser/content_settings/content_settings_observable_provider.h" 21#include "chrome/browser/content_settings/content_settings_policy_provider.h" 22#include "chrome/browser/content_settings/content_settings_pref_provider.h" 23#include "chrome/browser/content_settings/content_settings_provider.h" 24#include "chrome/browser/content_settings/content_settings_rule.h" 25#include "chrome/browser/content_settings/content_settings_utils.h" 26#include "chrome/browser/extensions/extension_service.h" 27#include "chrome/common/chrome_switches.h" 28#include "chrome/common/content_settings_pattern.h" 29#include "chrome/common/pref_names.h" 30#include "chrome/common/url_constants.h" 31#include "components/user_prefs/pref_registry_syncable.h" 32#include "content/public/browser/browser_thread.h" 33#include "content/public/browser/notification_service.h" 34#include "content/public/browser/notification_source.h" 35#include "content/public/browser/user_metrics.h" 36#include "content/public/common/content_switches.h" 37#include "extensions/browser/extension_prefs.h" 38#include "extensions/common/constants.h" 39#include "net/base/net_errors.h" 40#include "net/base/static_cookie_policy.h" 41#include "url/gurl.h" 42 43using base::UserMetricsAction; 44using content::BrowserThread; 45 46namespace { 47 48typedef std::vector<content_settings::Rule> Rules; 49 50typedef std::pair<std::string, std::string> StringPair; 51 52const char* kProviderNames[] = { 53 "platform_app", 54 "policy", 55 "extension", 56 "preference", 57 "default" 58}; 59 60content_settings::SettingSource kProviderSourceMap[] = { 61 content_settings::SETTING_SOURCE_EXTENSION, 62 content_settings::SETTING_SOURCE_POLICY, 63 content_settings::SETTING_SOURCE_EXTENSION, 64 content_settings::SETTING_SOURCE_USER, 65 content_settings::SETTING_SOURCE_USER, 66}; 67COMPILE_ASSERT(arraysize(kProviderSourceMap) == 68 HostContentSettingsMap::NUM_PROVIDER_TYPES, 69 kProviderSourceMap_has_incorrect_size); 70 71// Returns true if the |content_type| supports a resource identifier. 72// Resource identifiers are supported (but not required) for plug-ins. 73bool SupportsResourceIdentifier(ContentSettingsType content_type) { 74 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 75} 76 77} // namespace 78 79HostContentSettingsMap::HostContentSettingsMap( 80 PrefService* prefs, 81 bool incognito) : 82#ifndef NDEBUG 83 used_from_thread_id_(base::PlatformThread::CurrentId()), 84#endif 85 prefs_(prefs), 86 is_off_the_record_(incognito) { 87 content_settings::ObservableProvider* policy_provider = 88 new content_settings::PolicyProvider(prefs_); 89 policy_provider->AddObserver(this); 90 content_settings_providers_[POLICY_PROVIDER] = policy_provider; 91 92 content_settings::ObservableProvider* pref_provider = 93 new content_settings::PrefProvider(prefs_, is_off_the_record_); 94 pref_provider->AddObserver(this); 95 content_settings_providers_[PREF_PROVIDER] = pref_provider; 96 97 content_settings::ObservableProvider* default_provider = 98 new content_settings::DefaultProvider(prefs_, is_off_the_record_); 99 default_provider->AddObserver(this); 100 content_settings_providers_[DEFAULT_PROVIDER] = default_provider; 101 102 if (!is_off_the_record_) { 103 // Migrate obsolete preferences. 104 MigrateObsoleteClearOnExitPref(); 105 } 106} 107 108#if defined(ENABLE_EXTENSIONS) 109void HostContentSettingsMap::RegisterExtensionService( 110 ExtensionService* extension_service) { 111 DCHECK(extension_service); 112 DCHECK(!content_settings_providers_[INTERNAL_EXTENSION_PROVIDER]); 113 DCHECK(!content_settings_providers_[CUSTOM_EXTENSION_PROVIDER]); 114 115 content_settings::InternalExtensionProvider* internal_extension_provider = 116 new content_settings::InternalExtensionProvider(extension_service); 117 internal_extension_provider->AddObserver(this); 118 content_settings_providers_[INTERNAL_EXTENSION_PROVIDER] = 119 internal_extension_provider; 120 121 content_settings::ObservableProvider* custom_extension_provider = 122 new content_settings::CustomExtensionProvider( 123 extensions::ExtensionPrefs::Get( 124 extension_service->GetBrowserContext())->content_settings_store(), 125 is_off_the_record_); 126 custom_extension_provider->AddObserver(this); 127 content_settings_providers_[CUSTOM_EXTENSION_PROVIDER] = 128 custom_extension_provider; 129 130#ifndef NDEBUG 131 DCHECK(used_from_thread_id_ != base::kInvalidThreadId) 132 << "Used from multiple threads before initialization complete."; 133#endif 134 135 OnContentSettingChanged(ContentSettingsPattern(), 136 ContentSettingsPattern(), 137 CONTENT_SETTINGS_TYPE_DEFAULT, 138 std::string()); 139} 140#endif 141 142// static 143void HostContentSettingsMap::RegisterProfilePrefs( 144 user_prefs::PrefRegistrySyncable* registry) { 145 registry->RegisterIntegerPref( 146 prefs::kContentSettingsWindowLastTabIndex, 147 0, 148 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 149 registry->RegisterIntegerPref( 150 prefs::kContentSettingsDefaultWhitelistVersion, 151 0, 152 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 153 registry->RegisterBooleanPref( 154 prefs::kContentSettingsClearOnExitMigrated, 155 false, 156 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 157 158 // Register the prefs for the content settings providers. 159 content_settings::DefaultProvider::RegisterProfilePrefs(registry); 160 content_settings::PrefProvider::RegisterProfilePrefs(registry); 161 content_settings::PolicyProvider::RegisterProfilePrefs(registry); 162} 163 164ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider( 165 ContentSettingsType content_type, 166 content_settings::ProviderInterface* provider) const { 167 scoped_ptr<content_settings::RuleIterator> rule_iterator( 168 provider->GetRuleIterator(content_type, std::string(), false)); 169 170 ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); 171 while (rule_iterator->HasNext()) { 172 content_settings::Rule rule = rule_iterator->Next(); 173 if (rule.primary_pattern == wildcard && 174 rule.secondary_pattern == wildcard) { 175 return content_settings::ValueToContentSetting(rule.value.get()); 176 } 177 } 178 return CONTENT_SETTING_DEFAULT; 179} 180 181ContentSetting HostContentSettingsMap::GetDefaultContentSetting( 182 ContentSettingsType content_type, 183 std::string* provider_id) const { 184 UsedContentSettingsProviders(); 185 186 // Iterate through the list of providers and return the first non-NULL value 187 // that matches |primary_url| and |secondary_url|. 188 for (ConstProviderIterator provider = content_settings_providers_.begin(); 189 provider != content_settings_providers_.end(); 190 ++provider) { 191 if (provider->first == PREF_PROVIDER) 192 continue; 193 ContentSetting default_setting = 194 GetDefaultContentSettingFromProvider(content_type, provider->second); 195 if (default_setting != CONTENT_SETTING_DEFAULT) { 196 if (provider_id) 197 *provider_id = kProviderNames[provider->first]; 198 return default_setting; 199 } 200 } 201 202 // The method GetDefaultContentSetting always has to return an explicit 203 // value that is to be used as default. We here rely on the 204 // DefaultProvider to always provide a value. 205 NOTREACHED(); 206 return CONTENT_SETTING_DEFAULT; 207} 208 209ContentSetting HostContentSettingsMap::GetContentSetting( 210 const GURL& primary_url, 211 const GURL& secondary_url, 212 ContentSettingsType content_type, 213 const std::string& resource_identifier) const { 214 DCHECK(!ContentTypeHasCompoundValue(content_type)); 215 scoped_ptr<base::Value> value(GetWebsiteSetting( 216 primary_url, secondary_url, content_type, resource_identifier, NULL)); 217 return content_settings::ValueToContentSetting(value.get()); 218} 219 220void HostContentSettingsMap::GetSettingsForOneType( 221 ContentSettingsType content_type, 222 const std::string& resource_identifier, 223 ContentSettingsForOneType* settings) const { 224 DCHECK(SupportsResourceIdentifier(content_type) || 225 resource_identifier.empty()); 226 DCHECK(settings); 227 UsedContentSettingsProviders(); 228 229 settings->clear(); 230 for (ConstProviderIterator provider = content_settings_providers_.begin(); 231 provider != content_settings_providers_.end(); 232 ++provider) { 233 // For each provider, iterate first the incognito-specific rules, then the 234 // normal rules. 235 if (is_off_the_record_) { 236 AddSettingsForOneType(provider->second, 237 provider->first, 238 content_type, 239 resource_identifier, 240 settings, 241 true); 242 } 243 AddSettingsForOneType(provider->second, 244 provider->first, 245 content_type, 246 resource_identifier, 247 settings, 248 false); 249 } 250} 251 252void HostContentSettingsMap::SetDefaultContentSetting( 253 ContentSettingsType content_type, 254 ContentSetting setting) { 255 DCHECK(IsSettingAllowedForType(prefs_, setting, content_type)); 256 257 base::Value* value = NULL; 258 if (setting != CONTENT_SETTING_DEFAULT) 259 value = base::Value::CreateIntegerValue(setting); 260 SetWebsiteSetting( 261 ContentSettingsPattern::Wildcard(), 262 ContentSettingsPattern::Wildcard(), 263 content_type, 264 std::string(), 265 value); 266} 267 268void HostContentSettingsMap::SetWebsiteSetting( 269 const ContentSettingsPattern& primary_pattern, 270 const ContentSettingsPattern& secondary_pattern, 271 ContentSettingsType content_type, 272 const std::string& resource_identifier, 273 base::Value* value) { 274 DCHECK(IsValueAllowedForType(prefs_, value, content_type)); 275 DCHECK(SupportsResourceIdentifier(content_type) || 276 resource_identifier.empty()); 277 UsedContentSettingsProviders(); 278 279 for (ProviderIterator provider = content_settings_providers_.begin(); 280 provider != content_settings_providers_.end(); 281 ++provider) { 282 if (provider->second->SetWebsiteSetting(primary_pattern, 283 secondary_pattern, 284 content_type, 285 resource_identifier, 286 value)) { 287 return; 288 } 289 } 290 NOTREACHED(); 291} 292 293void HostContentSettingsMap::SetContentSetting( 294 const ContentSettingsPattern& primary_pattern, 295 const ContentSettingsPattern& secondary_pattern, 296 ContentSettingsType content_type, 297 const std::string& resource_identifier, 298 ContentSetting setting) { 299 DCHECK(!ContentTypeHasCompoundValue(content_type)); 300 base::Value* value = NULL; 301 if (setting != CONTENT_SETTING_DEFAULT) 302 value = base::Value::CreateIntegerValue(setting); 303 SetWebsiteSetting(primary_pattern, 304 secondary_pattern, 305 content_type, 306 resource_identifier, 307 value); 308} 309 310void HostContentSettingsMap::AddExceptionForURL( 311 const GURL& primary_url, 312 const GURL& secondary_url, 313 ContentSettingsType content_type, 314 ContentSetting setting) { 315 // TODO(markusheintz): Until the UI supports pattern pairs, both urls must 316 // match. 317 DCHECK(primary_url == secondary_url); 318 DCHECK(!ContentTypeHasCompoundValue(content_type)); 319 320 // Make sure there is no entry that would override the pattern we are about 321 // to insert for exactly this URL. 322 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url), 323 ContentSettingsPattern::Wildcard(), 324 content_type, 325 std::string(), 326 CONTENT_SETTING_DEFAULT); 327 328 SetContentSetting(ContentSettingsPattern::FromURL(primary_url), 329 ContentSettingsPattern::Wildcard(), 330 content_type, 331 std::string(), 332 setting); 333} 334 335void HostContentSettingsMap::ClearSettingsForOneType( 336 ContentSettingsType content_type) { 337 UsedContentSettingsProviders(); 338 for (ProviderIterator provider = content_settings_providers_.begin(); 339 provider != content_settings_providers_.end(); 340 ++provider) { 341 provider->second->ClearAllContentSettingsRules(content_type); 342 } 343} 344 345bool HostContentSettingsMap::IsValueAllowedForType( 346 PrefService* prefs, const base::Value* value, ContentSettingsType type) { 347 return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType( 348 prefs, content_settings::ValueToContentSetting(value), type); 349} 350 351// static 352bool HostContentSettingsMap::IsSettingAllowedForType( 353 PrefService* prefs, 354 ContentSetting setting, 355 ContentSettingsType content_type) { 356 // We don't yet support stored content settings for mixed scripting. 357 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) 358 return false; 359 360 // BLOCK semantics are not implemented for fullscreen. 361 if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN && 362 setting == CONTENT_SETTING_BLOCK) { 363 return false; 364 } 365 366 // We don't support ALLOW for media default setting. 367 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM && 368 setting == CONTENT_SETTING_ALLOW) { 369 return false; 370 } 371 372#if defined(OS_ANDROID) 373 // App banners store a dictionary. 374 if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER) 375 return false; 376#endif 377 378 // DEFAULT, ALLOW and BLOCK are always allowed. 379 if (setting == CONTENT_SETTING_DEFAULT || 380 setting == CONTENT_SETTING_ALLOW || 381 setting == CONTENT_SETTING_BLOCK) { 382 return true; 383 } 384 switch (content_type) { 385 case CONTENT_SETTINGS_TYPE_COOKIES: 386 return setting == CONTENT_SETTING_SESSION_ONLY; 387 case CONTENT_SETTINGS_TYPE_PLUGINS: 388 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 389 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 390 case CONTENT_SETTINGS_TYPE_MOUSELOCK: 391 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 392 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 393 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 394 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: 395 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: 396 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 397 return setting == CONTENT_SETTING_ASK; 398 default: 399 return false; 400 } 401} 402 403// static 404bool HostContentSettingsMap::ContentTypeHasCompoundValue( 405 ContentSettingsType type) { 406 // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE and 407 // CONTENT_SETTINGS_TYPE_MEDIASTREAM are of type dictionary/map. Compound 408 // types like dictionaries can't be mapped to the type |ContentSetting|. 409#if defined(OS_ANDROID) 410 if (type == CONTENT_SETTINGS_TYPE_APP_BANNER) 411 return true; 412#endif 413 414 return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE || 415 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM); 416} 417 418void HostContentSettingsMap::OnContentSettingChanged( 419 const ContentSettingsPattern& primary_pattern, 420 const ContentSettingsPattern& secondary_pattern, 421 ContentSettingsType content_type, 422 std::string resource_identifier) { 423 const ContentSettingsDetails details(primary_pattern, 424 secondary_pattern, 425 content_type, 426 resource_identifier); 427 content::NotificationService::current()->Notify( 428 chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED, 429 content::Source<HostContentSettingsMap>(this), 430 content::Details<const ContentSettingsDetails>(&details)); 431} 432 433HostContentSettingsMap::~HostContentSettingsMap() { 434 DCHECK(!prefs_); 435 STLDeleteValues(&content_settings_providers_); 436} 437 438void HostContentSettingsMap::ShutdownOnUIThread() { 439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 440 DCHECK(prefs_); 441 prefs_ = NULL; 442 for (ProviderIterator it = content_settings_providers_.begin(); 443 it != content_settings_providers_.end(); 444 ++it) { 445 it->second->ShutdownOnUIThread(); 446 } 447} 448 449void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() { 450 // Don't migrate more than once. 451 if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) && 452 prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) { 453 return; 454 } 455 456 if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) { 457 // Nothing to be done 458 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 459 return; 460 } 461 462 // Change the default cookie settings: 463 // old new 464 // ---------------- ---------------- 465 // ALLOW SESSION_ONLY 466 // SESSION_ONLY SESSION_ONLY 467 // BLOCK BLOCK 468 ContentSetting default_setting = GetDefaultContentSettingFromProvider( 469 CONTENT_SETTINGS_TYPE_COOKIES, 470 content_settings_providers_[DEFAULT_PROVIDER]); 471 if (default_setting == CONTENT_SETTING_ALLOW) { 472 SetDefaultContentSetting( 473 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY); 474 } 475 476 // Change the exceptions using the same rules. 477 ContentSettingsForOneType exceptions; 478 AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER], 479 PREF_PROVIDER, 480 CONTENT_SETTINGS_TYPE_COOKIES, 481 std::string(), 482 &exceptions, 483 false); 484 for (ContentSettingsForOneType::iterator it = exceptions.begin(); 485 it != exceptions.end(); ++it) { 486 if (it->setting != CONTENT_SETTING_ALLOW) 487 continue; 488 SetWebsiteSetting(it->primary_pattern, 489 it->secondary_pattern, 490 CONTENT_SETTINGS_TYPE_COOKIES, 491 std::string(), 492 base::Value::CreateIntegerValue( 493 CONTENT_SETTING_SESSION_ONLY)); 494 } 495 496 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 497} 498 499void HostContentSettingsMap::AddSettingsForOneType( 500 const content_settings::ProviderInterface* provider, 501 ProviderType provider_type, 502 ContentSettingsType content_type, 503 const std::string& resource_identifier, 504 ContentSettingsForOneType* settings, 505 bool incognito) const { 506 scoped_ptr<content_settings::RuleIterator> rule_iterator( 507 provider->GetRuleIterator(content_type, 508 resource_identifier, 509 incognito)); 510 while (rule_iterator->HasNext()) { 511 const content_settings::Rule& rule = rule_iterator->Next(); 512 ContentSetting setting_value = CONTENT_SETTING_DEFAULT; 513 // TODO(bauerb): Return rules as a list of values, not content settings. 514 // Handle the case using compound values for its exceptions and arbitrary 515 // values for its default setting. Here we assume all the exceptions 516 // are granted as |CONTENT_SETTING_ALLOW|. 517 if (ContentTypeHasCompoundValue(content_type) && 518 rule.value.get() && 519 rule.primary_pattern != ContentSettingsPattern::Wildcard()) { 520 setting_value = CONTENT_SETTING_ALLOW; 521 } else { 522 setting_value = content_settings::ValueToContentSetting(rule.value.get()); 523 } 524 settings->push_back(ContentSettingPatternSource( 525 rule.primary_pattern, rule.secondary_pattern, 526 setting_value, 527 kProviderNames[provider_type], 528 incognito)); 529 } 530} 531 532void HostContentSettingsMap::UsedContentSettingsProviders() const { 533#ifndef NDEBUG 534 if (used_from_thread_id_ == base::kInvalidThreadId) 535 return; 536 537 if (base::PlatformThread::CurrentId() != used_from_thread_id_) 538 used_from_thread_id_ = base::kInvalidThreadId; 539#endif 540} 541 542bool HostContentSettingsMap::ShouldAllowAllContent( 543 const GURL& primary_url, 544 const GURL& secondary_url, 545 ContentSettingsType content_type) { 546 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS || 547 content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 548 content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 549 return false; 550 } 551#if defined(OS_ANDROID) || defined(OS_CHROMEOS) 552 if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { 553 return false; 554 } 555#endif 556 if (secondary_url.SchemeIs(content::kChromeUIScheme) && 557 content_type == CONTENT_SETTINGS_TYPE_COOKIES && 558 primary_url.SchemeIsSecure()) { 559 return true; 560 } 561 if (primary_url.SchemeIs(extensions::kExtensionScheme)) { 562 switch (content_type) { 563 case CONTENT_SETTINGS_TYPE_PLUGINS: 564 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 565 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 566 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 567 return false; 568 case CONTENT_SETTINGS_TYPE_COOKIES: 569 return secondary_url.SchemeIs(extensions::kExtensionScheme); 570 default: 571 return true; 572 } 573 } 574 return primary_url.SchemeIs(content::kChromeDevToolsScheme) || 575 primary_url.SchemeIs(content::kChromeUIScheme); 576} 577 578base::Value* HostContentSettingsMap::GetWebsiteSetting( 579 const GURL& primary_url, 580 const GURL& secondary_url, 581 ContentSettingsType content_type, 582 const std::string& resource_identifier, 583 content_settings::SettingInfo* info) const { 584 DCHECK(SupportsResourceIdentifier(content_type) || 585 resource_identifier.empty()); 586 587 // Check if the scheme of the requesting url is whitelisted. 588 if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) { 589 if (info) { 590 info->source = content_settings::SETTING_SOURCE_WHITELIST; 591 info->primary_pattern = ContentSettingsPattern::Wildcard(); 592 info->secondary_pattern = ContentSettingsPattern::Wildcard(); 593 } 594 return base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW); 595 } 596 597 ContentSettingsPattern* primary_pattern = NULL; 598 ContentSettingsPattern* secondary_pattern = NULL; 599 if (info) { 600 primary_pattern = &info->primary_pattern; 601 secondary_pattern = &info->secondary_pattern; 602 } 603 604 // The list of |content_settings_providers_| is ordered according to their 605 // precedence. 606 for (ConstProviderIterator provider = content_settings_providers_.begin(); 607 provider != content_settings_providers_.end(); 608 ++provider) { 609 base::Value* value = content_settings::GetContentSettingValueAndPatterns( 610 provider->second, primary_url, secondary_url, content_type, 611 resource_identifier, is_off_the_record_, 612 primary_pattern, secondary_pattern); 613 if (value) { 614 if (info) 615 info->source = kProviderSourceMap[provider->first]; 616 return value; 617 } 618 } 619 620 if (info) { 621 info->source = content_settings::SETTING_SOURCE_NONE; 622 info->primary_pattern = ContentSettingsPattern(); 623 info->secondary_pattern = ContentSettingsPattern(); 624 } 625 return NULL; 626} 627 628// static 629HostContentSettingsMap::ProviderType 630 HostContentSettingsMap::GetProviderTypeFromSource( 631 const std::string& source) { 632 for (size_t i = 0; i < arraysize(kProviderNames); ++i) { 633 if (source == kProviderNames[i]) 634 return static_cast<ProviderType>(i); 635 } 636 637 NOTREACHED(); 638 return DEFAULT_PROVIDER; 639} 640