desktop_notification_service.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
1// Copyright (c) 2012 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/notifications/desktop_notification_service.h" 6 7#include "base/metrics/histogram.h" 8#include "base/prefs/scoped_user_pref_update.h" 9#include "base/strings/utf_string_conversions.h" 10#include "base/threading/thread.h" 11#include "chrome/browser/browser_process.h" 12#include "chrome/browser/chrome_notification_types.h" 13#include "chrome/browser/content_settings/content_settings_details.h" 14#include "chrome/browser/content_settings/content_settings_provider.h" 15#include "chrome/browser/content_settings/host_content_settings_map.h" 16#include "chrome/browser/extensions/api/notifications/notifications_api.h" 17#include "chrome/browser/extensions/event_router.h" 18#include "chrome/browser/extensions/extension_info_map.h" 19#include "chrome/browser/extensions/extension_service.h" 20#include "chrome/browser/extensions/extension_system.h" 21#include "chrome/browser/infobars/confirm_infobar_delegate.h" 22#include "chrome/browser/infobars/infobar_service.h" 23#include "chrome/browser/notifications/desktop_notification_service_factory.h" 24#include "chrome/browser/notifications/notification.h" 25#include "chrome/browser/notifications/notification_object_proxy.h" 26#include "chrome/browser/notifications/notification_ui_manager.h" 27#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" 28#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h" 29#include "chrome/browser/profiles/profile.h" 30#include "chrome/browser/ui/browser.h" 31#include "chrome/common/content_settings.h" 32#include "chrome/common/content_settings_pattern.h" 33#include "chrome/common/pref_names.h" 34#include "chrome/common/url_constants.h" 35#include "components/user_prefs/pref_registry_syncable.h" 36#include "content/public/browser/browser_thread.h" 37#include "content/public/browser/notification_service.h" 38#include "content/public/browser/render_view_host.h" 39#include "content/public/browser/web_contents.h" 40#include "content/public/common/show_desktop_notification_params.h" 41#include "extensions/common/constants.h" 42#include "grit/browser_resources.h" 43#include "grit/chromium_strings.h" 44#include "grit/generated_resources.h" 45#include "grit/theme_resources.h" 46#include "net/base/escape.h" 47#include "ui/base/l10n/l10n_util.h" 48#include "ui/base/resource/resource_bundle.h" 49#include "ui/base/webui/web_ui_util.h" 50#include "ui/message_center/message_center_util.h" 51#include "ui/message_center/notifier_settings.h" 52 53#if defined(OS_CHROMEOS) 54#include "ash/system/system_notifier.h" 55#endif 56 57using content::BrowserThread; 58using content::RenderViewHost; 59using content::WebContents; 60using message_center::NotifierId; 61using WebKit::WebNotificationPresenter; 62using WebKit::WebTextDirection; 63 64 65// NotificationPermissionInfoBarDelegate -------------------------------------- 66 67// The delegate for the infobar shown when an origin requests notification 68// permissions. 69class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate { 70 public: 71 // Creates a notification permission infobar delegate and adds it to 72 // |infobar_service|. 73 static void Create(InfoBarService* infobar_service, 74 DesktopNotificationService* notification_service, 75 const GURL& origin, 76 const string16& display_name, 77 int process_id, 78 int route_id, 79 int callback_context); 80 81 private: 82 NotificationPermissionInfoBarDelegate( 83 InfoBarService* infobar_service, 84 DesktopNotificationService* notification_service, 85 const GURL& origin, 86 const string16& display_name, 87 int process_id, 88 int route_id, 89 int callback_context); 90 virtual ~NotificationPermissionInfoBarDelegate(); 91 92 // ConfirmInfoBarDelegate: 93 virtual int GetIconID() const OVERRIDE; 94 virtual Type GetInfoBarType() const OVERRIDE; 95 virtual string16 GetMessageText() const OVERRIDE; 96 virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE; 97 virtual bool Accept() OVERRIDE; 98 virtual bool Cancel() OVERRIDE; 99 100 // The origin we are asking for permissions on. 101 GURL origin_; 102 103 // The display name for the origin to be displayed. Will be different from 104 // origin_ for extensions. 105 string16 display_name_; 106 107 // The notification service to be used. 108 DesktopNotificationService* notification_service_; 109 110 // The callback information that tells us how to respond to javascript via 111 // the correct RenderView. 112 int process_id_; 113 int route_id_; 114 int callback_context_; 115 116 // Whether the user clicked one of the buttons. 117 bool action_taken_; 118 119 DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate); 120}; 121 122// static 123void NotificationPermissionInfoBarDelegate::Create( 124 InfoBarService* infobar_service, 125 DesktopNotificationService* notification_service, 126 const GURL& origin, 127 const string16& display_name, 128 int process_id, 129 int route_id, 130 int callback_context) { 131 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 132 new NotificationPermissionInfoBarDelegate( 133 infobar_service, notification_service, origin, display_name, 134 process_id, route_id, callback_context))); 135} 136 137NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate( 138 InfoBarService* infobar_service, 139 DesktopNotificationService* notification_service, 140 const GURL& origin, 141 const string16& display_name, 142 int process_id, 143 int route_id, 144 int callback_context) 145 : ConfirmInfoBarDelegate(infobar_service), 146 origin_(origin), 147 display_name_(display_name), 148 notification_service_(notification_service), 149 process_id_(process_id), 150 route_id_(route_id), 151 callback_context_(callback_context), 152 action_taken_(false) { 153} 154 155NotificationPermissionInfoBarDelegate:: 156 ~NotificationPermissionInfoBarDelegate() { 157 if (!action_taken_) 158 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1); 159 160 RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_); 161 if (host) 162 host->DesktopNotificationPermissionRequestDone(callback_context_); 163} 164 165int NotificationPermissionInfoBarDelegate::GetIconID() const { 166 return IDR_INFOBAR_DESKTOP_NOTIFICATIONS; 167} 168 169InfoBarDelegate::Type 170 NotificationPermissionInfoBarDelegate::GetInfoBarType() const { 171 return PAGE_ACTION_TYPE; 172} 173 174string16 NotificationPermissionInfoBarDelegate::GetMessageText() const { 175 return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS, 176 display_name_); 177} 178 179string16 NotificationPermissionInfoBarDelegate::GetButtonLabel( 180 InfoBarButton button) const { 181 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 182 IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO); 183} 184 185bool NotificationPermissionInfoBarDelegate::Accept() { 186 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1); 187 notification_service_->GrantPermission(origin_); 188 action_taken_ = true; 189 return true; 190} 191 192bool NotificationPermissionInfoBarDelegate::Cancel() { 193 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1); 194 notification_service_->DenyPermission(origin_); 195 action_taken_ = true; 196 return true; 197} 198 199 200// DesktopNotificationService ------------------------------------------------- 201 202// static 203void DesktopNotificationService::RegisterProfilePrefs( 204 user_prefs::PrefRegistrySyncable* registry) { 205 registry->RegisterListPref( 206 prefs::kMessageCenterDisabledExtensionIds, 207 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 208 registry->RegisterListPref( 209 prefs::kMessageCenterDisabledSystemComponentIds, 210 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 211 registry->RegisterListPref( 212 prefs::kMessageCenterEnabledSyncNotifierIds, 213 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 214 WelcomeNotification::RegisterProfilePrefs(registry); 215} 216 217// static 218string16 DesktopNotificationService::CreateDataUrl( 219 const GURL& icon_url, const string16& title, const string16& body, 220 WebTextDirection dir) { 221 int resource; 222 std::vector<std::string> subst; 223 if (icon_url.is_valid()) { 224 resource = IDR_NOTIFICATION_ICON_HTML; 225 subst.push_back(icon_url.spec()); 226 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(title))); 227 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(body))); 228 // icon float position 229 subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ? 230 "right" : "left"); 231 } else if (title.empty() || body.empty()) { 232 resource = IDR_NOTIFICATION_1LINE_HTML; 233 string16 line = title.empty() ? body : title; 234 // Strings are div names in the template file. 235 string16 line_name = title.empty() ? ASCIIToUTF16("description") 236 : ASCIIToUTF16("title"); 237 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(line_name))); 238 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(line))); 239 } else { 240 resource = IDR_NOTIFICATION_2LINE_HTML; 241 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(title))); 242 subst.push_back(net::EscapeForHTML(UTF16ToUTF8(body))); 243 } 244 // body text direction 245 subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ? 246 "rtl" : "ltr"); 247 248 return CreateDataUrl(resource, subst); 249} 250 251// static 252string16 DesktopNotificationService::CreateDataUrl( 253 int resource, const std::vector<std::string>& subst) { 254 const base::StringPiece template_html( 255 ResourceBundle::GetSharedInstance().GetRawDataResource( 256 resource)); 257 258 if (template_html.empty()) { 259 NOTREACHED() << "unable to load template. ID: " << resource; 260 return string16(); 261 } 262 263 std::string data = ReplaceStringPlaceholders(template_html, subst, NULL); 264 return UTF8ToUTF16("data:text/html;charset=utf-8," + 265 net::EscapeQueryParamValue(data, false)); 266} 267 268// static 269std::string DesktopNotificationService::AddNotification( 270 const GURL& origin_url, 271 const string16& title, 272 const string16& message, 273 const GURL& icon_url, 274 const string16& replace_id, 275 NotificationDelegate* delegate, 276 Profile* profile) { 277 if (message_center::IsRichNotificationEnabled()) { 278 // For message center create a non-HTML notification with |icon_url|. 279 Notification notification(origin_url, icon_url, title, message, 280 WebKit::WebTextDirectionDefault, 281 string16(), replace_id, delegate); 282 g_browser_process->notification_ui_manager()->Add(notification, profile); 283 return notification.notification_id(); 284 } 285 286 // Generate a data URL embedding the icon URL, title, and message. 287 GURL content_url(CreateDataUrl( 288 icon_url, title, message, WebKit::WebTextDirectionDefault)); 289 Notification notification( 290 GURL(), content_url, string16(), replace_id, delegate); 291 g_browser_process->notification_ui_manager()->Add(notification, profile); 292 return notification.notification_id(); 293} 294 295// static 296std::string DesktopNotificationService::AddIconNotification( 297 const GURL& origin_url, 298 const string16& title, 299 const string16& message, 300 const gfx::Image& icon, 301 const string16& replace_id, 302 NotificationDelegate* delegate, 303 Profile* profile) { 304 if (message_center::IsRichNotificationEnabled()) { 305 // For message center create a non-HTML notification with |icon|. 306 Notification notification(origin_url, icon, title, message, 307 WebKit::WebTextDirectionDefault, 308 string16(), replace_id, delegate); 309 g_browser_process->notification_ui_manager()->Add(notification, profile); 310 return notification.notification_id(); 311 } 312 313 GURL icon_url; 314 if (!icon.IsEmpty()) 315 icon_url = GURL(webui::GetBitmapDataUrl(*icon.ToSkBitmap())); 316 return AddNotification( 317 origin_url, title, message, icon_url, replace_id, delegate, profile); 318} 319 320// static 321void DesktopNotificationService::RemoveNotification( 322 const std::string& notification_id) { 323 g_browser_process->notification_ui_manager()->CancelById(notification_id); 324} 325 326DesktopNotificationService::DesktopNotificationService( 327 Profile* profile, 328 NotificationUIManager* ui_manager) 329 : profile_(profile), 330 ui_manager_(ui_manager) { 331 OnStringListPrefChanged( 332 prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_); 333 OnStringListPrefChanged( 334 prefs::kMessageCenterDisabledSystemComponentIds, 335 &disabled_system_component_ids_); 336 OnStringListPrefChanged( 337 prefs::kMessageCenterEnabledSyncNotifierIds, &enabled_sync_notifier_ids_); 338 disabled_extension_id_pref_.Init( 339 prefs::kMessageCenterDisabledExtensionIds, 340 profile_->GetPrefs(), 341 base::Bind( 342 &DesktopNotificationService::OnStringListPrefChanged, 343 base::Unretained(this), 344 base::Unretained(prefs::kMessageCenterDisabledExtensionIds), 345 base::Unretained(&disabled_extension_ids_))); 346 disabled_system_component_id_pref_.Init( 347 prefs::kMessageCenterDisabledSystemComponentIds, 348 profile_->GetPrefs(), 349 base::Bind( 350 &DesktopNotificationService::OnStringListPrefChanged, 351 base::Unretained(this), 352 base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds), 353 base::Unretained(&disabled_system_component_ids_))); 354 enabled_sync_notifier_id_pref_.Init( 355 prefs::kMessageCenterEnabledSyncNotifierIds, 356 profile_->GetPrefs(), 357 base::Bind( 358 &DesktopNotificationService::OnStringListPrefChanged, 359 base::Unretained(this), 360 base::Unretained(prefs::kMessageCenterEnabledSyncNotifierIds), 361 base::Unretained(&enabled_sync_notifier_ids_))); 362 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 363 content::Source<Profile>(profile_)); 364} 365 366DesktopNotificationService::~DesktopNotificationService() { 367} 368 369void DesktopNotificationService::GrantPermission(const GURL& origin) { 370 ContentSettingsPattern primary_pattern = 371 ContentSettingsPattern::FromURLNoWildcard(origin); 372 profile_->GetHostContentSettingsMap()->SetContentSetting( 373 primary_pattern, 374 ContentSettingsPattern::Wildcard(), 375 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 376 NO_RESOURCE_IDENTIFIER, 377 CONTENT_SETTING_ALLOW); 378} 379 380void DesktopNotificationService::DenyPermission(const GURL& origin) { 381 ContentSettingsPattern primary_pattern = 382 ContentSettingsPattern::FromURLNoWildcard(origin); 383 profile_->GetHostContentSettingsMap()->SetContentSetting( 384 primary_pattern, 385 ContentSettingsPattern::Wildcard(), 386 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 387 NO_RESOURCE_IDENTIFIER, 388 CONTENT_SETTING_BLOCK); 389} 390 391ContentSetting DesktopNotificationService::GetDefaultContentSetting( 392 std::string* provider_id) { 393 return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( 394 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, provider_id); 395} 396 397void DesktopNotificationService::SetDefaultContentSetting( 398 ContentSetting setting) { 399 profile_->GetHostContentSettingsMap()->SetDefaultContentSetting( 400 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting); 401} 402 403void DesktopNotificationService::ResetToDefaultContentSetting() { 404 profile_->GetHostContentSettingsMap()->SetDefaultContentSetting( 405 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_DEFAULT); 406} 407 408void DesktopNotificationService::GetNotificationsSettings( 409 ContentSettingsForOneType* settings) { 410 profile_->GetHostContentSettingsMap()->GetSettingsForOneType( 411 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 412 NO_RESOURCE_IDENTIFIER, 413 settings); 414} 415 416void DesktopNotificationService::ClearSetting( 417 const ContentSettingsPattern& pattern) { 418 profile_->GetHostContentSettingsMap()->SetContentSetting( 419 pattern, 420 ContentSettingsPattern::Wildcard(), 421 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 422 NO_RESOURCE_IDENTIFIER, 423 CONTENT_SETTING_DEFAULT); 424} 425 426void DesktopNotificationService::ResetAllOrigins() { 427 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( 428 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 429} 430 431ContentSetting DesktopNotificationService::GetContentSetting( 432 const GURL& origin) { 433 return profile_->GetHostContentSettingsMap()->GetContentSetting( 434 origin, 435 origin, 436 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 437 NO_RESOURCE_IDENTIFIER); 438} 439 440void DesktopNotificationService::RequestPermission( 441 const GURL& origin, int process_id, int route_id, int callback_context, 442 WebContents* contents) { 443 // If |origin| hasn't been seen before and the default content setting for 444 // notifications is "ask", show an infobar. 445 // The cache can only answer queries on the IO thread once it's initialized, 446 // so don't ask the cache. 447 ContentSetting setting = GetContentSetting(origin); 448 if (setting == CONTENT_SETTING_ASK) { 449 // Show an info bar requesting permission. 450 InfoBarService* infobar_service = 451 InfoBarService::FromWebContents(contents); 452 // |infobar_service| may be NULL, e.g., if this request originated in a 453 // browser action popup, extension background page, or any HTML that runs 454 // outside of a tab. 455 if (infobar_service) { 456 NotificationPermissionInfoBarDelegate::Create( 457 infobar_service, 458 DesktopNotificationServiceFactory::GetForProfile( 459 Profile::FromBrowserContext(contents->GetBrowserContext())), 460 origin, DisplayNameForOriginInProcessId(origin, process_id), 461 process_id, route_id, callback_context); 462 return; 463 } 464 } 465 466 // Notify renderer immediately. 467 RenderViewHost* host = RenderViewHost::FromID(process_id, route_id); 468 if (host) 469 host->DesktopNotificationPermissionRequestDone(callback_context); 470} 471 472#if !defined(OS_WIN) 473void DesktopNotificationService::ShowNotification( 474 const Notification& notification) { 475 GetUIManager()->Add(notification, profile_); 476} 477 478bool DesktopNotificationService::CancelDesktopNotification( 479 int process_id, int route_id, int notification_id) { 480 scoped_refptr<NotificationObjectProxy> proxy( 481 new NotificationObjectProxy(process_id, route_id, notification_id, 482 false)); 483 return GetUIManager()->CancelById(proxy->id()); 484} 485#endif // OS_WIN 486 487bool DesktopNotificationService::ShowDesktopNotification( 488 const content::ShowDesktopNotificationHostMsgParams& params, 489 int process_id, int route_id, DesktopNotificationSource source) { 490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 491 const GURL& origin = params.origin; 492 NotificationObjectProxy* proxy = 493 new NotificationObjectProxy(process_id, route_id, 494 params.notification_id, 495 source == WorkerNotification); 496 497 string16 display_source = DisplayNameForOriginInProcessId(origin, process_id); 498 if (params.is_html) { 499 ShowNotification(Notification(origin, params.contents_url, display_source, 500 params.replace_id, proxy)); 501 } else { 502 Notification notification(origin, params.icon_url, params.title, 503 params.body, params.direction, display_source, params.replace_id, 504 proxy); 505 // The webkit notification doesn't timeout. 506 notification.set_never_timeout(true); 507 ShowNotification(notification); 508 } 509 return true; 510} 511 512string16 DesktopNotificationService::DisplayNameForOriginInProcessId( 513 const GURL& origin, int process_id) { 514 // If the source is an extension, lookup the display name. 515 // Message center prefers to use extension name if the notification 516 // is allowed by an extension. 517 if (NotificationUIManager::DelegatesToMessageCenter() || 518 origin.SchemeIs(extensions::kExtensionScheme)) { 519 ExtensionInfoMap* extension_info_map = 520 extensions::ExtensionSystem::Get(profile_)->info_map(); 521 if (extension_info_map) { 522 ExtensionSet extensions; 523 extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin( 524 origin, process_id, extensions::APIPermission::kNotification, 525 &extensions); 526 for (ExtensionSet::const_iterator iter = extensions.begin(); 527 iter != extensions.end(); ++iter) { 528 NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id()); 529 if (IsNotifierEnabled(notifier_id)) 530 return UTF8ToUTF16((*iter)->name()); 531 } 532 } 533 } 534 return UTF8ToUTF16(origin.host()); 535} 536 537void DesktopNotificationService::NotifySettingsChange() { 538 content::NotificationService::current()->Notify( 539 chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED, 540 content::Source<DesktopNotificationService>(this), 541 content::NotificationService::NoDetails()); 542} 543 544NotificationUIManager* DesktopNotificationService::GetUIManager() { 545 // We defer setting ui_manager_ to the global singleton until we need it 546 // in order to avoid UI dependent construction during startup. 547 if (!ui_manager_) 548 ui_manager_ = g_browser_process->notification_ui_manager(); 549 return ui_manager_; 550} 551 552bool DesktopNotificationService::IsNotifierEnabled( 553 const NotifierId& notifier_id) { 554 switch (notifier_id.type) { 555 case NotifierId::APPLICATION: 556 return disabled_extension_ids_.find(notifier_id.id) == 557 disabled_extension_ids_.end(); 558 case NotifierId::WEB_PAGE: 559 return GetContentSetting(notifier_id.url) == CONTENT_SETTING_ALLOW; 560 case NotifierId::SYSTEM_COMPONENT: 561#if defined(OS_CHROMEOS) 562 return disabled_system_component_ids_.find( 563 ash::system_notifier::SystemComponentTypeToString( 564 static_cast<ash::system_notifier::AshSystemComponentNotifierType>( 565 notifier_id.system_component_type))) 566 == disabled_system_component_ids_.end(); 567#else 568 return false; 569#endif 570 case NotifierId::SYNCED_NOTIFICATION_SERVICE: 571 return enabled_sync_notifier_ids_.find(notifier_id.id) != 572 enabled_sync_notifier_ids_.end(); 573 } 574 575 NOTREACHED(); 576 return false; 577} 578 579void DesktopNotificationService::SetNotifierEnabled( 580 const NotifierId& notifier_id, 581 bool enabled) { 582 DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type); 583 584 bool add_new_item = false; 585 const char* pref_name = NULL; 586 scoped_ptr<base::StringValue> id; 587 switch (notifier_id.type) { 588 case NotifierId::APPLICATION: 589 pref_name = prefs::kMessageCenterDisabledExtensionIds; 590 add_new_item = !enabled; 591 id.reset(new base::StringValue(notifier_id.id)); 592 FirePermissionLevelChangedEvent(notifier_id, enabled); 593 break; 594 case NotifierId::SYSTEM_COMPONENT: 595#if defined(OS_CHROMEOS) 596 pref_name = prefs::kMessageCenterDisabledSystemComponentIds; 597 add_new_item = !enabled; 598 id.reset(new base::StringValue( 599 ash::system_notifier::SystemComponentTypeToString( 600 static_cast<ash::system_notifier::AshSystemComponentNotifierType>( 601 notifier_id.system_component_type)))); 602#else 603 return; 604#endif 605 break; 606 case NotifierId::SYNCED_NOTIFICATION_SERVICE: 607 pref_name = prefs::kMessageCenterEnabledSyncNotifierIds; 608 // Adding a new item if |enabled| == true, since synced notification 609 // services are opt-in. 610 add_new_item = enabled; 611 id.reset(new base::StringValue(notifier_id.id)); 612 break; 613 default: 614 NOTREACHED(); 615 } 616 DCHECK(pref_name != NULL); 617 618 ListPrefUpdate update(profile_->GetPrefs(), pref_name); 619 base::ListValue* const list = update.Get(); 620 if (add_new_item) { 621 // AppendIfNotPresent will delete |adding_value| when the same value 622 // already exists. 623 list->AppendIfNotPresent(id.release()); 624 } else { 625 list->Remove(*id, NULL); 626 } 627} 628 629void DesktopNotificationService::ShowWelcomeNotificationIfNecessary( 630 const Notification& notification) { 631 if (!welcome_notification && message_center::IsRichNotificationEnabled()) { 632 welcome_notification.reset( 633 new WelcomeNotification(profile_, g_browser_process->message_center())); 634 } 635 636 if (welcome_notification) 637 welcome_notification->ShowWelcomeNotificationIfNecessary(notification); 638} 639 640void DesktopNotificationService::OnStringListPrefChanged( 641 const char* pref_name, std::set<std::string>* ids_field) { 642 ids_field->clear(); 643 const base::ListValue* pref_list = profile_->GetPrefs()->GetList(pref_name); 644 for (size_t i = 0; i < pref_list->GetSize(); ++i) { 645 std::string element; 646 if (pref_list->GetString(i, &element) && !element.empty()) 647 ids_field->insert(element); 648 else 649 LOG(WARNING) << i << "-th element is not a string for " << pref_name; 650 } 651} 652 653WebKit::WebNotificationPresenter::Permission 654 DesktopNotificationService::HasPermission(const GURL& origin) { 655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 656 HostContentSettingsMap* host_content_settings_map = 657 profile_->GetHostContentSettingsMap(); 658 ContentSetting setting = host_content_settings_map->GetContentSetting( 659 origin, 660 origin, 661 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 662 NO_RESOURCE_IDENTIFIER); 663 664 if (setting == CONTENT_SETTING_ALLOW) 665 return WebKit::WebNotificationPresenter::PermissionAllowed; 666 if (setting == CONTENT_SETTING_BLOCK) 667 return WebKit::WebNotificationPresenter::PermissionDenied; 668 if (setting == CONTENT_SETTING_ASK) 669 return WebKit::WebNotificationPresenter::PermissionNotAllowed; 670 NOTREACHED() << "Invalid notifications settings value: " << setting; 671 return WebKit::WebNotificationPresenter::PermissionNotAllowed; 672} 673 674void DesktopNotificationService::Observe( 675 int type, 676 const content::NotificationSource& source, 677 const content::NotificationDetails& details) { 678 DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNINSTALLED, type); 679 680 extensions::Extension* extension = 681 content::Details<extensions::Extension>(details).ptr(); 682 NotifierId notifier_id(NotifierId::APPLICATION, extension->id()); 683 if (IsNotifierEnabled(notifier_id)) 684 return; 685 686 SetNotifierEnabled(notifier_id, true); 687} 688 689void DesktopNotificationService::FirePermissionLevelChangedEvent( 690 const NotifierId& notifier_id, bool enabled) { 691 DCHECK_EQ(NotifierId::APPLICATION, notifier_id.type); 692 extensions::api::notifications::PermissionLevel permission = 693 enabled ? extensions::api::notifications::PERMISSION_LEVEL_GRANTED 694 : extensions::api::notifications::PERMISSION_LEVEL_DENIED; 695 scoped_ptr<base::ListValue> args(new base::ListValue()); 696 args->Append(new base::StringValue( 697 extensions::api::notifications::ToString(permission))); 698 scoped_ptr<extensions::Event> event(new extensions::Event( 699 extensions::api::notifications::OnPermissionLevelChanged::kEventName, 700 args.Pass())); 701 extensions::ExtensionSystem::Get(profile_)->event_router()-> 702 DispatchEventToExtension(notifier_id.id, event.Pass()); 703} 704