Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / notifications / desktop_notification_service.cc
blobbde800ce9cb16ffbe0f3c6af073e3b280f8a60cf
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.
5 #include "chrome/browser/notifications/desktop_notification_service.h"
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/thread.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/content_settings/content_settings_details.h"
15 #include "chrome/browser/content_settings/content_settings_provider.h"
16 #include "chrome/browser/content_settings/host_content_settings_map.h"
17 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
18 #include "chrome/browser/infobars/infobar_service.h"
19 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
20 #include "chrome/browser/notifications/notification.h"
21 #include "chrome/browser/notifications/notification_object_proxy.h"
22 #include "chrome/browser/notifications/notification_ui_manager.h"
23 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
24 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
28 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
29 #include "chrome/common/content_settings.h"
30 #include "chrome/common/content_settings_pattern.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "components/infobars/core/infobar.h"
34 #include "components/user_prefs/pref_registry_syncable.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/render_frame_host.h"
38 #include "content/public/browser/render_process_host.h"
39 #include "content/public/browser/render_view_host.h"
40 #include "content/public/browser/web_contents.h"
41 #include "content/public/common/show_desktop_notification_params.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/notifier_settings.h"
52 #if defined(ENABLE_EXTENSIONS)
53 #include "chrome/browser/extensions/api/notifications/notifications_api.h"
54 #include "chrome/browser/extensions/extension_service.h"
55 #include "extensions/browser/event_router.h"
56 #include "extensions/browser/extension_system.h"
57 #include "extensions/browser/info_map.h"
58 #include "extensions/common/constants.h"
59 #include "extensions/common/extension.h"
60 #include "extensions/common/extension_set.h"
61 #endif
63 using blink::WebTextDirection;
64 using content::BrowserThread;
65 using content::RenderViewHost;
66 using content::WebContents;
67 using message_center::NotifierId;
69 namespace {
71 const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
73 // NotificationPermissionRequest ---------------------------------------
75 class NotificationPermissionRequest : public PermissionBubbleRequest {
76 public:
77 NotificationPermissionRequest(
78 DesktopNotificationService* notification_service,
79 const GURL& origin,
80 base::string16 display_name,
81 const base::Closure& callback);
82 virtual ~NotificationPermissionRequest();
84 // PermissionBubbleDelegate:
85 virtual int GetIconID() const OVERRIDE;
86 virtual base::string16 GetMessageText() const OVERRIDE;
87 virtual base::string16 GetMessageTextFragment() const OVERRIDE;
88 virtual bool HasUserGesture() const OVERRIDE;
89 virtual GURL GetRequestingHostname() const OVERRIDE;
90 virtual void PermissionGranted() OVERRIDE;
91 virtual void PermissionDenied() OVERRIDE;
92 virtual void Cancelled() OVERRIDE;
93 virtual void RequestFinished() OVERRIDE;
95 private:
96 // The notification service to be used.
97 DesktopNotificationService* notification_service_;
99 // The origin we are asking for permissions on.
100 GURL origin_;
102 // The display name for the origin to be displayed. Will be different from
103 // origin_ for extensions.
104 base::string16 display_name_;
106 // The callback information that tells us how to respond to javascript.
107 base::Closure callback_;
109 // Whether the user clicked one of the buttons.
110 bool action_taken_;
112 DISALLOW_COPY_AND_ASSIGN(NotificationPermissionRequest);
115 NotificationPermissionRequest::NotificationPermissionRequest(
116 DesktopNotificationService* notification_service,
117 const GURL& origin,
118 base::string16 display_name,
119 const base::Closure& callback)
120 : notification_service_(notification_service),
121 origin_(origin),
122 display_name_(display_name),
123 callback_(callback),
124 action_taken_(false) {}
126 NotificationPermissionRequest::~NotificationPermissionRequest() {}
128 int NotificationPermissionRequest::GetIconID() const {
129 return IDR_INFOBAR_DESKTOP_NOTIFICATIONS;
132 base::string16 NotificationPermissionRequest::GetMessageText() const {
133 return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
134 display_name_);
137 base::string16
138 NotificationPermissionRequest::GetMessageTextFragment() const {
139 return l10n_util::GetStringUTF16(IDS_NOTIFICATION_PERMISSIONS_FRAGMENT);
142 bool NotificationPermissionRequest::HasUserGesture() const {
143 // Currently notification permission requests are only issued on
144 // user gesture.
145 return true;
148 GURL NotificationPermissionRequest::GetRequestingHostname() const {
149 return origin_;
152 void NotificationPermissionRequest::PermissionGranted() {
153 action_taken_ = true;
154 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
155 notification_service_->GrantPermission(origin_);
158 void NotificationPermissionRequest::PermissionDenied() {
159 action_taken_ = true;
160 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
161 notification_service_->DenyPermission(origin_);
164 void NotificationPermissionRequest::Cancelled() {
167 void NotificationPermissionRequest::RequestFinished() {
168 if (!action_taken_)
169 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
171 callback_.Run();
173 delete this;
177 // NotificationPermissionInfoBarDelegate --------------------------------------
179 // The delegate for the infobar shown when an origin requests notification
180 // permissions.
181 class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
182 public:
183 // Creates a notification permission infobar and delegate and adds the infobar
184 // to |infobar_service|.
185 static void Create(InfoBarService* infobar_service,
186 DesktopNotificationService* notification_service,
187 const GURL& origin,
188 const base::string16& display_name,
189 const base::Closure& callback);
191 private:
192 NotificationPermissionInfoBarDelegate(
193 DesktopNotificationService* notification_service,
194 const GURL& origin,
195 const base::string16& display_name,
196 const base::Closure& callback);
197 virtual ~NotificationPermissionInfoBarDelegate();
199 // ConfirmInfoBarDelegate:
200 virtual int GetIconID() const OVERRIDE;
201 virtual Type GetInfoBarType() const OVERRIDE;
202 virtual base::string16 GetMessageText() const OVERRIDE;
203 virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
204 virtual bool Accept() OVERRIDE;
205 virtual bool Cancel() OVERRIDE;
207 // The origin we are asking for permissions on.
208 GURL origin_;
210 // The display name for the origin to be displayed. Will be different from
211 // origin_ for extensions.
212 base::string16 display_name_;
214 // The notification service to be used.
215 DesktopNotificationService* notification_service_;
217 // The callback information that tells us how to respond to javascript.
218 base::Closure callback_;
220 // Whether the user clicked one of the buttons.
221 bool action_taken_;
223 DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
226 // static
227 void NotificationPermissionInfoBarDelegate::Create(
228 InfoBarService* infobar_service,
229 DesktopNotificationService* notification_service,
230 const GURL& origin,
231 const base::string16& display_name,
232 const base::Closure& callback) {
233 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
234 scoped_ptr<ConfirmInfoBarDelegate>(
235 new NotificationPermissionInfoBarDelegate(
236 notification_service, origin, display_name, callback))));
239 NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
240 DesktopNotificationService* notification_service,
241 const GURL& origin,
242 const base::string16& display_name,
243 const base::Closure& callback)
244 : ConfirmInfoBarDelegate(),
245 origin_(origin),
246 display_name_(display_name),
247 notification_service_(notification_service),
248 callback_(callback),
249 action_taken_(false) {
252 NotificationPermissionInfoBarDelegate::
253 ~NotificationPermissionInfoBarDelegate() {
254 if (!action_taken_)
255 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
257 callback_.Run();
260 int NotificationPermissionInfoBarDelegate::GetIconID() const {
261 return IDR_INFOBAR_DESKTOP_NOTIFICATIONS;
264 infobars::InfoBarDelegate::Type
265 NotificationPermissionInfoBarDelegate::GetInfoBarType() const {
266 return PAGE_ACTION_TYPE;
269 base::string16 NotificationPermissionInfoBarDelegate::GetMessageText() const {
270 return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
271 display_name_);
274 base::string16 NotificationPermissionInfoBarDelegate::GetButtonLabel(
275 InfoBarButton button) const {
276 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
277 IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO);
280 bool NotificationPermissionInfoBarDelegate::Accept() {
281 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
282 notification_service_->GrantPermission(origin_);
283 action_taken_ = true;
284 return true;
287 bool NotificationPermissionInfoBarDelegate::Cancel() {
288 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
289 notification_service_->DenyPermission(origin_);
290 action_taken_ = true;
291 return true;
294 void CancelNotification(const std::string& id) {
295 g_browser_process->notification_ui_manager()->CancelById(id);
298 } // namespace
301 // DesktopNotificationService -------------------------------------------------
303 // static
304 void DesktopNotificationService::RegisterProfilePrefs(
305 user_prefs::PrefRegistrySyncable* registry) {
306 registry->RegisterListPref(
307 prefs::kMessageCenterDisabledExtensionIds,
308 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
309 registry->RegisterListPref(
310 prefs::kMessageCenterDisabledSystemComponentIds,
311 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
312 registry->RegisterListPref(
313 prefs::kMessageCenterEnabledSyncNotifierIds,
314 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
315 ExtensionWelcomeNotification::RegisterProfilePrefs(registry);
318 // static
319 base::string16 DesktopNotificationService::CreateDataUrl(
320 const GURL& icon_url,
321 const base::string16& title,
322 const base::string16& body,
323 WebTextDirection dir) {
324 int resource;
325 std::vector<std::string> subst;
326 if (icon_url.is_valid()) {
327 resource = IDR_NOTIFICATION_ICON_HTML;
328 subst.push_back(icon_url.spec());
329 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
330 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
331 // icon float position
332 subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
333 "right" : "left");
334 } else if (title.empty() || body.empty()) {
335 resource = IDR_NOTIFICATION_1LINE_HTML;
336 base::string16 line = title.empty() ? body : title;
337 // Strings are div names in the template file.
338 base::string16 line_name =
339 title.empty() ? base::ASCIIToUTF16("description")
340 : base::ASCIIToUTF16("title");
341 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line_name)));
342 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line)));
343 } else {
344 resource = IDR_NOTIFICATION_2LINE_HTML;
345 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
346 subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
348 // body text direction
349 subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
350 "rtl" : "ltr");
352 return CreateDataUrl(resource, subst);
355 // static
356 base::string16 DesktopNotificationService::CreateDataUrl(
357 int resource, const std::vector<std::string>& subst) {
358 const base::StringPiece template_html(
359 ResourceBundle::GetSharedInstance().GetRawDataResource(
360 resource));
362 if (template_html.empty()) {
363 NOTREACHED() << "unable to load template. ID: " << resource;
364 return base::string16();
367 std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
368 return base::UTF8ToUTF16("data:text/html;charset=utf-8," +
369 net::EscapeQueryParamValue(data, false));
372 // static
373 std::string DesktopNotificationService::AddIconNotification(
374 const GURL& origin_url,
375 const base::string16& title,
376 const base::string16& message,
377 const gfx::Image& icon,
378 const base::string16& replace_id,
379 NotificationDelegate* delegate,
380 Profile* profile) {
381 Notification notification(origin_url, icon, title, message,
382 blink::WebTextDirectionDefault,
383 base::string16(), replace_id, delegate);
384 g_browser_process->notification_ui_manager()->Add(notification, profile);
385 return notification.notification_id();
388 DesktopNotificationService::DesktopNotificationService(
389 Profile* profile,
390 NotificationUIManager* ui_manager)
391 : profile_(profile),
392 ui_manager_(ui_manager) {
393 OnStringListPrefChanged(
394 prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_);
395 OnStringListPrefChanged(
396 prefs::kMessageCenterDisabledSystemComponentIds,
397 &disabled_system_component_ids_);
398 OnStringListPrefChanged(
399 prefs::kMessageCenterEnabledSyncNotifierIds, &enabled_sync_notifier_ids_);
400 disabled_extension_id_pref_.Init(
401 prefs::kMessageCenterDisabledExtensionIds,
402 profile_->GetPrefs(),
403 base::Bind(
404 &DesktopNotificationService::OnStringListPrefChanged,
405 base::Unretained(this),
406 base::Unretained(prefs::kMessageCenterDisabledExtensionIds),
407 base::Unretained(&disabled_extension_ids_)));
408 disabled_system_component_id_pref_.Init(
409 prefs::kMessageCenterDisabledSystemComponentIds,
410 profile_->GetPrefs(),
411 base::Bind(
412 &DesktopNotificationService::OnStringListPrefChanged,
413 base::Unretained(this),
414 base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds),
415 base::Unretained(&disabled_system_component_ids_)));
416 enabled_sync_notifier_id_pref_.Init(
417 prefs::kMessageCenterEnabledSyncNotifierIds,
418 profile_->GetPrefs(),
419 base::Bind(
420 &DesktopNotificationService::OnStringListPrefChanged,
421 base::Unretained(this),
422 base::Unretained(prefs::kMessageCenterEnabledSyncNotifierIds),
423 base::Unretained(&enabled_sync_notifier_ids_)));
424 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
425 content::Source<Profile>(profile_));
428 DesktopNotificationService::~DesktopNotificationService() {
431 void DesktopNotificationService::GrantPermission(const GURL& origin) {
432 ContentSettingsPattern primary_pattern =
433 ContentSettingsPattern::FromURLNoWildcard(origin);
434 profile_->GetHostContentSettingsMap()->SetContentSetting(
435 primary_pattern,
436 ContentSettingsPattern::Wildcard(),
437 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
438 NO_RESOURCE_IDENTIFIER,
439 CONTENT_SETTING_ALLOW);
442 void DesktopNotificationService::DenyPermission(const GURL& origin) {
443 ContentSettingsPattern primary_pattern =
444 ContentSettingsPattern::FromURLNoWildcard(origin);
445 profile_->GetHostContentSettingsMap()->SetContentSetting(
446 primary_pattern,
447 ContentSettingsPattern::Wildcard(),
448 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
449 NO_RESOURCE_IDENTIFIER,
450 CONTENT_SETTING_BLOCK);
453 ContentSetting DesktopNotificationService::GetDefaultContentSetting(
454 std::string* provider_id) {
455 return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
456 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, provider_id);
459 void DesktopNotificationService::SetDefaultContentSetting(
460 ContentSetting setting) {
461 profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
462 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
465 void DesktopNotificationService::ResetToDefaultContentSetting() {
466 profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
467 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_DEFAULT);
470 void DesktopNotificationService::GetNotificationsSettings(
471 ContentSettingsForOneType* settings) {
472 profile_->GetHostContentSettingsMap()->GetSettingsForOneType(
473 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
474 NO_RESOURCE_IDENTIFIER,
475 settings);
478 void DesktopNotificationService::ClearSetting(
479 const ContentSettingsPattern& pattern) {
480 profile_->GetHostContentSettingsMap()->SetContentSetting(
481 pattern,
482 ContentSettingsPattern::Wildcard(),
483 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
484 NO_RESOURCE_IDENTIFIER,
485 CONTENT_SETTING_DEFAULT);
488 void DesktopNotificationService::ResetAllOrigins() {
489 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType(
490 CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
493 ContentSetting DesktopNotificationService::GetContentSetting(
494 const GURL& origin) {
495 return profile_->GetHostContentSettingsMap()->GetContentSetting(
496 origin,
497 origin,
498 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
499 NO_RESOURCE_IDENTIFIER);
502 void DesktopNotificationService::RequestPermission(
503 const GURL& origin,
504 content::RenderFrameHost* render_frame_host,
505 const base::Closure& callback) {
506 // If |origin| hasn't been seen before and the default content setting for
507 // notifications is "ask", show an infobar.
508 // The cache can only answer queries on the IO thread once it's initialized,
509 // so don't ask the cache.
510 WebContents* web_contents = WebContents::FromRenderFrameHost(
511 render_frame_host);
512 ContentSetting setting = GetContentSetting(origin);
513 if (setting == CONTENT_SETTING_ASK) {
514 if (PermissionBubbleManager::Enabled()) {
515 PermissionBubbleManager* bubble_manager =
516 PermissionBubbleManager::FromWebContents(web_contents);
517 bubble_manager->AddRequest(new NotificationPermissionRequest(
518 this,
519 origin,
520 DisplayNameForOriginInProcessId(
521 origin, render_frame_host->GetProcess()->GetID()),
522 callback));
523 return;
526 // Show an info bar requesting permission.
527 InfoBarService* infobar_service =
528 InfoBarService::FromWebContents(web_contents);
529 // |infobar_service| may be NULL, e.g., if this request originated in a
530 // browser action popup, extension background page, or any HTML that runs
531 // outside of a tab.
532 if (infobar_service) {
533 NotificationPermissionInfoBarDelegate::Create(
534 infobar_service, this, origin,
535 DisplayNameForOriginInProcessId(
536 origin, render_frame_host->GetProcess()->GetID()),
537 callback);
538 return;
542 // Notify renderer immediately.
543 callback.Run();
546 void DesktopNotificationService::ShowDesktopNotification(
547 const content::ShowDesktopNotificationHostMsgParams& params,
548 content::RenderFrameHost* render_frame_host,
549 content::DesktopNotificationDelegate* delegate,
550 base::Closure* cancel_callback) {
551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
552 const GURL& origin = params.origin;
553 NotificationObjectProxy* proxy =
554 new NotificationObjectProxy(render_frame_host, delegate);
556 base::string16 display_source = DisplayNameForOriginInProcessId(
557 origin, render_frame_host->GetProcess()->GetID());
558 Notification notification(origin, params.icon_url, params.title,
559 params.body, params.direction, display_source, params.replace_id,
560 proxy);
562 // The webkit notification doesn't timeout.
563 notification.set_never_timeout(true);
565 GetUIManager()->Add(notification, profile_);
566 if (cancel_callback)
567 *cancel_callback = base::Bind(&CancelNotification, proxy->id());
570 base::string16 DesktopNotificationService::DisplayNameForOriginInProcessId(
571 const GURL& origin, int process_id) {
572 #if defined(ENABLE_EXTENSIONS)
573 // If the source is an extension, lookup the display name.
574 if (origin.SchemeIs(extensions::kExtensionScheme)) {
575 extensions::InfoMap* extension_info_map =
576 extensions::ExtensionSystem::Get(profile_)->info_map();
577 if (extension_info_map) {
578 extensions::ExtensionSet extensions;
579 extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
580 origin, process_id, extensions::APIPermission::kNotification,
581 &extensions);
582 for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
583 iter != extensions.end(); ++iter) {
584 NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id());
585 if (IsNotifierEnabled(notifier_id))
586 return base::UTF8ToUTF16((*iter)->name());
590 #endif
592 return base::UTF8ToUTF16(origin.host());
595 void DesktopNotificationService::NotifySettingsChange() {
596 content::NotificationService::current()->Notify(
597 chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
598 content::Source<DesktopNotificationService>(this),
599 content::NotificationService::NoDetails());
602 NotificationUIManager* DesktopNotificationService::GetUIManager() {
603 // We defer setting ui_manager_ to the global singleton until we need it
604 // in order to avoid UI dependent construction during startup.
605 if (!ui_manager_)
606 ui_manager_ = g_browser_process->notification_ui_manager();
607 return ui_manager_;
610 bool DesktopNotificationService::IsNotifierEnabled(
611 const NotifierId& notifier_id) {
612 switch (notifier_id.type) {
613 case NotifierId::APPLICATION:
614 return disabled_extension_ids_.find(notifier_id.id) ==
615 disabled_extension_ids_.end();
616 case NotifierId::WEB_PAGE:
617 return GetContentSetting(notifier_id.url) == CONTENT_SETTING_ALLOW;
618 case NotifierId::SYSTEM_COMPONENT:
619 #if defined(OS_CHROMEOS)
620 return disabled_system_component_ids_.find(notifier_id.id) ==
621 disabled_system_component_ids_.end();
622 #else
623 // We do not disable system component notifications.
624 return true;
625 #endif
626 case NotifierId::SYNCED_NOTIFICATION_SERVICE:
627 return enabled_sync_notifier_ids_.find(notifier_id.id) !=
628 enabled_sync_notifier_ids_.end();
631 NOTREACHED();
632 return false;
635 void DesktopNotificationService::SetNotifierEnabled(
636 const NotifierId& notifier_id,
637 bool enabled) {
638 DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type);
640 bool add_new_item = false;
641 const char* pref_name = NULL;
642 scoped_ptr<base::StringValue> id;
643 switch (notifier_id.type) {
644 case NotifierId::APPLICATION:
645 pref_name = prefs::kMessageCenterDisabledExtensionIds;
646 add_new_item = !enabled;
647 id.reset(new base::StringValue(notifier_id.id));
648 FirePermissionLevelChangedEvent(notifier_id, enabled);
649 break;
650 case NotifierId::SYSTEM_COMPONENT:
651 #if defined(OS_CHROMEOS)
652 pref_name = prefs::kMessageCenterDisabledSystemComponentIds;
653 add_new_item = !enabled;
654 id.reset(new base::StringValue(notifier_id.id));
655 #else
656 return;
657 #endif
658 break;
659 case NotifierId::SYNCED_NOTIFICATION_SERVICE:
660 pref_name = prefs::kMessageCenterEnabledSyncNotifierIds;
661 // Adding a new item if |enabled| == true, since synced notification
662 // services are opt-in.
663 add_new_item = enabled;
664 id.reset(new base::StringValue(notifier_id.id));
665 break;
666 default:
667 NOTREACHED();
669 DCHECK(pref_name != NULL);
671 ListPrefUpdate update(profile_->GetPrefs(), pref_name);
672 base::ListValue* const list = update.Get();
673 if (add_new_item) {
674 // AppendIfNotPresent will delete |adding_value| when the same value
675 // already exists.
676 list->AppendIfNotPresent(id.release());
677 } else {
678 list->Remove(*id, NULL);
682 void DesktopNotificationService::ShowWelcomeNotificationIfNecessary(
683 const Notification& notification) {
684 if (!chrome_now_welcome_notification_) {
685 chrome_now_welcome_notification_ =
686 ExtensionWelcomeNotification::Create(kChromeNowExtensionID, profile_);
689 if (chrome_now_welcome_notification_) {
690 chrome_now_welcome_notification_->ShowWelcomeNotificationIfNecessary(
691 notification);
695 void DesktopNotificationService::OnStringListPrefChanged(
696 const char* pref_name, std::set<std::string>* ids_field) {
697 ids_field->clear();
698 // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
699 const PrefService* pref_service = profile_->GetPrefs();
700 CHECK(pref_service);
701 const base::ListValue* pref_list = pref_service->GetList(pref_name);
702 for (size_t i = 0; i < pref_list->GetSize(); ++i) {
703 std::string element;
704 if (pref_list->GetString(i, &element) && !element.empty())
705 ids_field->insert(element);
706 else
707 LOG(WARNING) << i << "-th element is not a string for " << pref_name;
711 void DesktopNotificationService::Observe(
712 int type,
713 const content::NotificationSource& source,
714 const content::NotificationDetails& details) {
715 #if defined(ENABLE_EXTENSIONS)
716 DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNINSTALLED, type);
718 extensions::Extension* extension =
719 content::Details<extensions::Extension>(details).ptr();
720 NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
721 if (IsNotifierEnabled(notifier_id))
722 return;
724 // The settings for ephemeral apps will be persisted across cache evictions.
725 if (extension->is_ephemeral())
726 return;
728 SetNotifierEnabled(notifier_id, true);
729 #endif
732 void DesktopNotificationService::FirePermissionLevelChangedEvent(
733 const NotifierId& notifier_id, bool enabled) {
734 #if defined(ENABLE_EXTENSIONS)
735 DCHECK_EQ(NotifierId::APPLICATION, notifier_id.type);
736 extensions::api::notifications::PermissionLevel permission =
737 enabled ? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
738 : extensions::api::notifications::PERMISSION_LEVEL_DENIED;
739 scoped_ptr<base::ListValue> args(new base::ListValue());
740 args->Append(new base::StringValue(
741 extensions::api::notifications::ToString(permission)));
742 scoped_ptr<extensions::Event> event(new extensions::Event(
743 extensions::api::notifications::OnPermissionLevelChanged::kEventName,
744 args.Pass()));
745 extensions::EventRouter::Get(profile_)
746 ->DispatchEventToExtension(notifier_id.id, event.Pass());
748 // Tell the IO thread that this extension's permission for notifications
749 // has changed.
750 extensions::InfoMap* extension_info_map =
751 extensions::ExtensionSystem::Get(profile_)->info_map();
752 BrowserThread::PostTask(
753 BrowserThread::IO, FROM_HERE,
754 base::Bind(&extensions::InfoMap::SetNotificationsDisabled,
755 extension_info_map, notifier_id.id, !enabled));
756 #endif