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