• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "base/command_line.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/content_settings/content_settings_details.h"
11 #include "chrome/browser/content_settings/content_settings_policy_provider.h"
12 #include "chrome/browser/content_settings/content_settings_pref_provider.h"
13 #include "chrome/browser/content_settings/content_settings_provider.h"
14 #include "chrome/browser/metrics/user_metrics.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/prefs/scoped_user_pref_update.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/common/url_constants.h"
21 #include "content/browser/browser_thread.h"
22 #include "content/common/notification_service.h"
23 #include "content/common/notification_source.h"
24 #include "content/common/notification_type.h"
25 #include "googleurl/src/gurl.h"
26 #include "net/base/net_util.h"
27 #include "net/base/static_cookie_policy.h"
28 
29 namespace {
30 
31 // Returns true if we should allow all content types for this URL.  This is
32 // true for various internal objects like chrome:// URLs, so UI and other
33 // things users think of as "not webpages" don't break.
ShouldAllowAllContent(const GURL & url)34 static bool ShouldAllowAllContent(const GURL& url) {
35   return url.SchemeIs(chrome::kChromeDevToolsScheme) ||
36          url.SchemeIs(chrome::kChromeInternalScheme) ||
37          url.SchemeIs(chrome::kChromeUIScheme) ||
38          url.SchemeIs(chrome::kExtensionScheme) ||
39          url.SchemeIs(chrome::kUserScriptScheme);
40 }
41 
42 typedef linked_ptr<content_settings::DefaultProviderInterface>
43     DefaultContentSettingsProviderPtr;
44 typedef std::vector<DefaultContentSettingsProviderPtr>::iterator
45     DefaultProviderIterator;
46 typedef std::vector<DefaultContentSettingsProviderPtr>::const_iterator
47     ConstDefaultProviderIterator;
48 
49 typedef linked_ptr<content_settings::ProviderInterface> ProviderPtr;
50 typedef std::vector<ProviderPtr>::iterator ProviderIterator;
51 typedef std::vector<ProviderPtr>::const_iterator ConstProviderIterator;
52 
53 typedef content_settings::ProviderInterface::Rules Rules;
54 typedef content_settings::ProviderInterface::Rules::iterator
55     rules_iterator;
56 typedef content_settings::ProviderInterface::Rules::const_iterator
57     const_rules_iterator;
58 
59 }  // namespace
60 
HostContentSettingsMap(Profile * profile)61 HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
62     : profile_(profile),
63       is_off_the_record_(profile_->IsOffTheRecord()),
64       updating_preferences_(false),
65       block_third_party_cookies_(false),
66       is_block_third_party_cookies_managed_(false) {
67   // The order in which the default content settings providers are created is
68   // critical, as providers that are further down in the list (i.e. added later)
69   // override providers further up.
70   default_content_settings_providers_.push_back(
71       DefaultContentSettingsProviderPtr(
72           new content_settings::PrefDefaultProvider(profile)));
73   default_content_settings_providers_.push_back(
74       DefaultContentSettingsProviderPtr(
75           new content_settings::PolicyDefaultProvider(profile)));
76 
77   PrefService* prefs = profile_->GetPrefs();
78 
79   // TODO(markusheintz): Discuss whether it is sensible to move migration code
80   // to PrefContentSettingsProvider.
81   MigrateObsoleteCookiePref(prefs);
82 
83   // Read misc. global settings.
84   block_third_party_cookies_ =
85       prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
86   if (block_third_party_cookies_) {
87     UserMetrics::RecordAction(
88         UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
89   } else {
90     UserMetrics::RecordAction(
91         UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
92   }
93   is_block_third_party_cookies_managed_ =
94       prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies);
95   block_nonsandboxed_plugins_ =
96       prefs->GetBoolean(prefs::kBlockNonsandboxedPlugins);
97 
98   // User defined non default content settings are provided by the PrefProvider.
99   // The order in which the content settings providers are created is critical,
100   // as providers that are further up in the list (i.e. added earlier) override
101   // providers further down.
102   content_settings_providers_.push_back(
103       make_linked_ptr(new content_settings::PolicyProvider(profile)));
104   content_settings_providers_.push_back(
105       make_linked_ptr(new content_settings::PrefProvider(profile)));
106 
107   pref_change_registrar_.Init(prefs);
108   pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
109   pref_change_registrar_.Add(prefs::kBlockNonsandboxedPlugins, this);
110   notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
111                               Source<Profile>(profile_));
112 }
113 
114 // static
RegisterUserPrefs(PrefService * prefs)115 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
116   prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, false);
117   prefs->RegisterBooleanPref(prefs::kBlockNonsandboxedPlugins, false);
118   prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0);
119 
120   // Obsolete prefs, for migration:
121   prefs->RegisterIntegerPref(prefs::kCookieBehavior,
122                              net::StaticCookiePolicy::ALLOW_ALL_COOKIES);
123 
124   // Register the prefs for the content settings providers.
125   content_settings::PrefDefaultProvider::RegisterUserPrefs(prefs);
126   content_settings::PolicyDefaultProvider::RegisterUserPrefs(prefs);
127   content_settings::PrefProvider::RegisterUserPrefs(prefs);
128   content_settings::PolicyProvider::RegisterUserPrefs(prefs);
129 }
130 
GetDefaultContentSetting(ContentSettingsType content_type) const131 ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
132     ContentSettingsType content_type) const {
133   ContentSetting setting = CONTENT_SETTING_DEFAULT;
134   for (ConstDefaultProviderIterator provider =
135            default_content_settings_providers_.begin();
136        provider != default_content_settings_providers_.end(); ++provider) {
137     ContentSetting provided_setting =
138         (*provider)->ProvideDefaultSetting(content_type);
139     if (provided_setting != CONTENT_SETTING_DEFAULT)
140       setting = provided_setting;
141   }
142   // The method GetDefaultContentSetting always has to return an explicit
143   // value that is to be used as default. We here rely on the
144   // PrefContentSettingProvider to always provide a value.
145   CHECK_NE(CONTENT_SETTING_DEFAULT, setting);
146   return setting;
147 }
148 
GetContentSetting(const GURL & url,ContentSettingsType content_type,const std::string & resource_identifier) const149 ContentSetting HostContentSettingsMap::GetContentSetting(
150     const GURL& url,
151     ContentSettingsType content_type,
152     const std::string& resource_identifier) const {
153   ContentSetting setting = GetNonDefaultContentSetting(url,
154                                                        content_type,
155                                                        resource_identifier);
156   if (setting == CONTENT_SETTING_DEFAULT)
157     return GetDefaultContentSetting(content_type);
158   return setting;
159 }
160 
GetNonDefaultContentSetting(const GURL & url,ContentSettingsType content_type,const std::string & resource_identifier) const161 ContentSetting HostContentSettingsMap::GetNonDefaultContentSetting(
162     const GURL& url,
163     ContentSettingsType content_type,
164     const std::string& resource_identifier) const {
165   if (ShouldAllowAllContent(url))
166     return CONTENT_SETTING_ALLOW;
167 
168   // Iterate through the list of providers and break when the first non default
169   // setting is found.
170   ContentSetting provided_setting(CONTENT_SETTING_DEFAULT);
171   for (ConstProviderIterator provider = content_settings_providers_.begin();
172        provider != content_settings_providers_.end();
173        ++provider) {
174     provided_setting = (*provider)->GetContentSetting(
175         url, url, content_type, resource_identifier);
176     bool isManaged = (*provider)->ContentSettingsTypeIsManaged(content_type);
177     if (provided_setting != CONTENT_SETTING_DEFAULT || isManaged)
178       return provided_setting;
179   }
180   return provided_setting;
181 }
182 
GetContentSettings(const GURL & url) const183 ContentSettings HostContentSettingsMap::GetContentSettings(
184     const GURL& url) const {
185   ContentSettings output = GetNonDefaultContentSettings(url);
186 
187   // If we require a resource identifier, set the content settings to default,
188   // otherwise make the defaults explicit.
189   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
190     // A managed default content setting has the highest priority and hence
191     // will overwrite any previously set value.
192     if (output.settings[j] == CONTENT_SETTING_DEFAULT &&
193         j != CONTENT_SETTINGS_TYPE_PLUGINS) {
194       output.settings[j] = GetDefaultContentSetting(ContentSettingsType(j));
195     }
196   }
197   return output;
198 }
199 
GetNonDefaultContentSettings(const GURL & url) const200 ContentSettings HostContentSettingsMap::GetNonDefaultContentSettings(
201     const GURL& url) const {
202   if (ShouldAllowAllContent(url))
203       return ContentSettings(CONTENT_SETTING_ALLOW);
204 
205   ContentSettings output(CONTENT_SETTING_DEFAULT);
206   for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
207     output.settings[j] = GetNonDefaultContentSetting(
208         url, ContentSettingsType(j) , "");
209   }
210   return output;
211 }
212 
GetSettingsForOneType(ContentSettingsType content_type,const std::string & resource_identifier,SettingsForOneType * settings) const213 void HostContentSettingsMap::GetSettingsForOneType(
214     ContentSettingsType content_type,
215     const std::string& resource_identifier,
216     SettingsForOneType* settings) const {
217   DCHECK(settings);
218   settings->clear();
219 
220   // Collect content_settings::Rules for the given content_type and
221   // resource_identifier from the content settings providers.
222   Rules content_settings_rules;
223   for (ConstProviderIterator provider = content_settings_providers_.begin();
224        provider != content_settings_providers_.end();
225        ++provider) {
226     // TODO(markusheintz): Only the rules that are applied should be collected.
227     // Merge rules.
228     // TODO(markusheintz): GetAllContentSettingsRules should maybe not clear the
229     // passed vector in case rule sets are just unified.
230     Rules rules;
231     (*provider)->GetAllContentSettingsRules(
232         content_type, resource_identifier, &rules);
233     content_settings_rules.insert(content_settings_rules.end(),
234                                   rules.begin(),
235                                   rules.end());
236   }
237 
238   // convert Rules to SettingsForOneType
239   for (const_rules_iterator rule_iterator =
240            content_settings_rules.begin();
241        rule_iterator != content_settings_rules.end();
242        ++rule_iterator) {
243     settings->push_back(std::make_pair(ContentSettingsPattern(
244         rule_iterator->requesting_url_pattern),
245         rule_iterator->content_setting));
246   }
247 }
248 
SetDefaultContentSetting(ContentSettingsType content_type,ContentSetting setting)249 void HostContentSettingsMap::SetDefaultContentSetting(
250     ContentSettingsType content_type,
251     ContentSetting setting) {
252   for (DefaultProviderIterator provider =
253            default_content_settings_providers_.begin();
254        provider != default_content_settings_providers_.end(); ++provider) {
255     (*provider)->UpdateDefaultSetting(content_type, setting);
256   }
257 }
258 
SetContentSetting(const ContentSettingsPattern & pattern,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting)259 void HostContentSettingsMap::SetContentSetting(
260     const ContentSettingsPattern& pattern,
261     ContentSettingsType content_type,
262     const std::string& resource_identifier,
263     ContentSetting setting) {
264   for (ProviderIterator provider = content_settings_providers_.begin();
265        provider != content_settings_providers_.end();
266        ++provider) {
267     (*provider)->SetContentSetting(
268         pattern, pattern, content_type, resource_identifier, setting);
269   }
270 }
271 
AddExceptionForURL(const GURL & url,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting)272 void HostContentSettingsMap::AddExceptionForURL(
273     const GURL& url,
274     ContentSettingsType content_type,
275     const std::string& resource_identifier,
276     ContentSetting setting) {
277   // Make sure there is no entry that would override the pattern we are about
278   // to insert for exactly this URL.
279   SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(url),
280                     content_type,
281                     resource_identifier,
282                     CONTENT_SETTING_DEFAULT);
283   SetContentSetting(ContentSettingsPattern::FromURL(url),
284                     content_type,
285                     resource_identifier,
286                     setting);
287 }
288 
ClearSettingsForOneType(ContentSettingsType content_type)289 void HostContentSettingsMap::ClearSettingsForOneType(
290     ContentSettingsType content_type) {
291   for (ProviderIterator provider = content_settings_providers_.begin();
292        provider != content_settings_providers_.end();
293        ++provider) {
294     (*provider)->ClearAllContentSettingsRules(content_type);
295   }
296 }
297 
SetBlockThirdPartyCookies(bool block)298 void HostContentSettingsMap::SetBlockThirdPartyCookies(bool block) {
299   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
300 
301   // This setting may not be directly modified for OTR sessions.  Instead, it
302   // is synced to the main profile's setting.
303   if (is_off_the_record_) {
304     NOTREACHED();
305     return;
306   }
307 
308   PrefService* prefs = profile_->GetPrefs();
309   // If the preference block-third-party-cookies is managed then do not allow to
310   // change it.
311   if (prefs->IsManagedPreference(prefs::kBlockThirdPartyCookies)) {
312     NOTREACHED();
313     return;
314   }
315 
316   {
317     base::AutoLock auto_lock(lock_);
318     block_third_party_cookies_ = block;
319   }
320 
321   if (block)
322     prefs->SetBoolean(prefs::kBlockThirdPartyCookies, true);
323   else
324     prefs->ClearPref(prefs::kBlockThirdPartyCookies);
325 }
326 
SetBlockNonsandboxedPlugins(bool block)327 void HostContentSettingsMap::SetBlockNonsandboxedPlugins(bool block) {
328   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
329 
330   // This setting may not be directly modified for OTR sessions.  Instead, it
331   // is synced to the main profile's setting.
332   if (is_off_the_record_) {
333     NOTREACHED();
334     return;
335   }
336 
337   {
338     base::AutoLock auto_lock(lock_);
339     block_nonsandboxed_plugins_ = block;
340   }
341 
342   PrefService* prefs = profile_->GetPrefs();
343   if (block) {
344     UserMetrics::RecordAction(
345         UserMetricsAction("BlockNonsandboxedPlugins_Enable"));
346     prefs->SetBoolean(prefs::kBlockNonsandboxedPlugins, true);
347   } else {
348     UserMetrics::RecordAction(
349         UserMetricsAction("BlockNonsandboxedPlugins_Disable"));
350     prefs->ClearPref(prefs::kBlockNonsandboxedPlugins);
351   }
352 }
353 
ResetToDefaults()354 void HostContentSettingsMap::ResetToDefaults() {
355   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
356 
357   {
358     base::AutoLock auto_lock(lock_);
359     for (DefaultProviderIterator provider =
360              default_content_settings_providers_.begin();
361          provider != default_content_settings_providers_.end(); ++provider) {
362       (*provider)->ResetToDefaults();
363     }
364 
365     for (ProviderIterator provider = content_settings_providers_.begin();
366          provider != content_settings_providers_.end();
367          ++provider) {
368       (*provider)->ResetToDefaults();
369     }
370 
371     // Don't reset block third party cookies if they are managed.
372     if (!IsBlockThirdPartyCookiesManaged())
373       block_third_party_cookies_ = false;
374     block_nonsandboxed_plugins_ = false;
375   }
376 
377   if (!is_off_the_record_) {
378     PrefService* prefs = profile_->GetPrefs();
379     updating_preferences_ = true;
380     // If the block third party cookies preference is managed we still must
381     // clear it in order to restore the default value for later when the
382     // preference is not managed anymore.
383     prefs->ClearPref(prefs::kBlockThirdPartyCookies);
384     prefs->ClearPref(prefs::kBlockNonsandboxedPlugins);
385     updating_preferences_ = false;
386     NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
387                                            CONTENT_SETTINGS_TYPE_DEFAULT,
388                                            ""));
389   }
390 }
391 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)392 void HostContentSettingsMap::Observe(NotificationType type,
393                                      const NotificationSource& source,
394                                      const NotificationDetails& details) {
395   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 
397   if (type == NotificationType::PREF_CHANGED) {
398     DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
399     if (updating_preferences_)
400       return;
401 
402     std::string* name = Details<std::string>(details).ptr();
403     if (*name == prefs::kBlockThirdPartyCookies) {
404       base::AutoLock auto_lock(lock_);
405       block_third_party_cookies_ = profile_->GetPrefs()->GetBoolean(
406           prefs::kBlockThirdPartyCookies);
407       is_block_third_party_cookies_managed_ =
408           profile_->GetPrefs()->IsManagedPreference(
409               prefs::kBlockThirdPartyCookies);
410     } else if (*name == prefs::kBlockNonsandboxedPlugins) {
411       base::AutoLock auto_lock(lock_);
412       block_nonsandboxed_plugins_ = profile_->GetPrefs()->GetBoolean(
413           prefs::kBlockNonsandboxedPlugins);
414     } else {
415       NOTREACHED() << "Unexpected preference observed";
416       return;
417     }
418 
419     if (!is_off_the_record_) {
420       NotifyObservers(ContentSettingsDetails(ContentSettingsPattern(),
421                                              CONTENT_SETTINGS_TYPE_DEFAULT,
422                                              ""));
423     }
424   } else if (type == NotificationType::PROFILE_DESTROYED) {
425     DCHECK_EQ(profile_, Source<Profile>(source).ptr());
426     UnregisterObservers();
427   } else {
428     NOTREACHED() << "Unexpected notification";
429   }
430 }
431 
~HostContentSettingsMap()432 HostContentSettingsMap::~HostContentSettingsMap() {
433   UnregisterObservers();
434 }
435 
IsDefaultContentSettingManaged(ContentSettingsType content_type) const436 bool HostContentSettingsMap::IsDefaultContentSettingManaged(
437     ContentSettingsType content_type) const {
438   for (ConstDefaultProviderIterator provider =
439            default_content_settings_providers_.begin();
440        provider != default_content_settings_providers_.end(); ++provider) {
441     if ((*provider)->DefaultSettingIsManaged(content_type))
442       return true;
443   }
444   return false;
445 }
446 
NotifyObservers(const ContentSettingsDetails & details)447 void HostContentSettingsMap::NotifyObservers(
448     const ContentSettingsDetails& details) {
449   NotificationService::current()->Notify(
450       NotificationType::CONTENT_SETTINGS_CHANGED,
451       Source<HostContentSettingsMap>(this),
452       Details<const ContentSettingsDetails>(&details));
453 }
454 
UnregisterObservers()455 void HostContentSettingsMap::UnregisterObservers() {
456   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
457   if (!profile_)
458     return;
459   pref_change_registrar_.RemoveAll();
460   notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
461                                  Source<Profile>(profile_));
462   profile_ = NULL;
463 }
464 
MigrateObsoleteCookiePref(PrefService * prefs)465 void HostContentSettingsMap::MigrateObsoleteCookiePref(PrefService* prefs) {
466   if (prefs->HasPrefPath(prefs::kCookieBehavior)) {
467     int cookie_behavior = prefs->GetInteger(prefs::kCookieBehavior);
468     prefs->ClearPref(prefs::kCookieBehavior);
469     if (!prefs->HasPrefPath(prefs::kDefaultContentSettings)) {
470         SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
471             (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ?
472                 CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW);
473     }
474     if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
475       SetBlockThirdPartyCookies(cookie_behavior ==
476           net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
477     }
478   }
479 }
480