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 } // namespace | |
49 | |
50 class CookieSettings::Factory : public ProfileKeyedServiceFactory { | |
51 public: | |
52 static Factory* GetInstance(); | |
53 | |
54 CookieSettingsWrapper* GetWrapperForProfile(Profile* profile); | |
55 | |
56 private: | |
57 friend struct DefaultSingletonTraits<Factory>; | |
58 | |
59 Factory(); | |
60 virtual ~Factory() {} | |
61 | |
62 // PrefoileKeyedServiceFactory methods: | |
63 virtual CookieSettingsWrapper* BuildServiceInstanceFor( | |
64 Profile* profile) const OVERRIDE; | |
65 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } | |
66 }; | |
67 | |
68 // static | |
69 CookieSettings::Factory* CookieSettings::Factory::GetInstance() { | |
70 return Singleton<CookieSettings::Factory>::get(); | |
71 } | |
72 | |
73 CookieSettingsWrapper* CookieSettings::Factory::GetWrapperForProfile( | |
74 Profile* profile) { | |
75 return static_cast<CookieSettingsWrapper*>( | |
76 GetServiceForProfile(profile,true)); | |
77 } | |
78 | |
79 CookieSettings::Factory::Factory() | |
80 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { | |
81 } | |
82 | |
83 CookieSettingsWrapper* CookieSettings::Factory::BuildServiceInstanceFor( | |
84 Profile* profile) const { | |
85 scoped_refptr<CookieSettings> cookie_settings = new CookieSettings( | |
86 profile->GetHostContentSettingsMap(), | |
87 profile->GetPrefs(), | |
88 profile->IsOffTheRecord()); | |
89 return new CookieSettingsWrapper(cookie_settings); | |
90 } | |
91 | |
92 CookieSettings::CookieSettings( | |
93 HostContentSettingsMap* host_content_settings_map, | |
94 PrefService* prefs, | |
95 bool incognito) | |
96 : host_content_settings_map_(host_content_settings_map), | |
97 prefs_(prefs), | |
98 is_off_the_record_(incognito), | |
99 block_third_party_cookies_(false) { | |
100 block_third_party_cookies_ = | |
101 prefs_->GetBoolean(prefs::kBlockThirdPartyCookies); | |
102 if (block_third_party_cookies_) { | |
103 UserMetrics::RecordAction( | |
104 UserMetricsAction("ThirdPartyCookieBlockingEnabled")); | |
105 } else { | |
106 UserMetrics::RecordAction( | |
107 UserMetricsAction("ThirdPartyCookieBlockingDisabled")); | |
108 } | |
109 | |
110 pref_change_registrar_.Init(prefs_); | |
111 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this); | |
112 } | |
113 | |
114 CookieSettings::~CookieSettings() { | |
115 } | |
116 | |
117 // static | |
118 CookieSettings* CookieSettings::GetForProfile(Profile* profile) { | |
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
120 CookieSettings* cookie_settings = | |
121 Factory::GetInstance()->GetWrapperForProfile(profile)->cookie_settings(); | |
122 DCHECK(cookie_settings); | |
123 return cookie_settings; | |
124 } | |
125 | |
126 ContentSetting CookieSettings::GetDefaultSetting() const { | |
127 ContentSetting allow_or_block = | |
128 host_content_settings_map_->GetDefaultContentSetting( | |
129 CONTENT_SETTINGS_TYPE_COOKIES); | |
130 DCHECK(allow_or_block == CONTENT_SETTING_ALLOW || | |
131 allow_or_block == CONTENT_SETTING_BLOCK); | |
132 if (allow_or_block == CONTENT_SETTING_BLOCK) | |
133 return allow_or_block; | |
134 ContentSetting session_only = | |
135 host_content_settings_map_->GetDefaultContentSetting( | |
136 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY); | |
137 DCHECK(allow_or_block == CONTENT_SETTING_ALLOW || | |
138 allow_or_block == CONTENT_SETTING_SESSION_ONLY); | |
139 return session_only; | |
140 } | |
141 | |
142 bool CookieSettings::IsReadingCookieAllowed(const GURL& url, | |
143 const GURL& first_party_url) const { | |
144 ContentSetting setting = GetCookieContentSetting( | |
145 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, false); | |
146 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
147 setting == CONTENT_SETTING_BLOCK); | |
148 return setting == CONTENT_SETTING_ALLOW; | |
149 } | |
150 | |
151 bool CookieSettings::IsSettingCookieAllowed(const GURL& url, | |
152 const GURL& first_party_url) const { | |
153 ContentSetting setting = GetCookieContentSetting( | |
154 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, true); | |
155 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
156 setting == CONTENT_SETTING_BLOCK); | |
157 return setting == CONTENT_SETTING_ALLOW; | |
158 } | |
159 | |
160 bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const { | |
161 ContentSetting setting = GetCookieContentSetting( | |
162 origin, origin, CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, true); | |
163 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
164 setting == CONTENT_SETTING_SESSION_ONLY); | |
165 return (setting == CONTENT_SETTING_SESSION_ONLY); | |
166 } | |
167 | |
168 void CookieSettings::SetDefaultSetting(ContentSetting setting) { | |
Bernhard Bauer
2011/09/05 11:05:38
I think you could pull out methods here that retur
marja
2011/09/06 08:30:15
Done.
| |
169 DCHECK(setting == CONTENT_SETTING_ALLOW || | |
170 setting == CONTENT_SETTING_SESSION_ONLY || | |
171 setting == CONTENT_SETTING_BLOCK); | |
172 ContentSetting allowed = CONTENT_SETTING_BLOCK; | |
Bernhard Bauer
2011/09/05 11:05:38
Nit: this line reads very confusing at first. Coul
marja
2011/09/06 08:30:15
Done.
| |
173 ContentSetting session_only = CONTENT_SETTING_ALLOW; | |
174 if (setting == CONTENT_SETTING_ALLOW || | |
175 setting == CONTENT_SETTING_SESSION_ONLY) | |
176 allowed = CONTENT_SETTING_ALLOW; | |
177 if (setting == CONTENT_SETTING_SESSION_ONLY) | |
178 session_only = CONTENT_SETTING_SESSION_ONLY; | |
179 host_content_settings_map_->SetDefaultContentSetting( | |
180 CONTENT_SETTINGS_TYPE_COOKIES, allowed); | |
181 host_content_settings_map_->SetDefaultContentSetting( | |
182 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, session_only); | |
183 } | |
184 | |
185 void CookieSettings::SetCookieSetting( | |
186 const ContentSettingsPattern& primary_pattern, | |
187 ContentSetting content_setting) { | |
188 DCHECK(content_setting == CONTENT_SETTING_ALLOW || | |
189 content_setting == CONTENT_SETTING_SESSION_ONLY || | |
190 content_setting == CONTENT_SETTING_BLOCK); | |
191 bool allowed = | |
192 content_setting == CONTENT_SETTING_ALLOW || | |
193 content_setting == CONTENT_SETTING_SESSION_ONLY; | |
194 bool session_only = (content_setting == CONTENT_SETTING_SESSION_ONLY); | |
195 host_content_settings_map_->SetContentSetting( | |
196 primary_pattern, ContentSettingsPattern::Wildcard(), | |
197 CONTENT_SETTINGS_TYPE_COOKIES, "", | |
198 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); | |
199 host_content_settings_map_->SetContentSetting( | |
200 primary_pattern, ContentSettingsPattern::Wildcard(), | |
201 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "", | |
202 session_only ? CONTENT_SETTING_SESSION_ONLY : CONTENT_SETTING_ALLOW); | |
203 } | |
204 | |
205 void CookieSettings::ResetCookieSetting( | |
206 const ContentSettingsPattern& primary_pattern) { | |
207 host_content_settings_map_->SetContentSetting( | |
208 primary_pattern, ContentSettingsPattern::Wildcard(), | |
209 CONTENT_SETTINGS_TYPE_COOKIES, "", | |
210 CONTENT_SETTING_DEFAULT); | |
211 host_content_settings_map_->SetContentSetting( | |
212 primary_pattern, ContentSettingsPattern::Wildcard(), | |
213 CONTENT_SETTINGS_TYPE_COOKIES_SESSION_ONLY, "", | |
214 CONTENT_SETTING_DEFAULT); | |
215 } | |
216 | |
217 void CookieSettings::SetBlockThirdPartyCookies(bool block) { | |
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
219 DCHECK(prefs_); | |
220 | |
221 // This setting may not be directly modified for OTR sessions. Instead, it | |
222 // is synced to the main profile's setting. | |
223 if (is_off_the_record_) { | |
224 NOTREACHED(); | |
225 return; | |
226 } | |
227 | |
228 // If the preference block-third-party-cookies is managed then do not allow to | |
229 // change it. | |
230 if (prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies)) { | |
231 NOTREACHED(); | |
232 return; | |
233 } | |
234 | |
235 { | |
236 base::AutoLock auto_lock(lock_); | |
237 block_third_party_cookies_ = block; | |
238 } | |
239 | |
240 prefs_->SetBoolean(prefs::kBlockThirdPartyCookies, block); | |
241 } | |
242 | |
243 void CookieSettings::Observe(int type, | |
244 const NotificationSource& source, | |
245 const NotificationDetails& details) { | |
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
247 | |
248 if (type == chrome::NOTIFICATION_PREF_CHANGED) { | |
249 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr()); | |
250 | |
251 std::string* name = Details<std::string>(details).ptr(); | |
252 if (*name == prefs::kBlockThirdPartyCookies) { | |
253 base::AutoLock auto_lock(lock_); | |
254 block_third_party_cookies_ = prefs_->GetBoolean( | |
255 prefs::kBlockThirdPartyCookies); | |
256 } else { | |
257 NOTREACHED() << "Unexpected preference observed"; | |
258 return; | |
259 } | |
260 } else { | |
261 NOTREACHED() << "Unexpected notification"; | |
262 } | |
263 } | |
264 | |
265 void CookieSettings::ShutdownOnUIThread() { | |
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
267 pref_change_registrar_.RemoveAll(); | |
268 } | |
269 | |
270 ContentSetting CookieSettings::GetCookieContentSetting( | |
271 const GURL& url, | |
272 const GURL& first_party_url, | |
273 ContentSettingsType content_type, | |
274 bool setting_cookie) const { | |
275 if (HostContentSettingsMap::ShouldAllowAllContent( | |
276 first_party_url, CONTENT_SETTINGS_TYPE_COOKIES)) | |
277 return CONTENT_SETTING_ALLOW; | |
278 | |
279 // First get any host-specific settings. | |
280 ContentSetting setting = | |
281 host_content_settings_map_->GetNonDefaultContentSetting( | |
282 url, first_party_url, content_type, ""); | |
283 | |
284 // Check if third-party cookie settings deny the cookie. This check makes | |
285 // sense only for the CONTENT_SETTINGS_TYPE_COOKIES, since the session only | |
286 // check is based on one url only. | |
287 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && | |
288 setting == CONTENT_SETTING_DEFAULT && | |
289 ShouldBlockThirdPartyCookies()) { | |
290 bool strict = CommandLine::ForCurrentProcess()->HasSwitch( | |
291 switches::kBlockReadingThirdPartyCookies); | |
292 net::StaticCookiePolicy policy(strict ? | |
293 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES : | |
294 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); | |
295 int rv; | |
296 if (setting_cookie) | |
297 rv = policy.CanSetCookie(url, first_party_url); | |
298 else | |
299 rv = policy.CanGetCookies(url, first_party_url); | |
300 DCHECK_NE(net::ERR_IO_PENDING, rv); | |
301 if (rv != net::OK) | |
302 setting = CONTENT_SETTING_BLOCK; | |
303 } | |
304 | |
305 // If no other policy has changed the setting, use the default. | |
306 if (setting == CONTENT_SETTING_DEFAULT) { | |
307 setting = | |
308 host_content_settings_map_->GetDefaultContentSetting(content_type); | |
309 } | |
310 return setting; | |
311 } | |
OLD | NEW |