Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: chrome/browser/notifications/message_center_settings_controller.cc

Issue 2064363002: Refactor MessageCenterSettingsController. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unrelated files from the patch. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/notifications/message_center_settings_controller.h" 5 #include "chrome/browser/notifications/message_center_settings_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/i18n/string_compare.h" 12 #include "base/i18n/string_compare.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/task/cancelable_task_tracker.h" 14 #include "base/task/cancelable_task_tracker.h"
15 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
16 #include "build/build_config.h" 16 #include "build/build_config.h"
17 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_notification_types.h" 18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 19 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
20 #include "chrome/browser/extensions/extension_app_icon_loader.h" 20 #include "chrome/browser/extensions/extension_app_icon_loader.h"
21 #include "chrome/browser/favicon/favicon_service_factory.h" 21 #include "chrome/browser/favicon/favicon_service_factory.h"
22 #include "chrome/browser/notifications/desktop_notification_profile_util.h" 22 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
23 #include "chrome/browser/notifications/notifier_source.h"
23 #include "chrome/browser/notifications/notifier_state_tracker.h" 24 #include "chrome/browser/notifications/notifier_state_tracker.h"
24 #include "chrome/browser/notifications/notifier_state_tracker_factory.h" 25 #include "chrome/browser/notifications/notifier_state_tracker_factory.h"
25 #include "chrome/browser/profiles/profile.h" 26 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/profiles/profile_attributes_entry.h" 27 #include "chrome/browser/profiles/profile_attributes_entry.h"
27 #include "chrome/browser/profiles/profile_attributes_storage.h" 28 #include "chrome/browser/profiles/profile_attributes_storage.h"
28 #include "chrome/browser/profiles/profile_manager.h" 29 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/common/extensions/api/notifications.h" 30 #include "chrome/common/extensions/api/notifications.h"
30 #include "chrome/common/extensions/extension_constants.h" 31 #include "chrome/common/extensions/extension_constants.h"
31 #include "components/content_settings/core/browser/host_content_settings_map.h" 32 #include "components/content_settings/core/browser/host_content_settings_map.h"
32 #include "components/favicon/core/favicon_service.h" 33 #include "components/favicon/core/favicon_service.h"
33 #include "components/favicon_base/favicon_types.h" 34 #include "components/favicon_base/favicon_types.h"
34 #include "components/history/core/browser/history_types.h" 35 #include "components/history/core/browser/history_types.h"
35 #include "content/public/browser/notification_service.h" 36 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/notification_source.h" 37 #include "content/public/browser/notification_source.h"
37 #include "extensions/browser/event_router.h" 38 #include "extensions/browser/event_router.h"
38 #include "extensions/browser/extension_registry.h" 39 #include "extensions/browser/extension_registry.h"
39 #include "extensions/common/constants.h" 40 #include "extensions/common/constants.h"
40 #include "extensions/common/extension.h" 41 #include "extensions/common/extension.h"
41 #include "extensions/common/permissions/permissions_data.h" 42 #include "extensions/common/permissions/permissions_data.h"
42 #include "grit/theme_resources.h" 43 #include "grit/theme_resources.h"
43 #include "ui/base/l10n/l10n_util.h" 44 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h" 45 #include "ui/base/resource/resource_bundle.h"
45 #include "ui/gfx/image/image.h" 46 #include "ui/gfx/image/image.h"
46 #include "ui/message_center/message_center_style.h" 47 #include "ui/message_center/message_center_style.h"
47 #include "ui/strings/grit/ui_strings.h" 48 #include "ui/strings/grit/ui_strings.h"
48 49
49 #if defined(OS_CHROMEOS) 50 #if defined(OS_CHROMEOS)
50 #include "ash/system/system_notifier.h" 51 #include "ash/system/system_notifier.h"
51 #include "chrome/browser/chromeos/profiles/profile_helper.h" 52 #include "chrome/browser/chromeos/profiles/profile_helper.h"
52 #include "chrome/browser/notifications/arc_notifier_manager.h" 53 #include "chrome/browser/notifications/arc_notifier_source.h"
53 #include "components/arc/arc_bridge_service.h"
54 #endif 54 #endif
55 55
56 using message_center::Notifier; 56 using message_center::Notifier;
57 using message_center::NotifierId; 57 using message_center::NotifierId;
58 58
59 namespace message_center { 59 namespace message_center {
60 60
61 class ProfileNotifierGroup : public message_center::NotifierGroup { 61 class ProfileNotifierGroup : public message_center::NotifierGroup {
62 public: 62 public:
63 ProfileNotifierGroup(const gfx::Image& icon, 63 ProfileNotifierGroup(const gfx::Image& icon,
(...skipping 27 matching lines...) Expand all
91 const base::string16& display_name, 91 const base::string16& display_name,
92 const base::string16& login_info, 92 const base::string16& login_info,
93 Profile* profile) 93 Profile* profile)
94 : message_center::NotifierGroup(icon, display_name, login_info), 94 : message_center::NotifierGroup(icon, display_name, login_info),
95 profile_(profile) { 95 profile_(profile) {
96 } 96 }
97 97
98 } // namespace message_center 98 } // namespace message_center
99 99
100 namespace { 100 namespace {
101
101 class NotifierComparator { 102 class NotifierComparator {
102 public: 103 public:
103 explicit NotifierComparator(icu::Collator* collator) : collator_(collator) {} 104 explicit NotifierComparator(icu::Collator* collator) : collator_(collator) {}
104 105
105 bool operator() (Notifier* n1, Notifier* n2) { 106 bool operator() (Notifier* n1, Notifier* n2) {
106 if (n1->notifier_id.type != n2->notifier_id.type) 107 if (n1->notifier_id.type != n2->notifier_id.type)
107 return n1->notifier_id.type < n2->notifier_id.type; 108 return n1->notifier_id.type < n2->notifier_id.type;
108 109
109 if (collator_) { 110 if (collator_) {
110 return base::i18n::CompareString16WithCollator(*collator_, n1->name, 111 return base::i18n::CompareString16WithCollator(*collator_, n1->name,
111 n2->name) == UCOL_LESS; 112 n2->name) == UCOL_LESS;
112 } 113 }
113 return n1->name < n2->name; 114 return n1->name < n2->name;
114 } 115 }
115 116
116 private: 117 private:
117 icu::Collator* collator_; 118 icu::Collator* collator_;
118 }; 119 };
119 120
121 class ApplicationNotifiereSource : public NotifierSource,
dewittj 2016/06/16 19:45:36 I think this deserves its own h/cc files. Probabl
hirono 2016/06/17 04:56:46 Separating files is done. The names of source clas
122 public AppIconLoaderDelegate {
123 public:
124 explicit ApplicationNotifiereSource(
dewittj 2016/06/16 19:45:36 This should be spelled ApplicationNotifierSource,
hirono 2016/06/17 04:56:46 Oops, yes!
125 message_center::NotifierSettingsObserver* parent)
126 : NotifierSource(parent) {}
127
128 std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
129 Profile* profile) override {
130 std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
131 NotifierStateTracker* const notifier_state_tracker =
132 NotifierStateTrackerFactory::GetForProfile(profile);
133 const extensions::ExtensionSet& extension_set =
134 extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
135 // The extension icon size has to be 32x32 at least to load bigger icons if
136 // the icon doesn't exist for the specified size, and in that case it falls
137 // back to the default icon. The fetched icon will be resized in the
138 // settings dialog. See chrome/browser/extensions/extension_icon_image.cc
139 // and crbug.com/222931
140 app_icon_loader_.reset(new extensions::ExtensionAppIconLoader(
141 profile, extension_misc::EXTENSION_ICON_SMALL, this));
142 for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
143 iter != extension_set.end(); ++iter) {
144 const extensions::Extension* extension = iter->get();
145 if (!extension->permissions_data()->HasAPIPermission(
146 extensions::APIPermission::kNotifications)) {
147 continue;
148 }
149
150 // Hosted apps are no longer able to affect the notifications permission
151 // state for web notifications.
152 // TODO(dewittj): Deprecate the 'notifications' permission for hosted
153 // apps.
154 if (extension->is_hosted_app())
155 continue;
156
157 NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
158 notifiers.emplace_back(
159 new Notifier(notifier_id, base::UTF8ToUTF16(extension->name()),
160 notifier_state_tracker->IsNotifierEnabled(notifier_id)));
161 app_icon_loader_->FetchImage(extension->id());
162 }
163
164 return notifiers;
165 }
166
167 void SetNotifierEnabled(Profile* profile,
168 const message_center::Notifier& notifier,
169 bool enabled) override {
170 NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
171 notifier.notifier_id, enabled);
172 parent_->NotifierEnabledChanged(notifier.notifier_id, enabled);
173 }
174
175 message_center::NotifierId::NotifierType GetNotifierType() override {
176 return NotifierId::APPLICATION;
177 }
178
179 private:
180 // Overridden from AppIconLoaderDelegate.
181 void OnAppImageUpdated(const std::string& id,
182 const gfx::ImageSkia& image) override {
183 parent_->UpdateIconImage(NotifierId(NotifierId::APPLICATION, id),
184 gfx::Image(image));
185 }
186
187 std::unique_ptr<AppIconLoader> app_icon_loader_;
188 };
189
190 class WebPageNotifiereSource : public NotifierSource {
191 public:
192 explicit WebPageNotifiereSource(
193 message_center::NotifierSettingsObserver* parent)
194 : NotifierSource(parent) {}
195
196 std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
197 Profile* profile) override {
198 std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
199 NotifierStateTracker* const notifier_state_tracker =
200 NotifierStateTrackerFactory::GetForProfile(profile);
201 ContentSettingsForOneType settings;
202 DesktopNotificationProfileUtil::GetNotificationsSettings(profile,
203 &settings);
204
205 favicon::FaviconService* const favicon_service =
206 FaviconServiceFactory::GetForProfile(
207 profile, ServiceAccessType::EXPLICIT_ACCESS);
208 favicon_tracker_.reset(new base::CancelableTaskTracker());
209 patterns_.clear();
210 for (ContentSettingsForOneType::const_iterator iter = settings.begin();
211 iter != settings.end(); ++iter) {
212 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
213 iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
214 iter->source != "preference") {
215 continue;
216 }
217
218 std::string url_pattern = iter->primary_pattern.ToString();
219 base::string16 name = base::UTF8ToUTF16(url_pattern);
220 GURL url(url_pattern);
221 NotifierId notifier_id(url);
222 notifiers.emplace_back(
223 new Notifier(notifier_id, name,
224 notifier_state_tracker->IsNotifierEnabled(notifier_id)));
225 patterns_[name] = iter->primary_pattern;
226 // Note that favicon service obtains the favicon from history. This means
227 // that it will fail to obtain the image if there are no history data for
228 // that URL.
229 favicon_service->GetFaviconImageForPageURL(
230 url, base::Bind(&WebPageNotifiereSource::OnFaviconLoaded,
231 base::Unretained(this), url),
232 favicon_tracker_.get());
233 }
234
235 return notifiers;
236 }
237
238 void SetNotifierEnabled(Profile* profile,
239 const message_center::Notifier& notifier,
240 bool enabled) override {
241 // WEB_PAGE notifier cannot handle in DesktopNotificationService
242 // since it has the exact URL pattern.
243 // TODO(mukai): fix this.
244 ContentSetting default_setting =
245 HostContentSettingsMapFactory::GetForProfile(profile)
246 ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
247 NULL);
248
249 DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
250 default_setting == CONTENT_SETTING_BLOCK ||
251 default_setting == CONTENT_SETTING_ASK);
252
253 // The content setting for notifications needs to clear when it changes to
254 // the default value or get explicitly set when it differs from the
255 // default.
256 bool differs_from_default_value =
257 (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
258 (default_setting == CONTENT_SETTING_ALLOW && !enabled);
259
260 if (differs_from_default_value) {
261 if (notifier.notifier_id.url.is_valid()) {
262 if (enabled) {
263 DesktopNotificationProfileUtil::GrantPermission(
264 profile, notifier.notifier_id.url);
265 } else {
266 DesktopNotificationProfileUtil::DenyPermission(
267 profile, notifier.notifier_id.url);
268 }
269 } else {
270 LOG(ERROR) << "Invalid url pattern: "
271 << notifier.notifier_id.url.spec();
272 }
273 } else {
274 ContentSettingsPattern pattern;
275
276 const auto& iter = patterns_.find(notifier.name);
277 if (iter != patterns_.end()) {
278 pattern = iter->second;
279 } else if (notifier.notifier_id.url.is_valid()) {
280 pattern =
281 ContentSettingsPattern::FromURLNoWildcard(notifier.notifier_id.url);
282 } else {
283 LOG(ERROR) << "Invalid url pattern: "
284 << notifier.notifier_id.url.spec();
285 }
286
287 if (pattern.IsValid()) {
288 // Note that we don't use
289 // DesktopNotificationProfileUtil::ClearSetting()
290 // here because pattern might be from user manual input and not match
291 // the default one used by ClearSetting().
292 HostContentSettingsMapFactory::GetForProfile(profile)
293 ->SetContentSettingCustomScope(
294 pattern, ContentSettingsPattern::Wildcard(),
295 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
296 content_settings::ResourceIdentifier(),
297 CONTENT_SETTING_DEFAULT);
298 }
299 }
300
301 parent_->NotifierEnabledChanged(notifier.notifier_id, enabled);
302 }
303
304 void OnNotifierSettingsClosing() override {
305 DCHECK(favicon_tracker_.get());
306 favicon_tracker_->TryCancelAll();
307 patterns_.clear();
308 }
309
310 message_center::NotifierId::NotifierType GetNotifierType() override {
311 return NotifierId::WEB_PAGE;
312 }
313
314 private:
315 void OnFaviconLoaded(const GURL& url,
316 const favicon_base::FaviconImageResult& favicon_result) {
317 parent_->UpdateIconImage(NotifierId(url), favicon_result.image);
318 }
319
320 std::map<base::string16, ContentSettingsPattern> patterns_;
321
322 // The task tracker for loading favicons.
323 std::unique_ptr<base::CancelableTaskTracker> favicon_tracker_;
324 };
325
326 #if defined(OS_CHROMEOS)
327 class SystemComponentNotifierSource : public NotifierSource {
328 public:
329 explicit SystemComponentNotifierSource(
330 message_center::NotifierSettingsObserver* parent)
331 : NotifierSource(parent) {}
332
333 std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
334 Profile* profile) override {
335 std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
336 NotifierStateTracker* const notifier_state_tracker =
337 NotifierStateTrackerFactory::GetForProfile(profile);
338
339 // Screenshot notification feature is only for ChromeOS. See
340 // crbug.com/238358
341 const base::string16& screenshot_name =
342 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
343 NotifierId screenshot_notifier_id(
344 NotifierId::SYSTEM_COMPONENT,
345 ash::system_notifier::kNotifierScreenshot);
346 Notifier* const screenshot_notifier = new Notifier(
347 screenshot_notifier_id, screenshot_name,
348 notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
349 screenshot_notifier->icon =
350 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
351 IDR_SCREENSHOT_NOTIFICATION_ICON);
352 notifiers.emplace_back(screenshot_notifier);
353 return notifiers;
354 }
355
356 void SetNotifierEnabled(Profile* profile,
357 const message_center::Notifier& notifier,
358 bool enabled) override {
359 NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
360 notifier.notifier_id, enabled);
361 parent_->NotifierEnabledChanged(notifier.notifier_id, enabled);
362 }
363
364 message_center::NotifierId::NotifierType GetNotifierType() override {
365 return NotifierId::SYSTEM_COMPONENT;
366 }
367 };
368 #endif
369
120 } // namespace 370 } // namespace
121 371
122 MessageCenterSettingsController::MessageCenterSettingsController( 372 MessageCenterSettingsController::MessageCenterSettingsController(
123 ProfileAttributesStorage& profile_attributes_storage) 373 ProfileAttributesStorage& profile_attributes_storage)
124 : current_notifier_group_(0), 374 : current_notifier_group_(0),
125 profile_attributes_storage_(profile_attributes_storage), 375 profile_attributes_storage_(profile_attributes_storage),
126 weak_factory_(this) { 376 weak_factory_(this) {
127 // The following events all represent changes that may need to be reflected in 377 // The following events all represent changes that may need to be reflected in
128 // the profile selector context menu, so listen for them all. We'll just 378 // the profile selector context menu, so listen for them all. We'll just
129 // rebuild the list when we get any of them. 379 // rebuild the list when we get any of them.
130 registrar_.Add(this, 380 registrar_.Add(this,
131 chrome::NOTIFICATION_PROFILE_CREATED, 381 chrome::NOTIFICATION_PROFILE_CREATED,
132 content::NotificationService::AllBrowserContextsAndSources()); 382 content::NotificationService::AllBrowserContextsAndSources());
133 registrar_.Add(this, 383 registrar_.Add(this,
134 chrome::NOTIFICATION_PROFILE_ADDED, 384 chrome::NOTIFICATION_PROFILE_ADDED,
135 content::NotificationService::AllBrowserContextsAndSources()); 385 content::NotificationService::AllBrowserContextsAndSources());
136 registrar_.Add(this, 386 registrar_.Add(this,
137 chrome::NOTIFICATION_PROFILE_DESTROYED, 387 chrome::NOTIFICATION_PROFILE_DESTROYED,
138 content::NotificationService::AllBrowserContextsAndSources()); 388 content::NotificationService::AllBrowserContextsAndSources());
139 profile_attributes_storage_.AddObserver(this); 389 profile_attributes_storage_.AddObserver(this);
140 RebuildNotifierGroups(false); 390 RebuildNotifierGroups(false);
141 391
392 sources_.insert(std::make_pair(
393 NotifierId::APPLICATION,
394 std::unique_ptr<NotifierSource>(new ApplicationNotifiereSource(this))));
395 sources_.insert(std::make_pair(
396 NotifierId::WEB_PAGE,
397 std::unique_ptr<NotifierSource>(new WebPageNotifiereSource(this))));
398
142 #if defined(OS_CHROMEOS) 399 #if defined(OS_CHROMEOS)
143 // UserManager may not exist in some tests. 400 // UserManager may not exist in some tests.
144 if (user_manager::UserManager::IsInitialized()) 401 if (user_manager::UserManager::IsInitialized())
145 user_manager::UserManager::Get()->AddSessionStateObserver(this); 402 user_manager::UserManager::Get()->AddSessionStateObserver(this);
146 // Check if ARC is enabled. 403 // FOr system components.
147 if (arc::ArcBridgeService::Get()) 404 sources_.insert(std::make_pair(NotifierId::SYSTEM_COMPONENT,
148 arc_notifier_manager_.reset(new arc::ArcNotifierManager()); 405 std::unique_ptr<NotifierSource>(
406 new SystemComponentNotifierSource(this))));
407 sources_.insert(std::make_pair(
408 NotifierId::ARC_APPLICATION,
409 std::unique_ptr<NotifierSource>(new arc::ArcNotifierSource(this))));
149 #endif 410 #endif
150 } 411 }
151 412
152 MessageCenterSettingsController::~MessageCenterSettingsController() { 413 MessageCenterSettingsController::~MessageCenterSettingsController() {
153 profile_attributes_storage_.RemoveObserver(this); 414 profile_attributes_storage_.RemoveObserver(this);
154 #if defined(OS_CHROMEOS) 415 #if defined(OS_CHROMEOS)
155 // UserManager may not exist in some tests. 416 // UserManager may not exist in some tests.
156 if (user_manager::UserManager::IsInitialized()) 417 if (user_manager::UserManager::IsInitialized())
157 user_manager::UserManager::Get()->RemoveSessionStateObserver(this); 418 user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
158 #endif 419 #endif
(...skipping 29 matching lines...) Expand all
188 DCHECK_LT(current_notifier_group_, notifier_groups_.size()); 449 DCHECK_LT(current_notifier_group_, notifier_groups_.size());
189 return *(notifier_groups_[current_notifier_group_]); 450 return *(notifier_groups_[current_notifier_group_]);
190 } 451 }
191 452
192 void MessageCenterSettingsController::SwitchToNotifierGroup(size_t index) { 453 void MessageCenterSettingsController::SwitchToNotifierGroup(size_t index) {
193 DCHECK_LT(index, notifier_groups_.size()); 454 DCHECK_LT(index, notifier_groups_.size());
194 if (current_notifier_group_ == index) 455 if (current_notifier_group_ == index)
195 return; 456 return;
196 457
197 current_notifier_group_ = index; 458 current_notifier_group_ = index;
198 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, 459 NotifierGroupChanged();
199 observers_,
200 NotifierGroupChanged());
201 } 460 }
202 461
203 void MessageCenterSettingsController::GetNotifierList( 462 void MessageCenterSettingsController::GetNotifierList(
204 std::vector<Notifier*>* notifiers) { 463 std::vector<Notifier*>* notifiers) {
205 DCHECK(notifiers); 464 DCHECK(notifiers);
206 if (notifier_groups_.size() <= current_notifier_group_) 465 if (notifier_groups_.size() <= current_notifier_group_)
207 return; 466 return;
208 // Temporarily use the last used profile to prevent chrome from crashing when 467 // Temporarily use the last used profile to prevent chrome from crashing when
209 // the default profile is not loaded. 468 // the default profile is not loaded.
210 Profile* profile = notifier_groups_[current_notifier_group_]->profile(); 469 Profile* profile = notifier_groups_[current_notifier_group_]->profile();
211 470
212 NotifierStateTracker* notifier_state_tracker = 471 for (auto& source : sources_) {
213 NotifierStateTrackerFactory::GetForProfile(profile); 472 auto source_notifiers = source.second->GetNotifierList(profile);
214 473 for (auto& notifier : source_notifiers) {
215 const extensions::ExtensionSet& extension_set =
216 extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
217 // The extension icon size has to be 32x32 at least to load bigger icons if
218 // the icon doesn't exist for the specified size, and in that case it falls
219 // back to the default icon. The fetched icon will be resized in the settings
220 // dialog. See chrome/browser/extensions/extension_icon_image.cc and
221 // crbug.com/222931
222 app_icon_loader_.reset(new extensions::ExtensionAppIconLoader(
223 profile, extension_misc::EXTENSION_ICON_SMALL, this));
224 for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
225 iter != extension_set.end();
226 ++iter) {
227 const extensions::Extension* extension = iter->get();
228 if (!extension->permissions_data()->HasAPIPermission(
229 extensions::APIPermission::kNotifications)) {
230 continue;
231 }
232
233 // Hosted apps are no longer able to affect the notifications permission
234 // state for web notifications.
235 // TODO(dewittj): Deprecate the 'notifications' permission for hosted apps.
236 if (extension->is_hosted_app())
237 continue;
238
239 NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
240 notifiers->push_back(new Notifier(
241 notifier_id,
242 base::UTF8ToUTF16(extension->name()),
243 notifier_state_tracker->IsNotifierEnabled(notifier_id)));
244 app_icon_loader_->FetchImage(extension->id());
245 }
246
247 ContentSettingsForOneType settings;
248 DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
249
250 favicon::FaviconService* favicon_service =
251 FaviconServiceFactory::GetForProfile(profile,
252 ServiceAccessType::EXPLICIT_ACCESS);
253 favicon_tracker_.reset(new base::CancelableTaskTracker());
254 patterns_.clear();
255 for (ContentSettingsForOneType::const_iterator iter = settings.begin();
256 iter != settings.end(); ++iter) {
257 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
258 iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
259 iter->source != "preference") {
260 continue;
261 }
262
263 std::string url_pattern = iter->primary_pattern.ToString();
264 base::string16 name = base::UTF8ToUTF16(url_pattern);
265 GURL url(url_pattern);
266 NotifierId notifier_id(url);
267 notifiers->push_back(new Notifier(
268 notifier_id,
269 name,
270 notifier_state_tracker->IsNotifierEnabled(notifier_id)));
271 patterns_[name] = iter->primary_pattern;
272 // Note that favicon service obtains the favicon from history. This means
273 // that it will fail to obtain the image if there are no history data for
274 // that URL.
275 favicon_service->GetFaviconImageForPageURL(
276 url,
277 base::Bind(&MessageCenterSettingsController::OnFaviconLoaded,
278 base::Unretained(this),
279 url),
280 favicon_tracker_.get());
281 }
282
283 #if defined(OS_CHROMEOS)
284 // Add ARC++ apps.
285 if (arc_notifier_manager_) {
286 auto list = arc_notifier_manager_->GetNotifiers(profile);
287 for (auto& notifier : list) {
288 notifiers->push_back(notifier.release()); 474 notifiers->push_back(notifier.release());
289 } 475 }
290 } 476 }
291 477
292 // Screenshot notification feature is only for ChromeOS. See crbug.com/238358
293 const base::string16& screenshot_name =
294 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
295 NotifierId screenshot_notifier_id(
296 NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierScreenshot);
297 Notifier* const screenshot_notifier = new Notifier(
298 screenshot_notifier_id,
299 screenshot_name,
300 notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
301 screenshot_notifier->icon =
302 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
303 IDR_SCREENSHOT_NOTIFICATION_ICON);
304 notifiers->push_back(screenshot_notifier);
305 #endif
306
307 UErrorCode error = U_ZERO_ERROR; 478 UErrorCode error = U_ZERO_ERROR;
308 std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(error)); 479 std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(error));
309 std::unique_ptr<NotifierComparator> comparator( 480 std::unique_ptr<NotifierComparator> comparator(
310 new NotifierComparator(U_SUCCESS(error) ? collator.get() : NULL)); 481 new NotifierComparator(U_SUCCESS(error) ? collator.get() : NULL));
311 482
312 std::sort(notifiers->begin(), notifiers->end(), *comparator); 483 std::sort(notifiers->begin(), notifiers->end(), *comparator);
313 } 484 }
314 485
315 void MessageCenterSettingsController::SetNotifierEnabled( 486 void MessageCenterSettingsController::SetNotifierEnabled(
316 const Notifier& notifier, 487 const Notifier& notifier,
317 bool enabled) { 488 bool enabled) {
318 DCHECK_LT(current_notifier_group_, notifier_groups_.size()); 489 DCHECK_LT(current_notifier_group_, notifier_groups_.size());
319 Profile* profile = notifier_groups_[current_notifier_group_]->profile(); 490 Profile* profile = notifier_groups_[current_notifier_group_]->profile();
320 491
321 switch (notifier.notifier_id.type) { 492 if (!sources_.count(notifier.notifier_id.type)) {
322 case NotifierId::WEB_PAGE: { 493 NOTREACHED();
323 // WEB_PAGE notifier cannot handle in DesktopNotificationService 494 return;
324 // since it has the exact URL pattern. 495 }
325 // TODO(mukai): fix this.
326 ContentSetting default_setting =
327 HostContentSettingsMapFactory::GetForProfile(profile)
328 ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
329 NULL);
330 496
331 DCHECK(default_setting == CONTENT_SETTING_ALLOW || 497 sources_[notifier.notifier_id.type]->SetNotifierEnabled(profile, notifier,
332 default_setting == CONTENT_SETTING_BLOCK || 498 enabled);
333 default_setting == CONTENT_SETTING_ASK);
334
335 // The content setting for notifications needs to clear when it changes to
336 // the default value or get explicitly set when it differs from the
337 // default.
338 bool differs_from_default_value =
339 (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
340 (default_setting == CONTENT_SETTING_ALLOW && !enabled);
341
342 if (differs_from_default_value) {
343 if (notifier.notifier_id.url.is_valid()) {
344 if (enabled) {
345 DesktopNotificationProfileUtil::GrantPermission(
346 profile, notifier.notifier_id.url);
347 } else {
348 DesktopNotificationProfileUtil::DenyPermission(
349 profile, notifier.notifier_id.url);
350 }
351 } else {
352 LOG(ERROR) << "Invalid url pattern: "
353 << notifier.notifier_id.url.spec();
354 }
355 } else {
356 ContentSettingsPattern pattern;
357
358 const auto& iter = patterns_.find(notifier.name);
359 if (iter != patterns_.end()) {
360 pattern = iter->second;
361 } else if (notifier.notifier_id.url.is_valid()) {
362 pattern = ContentSettingsPattern::FromURLNoWildcard(
363 notifier.notifier_id.url);
364 } else {
365 LOG(ERROR) << "Invalid url pattern: "
366 << notifier.notifier_id.url.spec();
367 }
368
369 if (pattern.IsValid()) {
370 // Note that we don't use
371 // DesktopNotificationProfileUtil::ClearSetting()
372 // here because pattern might be from user manual input and not match
373 // the default one used by ClearSetting().
374 HostContentSettingsMapFactory::GetForProfile(profile)
375 ->SetContentSettingCustomScope(
376 pattern, ContentSettingsPattern::Wildcard(),
377 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
378 content_settings::ResourceIdentifier(),
379 CONTENT_SETTING_DEFAULT);
380 }
381 }
382 break;
383 }
384 case NotifierId::APPLICATION:
385 case NotifierId::SYSTEM_COMPONENT: {
386 NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
387 notifier.notifier_id, enabled);
388 break;
389 }
390 case NotifierId::ARC_APPLICATION: {
391 #if defined(OS_CHROMEOS)
392 if (arc_notifier_manager_) {
393 arc_notifier_manager_->SetNotifierEnabled(notifier.notifier_id.id,
394 enabled);
395 }
396 #else
397 NOTREACHED();
398 #endif
399 break;
400 }
401 }
402 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
403 observers_,
404 NotifierEnabledChanged(notifier.notifier_id, enabled));
405 } 499 }
406 500
407 void MessageCenterSettingsController::OnNotifierSettingsClosing() { 501 void MessageCenterSettingsController::OnNotifierSettingsClosing() {
408 DCHECK(favicon_tracker_.get()); 502 for (auto& source : sources_) {
409 favicon_tracker_->TryCancelAll(); 503 source.second->OnNotifierSettingsClosing();
410 patterns_.clear(); 504 }
411 } 505 }
412 506
413 bool MessageCenterSettingsController::NotifierHasAdvancedSettings( 507 bool MessageCenterSettingsController::NotifierHasAdvancedSettings(
414 const NotifierId& notifier_id) const { 508 const NotifierId& notifier_id) const {
415 // TODO(dewittj): Refactor this so that notifiers have a delegate that can 509 // TODO(dewittj): Refactor this so that notifiers have a delegate that can
416 // handle this in a more appropriate location. 510 // handle this in a more appropriate location.
417 if (notifier_id.type != NotifierId::APPLICATION) 511 if (notifier_id.type != NotifierId::APPLICATION)
418 return false; 512 return false;
419 513
420 const std::string& extension_id = notifier_id.id; 514 const std::string& extension_id = notifier_id.id;
(...skipping 25 matching lines...) Expand all
446 extensions::EventRouter* event_router = extensions::EventRouter::Get(profile); 540 extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
447 std::unique_ptr<base::ListValue> args(new base::ListValue()); 541 std::unique_ptr<base::ListValue> args(new base::ListValue());
448 542
449 std::unique_ptr<extensions::Event> event(new extensions::Event( 543 std::unique_ptr<extensions::Event> event(new extensions::Event(
450 extensions::events::NOTIFICATIONS_ON_SHOW_SETTINGS, 544 extensions::events::NOTIFICATIONS_ON_SHOW_SETTINGS,
451 extensions::api::notifications::OnShowSettings::kEventName, 545 extensions::api::notifications::OnShowSettings::kEventName,
452 std::move(args))); 546 std::move(args)));
453 event_router->DispatchEventToExtension(extension_id, std::move(event)); 547 event_router->DispatchEventToExtension(extension_id, std::move(event));
454 } 548 }
455 549
456 void MessageCenterSettingsController::OnFaviconLoaded(
457 const GURL& url,
458 const favicon_base::FaviconImageResult& favicon_result) {
459 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
460 observers_,
461 UpdateIconImage(NotifierId(url), favicon_result.image));
462 }
463
464
465 #if defined(OS_CHROMEOS) 550 #if defined(OS_CHROMEOS)
466 void MessageCenterSettingsController::ActiveUserChanged( 551 void MessageCenterSettingsController::ActiveUserChanged(
467 const user_manager::User* active_user) { 552 const user_manager::User* active_user) {
468 RebuildNotifierGroups(false); 553 RebuildNotifierGroups(false);
469 } 554 }
470 #endif 555 #endif
471 556
472 void MessageCenterSettingsController::OnAppImageUpdated(
473 const std::string& id, const gfx::ImageSkia& image) {
474 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
475 observers_,
476 UpdateIconImage(NotifierId(NotifierId::APPLICATION, id),
477 gfx::Image(image)));
478 }
479
480 void MessageCenterSettingsController::Observe( 557 void MessageCenterSettingsController::Observe(
481 int type, 558 int type,
482 const content::NotificationSource& source, 559 const content::NotificationSource& source,
483 const content::NotificationDetails& details) { 560 const content::NotificationDetails& details) {
484 // GetOffTheRecordProfile() may create a new off-the-record profile, but that 561 // GetOffTheRecordProfile() may create a new off-the-record profile, but that
485 // doesn't need to rebuild the groups. 562 // doesn't need to rebuild the groups.
486 if (type == chrome::NOTIFICATION_PROFILE_CREATED && 563 if (type == chrome::NOTIFICATION_PROFILE_CREATED &&
487 content::Source<Profile>(source).ptr()->IsOffTheRecord()) { 564 content::Source<Profile>(source).ptr()->IsOffTheRecord()) {
488 return; 565 return;
489 } 566 }
(...skipping 13 matching lines...) Expand all
503 void MessageCenterSettingsController::OnProfileNameChanged( 580 void MessageCenterSettingsController::OnProfileNameChanged(
504 const base::FilePath& profile_path, 581 const base::FilePath& profile_path,
505 const base::string16& old_profile_name) { 582 const base::string16& old_profile_name) {
506 RebuildNotifierGroups(true); 583 RebuildNotifierGroups(true);
507 } 584 }
508 void MessageCenterSettingsController::OnProfileAuthInfoChanged( 585 void MessageCenterSettingsController::OnProfileAuthInfoChanged(
509 const base::FilePath& profile_path) { 586 const base::FilePath& profile_path) {
510 RebuildNotifierGroups(true); 587 RebuildNotifierGroups(true);
511 } 588 }
512 589
590 void MessageCenterSettingsController::UpdateIconImage(
591 const message_center::NotifierId& id,
592 const gfx::Image& image) {
593 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
594 UpdateIconImage(id, image));
595 }
596
597 void MessageCenterSettingsController::NotifierGroupChanged() {
598 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
599 NotifierGroupChanged());
600 }
601
602 void MessageCenterSettingsController::NotifierEnabledChanged(
603 const message_center::NotifierId& id,
604 bool enabled) {
605 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
606 NotifierEnabledChanged(id, enabled));
607 }
608
513 #if defined(OS_CHROMEOS) 609 #if defined(OS_CHROMEOS)
514 void MessageCenterSettingsController::CreateNotifierGroupForGuestLogin() { 610 void MessageCenterSettingsController::CreateNotifierGroupForGuestLogin() {
515 // Already created. 611 // Already created.
516 if (!notifier_groups_.empty()) 612 if (!notifier_groups_.empty())
517 return; 613 return;
518 614
519 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 615 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
520 // |notifier_groups_| can be empty in login screen too. 616 // |notifier_groups_| can be empty in login screen too.
521 if (!user_manager->IsLoggedInAsGuest()) 617 if (!user_manager->IsLoggedInAsGuest())
522 return; 618 return;
523 619
524 user_manager::User* user = user_manager->GetActiveUser(); 620 user_manager::User* user = user_manager->GetActiveUser();
525 Profile* profile = 621 Profile* profile =
526 chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); 622 chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user);
527 DCHECK(profile); 623 DCHECK(profile);
528 624
529 std::unique_ptr<message_center::ProfileNotifierGroup> group( 625 std::unique_ptr<message_center::ProfileNotifierGroup> group(
530 new message_center::ProfileNotifierGroup( 626 new message_center::ProfileNotifierGroup(
531 gfx::Image(user->GetImage()), user->GetDisplayName(), 627 gfx::Image(user->GetImage()), user->GetDisplayName(),
532 user->GetDisplayName(), profile)); 628 user->GetDisplayName(), profile));
533 629
534 notifier_groups_.push_back(std::move(group)); 630 notifier_groups_.push_back(std::move(group));
535 631 NotifierGroupChanged();
536 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
537 observers_,
538 NotifierGroupChanged());
539 } 632 }
540 #endif 633 #endif
541 634
542 void MessageCenterSettingsController::RebuildNotifierGroups(bool notify) { 635 void MessageCenterSettingsController::RebuildNotifierGroups(bool notify) {
543 notifier_groups_.clear(); 636 notifier_groups_.clear();
544 current_notifier_group_ = 0; 637 current_notifier_group_ = 0;
545 638
546 std::vector<ProfileAttributesEntry*> entries = 639 std::vector<ProfileAttributesEntry*> entries =
547 profile_attributes_storage_.GetAllProfilesAttributes(); 640 profile_attributes_storage_.GetAllProfilesAttributes();
548 for (const auto entry : entries) { 641 for (const auto entry : entries) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 // another creating a primary profile, and causes an infinite loop. 681 // another creating a primary profile, and causes an infinite loop.
589 // Thus, it would be better to delay creating group for guest login. 682 // Thus, it would be better to delay creating group for guest login.
590 base::ThreadTaskRunnerHandle::Get()->PostTask( 683 base::ThreadTaskRunnerHandle::Get()->PostTask(
591 FROM_HERE, 684 FROM_HERE,
592 base::Bind( 685 base::Bind(
593 &MessageCenterSettingsController::CreateNotifierGroupForGuestLogin, 686 &MessageCenterSettingsController::CreateNotifierGroupForGuestLogin,
594 weak_factory_.GetWeakPtr())); 687 weak_factory_.GetWeakPtr()));
595 } 688 }
596 #endif 689 #endif
597 690
598 if (notify) { 691 if (notify)
599 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, 692 NotifierGroupChanged();
600 observers_,
601 NotifierGroupChanged());
602 }
603 } 693 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698