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