Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / notifications / notifier_state_tracker.cc
blob86405a8f8e0c36661d12572f463adcc3a8652fa8
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"
7 #include "base/bind.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"
24 #endif
26 using message_center::NotifierId;
28 // static
29 void NotifierStateTracker::RegisterProfilePrefs(
30 user_prefs::PrefRegistrySyncable* registry) {
31 registry->RegisterListPref(prefs::kMessageCenterDisabledExtensionIds);
32 registry->RegisterListPref(prefs::kMessageCenterDisabledSystemComponentIds);
35 NotifierStateTracker::NotifierStateTracker(Profile* profile)
36 : profile_(profile)
37 #if defined(ENABLE_EXTENSIONS)
39 extension_registry_observer_(this)
40 #endif
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,
50 profile_->GetPrefs(),
51 base::Bind(
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,
59 profile_->GetPrefs(),
60 base::Bind(
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_));
69 #endif
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();
88 #else
89 // We do not disable system component notifications.
90 return true;
91 #endif
94 NOTREACHED();
95 return false;
98 void NotifierStateTracker::SetNotifierEnabled(
99 const NotifierId& notifier_id,
100 bool enabled) {
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);
113 #endif
114 break;
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));
120 #else
121 return;
122 #endif
123 break;
124 default:
125 NOTREACHED();
127 DCHECK(pref_name != NULL);
129 ListPrefUpdate update(profile_->GetPrefs(), pref_name);
130 base::ListValue* const list = update.Get();
131 if (add_new_item) {
132 // AppendIfNotPresent will delete |adding_value| when the same value
133 // already exists.
134 list->AppendIfNotPresent(id.release());
135 } else {
136 list->Remove(*id, NULL);
140 void NotifierStateTracker::OnStringListPrefChanged(
141 const char* pref_name, std::set<std::string>* ids_field) {
142 ids_field->clear();
143 // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
144 const PrefService* pref_service = profile_->GetPrefs();
145 CHECK(pref_service);
146 const base::ListValue* pref_list = pref_service->GetList(pref_name);
147 for (size_t i = 0; i < pref_list->GetSize(); ++i) {
148 std::string element;
149 if (pref_list->GetString(i, &element) && !element.empty())
150 ids_field->insert(element);
151 else
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))
163 return;
165 // The settings for ephemeral apps will be persisted across cache evictions.
166 if (extensions::util::IsEphemeralApp(extension->id(), profile_))
167 return;
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,
184 args.Pass()));
185 extensions::EventRouter::Get(profile_)
186 ->DispatchEventToExtension(notifier_id.id, event.Pass());
188 // Tell the IO thread that this extension's permission for notifications
189 // has changed.
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));
197 #endif