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_pattern.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/pref_names.h" | |
19 #include "content/browser/browser_thread.h" | |
20 #include "content/browser/user_metrics.h" | |
21 #include "content/common/notification_service.h" | |
22 #include "content/common/notification_source.h" | |
23 #include "googleurl/src/gurl.h" | |
24 #include "net/base/net_errors.h" | |
25 #include "net/base/static_cookie_policy.h" | |
26 | |
27 namespace { | |
28 | |
29 // ProfileKeyedFactory is the owner of the ProfileKeyedServices. This wrapper | |
30 // class allows others to hold shared pointers to CookieSettings. | |
31 class CookieSettingsWrapper : public ProfileKeyedService { | |
32 public: | |
33 explicit CookieSettingsWrapper(scoped_refptr<CookieSettings> cookie_settings) | |
34 : cookie_settings_(cookie_settings) {} | |
35 virtual ~CookieSettingsWrapper() {} | |
36 | |
37 CookieSettings* cookie_settings() { return cookie_settings_.get(); } | |
38 | |
39 private: | |
40 // ProfileKeyedService methods: | |
41 virtual void Shutdown() OVERRIDE { | |
42 cookie_settings_->ShutdownOnUIThread(); | |
43 } | |
44 | |
45 scoped_refptr<CookieSettings> cookie_settings_; | |
46 }; | |
47 | |
48 // Helper functions for converting cookie settings. | |
49 | |
50 // Converts a single cookie content setting into a content setting pair for | |
51 // (cookies, permanent cookies). | |
52 void ConvertCookieSettingToSettingPair( | |
53 ContentSetting setting, ContentSetting* cookies_allowed, | |
54 ContentSetting* permanent_cookies_allowed) { | |
55 *cookies_allowed = CONTENT_SETTING_BLOCK; | |
56 *permanent_cookies_allowed = CONTENT_SETTING_ALLOW; | |
57 if (setting == CONTENT_SETTING_ALLOW || | |
58 setting == CONTENT_SETTING_SESSION_ONLY) | |
59 *cookies_allowed = CONTENT_SETTING_ALLOW; | |
60 if (setting == CONTENT_SETTING_SESSION_ONLY) | |
61 *permanent_cookies_allowed = CONTENT_SETTING_BLOCK; | |
62 } | |
63 | |
64 // Converts the content settings pair (cookies, permanent cookies) into a | |
65 // single content setting. | |
66 ContentSetting ConvertSettingPairToCookieSetting( | |
67 ContentSetting cookies_allowed, ContentSetting permanent_cookies_allowed) { | |
68 DCHECK(cookies_allowed == CONTENT_SETTING_ALLOW || | |
69 cookies_allowed == CONTENT_SETTING_BLOCK); | |
70 DCHECK(permanent_cookies_allowed == CONTENT_SETTING_ALLOW || | |
71 permanent_cookies_allowed == CONTENT_SETTING_BLOCK); | |
72 if (cookies_allowed == CONTENT_SETTING_BLOCK) | |
73 return CONTENT_SETTING_BLOCK; | |
74 if (permanent_cookies_allowed == CONTENT_SETTING_ALLOW) | |
75 return CONTENT_SETTING_ALLOW; | |
76 return CONTENT_SETTING_SESSION_ONLY; | |
77 } | |
78 | |
79 } // namespace | |
80 | |
81 class CookieSettings::Factory : public ProfileKeyedServiceFactory { | |
82 public: | |
83 static Factory* GetInstance(); | |
84 | |
85 CookieSettingsWrapper* GetWrapperForProfile(Profile* profile); | |
86 | |
87 private: | |
88 friend struct DefaultSingletonTraits<Factory>; | |
89 | |
90 Factory(); | |
91 virtual ~Factory() {} | |
92 | |
93 // PrefoileKeyedServiceFactory methods: | |
Bernhard Bauer
2011/09/14 16:01:36
Nit: ProfileKeyedServiceFactory
| |
94 virtual CookieSettingsWrapper* BuildServiceInstanceFor( | |
95 Profile* profile) const OVERRIDE; | |
96 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } | |
97 }; | |
98 | |
99 // static | |
100 CookieSettings::Factory* CookieSettings::Factory::GetInstance() { | |
101 return Singleton<CookieSettings::Factory>::get(); | |
102 } | |
103 | |
104 CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile( | |
105 Profile* profile) { | |
106 return static_cast<CookieSettingsWrapper*>( | |
107 GetServiceForProfile(profile,true)); | |
108 } | |
109 | |
110 CookieSettings::Factory::Factory() | |
111 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { | |
112 } | |
113 | |
114 CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor( | |
115 Profile* profile) const { | |
116 scoped_refptr<CookieSettings> cookie_settings = new CookieSettings( | |
117 profile->GetHostContentSettingsMap(), | |
118 profile->GetPrefs()); | |
119 return new CookieSettingsWrapper(cookie_settings); | |
120 } | |
121 | |
122 CookieSettings::CookieSettings( | |
123 HostContentSettingsMap* host_content_settings_map, | |
124 PrefService* prefs) | |
125 : host_content_settings_map_(host_content_settings_map), | |
126 block_third_party_cookies_( | |
127 prefs->GetBoolean(prefs::kBlockThirdPartyCookies)) { | |
128 if (block_third_party_cookies_) { | |
129 UserMetrics::RecordAction( | |
130 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); | |
131 } else { | |
132 UserMetrics::RecordAction( | |
133 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); | |
134 } | |
135 | |
136 pref_change_registrar_.Init(prefs); | |
137 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); | |
138 } | |
139 | |
140 CookieSettings::~CookieSettings() { | |
141 } | |
142 | |
143 // static | |
144 CookieSettings* CookieSettings::GetForProfile(Profile* profile) { | |
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
146 CookieSettings* cookie_settings = | |
147 Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings(); | |
148 DCHECK(cookie_settings); | |
149 return cookie_settings; | |
150 } | |
151 | |
152 ContentSetting CookieSettings::GetDefaultCookieSetting() const { | |
153 ContentSetting cookies_allowed = | |
154 host_content_settings_map_->GetDefaultContentSetting( | |
155 CONTENT_SETTINGS_TYPE_COOKIES); | |
156 ContentSetting permanent_cookies_allowed = | |
157 host_content_settings_map_->GetDefaultContentSetting( | |
158 CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES); | |
159 return ConvertSettingPairToCookieSetting( | |
160 cookies_allowed, permanent_cookies_allowed); | |
161 } | |
162 | |
163 bool CookieSettings::IsReadingCookieAllowed(const GURL& url, | |
164 const GURL& first_party_url) const { | |
165 ContentSetting setting = GetCookieContentSetting( | |
166 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, false); | |
167 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
168 setting == CONTENT_SETTING_BLOCK); | |
169 return setting == CONTENT_SETTING_ALLOW; | |
170 } | |
171 | |
172 bool CookieSettings::IsSettingCookieAllowed(const GURL& url, | |
173 const GURL& first_party_url) const { | |
174 ContentSetting setting = GetCookieContentSetting( | |
175 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, true); | |
176 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
177 setting == CONTENT_SETTING_BLOCK); | |
178 return setting == CONTENT_SETTING_ALLOW; | |
179 } | |
180 | |
181 bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const { | |
182 ContentSetting setting = GetCookieContentSetting( | |
183 origin, origin, CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, true); | |
184 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
185 setting == CONTENT_SETTING_BLOCK); | |
186 return (setting == CONTENT_SETTING_BLOCK); | |
187 } | |
188 | |
189 void CookieSettings::GetCookieSettings( | |
190 HostContentSettingsMap::SettingsForOneType* settings) const { | |
191 DCHECK(settings); | |
192 settings->clear(); | |
193 | |
194 // 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
| |
195 // elements, since all exceptions are stored for both content types. | |
196 HostContentSettingsMap::SettingsForOneType cookie_settings; | |
197 host_content_settings_map_->GetSettingsForOneType( | |
198 CONTENT_SETTINGS_TYPE_COOKIES, "", &cookie_settings); | |
199 HostContentSettingsMap::SettingsForOneType permanent_cookie_settings; | |
200 host_content_settings_map_->GetSettingsForOneType( | |
201 CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "", &permanent_cookie_settings); | |
202 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
| |
203 | |
204 HostContentSettingsMap::PatternSettingSourceTuple setting; | |
205 setting.b = ContentSettingsPattern::Wildcard(); | |
206 for (size_t i = 0; i < cookie_settings.size(); ++i) { | |
207 DCHECK(cookie_settings[i].a == permanent_cookie_settings[i].a); | |
208 setting.a = cookie_settings[i].a; | |
209 setting.c = ConvertSettingPairToCookieSetting( | |
210 cookie_settings[i].c, permanent_cookie_settings[i].c); | |
211 settings->push_back(setting); | |
212 } | |
213 } | |
214 | |
215 void CookieSettings::SetDefaultCookieSetting(ContentSetting setting) { | |
216 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
217 setting == CONTENT_SETTING_SESSION_ONLY || | |
218 setting == CONTENT_SETTING_BLOCK); | |
219 ContentSetting cookies_allowed; | |
220 ContentSetting permanent_cookies_allowed; | |
221 ConvertCookieSettingToSettingPair(setting, | |
222 &cookies_allowed, | |
223 &permanent_cookies_allowed); | |
224 host_content_settings_map_->SetDefaultContentSetting( | |
225 CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, permanent_cookies_allowed); | |
226 host_content_settings_map_->SetDefaultContentSetting( | |
227 CONTENT_SETTINGS_TYPE_COOKIES, cookies_allowed); | |
228 } | |
229 | |
230 void CookieSettings::SetCookieSetting( | |
231 const ContentSettingsPattern& primary_pattern, | |
232 ContentSetting setting) { | |
233 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
234 setting == CONTENT_SETTING_SESSION_ONLY || | |
235 setting == CONTENT_SETTING_BLOCK); | |
236 ContentSetting cookies_allowed; | |
237 ContentSetting permanent_cookies_allowed; | |
238 ConvertCookieSettingToSettingPair(setting, | |
239 &cookies_allowed, | |
240 &permanent_cookies_allowed); | |
241 // Set CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES first; when clients monitoring | |
242 // CONTENT_SETTINGS_TYPE_COOKIES get a notification, we're already in a | |
243 // consistent state. | |
244 host_content_settings_map_->SetContentSetting( | |
245 primary_pattern, ContentSettingsPattern::Wildcard(), | |
246 CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "", | |
247 permanent_cookies_allowed); | |
248 host_content_settings_map_->SetContentSetting( | |
249 primary_pattern, ContentSettingsPattern::Wildcard(), | |
250 CONTENT_SETTINGS_TYPE_COOKIES, "", | |
251 cookies_allowed); | |
252 } | |
253 | |
254 void CookieSettings::ResetCookieSetting( | |
255 const ContentSettingsPattern& primary_pattern) { | |
256 // Set CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES first; when clients monitoring | |
257 // CONTENT_SETTINGS_TYPE_COOKIES get a notification, we're already in a | |
258 // consistent state. | |
259 host_content_settings_map_->SetContentSetting( | |
260 primary_pattern, ContentSettingsPattern::Wildcard(), | |
261 CONTENT_SETTINGS_TYPE_PERMANENT_COOKIES, "", | |
262 CONTENT_SETTING_DEFAULT); | |
263 host_content_settings_map_->SetContentSetting( | |
264 primary_pattern, ContentSettingsPattern::Wildcard(), | |
265 CONTENT_SETTINGS_TYPE_COOKIES, "", | |
266 CONTENT_SETTING_DEFAULT); | |
267 } | |
268 | |
269 void CookieSettings::Observe(int type, | |
270 const NotificationSource& source, | |
271 const NotificationDetails& details) { | |
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
273 | |
274 if (type == chrome::NOTIFICATION_PREF_CHANGED) { | |
275 PrefService* prefs = Source<PrefService>(source).ptr(); | |
276 | |
277 std::string* name = Details<std::string>(details).ptr(); | |
278 if (*name == prefs::kBlockThirdPartyCookies) { | |
279 base::AutoLock auto_lock(lock_); | |
280 block_third_party_cookies_ = prefs->GetBoolean( | |
281 prefs::kBlockThirdPartyCookies); | |
282 } else { | |
283 NOTREACHED() << "Unexpected preference observed"; | |
284 return; | |
285 } | |
286 } else { | |
287 NOTREACHED() << "Unexpected notification"; | |
288 } | |
289 } | |
290 | |
291 void CookieSettings::ShutdownOnUIThread() { | |
292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
293 pref_change_registrar_.RemoveAll(); | |
294 } | |
295 | |
296 ContentSetting CookieSettings::GetCookieContentSetting( | |
297 const GURL& url, | |
298 const GURL& first_party_url, | |
299 ContentSettingsType content_type, | |
300 bool setting_cookie) const { | |
301 if (HostContentSettingsMap::ShouldAllowAllContent( | |
302 first_party_url, CONTENT_SETTINGS_TYPE_COOKIES)) | |
303 return CONTENT_SETTING_ALLOW; | |
304 | |
305 // First get any host-specific settings. | |
306 ContentSetting setting = | |
307 host_content_settings_map_->GetNonDefaultContentSetting( | |
308 url, first_party_url, content_type, ""); | |
309 | |
310 // Check if third-party cookie settings deny the cookie. This check makes | |
311 // sense only for the CONTENT_SETTINGS_TYPE_COOKIES, since the session only | |
312 // check is based on one url only. | |
313 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && | |
314 setting == CONTENT_SETTING_DEFAULT && | |
315 ShouldBlockThirdPartyCookies()) { | |
316 bool strict = CommandLine::ForCurrentProcess()->HasSwitch( | |
317 switches::kBlockReadingThirdPartyCookies); | |
318 net::StaticCookiePolicy policy(strict ? | |
319 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES : | |
320 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); | |
321 int rv; | |
322 if (setting_cookie) | |
323 rv = policy.CanSetCookie(url, first_party_url); | |
324 else | |
325 rv = policy.CanGetCookies(url, first_party_url); | |
326 DCHECK_NE(net::ERR_IO_PENDING, rv); | |
327 if (rv != net::OK) | |
328 setting = CONTENT_SETTING_BLOCK; | |
329 } | |
330 | |
331 // If no other policy has changed the setting, use the default. | |
332 if (setting == CONTENT_SETTING_DEFAULT) { | |
333 setting = | |
334 host_content_settings_map_->GetDefaultContentSetting(content_type); | |
335 } | |
336 return setting; | |
337 } | |
338 | |
339 bool CookieSettings::ShouldBlockThirdPartyCookies() const { | |
340 base::AutoLock auto_lock(lock_); | |
341 return block_third_party_cookies_; | |
342 } | |
OLD | NEW |