Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(734)

Unified Diff: chrome/browser/content_settings/cookie_settings.cc

Issue 7713034: HostContentSettingsMap refactoring. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Keeping up to date with trunk. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/content_settings/cookie_settings.cc
diff --git a/chrome/browser/content_settings/cookie_settings.cc b/chrome/browser/content_settings/cookie_settings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3e74143fd23740e63f89f3f83d153f02afe1aa88
--- /dev/null
+++ b/chrome/browser/content_settings/cookie_settings.cc
@@ -0,0 +1,342 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/content_settings/cookie_settings.h"
+
+#include "base/command_line.h"
+#include "base/memory/singleton.h"
+#include "chrome/browser/content_settings/content_settings_pattern.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/user_metrics.h"
+#include "content/common/notification_service.h"
+#include "content/common/notification_source.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+#include "net/base/static_cookie_policy.h"
+
+namespace {
+
+// ProfileKeyedFactory is the owner of the ProfileKeyedServices. This wrapper
+// class allows others to hold shared pointers to CookieSettings.
+class CookieSettingsWrapper : public ProfileKeyedService {
+ public:
+ explicit CookieSettingsWrapper(scoped_refptr<CookieSettings> cookie_settings)
+ : cookie_settings_(cookie_settings) {}
+ virtual ~CookieSettingsWrapper() {}
+
+ CookieSettings* cookie_settings() { return cookie_settings_.get(); }
+
+ private:
+ // ProfileKeyedService methods:
+ virtual void Shutdown() OVERRIDE {
+ cookie_settings_->ShutdownOnUIThread();
+ }
+
+ scoped_refptr<CookieSettings> cookie_settings_;
+};
+
+// Helper functions for converting cookie settings.
+
+// Converts a single cookie content setting into a content setting pair for
+// (cookies, permanent cookies).
+void ConvertCookieSettingToSettingPair(
+ ContentSetting setting, ContentSetting* cookies_allowed,
+ ContentSetting* permanent_cookies_allowed) {
+ *cookies_allowed = CONTENT_SETTING_BLOCK;
+ *permanent_cookies_allowed = CONTENT_SETTING_ALLOW;
+ if (setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_SESSION_ONLY)
+ *cookies_allowed = CONTENT_SETTING_ALLOW;
+ if (setting == CONTENT_SETTING_SESSION_ONLY)
+ *permanent_cookies_allowed = CONTENT_SETTING_BLOCK;
+}
+
+// Converts the content settings pair (cookies, permanent cookies) into a
+// single content setting.
+ContentSetting ConvertSettingPairToCookieSetting(
+ ContentSetting cookies_allowed, ContentSetting permanent_cookies_allowed) {
+ DCHECK(cookies_allowed == CONTENT_SETTING_ALLOW ||
+ cookies_allowed == CONTENT_SETTING_BLOCK);
+ DCHECK(permanent_cookies_allowed == CONTENT_SETTING_ALLOW ||
+ permanent_cookies_allowed == CONTENT_SETTING_BLOCK);
+ if (cookies_allowed == CONTENT_SETTING_BLOCK)
+ return CONTENT_SETTING_BLOCK;
+ if (permanent_cookies_allowed == CONTENT_SETTING_ALLOW)
+ return CONTENT_SETTING_ALLOW;
+ return CONTENT_SETTING_SESSION_ONLY;
+}
+
+} // namespace
+
+class CookieSettings::Factory : public ProfileKeyedServiceFactory {
+ public:
+ static Factory* GetInstance();
+
+ CookieSettingsWrapper* GetWrapperForProfile(Profile* profile);
+
+ private:
+ friend struct DefaultSingletonTraits<Factory>;
+
+ Factory();
+ virtual ~Factory() {}
+
+ // PrefoileKeyedServiceFactory methods:
Bernhard Bauer 2011/09/14 16:01:36 Nit: ProfileKeyedServiceFactory
+ virtual CookieSettingsWrapper* BuildServiceInstanceFor(
+ Profile* profile) const OVERRIDE;
+ virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; }
+};
+
+// static
+CookieSettings::Factory* CookieSettings::Factory::GetInstance() {
+ return Singleton<CookieSettings::Factory>::get();
+}
+
+CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile(
+ Profile* profile) {
+ return static_cast<CookieSettingsWrapper*>(
+ GetServiceForProfile(profile,true));
+}
+
+CookieSettings::Factory::Factory()
+ : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) {
+}
+
+CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor(
+ Profile* profile) const {
+ scoped_refptr<CookieSettings> cookie_settings = new CookieSettings(
+ profile->GetHostContentSettingsMap(),
+ profile->GetPrefs());
+ return new CookieSettingsWrapper(cookie_settings);
+}
+
+CookieSettings::CookieSettings(
+ HostContentSettingsMap* host_content_settings_map,
+ PrefService* prefs)
+ : host_content_settings_map_(host_content_settings_map),
+ block_third_party_cookies_(
+ prefs->GetBoolean(prefs::kBlockThirdPartyCookies)) {
+ if (block_third_party_cookies_) {
+ UserMetrics::RecordAction(
+ UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
+ } else {
+ UserMetrics::RecordAction(
+ UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
+ }
+
+ pref_change_registrar_.Init(prefs);
+ pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
+}
+
+CookieSettings::~CookieSettings() {
+}
+
+// static
+CookieSettings* CookieSettings::GetForProfile(Profile* profile) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CookieSettings* cookie_settings =
+ Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings();
+ DCHECK(cookie_settings);
+ return cookie_settings;
+}
+
+ContentSetting CookieSettings::GetDefaultCookieSetting() const {
+ ContentSetting cookies_allowed =
+ host_content_settings_map_->GetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_COOKIES);
+ ContentSetting permanent_cookies_allowed =
+ host_content_settings_map_->GetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES);
+ return ConvertSettingPairToCookieSetting(
+ cookies_allowed, permanent_cookies_allowed);
+}
+
+bool CookieSettings::IsReadingCookieAllowed(const GURL& url,
+ const GURL& first_party_url) const {
+ ContentSetting setting = GetCookieContentSetting(
+ url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, false);
+ DCHECK(setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_BLOCK);
+ return setting == CONTENT_SETTING_ALLOW;
+}
+
+bool CookieSettings::IsSettingCookieAllowed(const GURL& url,
+ const GURL& first_party_url) const {
+ ContentSetting setting = GetCookieContentSetting(
+ url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, true);
+ DCHECK(setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_BLOCK);
+ return setting == CONTENT_SETTING_ALLOW;
+}
+
+bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const {
+ ContentSetting setting = GetCookieContentSetting(
+ origin, origin, CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, true);
+ DCHECK(setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_BLOCK);
+ return (setting == CONTENT_SETTING_BLOCK);
+}
+
+void CookieSettings::GetCookieSettings(
+ HostContentSettingsMap::SettingsForOneType* settings) const {
+ DCHECK(settings);
+ settings->clear();
+
+ // cookie_settings and permanent_cookie_settings will contain the same
Bernhard Bauer 2011/09/14 16:01:36 Nit: Please add bars around |cookie_settings| and
+ // elements, since all exceptions are stored for both content types.
+ HostContentSettingsMap::SettingsForOneType cookie_settings;
+ host_content_settings_map_->GetSettingsForOneType(
+ CONTENT_SETTINGS_TYPE_COOKIES, "", &cookie_settings);
+ HostContentSettingsMap::SettingsForOneType permanent_cookie_settings;
+ host_content_settings_map_->GetSettingsForOneType(
+ CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "", &permanent_cookie_settings);
+ DCHECK(cookie_settings.size() == permanent_cookie_settings.size());
Bernhard Bauer 2011/09/14 16:01:36 If you use DCHECK_EQ(expected, actual) you get nic
+
+ HostContentSettingsMap::PatternSettingSourceTuple setting;
+ setting.b = ContentSettingsPattern::Wildcard();
+ for (size_t i = 0; i < cookie_settings.size(); ++i) {
+ DCHECK(cookie_settings[i].a == permanent_cookie_settings[i].a);
+ setting.a = cookie_settings[i].a;
+ setting.c = ConvertSettingPairToCookieSetting(
+ cookie_settings[i].c, permanent_cookie_settings[i].c);
+ settings->push_back(setting);
+ }
+}
+
+void CookieSettings::SetDefaultCookieSetting(ContentSetting setting) {
+ DCHECK(setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_SESSION_ONLY ||
+ setting == CONTENT_SETTING_BLOCK);
+ ContentSetting cookies_allowed;
+ ContentSetting permanent_cookies_allowed;
+ ConvertCookieSettingToSettingPair(setting,
+ &cookies_allowed,
+ &permanent_cookies_allowed);
+ host_content_settings_map_->SetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, permanent_cookies_allowed);
+ host_content_settings_map_->SetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_COOKIES, cookies_allowed);
+}
+
+void CookieSettings::SetCookieSetting(
+ const ContentSettingsPattern& primary_pattern,
+ ContentSetting setting) {
+ DCHECK(setting == CONTENT_SETTING_ALLOW ||
+ setting == CONTENT_SETTING_SESSION_ONLY ||
+ setting == CONTENT_SETTING_BLOCK);
+ ContentSetting cookies_allowed;
+ ContentSetting permanent_cookies_allowed;
+ ConvertCookieSettingToSettingPair(setting,
+ &cookies_allowed,
+ &permanent_cookies_allowed);
+ // Set CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES first; when clients monitoring
+ // CONTENT_SETTINGS_TYPE_COOKIES get a notification, we're already in a
+ // consistent state.
+ host_content_settings_map_->SetContentSetting(
+ primary_pattern, ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "",
+ permanent_cookies_allowed);
+ host_content_settings_map_->SetContentSetting(
+ primary_pattern, ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_COOKIES, "",
+ cookies_allowed);
+}
+
+void CookieSettings::ResetCookieSetting(
+ const ContentSettingsPattern& primary_pattern) {
+ // Set CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES first; when clients monitoring
+ // CONTENT_SETTINGS_TYPE_COOKIES get a notification, we're already in a
+ // consistent state.
+ host_content_settings_map_->SetContentSetting(
+ primary_pattern, ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "",
+ CONTENT_SETTING_DEFAULT);
+ host_content_settings_map_->SetContentSetting(
+ primary_pattern, ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_COOKIES, "",
+ CONTENT_SETTING_DEFAULT);
+}
+
+void CookieSettings::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (type == chrome::NOTIFICATION_PREF_CHANGED) {
+ PrefService* prefs = Source<PrefService>(source).ptr();
+
+ std::string* name = Details<std::string>(details).ptr();
+ if (*name == prefs::kBlockThirdPartyCookies) {
+ base::AutoLock auto_lock(lock_);
+ block_third_party_cookies_ = prefs->GetBoolean(
+ prefs::kBlockThirdPartyCookies);
+ } else {
+ NOTREACHED() << "Unexpected preference observed";
+ return;
+ }
+ } else {
+ NOTREACHED() << "Unexpected notification";
+ }
+}
+
+void CookieSettings::ShutdownOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ pref_change_registrar_.RemoveAll();
+}
+
+ContentSetting CookieSettings::GetCookieContentSetting(
+ const GURL& url,
+ const GURL& first_party_url,
+ ContentSettingsType content_type,
+ bool setting_cookie) const {
+ if (HostContentSettingsMap::ShouldAllowAllContent(
+ first_party_url, CONTENT_SETTINGS_TYPE_COOKIES))
+ return CONTENT_SETTING_ALLOW;
+
+ // First get any host-specific settings.
+ ContentSetting setting =
+ host_content_settings_map_->GetNonDefaultContentSetting(
+ url, first_party_url, content_type, "");
+
+ // Check if third-party cookie settings deny the cookie. This check makes
+ // sense only for the CONTENT_SETTINGS_TYPE_COOKIES, since the session only
+ // check is based on one url only.
+ if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
+ setting == CONTENT_SETTING_DEFAULT &&
+ ShouldBlockThirdPartyCookies()) {
+ bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kBlockReadingThirdPartyCookies);
+ net::StaticCookiePolicy policy(strict ?
+ net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
+ net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
+ int rv;
+ if (setting_cookie)
+ rv = policy.CanSetCookie(url, first_party_url);
+ else
+ rv = policy.CanGetCookies(url, first_party_url);
+ DCHECK_NE(net::ERR_IO_PENDING, rv);
+ if (rv != net::OK)
+ setting = CONTENT_SETTING_BLOCK;
+ }
+
+ // If no other policy has changed the setting, use the default.
+ if (setting == CONTENT_SETTING_DEFAULT) {
+ setting =
+ host_content_settings_map_->GetDefaultContentSetting(content_type);
+ }
+ return setting;
+}
+
+bool CookieSettings::ShouldBlockThirdPartyCookies() const {
+ base::AutoLock auto_lock(lock_);
+ return block_third_party_cookies_;
+}

Powered by Google App Engine
This is Rietveld 408576698