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