| 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 |