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 | |
6 #include "chrome/browser/content_settings/content_settings_notification_provider
.h" | |
7 | |
8 #include "base/string_util.h" | |
9 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | |
10 #include "chrome/browser/notifications/notification.h" | |
11 #include "chrome/browser/notifications/notifications_prefs_cache.h" | |
12 #include "chrome/browser/notifications/notification_ui_manager.h" | |
13 #include "chrome/browser/prefs/pref_service.h" | |
14 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
15 #include "chrome/browser/profiles/profile.h" | |
16 #include "chrome/common/chrome_notification_types.h" | |
17 #include "chrome/common/content_settings_types.h" | |
18 #include "chrome/common/pref_names.h" | |
19 #include "chrome/common/url_constants.h" | |
20 #include "content/common/notification_service.h" | |
21 #include "googleurl/src/gurl.h" | |
22 | |
23 namespace { | |
24 | |
25 const ContentSetting kDefaultSetting = CONTENT_SETTING_ASK; | |
26 | |
27 } // namespace | |
28 | |
29 namespace content_settings { | |
30 | |
31 // //////////////////////////////////////////////////////////////////////////// | |
32 // NotificationProvider | |
33 // | |
34 | |
35 // static | |
36 void NotificationProvider::RegisterUserPrefs(PrefService* user_prefs) { | |
37 if (!user_prefs->FindPreference(prefs::kDesktopNotificationAllowedOrigins)) | |
38 user_prefs->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins, | |
39 PrefService::SYNCABLE_PREF); | |
40 if (!user_prefs->FindPreference(prefs::kDesktopNotificationDeniedOrigins)) | |
41 user_prefs->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins, | |
42 PrefService::SYNCABLE_PREF); | |
43 } | |
44 | |
45 // TODO(markusheintz): Re-factoring in progress. Do not move or touch the | |
46 // following two static methods as you might cause trouble. Thanks! | |
47 | |
48 // static | |
49 ContentSettingsPattern NotificationProvider::ToContentSettingsPattern( | |
50 const GURL& origin) { | |
51 // Fix empty GURLs. | |
52 if (origin.spec().empty()) { | |
53 std::string pattern_spec(chrome::kFileScheme); | |
54 pattern_spec += chrome::kStandardSchemeSeparator; | |
55 return ContentSettingsPattern::FromString(pattern_spec); | |
56 } | |
57 return ContentSettingsPattern::FromURLNoWildcard(origin); | |
58 } | |
59 | |
60 // static | |
61 GURL NotificationProvider::ToGURL(const ContentSettingsPattern& pattern) { | |
62 std::string pattern_spec(pattern.ToString()); | |
63 if (!pattern.IsValid() || | |
64 (pattern_spec.find(std::string( | |
65 ContentSettingsPattern::kDomainWildcard)) != std::string::npos)) { | |
66 NOTREACHED(); | |
67 } | |
68 return GURL(pattern_spec); | |
69 } | |
70 | |
71 NotificationProvider::NotificationProvider( | |
72 Profile* profile) | |
73 : profile_(profile) { | |
74 prefs_registrar_.Init(profile_->GetPrefs()); | |
75 StartObserving(); | |
76 } | |
77 | |
78 NotificationProvider::~NotificationProvider() { | |
79 StopObserving(); | |
80 } | |
81 | |
82 ContentSetting NotificationProvider::GetContentSetting( | |
83 const GURL& requesting_url, | |
84 const GURL& embedding_url, | |
85 ContentSettingsType content_type, | |
86 const ResourceIdentifier& resource_identifier) const { | |
87 if (content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) | |
88 return CONTENT_SETTING_DEFAULT; | |
89 | |
90 return GetContentSetting(requesting_url); | |
91 } | |
92 | |
93 void NotificationProvider::SetContentSetting( | |
94 const ContentSettingsPattern& requesting_url_pattern, | |
95 const ContentSettingsPattern& embedding_url_pattern, | |
96 ContentSettingsType content_type, | |
97 const ResourceIdentifier& resource_identifier, | |
98 ContentSetting content_setting) { | |
99 if (content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) | |
100 return; | |
101 | |
102 GURL origin = ToGURL(requesting_url_pattern); | |
103 if (CONTENT_SETTING_ALLOW == content_setting) { | |
104 GrantPermission(origin); | |
105 } else if (CONTENT_SETTING_BLOCK == content_setting) { | |
106 DenyPermission(origin); | |
107 } else if (CONTENT_SETTING_DEFAULT == content_setting) { | |
108 ContentSetting current_setting = GetContentSetting(origin); | |
109 if (CONTENT_SETTING_ALLOW == current_setting) { | |
110 ResetAllowedOrigin(origin); | |
111 } else if (CONTENT_SETTING_BLOCK == current_setting) { | |
112 ResetBlockedOrigin(origin); | |
113 } else { | |
114 NOTREACHED(); | |
115 } | |
116 } else { | |
117 NOTREACHED(); | |
118 } | |
119 } | |
120 | |
121 void NotificationProvider::GetAllContentSettingsRules( | |
122 ContentSettingsType content_type, | |
123 const ResourceIdentifier& resource_identifier, | |
124 Rules* content_setting_rules) const { | |
125 if (content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) | |
126 return; | |
127 | |
128 std::vector<GURL> allowed_origins = GetAllowedOrigins(); | |
129 std::vector<GURL> denied_origins = GetBlockedOrigins(); | |
130 | |
131 for (std::vector<GURL>::iterator url = allowed_origins.begin(); | |
132 url != allowed_origins.end(); | |
133 ++url) { | |
134 ContentSettingsPattern pattern = | |
135 ContentSettingsPattern::FromURLNoWildcard(*url); | |
136 content_setting_rules->push_back(Rule( | |
137 pattern, | |
138 pattern, | |
139 CONTENT_SETTING_ALLOW)); | |
140 } | |
141 for (std::vector<GURL>::iterator url = denied_origins.begin(); | |
142 url != denied_origins.end(); | |
143 ++url) { | |
144 ContentSettingsPattern pattern = | |
145 ContentSettingsPattern::FromURLNoWildcard(*url); | |
146 content_setting_rules->push_back(Rule( | |
147 pattern, | |
148 pattern, | |
149 CONTENT_SETTING_BLOCK)); | |
150 } | |
151 } | |
152 | |
153 void NotificationProvider::ClearAllContentSettingsRules( | |
154 ContentSettingsType content_type) { | |
155 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) | |
156 ResetAllOrigins(); | |
157 } | |
158 | |
159 void NotificationProvider::ShutdownOnUIThread() { | |
160 } | |
161 | |
162 void NotificationProvider::Observe(int type, | |
163 const NotificationSource& source, | |
164 const NotificationDetails& details) { | |
165 if (chrome::NOTIFICATION_PREF_CHANGED == type) { | |
166 const std::string& name = *Details<std::string>(details).ptr(); | |
167 OnPrefsChanged(name); | |
168 } else if (chrome::NOTIFICATION_PROFILE_DESTROYED == type) { | |
169 StopObserving(); | |
170 } | |
171 } | |
172 | |
173 ///////////////////////////////////////////////////////////////////// | |
174 // Private | |
175 // | |
176 | |
177 void NotificationProvider::StartObserving() { | |
178 if (!profile_->IsOffTheRecord()) { | |
179 prefs_registrar_.Add(prefs::kDesktopNotificationAllowedOrigins, this); | |
180 prefs_registrar_.Add(prefs::kDesktopNotificationDeniedOrigins, this); | |
181 | |
182 notification_registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
183 NotificationService::AllSources()); | |
184 } | |
185 | |
186 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
187 Source<Profile>(profile_)); | |
188 } | |
189 | |
190 void NotificationProvider::StopObserving() { | |
191 if (!profile_->IsOffTheRecord()) { | |
192 prefs_registrar_.RemoveAll(); | |
193 } | |
194 notification_registrar_.RemoveAll(); | |
195 } | |
196 | |
197 void NotificationProvider::OnPrefsChanged(const std::string& pref_name) { | |
198 if (pref_name == prefs::kDesktopNotificationAllowedOrigins) { | |
199 NotifySettingsChange(); | |
200 } else if (pref_name == prefs::kDesktopNotificationDeniedOrigins) { | |
201 NotifySettingsChange(); | |
202 } | |
203 } | |
204 | |
205 void NotificationProvider::NotifySettingsChange() { | |
206 // TODO(markusheintz): Re-factoring work in progress: Replace the | |
207 // DESKTOP_NOTIFICATION_SETTINGS_CHANGED with a CONTENT_SETTINGS_CHANGED | |
208 // notification, and use the HostContentSettingsMap as source once this | |
209 // content settings provider in integrated in the HostContentSetttingsMap. | |
210 NotificationService::current()->Notify( | |
211 chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED, | |
212 Source<DesktopNotificationService>( | |
213 DesktopNotificationServiceFactory::GetForProfile(profile_)), | |
214 NotificationService::NoDetails()); | |
215 } | |
216 | |
217 std::vector<GURL> NotificationProvider::GetAllowedOrigins() const { | |
218 std::vector<GURL> allowed_origins; | |
219 PrefService* prefs = profile_->GetPrefs(); | |
220 const ListValue* allowed_sites = | |
221 prefs->GetList(prefs::kDesktopNotificationAllowedOrigins); | |
222 if (allowed_sites) { | |
223 // TODO(markusheintz): Remove dependency to PrefsCache | |
224 NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites, | |
225 &allowed_origins); | |
226 } | |
227 return allowed_origins; | |
228 } | |
229 | |
230 std::vector<GURL> NotificationProvider::GetBlockedOrigins() const { | |
231 std::vector<GURL> denied_origins; | |
232 PrefService* prefs = profile_->GetPrefs(); | |
233 const ListValue* denied_sites = | |
234 prefs->GetList(prefs::kDesktopNotificationDeniedOrigins); | |
235 if (denied_sites) { | |
236 // TODO(markusheintz): Remove dependency to PrefsCache | |
237 NotificationsPrefsCache::ListValueToGurlVector(*denied_sites, | |
238 &denied_origins); | |
239 } | |
240 return denied_origins; | |
241 } | |
242 | |
243 void NotificationProvider::GrantPermission(const GURL& origin) { | |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
245 PersistPermissionChange(origin, true); | |
246 NotifySettingsChange(); | |
247 } | |
248 | |
249 void NotificationProvider::DenyPermission(const GURL& origin) { | |
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
251 PersistPermissionChange(origin, false); | |
252 NotifySettingsChange(); | |
253 } | |
254 | |
255 void NotificationProvider::PersistPermissionChange( | |
256 const GURL& origin, bool is_allowed) { | |
257 // Don't persist changes when incognito. | |
258 if (profile_->IsOffTheRecord()) | |
259 return; | |
260 PrefService* prefs = profile_->GetPrefs(); | |
261 | |
262 // |Observe()| updates the whole permission set in the cache, but only a | |
263 // single origin has changed. Hence, callers of this method manually | |
264 // schedule a task to update the prefs cache, and the prefs observer is | |
265 // disabled while the update runs. | |
266 StopObserving(); | |
267 | |
268 bool allowed_changed = false; | |
269 bool denied_changed = false; | |
270 | |
271 { | |
272 ListPrefUpdate update_allowed_sites( | |
273 prefs, prefs::kDesktopNotificationAllowedOrigins); | |
274 ListPrefUpdate update_denied_sites( | |
275 prefs, prefs::kDesktopNotificationDeniedOrigins); | |
276 ListValue* allowed_sites = update_allowed_sites.Get(); | |
277 ListValue* denied_sites = update_denied_sites.Get(); | |
278 // |value| is passed to the preferences list, or deleted. | |
279 StringValue* value = new StringValue(origin.spec()); | |
280 | |
281 // Remove from one list and add to the other. | |
282 if (is_allowed) { | |
283 // Remove from the denied list. | |
284 if (denied_sites->Remove(*value, NULL)) | |
285 denied_changed = true; | |
286 | |
287 // Add to the allowed list. | |
288 if (allowed_sites->AppendIfNotPresent(value)) | |
289 allowed_changed = true; | |
290 } else { | |
291 // Remove from the allowed list. | |
292 if (allowed_sites->Remove(*value, NULL)) | |
293 allowed_changed = true; | |
294 | |
295 // Add to the denied list. | |
296 if (denied_sites->AppendIfNotPresent(value)) | |
297 denied_changed = true; | |
298 } | |
299 } | |
300 | |
301 // Persist the pref if anthing changed, but only send updates for the | |
302 // list that changed. | |
303 if (allowed_changed || denied_changed) | |
304 prefs->ScheduleSavePersistentPrefs(); | |
305 StartObserving(); | |
306 } | |
307 | |
308 ContentSetting NotificationProvider::GetContentSetting( | |
309 const GURL& origin) const { | |
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
311 | |
312 if (profile_->IsOffTheRecord()) | |
313 return kDefaultSetting; | |
314 | |
315 std::vector<GURL> allowed_origins(GetAllowedOrigins()); | |
316 if (std::find(allowed_origins.begin(), allowed_origins.end(), origin) != | |
317 allowed_origins.end()) | |
318 return CONTENT_SETTING_ALLOW; | |
319 | |
320 std::vector<GURL> denied_origins(GetBlockedOrigins()); | |
321 if (std::find(denied_origins.begin(), denied_origins.end(), origin) != | |
322 denied_origins.end()) | |
323 return CONTENT_SETTING_BLOCK; | |
324 | |
325 return CONTENT_SETTING_DEFAULT; | |
326 } | |
327 | |
328 void NotificationProvider::ResetAllowedOrigin(const GURL& origin) { | |
329 if (profile_->IsOffTheRecord()) | |
330 return; | |
331 | |
332 // Since this isn't called often, let the normal observer behavior update the | |
333 // cache in this case. | |
334 PrefService* prefs = profile_->GetPrefs(); | |
335 { | |
336 ListPrefUpdate update(prefs, prefs::kDesktopNotificationAllowedOrigins); | |
337 ListValue* allowed_sites = update.Get(); | |
338 StringValue value(origin.spec()); | |
339 bool removed = allowed_sites->Remove(value, NULL); | |
340 DCHECK_NE(false, removed) << origin << " was not allowed"; | |
341 } | |
342 prefs->ScheduleSavePersistentPrefs(); | |
343 } | |
344 | |
345 void NotificationProvider::ResetBlockedOrigin(const GURL& origin) { | |
346 if (profile_->IsOffTheRecord()) | |
347 return; | |
348 | |
349 // Since this isn't called often, let the normal observer behavior update the | |
350 // cache in this case. | |
351 PrefService* prefs = profile_->GetPrefs(); | |
352 { | |
353 ListPrefUpdate update(prefs, prefs::kDesktopNotificationDeniedOrigins); | |
354 ListValue* denied_sites = update.Get(); | |
355 StringValue value(origin.spec()); | |
356 bool removed = denied_sites->Remove(value, NULL); | |
357 DCHECK_NE(false, removed) << origin << " was not blocked"; | |
358 } | |
359 prefs->ScheduleSavePersistentPrefs(); | |
360 } | |
361 | |
362 void NotificationProvider::ResetAllOrigins() { | |
363 PrefService* prefs = profile_->GetPrefs(); | |
364 prefs->ClearPref(prefs::kDesktopNotificationAllowedOrigins); | |
365 prefs->ClearPref(prefs::kDesktopNotificationDeniedOrigins); | |
366 } | |
367 | |
368 } // namespace content_settings | |
OLD | NEW |