1 // Copyright 2015 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/notifier_state_tracker.h"
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/values.h"
10 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/pref_registry/pref_registry_syncable.h"
14 #include "ui/message_center/notifier_settings.h"
16 #if defined(ENABLE_EXTENSIONS)
17 #include "chrome/common/extensions/api/notifications.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_event_histogram_value.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/browser/extension_util.h"
23 #include "extensions/browser/info_map.h"
26 using message_center::NotifierId
;
29 void NotifierStateTracker::RegisterProfilePrefs(
30 user_prefs::PrefRegistrySyncable
* registry
) {
31 registry
->RegisterListPref(prefs::kMessageCenterDisabledExtensionIds
);
32 registry
->RegisterListPref(prefs::kMessageCenterDisabledSystemComponentIds
);
35 NotifierStateTracker::NotifierStateTracker(Profile
* profile
)
37 #if defined(ENABLE_EXTENSIONS)
39 extension_registry_observer_(this)
42 OnStringListPrefChanged(
43 prefs::kMessageCenterDisabledExtensionIds
, &disabled_extension_ids_
);
44 OnStringListPrefChanged(
45 prefs::kMessageCenterDisabledSystemComponentIds
,
46 &disabled_system_component_ids_
);
48 disabled_extension_id_pref_
.Init(
49 prefs::kMessageCenterDisabledExtensionIds
,
52 &NotifierStateTracker::OnStringListPrefChanged
,
53 base::Unretained(this),
54 base::Unretained(prefs::kMessageCenterDisabledExtensionIds
),
55 base::Unretained(&disabled_extension_ids_
)));
57 disabled_system_component_id_pref_
.Init(
58 prefs::kMessageCenterDisabledSystemComponentIds
,
61 &NotifierStateTracker::OnStringListPrefChanged
,
62 base::Unretained(this),
63 base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds
),
64 base::Unretained(&disabled_system_component_ids_
)));
66 #if defined(ENABLE_EXTENSIONS)
67 extension_registry_observer_
.Add(
68 extensions::ExtensionRegistry::Get(profile_
));
72 NotifierStateTracker::~NotifierStateTracker() {
75 bool NotifierStateTracker::IsNotifierEnabled(
76 const NotifierId
& notifier_id
) const {
77 switch (notifier_id
.type
) {
78 case NotifierId::APPLICATION
:
79 return disabled_extension_ids_
.find(notifier_id
.id
) ==
80 disabled_extension_ids_
.end();
81 case NotifierId::WEB_PAGE
:
82 return DesktopNotificationProfileUtil::GetContentSetting(
83 profile_
, notifier_id
.url
) == CONTENT_SETTING_ALLOW
;
84 case NotifierId::SYSTEM_COMPONENT
:
85 #if defined(OS_CHROMEOS)
86 return disabled_system_component_ids_
.find(notifier_id
.id
) ==
87 disabled_system_component_ids_
.end();
89 // We do not disable system component notifications.
98 void NotifierStateTracker::SetNotifierEnabled(
99 const NotifierId
& notifier_id
,
101 DCHECK_NE(NotifierId::WEB_PAGE
, notifier_id
.type
);
103 bool add_new_item
= false;
104 const char* pref_name
= NULL
;
105 scoped_ptr
<base::StringValue
> id
;
106 switch (notifier_id
.type
) {
107 case NotifierId::APPLICATION
:
108 pref_name
= prefs::kMessageCenterDisabledExtensionIds
;
109 add_new_item
= !enabled
;
110 id
.reset(new base::StringValue(notifier_id
.id
));
111 #if defined(ENABLE_EXTENSIONS)
112 FirePermissionLevelChangedEvent(notifier_id
, enabled
);
115 case NotifierId::SYSTEM_COMPONENT
:
116 #if defined(OS_CHROMEOS)
117 pref_name
= prefs::kMessageCenterDisabledSystemComponentIds
;
118 add_new_item
= !enabled
;
119 id
.reset(new base::StringValue(notifier_id
.id
));
127 DCHECK(pref_name
!= NULL
);
129 ListPrefUpdate
update(profile_
->GetPrefs(), pref_name
);
130 base::ListValue
* const list
= update
.Get();
132 // AppendIfNotPresent will delete |adding_value| when the same value
134 list
->AppendIfNotPresent(id
.release());
136 list
->Remove(*id
, NULL
);
140 void NotifierStateTracker::OnStringListPrefChanged(
141 const char* pref_name
, std::set
<std::string
>* ids_field
) {
143 // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
144 const PrefService
* pref_service
= profile_
->GetPrefs();
146 const base::ListValue
* pref_list
= pref_service
->GetList(pref_name
);
147 for (size_t i
= 0; i
< pref_list
->GetSize(); ++i
) {
149 if (pref_list
->GetString(i
, &element
) && !element
.empty())
150 ids_field
->insert(element
);
152 LOG(WARNING
) << i
<< "-th element is not a string for " << pref_name
;
156 #if defined(ENABLE_EXTENSIONS)
157 void NotifierStateTracker::OnExtensionUninstalled(
158 content::BrowserContext
* browser_context
,
159 const extensions::Extension
* extension
,
160 extensions::UninstallReason reason
) {
161 NotifierId
notifier_id(NotifierId::APPLICATION
, extension
->id());
162 if (IsNotifierEnabled(notifier_id
))
165 // The settings for ephemeral apps will be persisted across cache evictions.
166 if (extensions::util::IsEphemeralApp(extension
->id(), profile_
))
169 SetNotifierEnabled(notifier_id
, true);
172 void NotifierStateTracker::FirePermissionLevelChangedEvent(
173 const NotifierId
& notifier_id
, bool enabled
) {
174 DCHECK_EQ(NotifierId::APPLICATION
, notifier_id
.type
);
175 extensions::api::notifications::PermissionLevel permission
=
176 enabled
? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
177 : extensions::api::notifications::PERMISSION_LEVEL_DENIED
;
178 scoped_ptr
<base::ListValue
> args(new base::ListValue());
179 args
->Append(new base::StringValue(
180 extensions::api::notifications::ToString(permission
)));
181 scoped_ptr
<extensions::Event
> event(new extensions::Event(
182 extensions::events::NOTIFICATIONS_ON_PERMISSION_LEVEL_CHANGED
,
183 extensions::api::notifications::OnPermissionLevelChanged::kEventName
,
185 extensions::EventRouter::Get(profile_
)
186 ->DispatchEventToExtension(notifier_id
.id
, event
.Pass());
188 // Tell the IO thread that this extension's permission for notifications
190 extensions::InfoMap
* extension_info_map
=
191 extensions::ExtensionSystem::Get(profile_
)->info_map();
192 content::BrowserThread::PostTask(
193 content::BrowserThread::IO
, FROM_HERE
,
194 base::Bind(&extensions::InfoMap::SetNotificationsDisabled
,
195 extension_info_map
, notifier_id
.id
, !enabled
));