OLD | NEW |
---|---|
(Empty) | |
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/cookie_settings.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/memory/singleton.h" | |
9 #include "chrome/browser/content_settings/content_settings_utils.h" | |
10 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
11 #include "chrome/browser/prefs/pref_service.h" | |
12 #include "chrome/browser/profiles/profile.h" | |
13 #include "chrome/browser/profiles/profile_dependency_manager.h" | |
14 #include "chrome/browser/profiles/profile_keyed_service.h" | |
15 #include "chrome/browser/profiles/profile_keyed_service_factory.h" | |
16 #include "chrome/common/chrome_notification_types.h" | |
17 #include "chrome/common/chrome_switches.h" | |
18 #include "chrome/common/content_settings_pattern.h" | |
19 #include "chrome/common/pref_names.h" | |
20 #include "content/browser/browser_thread.h" | |
21 #include "content/browser/user_metrics.h" | |
22 #include "content/public/browser/notification_service.h" | |
23 #include "content/public/browser/notification_source.h" | |
24 #include "googleurl/src/gurl.h" | |
25 #include "net/base/net_errors.h" | |
26 #include "net/base/static_cookie_policy.h" | |
27 | |
28 namespace { | |
29 | |
30 // |ProfileKeyedFactory| is the owner of the |ProfileKeyedService|s. This | |
31 // wrapper class allows others to hold shared pointers to CookieSettings. | |
32 class CookieSettingsWrapper : public ProfileKeyedService { | |
33 public: | |
34 explicit CookieSettingsWrapper(scoped_refptr<CookieSettings> cookie_settings) | |
35 : cookie_settings_(cookie_settings) {} | |
36 virtual ~CookieSettingsWrapper() {} | |
37 | |
38 CookieSettings* cookie_settings() { return cookie_settings_.get(); } | |
39 | |
40 private: | |
41 // ProfileKeyedService methods: | |
42 virtual void Shutdown() OVERRIDE { | |
43 cookie_settings_->ShutdownOnUIThread(); | |
44 } | |
45 | |
46 scoped_refptr<CookieSettings> cookie_settings_; | |
47 }; | |
48 | |
49 } // namespace | |
50 | |
51 class CookieSettings::Factory : public ProfileKeyedServiceFactory { | |
52 public: | |
53 static Factory* GetInstance(); | |
Bernhard Bauer
2011/10/25 13:11:21
You're probably going to have to initialize the fa
marja
2011/10/26 13:03:21
Done.
| |
54 | |
55 CookieSettingsWrapper* GetWrapperForProfile(Profile* profile); | |
56 | |
57 private: | |
58 friend struct DefaultSingletonTraits<Factory>; | |
59 | |
60 Factory(); | |
61 virtual ~Factory() {} | |
62 | |
63 // |ProfileKeyedServiceFactory| methods: | |
64 virtual CookieSettingsWrapper* BuildServiceInstanceFor( | |
65 Profile* profile) const OVERRIDE; | |
66 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } | |
67 }; | |
68 | |
69 // static | |
70 CookieSettings::Factory* CookieSettings::Factory::GetInstance() { | |
71 return Singleton<CookieSettings::Factory>::get(); | |
72 } | |
73 | |
74 CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile( | |
75 Profile* profile) { | |
76 return static_cast<CookieSettingsWrapper*>( | |
77 GetServiceForProfile(profile,true)); | |
78 } | |
79 | |
80 CookieSettings::Factory::Factory() | |
81 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { | |
82 } | |
83 | |
84 CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor( | |
85 Profile* profile) const { | |
86 scoped_refptr<CookieSettings> cookie_settings = new CookieSettings( | |
87 profile->GetHostContentSettingsMap(), | |
88 profile->GetPrefs()); | |
89 return new CookieSettingsWrapper(cookie_settings); | |
90 } | |
91 | |
92 CookieSettings::CookieSettings( | |
93 HostContentSettingsMap* host_content_settings_map, | |
94 PrefService* prefs) | |
95 : host_content_settings_map_(host_content_settings_map), | |
96 block_third_party_cookies_( | |
97 prefs->GetBoolean(prefs::kBlockThirdPartyCookies)) { | |
98 if (block_third_party_cookies_) { | |
99 UserMetrics::RecordAction( | |
100 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); | |
101 } else { | |
102 UserMetrics::RecordAction( | |
103 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); | |
104 } | |
105 | |
106 pref_change_registrar_.Init(prefs); | |
107 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); | |
108 } | |
109 | |
110 CookieSettings::~CookieSettings() { | |
111 } | |
112 | |
113 // static | |
114 CookieSettings* CookieSettings::GetForProfile(Profile* profile) { | |
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
116 CookieSettings* cookie_settings = | |
117 Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings(); | |
118 DCHECK(cookie_settings); | |
119 return cookie_settings; | |
120 } | |
121 | |
122 ContentSetting | |
123 CookieSettings::GetDefaultCookieSetting(std::string* provider_id) const { | |
124 return host_content_settings_map_->GetDefaultContentSetting( | |
125 CONTENT_SETTINGS_TYPE_COOKIES, provider_id); | |
126 } | |
127 | |
128 bool CookieSettings::IsReadingCookieAllowed(const GURL& url, | |
129 const GURL& first_party_url) const { | |
130 ContentSetting setting = GetCookieSetting(url, first_party_url, false); | |
131 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
132 setting == CONTENT_SETTING_SESSION_ONLY || | |
133 setting == CONTENT_SETTING_BLOCK); | |
134 return (setting == CONTENT_SETTING_ALLOW || | |
135 setting == CONTENT_SETTING_SESSION_ONLY); | |
136 } | |
137 | |
138 bool CookieSettings::IsSettingCookieAllowed(const GURL& url, | |
139 const GURL& first_party_url) const { | |
140 ContentSetting setting = GetCookieSetting(url, first_party_url, true); | |
141 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
Bernhard Bauer
2011/10/25 13:11:21
Can you pull this out into a shared method?
marja
2011/10/26 13:03:21
Done.
| |
142 setting == CONTENT_SETTING_SESSION_ONLY || | |
143 setting == CONTENT_SETTING_BLOCK); | |
144 return (setting == CONTENT_SETTING_ALLOW || | |
145 setting == CONTENT_SETTING_SESSION_ONLY); | |
146 } | |
147 | |
148 bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const { | |
149 ContentSetting setting = GetCookieSetting(origin, origin, true); | |
150 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
151 setting == CONTENT_SETTING_SESSION_ONLY || | |
152 setting == CONTENT_SETTING_BLOCK); | |
153 return (setting == CONTENT_SETTING_SESSION_ONLY); | |
154 } | |
155 | |
156 void CookieSettings::GetCookieSettings( | |
157 HostContentSettingsMap::SettingsForOneType* settings) const { | |
158 return host_content_settings_map_->GetSettingsForOneType( | |
159 CONTENT_SETTINGS_TYPE_COOKIES, "", settings); | |
160 } | |
161 | |
162 void CookieSettings::SetDefaultCookieSetting(ContentSetting setting) { | |
163 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
164 setting == CONTENT_SETTING_SESSION_ONLY || | |
165 setting == CONTENT_SETTING_BLOCK); | |
166 host_content_settings_map_->SetDefaultContentSetting( | |
167 CONTENT_SETTINGS_TYPE_COOKIES, setting); | |
168 } | |
169 | |
170 void CookieSettings::SetCookieSetting( | |
171 const ContentSettingsPattern& primary_pattern, | |
172 ContentSetting setting) { | |
173 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
174 setting == CONTENT_SETTING_SESSION_ONLY || | |
175 setting == CONTENT_SETTING_BLOCK); | |
176 host_content_settings_map_->SetContentSetting( | |
177 primary_pattern, ContentSettingsPattern::Wildcard(), | |
178 CONTENT_SETTINGS_TYPE_COOKIES, "", setting); | |
179 } | |
180 | |
181 void CookieSettings::SetCookieSetting( | |
182 const ContentSettingsPattern& primary_pattern, | |
183 const ContentSettingsPattern& secondary_pattern, | |
184 ContentSetting setting) { | |
185 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
186 setting == CONTENT_SETTING_BLOCK); | |
187 host_content_settings_map_->SetContentSetting( | |
188 primary_pattern, secondary_pattern, CONTENT_SETTINGS_TYPE_COOKIES, "", | |
189 setting); | |
190 } | |
191 | |
192 void CookieSettings::ResetCookieSetting( | |
193 const ContentSettingsPattern& primary_pattern) { | |
194 host_content_settings_map_->SetContentSetting( | |
195 primary_pattern, ContentSettingsPattern::Wildcard(), | |
196 CONTENT_SETTINGS_TYPE_COOKIES, "", CONTENT_SETTING_DEFAULT); | |
197 } | |
198 | |
199 void CookieSettings::ResetCookieSetting( | |
200 const ContentSettingsPattern& primary_pattern, | |
201 const ContentSettingsPattern& secondary_pattern) { | |
202 host_content_settings_map_->SetContentSetting( | |
203 primary_pattern, secondary_pattern, CONTENT_SETTINGS_TYPE_COOKIES, "", | |
204 CONTENT_SETTING_DEFAULT); | |
205 } | |
206 | |
207 void CookieSettings::Observe(int type, | |
208 const content::NotificationSource& source, | |
209 const content::NotificationDetails& details) { | |
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
211 | |
212 if (type == chrome::NOTIFICATION_PREF_CHANGED) { | |
213 PrefService* prefs = content::Source<PrefService>(source).ptr(); | |
214 std::string* name = content::Details<std::string>(details).ptr(); | |
215 if (*name == prefs::kBlockThirdPartyCookies) { | |
216 base::AutoLock auto_lock(lock_); | |
217 block_third_party_cookies_ = prefs->GetBoolean( | |
218 prefs::kBlockThirdPartyCookies); | |
219 } else { | |
220 NOTREACHED() << "Unexpected preference observed"; | |
221 return; | |
222 } | |
223 } else { | |
224 NOTREACHED() << "Unexpected notification"; | |
225 } | |
226 } | |
227 | |
228 void CookieSettings::ShutdownOnUIThread() { | |
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
230 pref_change_registrar_.RemoveAll(); | |
231 } | |
232 | |
233 ContentSetting CookieSettings::GetCookieSetting( | |
234 const GURL& url, | |
235 const GURL& first_party_url, | |
236 bool setting_cookie) const { | |
237 if (HostContentSettingsMap::ShouldAllowAllContent( | |
238 first_party_url, | |
239 CONTENT_SETTINGS_TYPE_COOKIES)) { | |
240 return CONTENT_SETTING_ALLOW; | |
241 } | |
242 | |
243 ContentSettingsPattern primary_pattern; | |
244 ContentSettingsPattern secondary_pattern; | |
245 // First get any host-specific settings. | |
246 scoped_ptr<base::Value> value( | |
247 host_content_settings_map_->GetContentSettingValue( | |
248 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, "", | |
249 &primary_pattern, &secondary_pattern)); | |
250 | |
251 // If no explicit exception has been made and third-party cookies are blocked | |
252 // by default, apply that rule. | |
253 if (primary_pattern == ContentSettingsPattern::Wildcard() && | |
254 secondary_pattern == ContentSettingsPattern::Wildcard() && | |
255 ShouldBlockThirdPartyCookies()) { | |
256 bool strict = CommandLine::ForCurrentProcess()->HasSwitch( | |
257 switches::kBlockReadingThirdPartyCookies); | |
258 net::StaticCookiePolicy policy(strict ? | |
259 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES : | |
260 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); | |
261 int rv; | |
262 if (setting_cookie) | |
263 rv = policy.CanSetCookie(url, first_party_url); | |
264 else | |
265 rv = policy.CanGetCookies(url, first_party_url); | |
266 DCHECK_NE(net::ERR_IO_PENDING, rv); | |
267 if (rv != net::OK) | |
268 return CONTENT_SETTING_BLOCK; | |
269 } | |
270 | |
271 // We should always have a value, at least from the default provider. | |
272 DCHECK(value.get()); | |
273 return content_settings::ValueToContentSetting(value.get()); | |
274 } | |
275 | |
276 bool CookieSettings::ShouldBlockThirdPartyCookies() const { | |
277 base::AutoLock auto_lock(lock_); | |
278 return block_third_party_cookies_; | |
279 } | |
OLD | NEW |