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