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/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/extension_service.h"
18 #include "chrome/browser/extensions/extension_system.h"
19 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
20 #include "chrome/browser/infobars/infobar.h"
21 #include "chrome/browser/infobars/infobar_service.h"
22 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
23 #include "chrome/browser/notifications/notification.h"
24 #include "chrome/browser/notifications/notification_object_proxy.h"
25 #include "chrome/browser/notifications/notification_ui_manager.h"
26 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
27 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/common/content_settings.h"
31 #include "chrome/common/content_settings_pattern.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/url_constants.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_view_host.h"
38 #include "content/public/browser/web_contents.h"
39 #include "content/public/common/show_desktop_notification_params.h"
40 #include "extensions/browser/event_router.h"
41 #include "extensions/browser/info_map.h"
42 #include "extensions/common/constants.h"
43 #include "extensions/common/extension.h"
44 #include "extensions/common/extension_set.h"
45 #include "grit/browser_resources.h"
46 #include "grit/chromium_strings.h"
47 #include "grit/generated_resources.h"
48 #include "grit/theme_resources.h"
49 #include "net/base/escape.h"
50 #include "ui/base/l10n/l10n_util.h"
51 #include "ui/base/resource/resource_bundle.h"
52 #include "ui/base/webui/web_ui_util.h"
53 #include "ui/message_center/message_center_util.h"
54 #include "ui/message_center/notifier_settings.h"
56 using content::BrowserThread
;
57 using content::RenderViewHost
;
58 using content::WebContents
;
59 using message_center::NotifierId
;
60 using blink::WebTextDirection
;
63 // NotificationPermissionInfoBarDelegate --------------------------------------
65 // The delegate for the infobar shown when an origin requests notification
67 class NotificationPermissionInfoBarDelegate
: public ConfirmInfoBarDelegate
{
69 // Creates a notification permission infobar and delegate and adds the infobar
70 // to |infobar_service|.
71 static void Create(InfoBarService
* infobar_service
,
72 DesktopNotificationService
* notification_service
,
74 const base::string16
& display_name
,
77 int callback_context
);
80 NotificationPermissionInfoBarDelegate(
81 DesktopNotificationService
* notification_service
,
83 const base::string16
& display_name
,
86 int callback_context
);
87 virtual ~NotificationPermissionInfoBarDelegate();
89 // ConfirmInfoBarDelegate:
90 virtual int GetIconID() const OVERRIDE
;
91 virtual Type
GetInfoBarType() const OVERRIDE
;
92 virtual base::string16
GetMessageText() const OVERRIDE
;
93 virtual base::string16
GetButtonLabel(InfoBarButton button
) const OVERRIDE
;
94 virtual bool Accept() OVERRIDE
;
95 virtual bool Cancel() OVERRIDE
;
97 // The origin we are asking for permissions on.
100 // The display name for the origin to be displayed. Will be different from
101 // origin_ for extensions.
102 base::string16 display_name_
;
104 // The notification service to be used.
105 DesktopNotificationService
* notification_service_
;
107 // The callback information that tells us how to respond to javascript via
108 // the correct RenderView.
111 int callback_context_
;
113 // Whether the user clicked one of the buttons.
116 DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate
);
120 void NotificationPermissionInfoBarDelegate::Create(
121 InfoBarService
* infobar_service
,
122 DesktopNotificationService
* notification_service
,
124 const base::string16
& display_name
,
127 int callback_context
) {
128 infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
129 scoped_ptr
<ConfirmInfoBarDelegate
>(
130 new NotificationPermissionInfoBarDelegate(
131 notification_service
, origin
, display_name
, process_id
, route_id
,
132 callback_context
))));
135 NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
136 DesktopNotificationService
* notification_service
,
138 const base::string16
& display_name
,
141 int callback_context
)
142 : ConfirmInfoBarDelegate(),
144 display_name_(display_name
),
145 notification_service_(notification_service
),
146 process_id_(process_id
),
148 callback_context_(callback_context
),
149 action_taken_(false) {
152 NotificationPermissionInfoBarDelegate::
153 ~NotificationPermissionInfoBarDelegate() {
155 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
157 RenderViewHost
* host
= RenderViewHost::FromID(process_id_
, route_id_
);
159 host
->DesktopNotificationPermissionRequestDone(callback_context_
);
162 int NotificationPermissionInfoBarDelegate::GetIconID() const {
163 return IDR_INFOBAR_DESKTOP_NOTIFICATIONS
;
166 InfoBarDelegate::Type
167 NotificationPermissionInfoBarDelegate::GetInfoBarType() const {
168 return PAGE_ACTION_TYPE
;
171 base::string16
NotificationPermissionInfoBarDelegate::GetMessageText() const {
172 return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS
,
176 base::string16
NotificationPermissionInfoBarDelegate::GetButtonLabel(
177 InfoBarButton button
) const {
178 return l10n_util::GetStringUTF16((button
== BUTTON_OK
) ?
179 IDS_NOTIFICATION_PERMISSION_YES
: IDS_NOTIFICATION_PERMISSION_NO
);
182 bool NotificationPermissionInfoBarDelegate::Accept() {
183 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
184 notification_service_
->GrantPermission(origin_
);
185 action_taken_
= true;
189 bool NotificationPermissionInfoBarDelegate::Cancel() {
190 UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
191 notification_service_
->DenyPermission(origin_
);
192 action_taken_
= true;
197 // DesktopNotificationService -------------------------------------------------
200 void DesktopNotificationService::RegisterProfilePrefs(
201 user_prefs::PrefRegistrySyncable
* registry
) {
202 registry
->RegisterListPref(
203 prefs::kMessageCenterDisabledExtensionIds
,
204 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
205 registry
->RegisterListPref(
206 prefs::kMessageCenterDisabledSystemComponentIds
,
207 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
208 registry
->RegisterListPref(
209 prefs::kMessageCenterEnabledSyncNotifierIds
,
210 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
211 WelcomeNotification::RegisterProfilePrefs(registry
);
215 base::string16
DesktopNotificationService::CreateDataUrl(
216 const GURL
& icon_url
,
217 const base::string16
& title
,
218 const base::string16
& body
,
219 WebTextDirection dir
) {
221 std::vector
<std::string
> subst
;
222 if (icon_url
.is_valid()) {
223 resource
= IDR_NOTIFICATION_ICON_HTML
;
224 subst
.push_back(icon_url
.spec());
225 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title
)));
226 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body
)));
227 // icon float position
228 subst
.push_back(dir
== blink::WebTextDirectionRightToLeft
?
230 } else if (title
.empty() || body
.empty()) {
231 resource
= IDR_NOTIFICATION_1LINE_HTML
;
232 base::string16 line
= title
.empty() ? body
: title
;
233 // Strings are div names in the template file.
234 base::string16 line_name
=
235 title
.empty() ? base::ASCIIToUTF16("description")
236 : base::ASCIIToUTF16("title");
237 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line_name
)));
238 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line
)));
240 resource
= IDR_NOTIFICATION_2LINE_HTML
;
241 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title
)));
242 subst
.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body
)));
244 // body text direction
245 subst
.push_back(dir
== blink::WebTextDirectionRightToLeft
?
248 return CreateDataUrl(resource
, subst
);
252 base::string16
DesktopNotificationService::CreateDataUrl(
253 int resource
, const std::vector
<std::string
>& subst
) {
254 const base::StringPiece
template_html(
255 ResourceBundle::GetSharedInstance().GetRawDataResource(
258 if (template_html
.empty()) {
259 NOTREACHED() << "unable to load template. ID: " << resource
;
260 return base::string16();
263 std::string data
= ReplaceStringPlaceholders(template_html
, subst
, NULL
);
264 return base::UTF8ToUTF16("data:text/html;charset=utf-8," +
265 net::EscapeQueryParamValue(data
, false));
269 std::string
DesktopNotificationService::AddNotification(
270 const GURL
& origin_url
,
271 const base::string16
& title
,
272 const base::string16
& message
,
273 const GURL
& icon_url
,
274 const base::string16
& replace_id
,
275 NotificationDelegate
* delegate
,
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 blink::WebTextDirectionDefault
,
281 base::string16(), replace_id
, delegate
);
282 g_browser_process
->notification_ui_manager()->Add(notification
, profile
);
283 return notification
.notification_id();
286 // Generate a data URL embedding the icon URL, title, and message.
287 GURL
content_url(CreateDataUrl(
288 icon_url
, title
, message
, blink::WebTextDirectionDefault
));
289 Notification
notification(
290 GURL(), content_url
, base::string16(), replace_id
, delegate
);
291 g_browser_process
->notification_ui_manager()->Add(notification
, profile
);
292 return notification
.notification_id();
296 std::string
DesktopNotificationService::AddIconNotification(
297 const GURL
& origin_url
,
298 const base::string16
& title
,
299 const base::string16
& message
,
300 const gfx::Image
& icon
,
301 const base::string16
& replace_id
,
302 NotificationDelegate
* delegate
,
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 blink::WebTextDirectionDefault
,
308 base::string16(), replace_id
, delegate
);
309 g_browser_process
->notification_ui_manager()->Add(notification
, profile
);
310 return notification
.notification_id();
315 icon_url
= GURL(webui::GetBitmapDataUrl(*icon
.ToSkBitmap()));
316 return AddNotification(
317 origin_url
, title
, message
, icon_url
, replace_id
, delegate
, profile
);
321 void DesktopNotificationService::RemoveNotification(
322 const std::string
& notification_id
) {
323 g_browser_process
->notification_ui_manager()->CancelById(notification_id
);
326 DesktopNotificationService::DesktopNotificationService(
328 NotificationUIManager
* ui_manager
)
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(),
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(),
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(),
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_
));
366 DesktopNotificationService::~DesktopNotificationService() {
369 void DesktopNotificationService::GrantPermission(const GURL
& origin
) {
370 ContentSettingsPattern primary_pattern
=
371 ContentSettingsPattern::FromURLNoWildcard(origin
);
372 profile_
->GetHostContentSettingsMap()->SetContentSetting(
374 ContentSettingsPattern::Wildcard(),
375 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
376 NO_RESOURCE_IDENTIFIER
,
377 CONTENT_SETTING_ALLOW
);
380 void DesktopNotificationService::DenyPermission(const GURL
& origin
) {
381 ContentSettingsPattern primary_pattern
=
382 ContentSettingsPattern::FromURLNoWildcard(origin
);
383 profile_
->GetHostContentSettingsMap()->SetContentSetting(
385 ContentSettingsPattern::Wildcard(),
386 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
387 NO_RESOURCE_IDENTIFIER
,
388 CONTENT_SETTING_BLOCK
);
391 ContentSetting
DesktopNotificationService::GetDefaultContentSetting(
392 std::string
* provider_id
) {
393 return profile_
->GetHostContentSettingsMap()->GetDefaultContentSetting(
394 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, provider_id
);
397 void DesktopNotificationService::SetDefaultContentSetting(
398 ContentSetting setting
) {
399 profile_
->GetHostContentSettingsMap()->SetDefaultContentSetting(
400 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, setting
);
403 void DesktopNotificationService::ResetToDefaultContentSetting() {
404 profile_
->GetHostContentSettingsMap()->SetDefaultContentSetting(
405 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, CONTENT_SETTING_DEFAULT
);
408 void DesktopNotificationService::GetNotificationsSettings(
409 ContentSettingsForOneType
* settings
) {
410 profile_
->GetHostContentSettingsMap()->GetSettingsForOneType(
411 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
412 NO_RESOURCE_IDENTIFIER
,
416 void DesktopNotificationService::ClearSetting(
417 const ContentSettingsPattern
& pattern
) {
418 profile_
->GetHostContentSettingsMap()->SetContentSetting(
420 ContentSettingsPattern::Wildcard(),
421 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
422 NO_RESOURCE_IDENTIFIER
,
423 CONTENT_SETTING_DEFAULT
);
426 void DesktopNotificationService::ResetAllOrigins() {
427 profile_
->GetHostContentSettingsMap()->ClearSettingsForOneType(
428 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
431 ContentSetting
DesktopNotificationService::GetContentSetting(
432 const GURL
& origin
) {
433 return profile_
->GetHostContentSettingsMap()->GetContentSetting(
436 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
437 NO_RESOURCE_IDENTIFIER
);
440 void 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
455 if (infobar_service
) {
456 NotificationPermissionInfoBarDelegate::Create(
458 DesktopNotificationServiceFactory::GetForProfile(
459 Profile::FromBrowserContext(contents
->GetBrowserContext())),
460 origin
, DisplayNameForOriginInProcessId(origin
, process_id
),
461 process_id
, route_id
, callback_context
);
466 // Notify renderer immediately.
467 RenderViewHost
* host
= RenderViewHost::FromID(process_id
, route_id
);
469 host
->DesktopNotificationPermissionRequestDone(callback_context
);
473 void DesktopNotificationService::ShowNotification(
474 const Notification
& notification
) {
475 GetUIManager()->Add(notification
, profile_
);
478 bool 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
,
483 return GetUIManager()->CancelById(proxy
->id());
487 bool 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
);
497 base::string16 display_source
=
498 DisplayNameForOriginInProcessId(origin
, process_id
);
499 Notification
notification(origin
, params
.icon_url
, params
.title
,
500 params
.body
, params
.direction
, display_source
, params
.replace_id
,
503 // The webkit notification doesn't timeout.
504 notification
.set_never_timeout(true);
506 ShowNotification(notification
);
510 base::string16
DesktopNotificationService::DisplayNameForOriginInProcessId(
511 const GURL
& origin
, int process_id
) {
512 // If the source is an extension, lookup the display name.
513 // Message center prefers to use extension name if the notification
514 // is allowed by an extension.
515 if (NotificationUIManager::DelegatesToMessageCenter() ||
516 origin
.SchemeIs(extensions::kExtensionScheme
)) {
517 extensions::InfoMap
* extension_info_map
=
518 extensions::ExtensionSystem::Get(profile_
)->info_map();
519 if (extension_info_map
) {
520 extensions::ExtensionSet extensions
;
521 extension_info_map
->GetExtensionsWithAPIPermissionForSecurityOrigin(
522 origin
, process_id
, extensions::APIPermission::kNotification
,
524 for (extensions::ExtensionSet::const_iterator iter
= extensions
.begin();
525 iter
!= extensions
.end(); ++iter
) {
526 NotifierId
notifier_id(NotifierId::APPLICATION
, (*iter
)->id());
527 if (IsNotifierEnabled(notifier_id
))
528 return base::UTF8ToUTF16((*iter
)->name());
532 return base::UTF8ToUTF16(origin
.host());
535 void DesktopNotificationService::NotifySettingsChange() {
536 content::NotificationService::current()->Notify(
537 chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED
,
538 content::Source
<DesktopNotificationService
>(this),
539 content::NotificationService::NoDetails());
542 NotificationUIManager
* DesktopNotificationService::GetUIManager() {
543 // We defer setting ui_manager_ to the global singleton until we need it
544 // in order to avoid UI dependent construction during startup.
546 ui_manager_
= g_browser_process
->notification_ui_manager();
550 bool DesktopNotificationService::IsNotifierEnabled(
551 const NotifierId
& notifier_id
) {
552 switch (notifier_id
.type
) {
553 case NotifierId::APPLICATION
:
554 return disabled_extension_ids_
.find(notifier_id
.id
) ==
555 disabled_extension_ids_
.end();
556 case NotifierId::WEB_PAGE
:
557 return GetContentSetting(notifier_id
.url
) == CONTENT_SETTING_ALLOW
;
558 case NotifierId::SYSTEM_COMPONENT
:
559 #if defined(OS_CHROMEOS)
560 return disabled_system_component_ids_
.find(notifier_id
.id
) ==
561 disabled_system_component_ids_
.end();
563 // We do not disable system component notifications.
566 case NotifierId::SYNCED_NOTIFICATION_SERVICE
:
567 return enabled_sync_notifier_ids_
.find(notifier_id
.id
) !=
568 enabled_sync_notifier_ids_
.end();
575 void DesktopNotificationService::SetNotifierEnabled(
576 const NotifierId
& notifier_id
,
578 DCHECK_NE(NotifierId::WEB_PAGE
, notifier_id
.type
);
580 bool add_new_item
= false;
581 const char* pref_name
= NULL
;
582 scoped_ptr
<base::StringValue
> id
;
583 switch (notifier_id
.type
) {
584 case NotifierId::APPLICATION
:
585 pref_name
= prefs::kMessageCenterDisabledExtensionIds
;
586 add_new_item
= !enabled
;
587 id
.reset(new base::StringValue(notifier_id
.id
));
588 FirePermissionLevelChangedEvent(notifier_id
, enabled
);
590 case NotifierId::SYSTEM_COMPONENT
:
591 #if defined(OS_CHROMEOS)
592 pref_name
= prefs::kMessageCenterDisabledSystemComponentIds
;
593 add_new_item
= !enabled
;
594 id
.reset(new base::StringValue(notifier_id
.id
));
599 case NotifierId::SYNCED_NOTIFICATION_SERVICE
:
600 pref_name
= prefs::kMessageCenterEnabledSyncNotifierIds
;
601 // Adding a new item if |enabled| == true, since synced notification
602 // services are opt-in.
603 add_new_item
= enabled
;
604 id
.reset(new base::StringValue(notifier_id
.id
));
609 DCHECK(pref_name
!= NULL
);
611 ListPrefUpdate
update(profile_
->GetPrefs(), pref_name
);
612 base::ListValue
* const list
= update
.Get();
614 // AppendIfNotPresent will delete |adding_value| when the same value
616 list
->AppendIfNotPresent(id
.release());
618 list
->Remove(*id
, NULL
);
622 void DesktopNotificationService::ShowWelcomeNotificationIfNecessary(
623 const Notification
& notification
) {
624 if (!welcome_notification
&& message_center::IsRichNotificationEnabled()) {
625 welcome_notification
.reset(
626 new WelcomeNotification(profile_
, g_browser_process
->message_center()));
629 if (welcome_notification
)
630 welcome_notification
->ShowWelcomeNotificationIfNecessary(notification
);
633 void DesktopNotificationService::OnStringListPrefChanged(
634 const char* pref_name
, std::set
<std::string
>* ids_field
) {
636 // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
637 const PrefService
* pref_service
= profile_
->GetPrefs();
639 const base::ListValue
* pref_list
= pref_service
->GetList(pref_name
);
640 for (size_t i
= 0; i
< pref_list
->GetSize(); ++i
) {
642 if (pref_list
->GetString(i
, &element
) && !element
.empty())
643 ids_field
->insert(element
);
645 LOG(WARNING
) << i
<< "-th element is not a string for " << pref_name
;
649 void DesktopNotificationService::Observe(
651 const content::NotificationSource
& source
,
652 const content::NotificationDetails
& details
) {
653 DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNINSTALLED
, type
);
655 extensions::Extension
* extension
=
656 content::Details
<extensions::Extension
>(details
).ptr();
657 NotifierId
notifier_id(NotifierId::APPLICATION
, extension
->id());
658 if (IsNotifierEnabled(notifier_id
))
661 SetNotifierEnabled(notifier_id
, true);
664 void DesktopNotificationService::FirePermissionLevelChangedEvent(
665 const NotifierId
& notifier_id
, bool enabled
) {
666 DCHECK_EQ(NotifierId::APPLICATION
, notifier_id
.type
);
667 extensions::api::notifications::PermissionLevel permission
=
668 enabled
? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
669 : extensions::api::notifications::PERMISSION_LEVEL_DENIED
;
670 scoped_ptr
<base::ListValue
> args(new base::ListValue());
671 args
->Append(new base::StringValue(
672 extensions::api::notifications::ToString(permission
)));
673 scoped_ptr
<extensions::Event
> event(new extensions::Event(
674 extensions::api::notifications::OnPermissionLevelChanged::kEventName
,
676 extensions::ExtensionSystem::Get(profile_
)->event_router()->
677 DispatchEventToExtension(notifier_id
.id
, event
.Pass());
679 // Tell the IO thread that this extension's permission for notifications
681 extensions::InfoMap
* extension_info_map
=
682 extensions::ExtensionSystem::Get(profile_
)->info_map();
683 BrowserThread::PostTask(
684 BrowserThread::IO
, FROM_HERE
,
685 base::Bind(&extensions::InfoMap::SetNotificationsDisabled
,
686 extension_info_map
, notifier_id
.id
, !enabled
));