• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
42 using content::BrowserThread;
43 using content::UserMetricsAction;
44 
45 namespace {
46 
47 typedef std::vector<content_settings::Rule> Rules;
48 
49 typedef std::pair<std::string, std::string> StringPair;
50 
51 const char* kProviderNames[] = {
52   "platform_app",
53   "policy",
54   "extension",
55   "preference",
56   "default"
57 };
58 
59 content_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 };
66 COMPILE_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.
SupportsResourceIdentifier(ContentSettingsType content_type)72 bool SupportsResourceIdentifier(ContentSettingsType content_type) {
73   return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
74 }
75 
76 }  // namespace
77 
HostContentSettingsMap(PrefService * prefs,bool incognito)78 HostContentSettingsMap::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)
RegisterExtensionService(ExtensionService * extension_service)108 void 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
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)141 void 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 
GetDefaultContentSettingFromProvider(ContentSettingsType content_type,content_settings::ProviderInterface * provider) const162 ContentSetting 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 
GetDefaultContentSetting(ContentSettingsType content_type,std::string * provider_id) const179 ContentSetting 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 
GetContentSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier) const207 ContentSetting 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 
GetSettingsForOneType(ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings) const218 void 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 
SetDefaultContentSetting(ContentSettingsType content_type,ContentSetting setting)250 void 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 = Value::CreateIntegerValue(setting);
258   SetWebsiteSetting(
259       ContentSettingsPattern::Wildcard(),
260       ContentSettingsPattern::Wildcard(),
261       content_type,
262       std::string(),
263       value);
264 }
265 
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,base::Value * value)266 void 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 
SetContentSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting)291 void 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 = Value::CreateIntegerValue(setting);
301   SetWebsiteSetting(primary_pattern,
302                     secondary_pattern,
303                     content_type,
304                     resource_identifier,
305                     value);
306 }
307 
AddExceptionForURL(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,ContentSetting setting)308 void 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 
ClearSettingsForOneType(ContentSettingsType content_type)333 void 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 
IsValueAllowedForType(PrefService * prefs,const base::Value * value,ContentSettingsType type)343 bool 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
IsSettingAllowedForType(PrefService * prefs,ContentSetting setting,ContentSettingsType content_type)350 bool 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   // DEFAULT, ALLOW and BLOCK are always allowed.
371   if (setting == CONTENT_SETTING_DEFAULT ||
372       setting == CONTENT_SETTING_ALLOW ||
373       setting == CONTENT_SETTING_BLOCK) {
374     return true;
375   }
376   switch (content_type) {
377     case CONTENT_SETTINGS_TYPE_COOKIES:
378       return setting == CONTENT_SETTING_SESSION_ONLY;
379     case CONTENT_SETTINGS_TYPE_PLUGINS:
380     case CONTENT_SETTINGS_TYPE_GEOLOCATION:
381     case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
382     case CONTENT_SETTINGS_TYPE_MOUSELOCK:
383     case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
384     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
385     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
386     case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
387     case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
388     case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
389       return setting == CONTENT_SETTING_ASK;
390     default:
391       return false;
392   }
393 }
394 
395 // static
ContentTypeHasCompoundValue(ContentSettingsType type)396 bool HostContentSettingsMap::ContentTypeHasCompoundValue(
397     ContentSettingsType type) {
398   // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE and
399   // CONTENT_SETTINGS_TYPE_MEDIASTREAM are of type dictionary/map. Compound
400   // types like dictionaries can't be mapped to the type |ContentSetting|.
401   return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
402           type == CONTENT_SETTINGS_TYPE_MEDIASTREAM);
403 }
404 
OnContentSettingChanged(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,std::string resource_identifier)405 void HostContentSettingsMap::OnContentSettingChanged(
406     const ContentSettingsPattern& primary_pattern,
407     const ContentSettingsPattern& secondary_pattern,
408     ContentSettingsType content_type,
409     std::string resource_identifier) {
410   const ContentSettingsDetails details(primary_pattern,
411                                        secondary_pattern,
412                                        content_type,
413                                        resource_identifier);
414   content::NotificationService::current()->Notify(
415       chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
416       content::Source<HostContentSettingsMap>(this),
417       content::Details<const ContentSettingsDetails>(&details));
418 }
419 
~HostContentSettingsMap()420 HostContentSettingsMap::~HostContentSettingsMap() {
421   DCHECK(!prefs_);
422   STLDeleteValues(&content_settings_providers_);
423 }
424 
ShutdownOnUIThread()425 void HostContentSettingsMap::ShutdownOnUIThread() {
426   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
427   DCHECK(prefs_);
428   prefs_ = NULL;
429   for (ProviderIterator it = content_settings_providers_.begin();
430        it != content_settings_providers_.end();
431        ++it) {
432     it->second->ShutdownOnUIThread();
433   }
434 }
435 
MigrateObsoleteClearOnExitPref()436 void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() {
437   // Don't migrate more than once.
438   if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) &&
439       prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) {
440     return;
441   }
442 
443   if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) {
444     // Nothing to be done
445     prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
446     return;
447   }
448 
449   // Change the default cookie settings:
450   //  old              new
451   //  ---------------- ----------------
452   //  ALLOW            SESSION_ONLY
453   //  SESSION_ONLY     SESSION_ONLY
454   //  BLOCK            BLOCK
455   ContentSetting default_setting = GetDefaultContentSettingFromProvider(
456       CONTENT_SETTINGS_TYPE_COOKIES,
457       content_settings_providers_[DEFAULT_PROVIDER]);
458   if (default_setting == CONTENT_SETTING_ALLOW) {
459     SetDefaultContentSetting(
460         CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY);
461   }
462 
463   // Change the exceptions using the same rules.
464   ContentSettingsForOneType exceptions;
465   AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER],
466                         PREF_PROVIDER,
467                         CONTENT_SETTINGS_TYPE_COOKIES,
468                         std::string(),
469                         &exceptions,
470                         false);
471   for (ContentSettingsForOneType::iterator it = exceptions.begin();
472        it != exceptions.end(); ++it) {
473     if (it->setting != CONTENT_SETTING_ALLOW)
474       continue;
475     SetWebsiteSetting(it->primary_pattern,
476                       it->secondary_pattern,
477                       CONTENT_SETTINGS_TYPE_COOKIES,
478                       std::string(),
479                       Value::CreateIntegerValue(CONTENT_SETTING_SESSION_ONLY));
480   }
481 
482   prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
483 }
484 
AddSettingsForOneType(const content_settings::ProviderInterface * provider,ProviderType provider_type,ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings,bool incognito) const485 void HostContentSettingsMap::AddSettingsForOneType(
486     const content_settings::ProviderInterface* provider,
487     ProviderType provider_type,
488     ContentSettingsType content_type,
489     const std::string& resource_identifier,
490     ContentSettingsForOneType* settings,
491     bool incognito) const {
492   scoped_ptr<content_settings::RuleIterator> rule_iterator(
493       provider->GetRuleIterator(content_type,
494                                 resource_identifier,
495                                 incognito));
496   while (rule_iterator->HasNext()) {
497     const content_settings::Rule& rule = rule_iterator->Next();
498     ContentSetting setting_value = CONTENT_SETTING_DEFAULT;
499     // TODO(bauerb): Return rules as a list of values, not content settings.
500     // Handle the case using compound values for its exceptions and arbitrary
501     // values for its default setting. Here we assume all the exceptions
502     // are granted as |CONTENT_SETTING_ALLOW|.
503     if (ContentTypeHasCompoundValue(content_type) &&
504         rule.value.get() &&
505         rule.primary_pattern != ContentSettingsPattern::Wildcard()) {
506       setting_value = CONTENT_SETTING_ALLOW;
507     } else {
508       setting_value = content_settings::ValueToContentSetting(rule.value.get());
509     }
510     settings->push_back(ContentSettingPatternSource(
511         rule.primary_pattern, rule.secondary_pattern,
512         setting_value,
513         kProviderNames[provider_type],
514         incognito));
515   }
516 }
517 
UsedContentSettingsProviders() const518 void HostContentSettingsMap::UsedContentSettingsProviders() const {
519 #ifndef NDEBUG
520   if (used_from_thread_id_ == base::kInvalidThreadId)
521     return;
522 
523   if (base::PlatformThread::CurrentId() != used_from_thread_id_)
524     used_from_thread_id_ = base::kInvalidThreadId;
525 #endif
526 }
527 
ShouldAllowAllContent(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type)528 bool HostContentSettingsMap::ShouldAllowAllContent(
529     const GURL& primary_url,
530     const GURL& secondary_url,
531     ContentSettingsType content_type) {
532   if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
533       content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
534       content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
535     return false;
536   }
537   if (secondary_url.SchemeIs(chrome::kChromeUIScheme) &&
538       content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
539       primary_url.SchemeIsSecure()) {
540     return true;
541   }
542   if (primary_url.SchemeIs(extensions::kExtensionScheme)) {
543     switch (content_type) {
544       case CONTENT_SETTINGS_TYPE_PLUGINS:
545       case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
546       case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
547       case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
548         return false;
549       case CONTENT_SETTINGS_TYPE_COOKIES:
550         return secondary_url.SchemeIs(extensions::kExtensionScheme);
551       default:
552         return true;
553     }
554   }
555   return primary_url.SchemeIs(chrome::kChromeDevToolsScheme) ||
556          primary_url.SchemeIs(chrome::kChromeUIScheme);
557 }
558 
GetWebsiteSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,content_settings::SettingInfo * info) const559 base::Value* HostContentSettingsMap::GetWebsiteSetting(
560     const GURL& primary_url,
561     const GURL& secondary_url,
562     ContentSettingsType content_type,
563     const std::string& resource_identifier,
564     content_settings::SettingInfo* info) const {
565   DCHECK(SupportsResourceIdentifier(content_type) ||
566          resource_identifier.empty());
567 
568   // Check if the scheme of the requesting url is whitelisted.
569   if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) {
570     if (info) {
571       info->source = content_settings::SETTING_SOURCE_WHITELIST;
572       info->primary_pattern = ContentSettingsPattern::Wildcard();
573       info->secondary_pattern = ContentSettingsPattern::Wildcard();
574     }
575     return Value::CreateIntegerValue(CONTENT_SETTING_ALLOW);
576   }
577 
578   ContentSettingsPattern* primary_pattern = NULL;
579   ContentSettingsPattern* secondary_pattern = NULL;
580   if (info) {
581     primary_pattern = &info->primary_pattern;
582     secondary_pattern = &info->secondary_pattern;
583   }
584 
585   // The list of |content_settings_providers_| is ordered according to their
586   // precedence.
587   for (ConstProviderIterator provider = content_settings_providers_.begin();
588        provider != content_settings_providers_.end();
589        ++provider) {
590     base::Value* value = content_settings::GetContentSettingValueAndPatterns(
591         provider->second, primary_url, secondary_url, content_type,
592         resource_identifier, is_off_the_record_,
593         primary_pattern, secondary_pattern);
594     if (value) {
595       if (info)
596         info->source = kProviderSourceMap[provider->first];
597       return value;
598     }
599   }
600 
601   if (info) {
602     info->source = content_settings::SETTING_SOURCE_NONE;
603     info->primary_pattern = ContentSettingsPattern();
604     info->secondary_pattern = ContentSettingsPattern();
605   }
606   return NULL;
607 }
608 
609 // static
610 HostContentSettingsMap::ProviderType
GetProviderTypeFromSource(const std::string & source)611     HostContentSettingsMap::GetProviderTypeFromSource(
612         const std::string& source) {
613   for (size_t i = 0; i < arraysize(kProviderNames); ++i) {
614     if (source == kProviderNames[i])
615       return static_cast<ProviderType>(i);
616   }
617 
618   NOTREACHED();
619   return DEFAULT_PROVIDER;
620 }
621