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