blob: 9ee187de23896698c072c8f059feac0f12e417b8 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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
3// found in the LICENSE file.
4
5#include "chrome/browser/notifications/message_center_settings_controller.h"
6
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007#include <algorithm>
8
9#include "base/i18n/string_compare.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "base/utf_string_conversions.h"
11#include "chrome/browser/extensions/app_icon_loader_impl.h"
12#include "chrome/browser/extensions/extension_service.h"
13#include "chrome/browser/favicon/favicon_service.h"
14#include "chrome/browser/favicon/favicon_service_factory.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010015#include "chrome/browser/favicon/favicon_types.h"
16#include "chrome/browser/history/history_types.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "chrome/browser/notifications/desktop_notification_service.h"
18#include "chrome/browser/notifications/desktop_notification_service_factory.h"
19#include "chrome/browser/profiles/profile.h"
20#include "chrome/browser/profiles/profile_manager.h"
21#include "chrome/common/cancelable_task_tracker.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010022#include "chrome/common/extensions/extension_constants.h"
23#include "grit/theme_resources.h"
24#include "grit/ui_strings.h"
25#include "ui/base/l10n/l10n_util.h"
26#include "ui/base/resource/resource_bundle.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027#include "ui/gfx/image/image.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010028#include "ui/message_center/message_center_style.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000029
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010030using message_center::Notifier;
31
32namespace {
33
34class NotifierComparator {
35 public:
36 explicit NotifierComparator(icu::Collator* collator) : collator_(collator) {}
37
38 bool operator() (Notifier* n1, Notifier* n2) {
39 return base::i18n::CompareString16WithCollator(
40 collator_, n1->name, n2->name) == UCOL_LESS;
41 }
42
43 private:
44 icu::Collator* collator_;
45};
46
47bool SimpleCompareNotifiers(Notifier* n1, Notifier* n2) {
48 return n1->name < n2->name;
49}
50
51} // namespace
52
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000053MessageCenterSettingsController::MessageCenterSettingsController()
54 : delegate_(NULL) {
55}
56
57MessageCenterSettingsController::~MessageCenterSettingsController() {
58}
59
60void MessageCenterSettingsController::ShowSettingsDialog(
61 gfx::NativeView context) {
62 delegate_ = message_center::ShowSettings(this, context);
63}
64
65void MessageCenterSettingsController::GetNotifierList(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 std::vector<Notifier*>* notifiers) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000067 DCHECK(notifiers);
68 // TODO(mukai): Fix this for multi-profile.
69 Profile* profile = ProfileManager::GetDefaultProfile();
70 DesktopNotificationService* notification_service =
71 DesktopNotificationServiceFactory::GetForProfile(profile);
72
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010073 UErrorCode error;
74 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(error));
75 scoped_ptr<NotifierComparator> comparator;
76 if (!U_FAILURE(error))
77 comparator.reset(new NotifierComparator(collator.get()));
78
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000079 ExtensionService* extension_service = profile->GetExtensionService();
80 const ExtensionSet* extension_set = extension_service->extensions();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010081 // The extension icon size has to be 32x32 at least to load bigger icons if
82 // the icon doesn't exist for the specified size, and in that case it falls
83 // back to the default icon. The fetched icon will be resized in the settings
84 // dialog. See chrome/browser/extensions/extension_icon_image.cc and
85 // crbug.com/222931
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000086 app_icon_loader_.reset(new extensions::AppIconLoaderImpl(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010087 profile, extension_misc::EXTENSION_ICON_SMALL, this));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088 for (ExtensionSet::const_iterator iter = extension_set->begin();
89 iter != extension_set->end(); ++iter) {
90 const extensions::Extension* extension = *iter;
91 if (!extension->HasAPIPermission(
92 extensions::APIPermission::kNotification)) {
93 continue;
94 }
95
96 notifiers->push_back(new message_center::Notifier(
97 extension->id(),
98 UTF8ToUTF16(extension->name()),
99 notification_service->IsExtensionEnabled(extension->id())));
100 app_icon_loader_->FetchImage(extension->id());
101 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100102 if (comparator)
103 std::sort(notifiers->begin(), notifiers->end(), *comparator);
104 else
105 std::sort(notifiers->begin(), notifiers->end(), SimpleCompareNotifiers);
106 int app_count = notifiers->size();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000107
108 ContentSettingsForOneType settings;
109 notification_service->GetNotificationsSettings(&settings);
110 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
111 profile, Profile::EXPLICIT_ACCESS);
112 favicon_tracker_.reset(new CancelableTaskTracker());
113 patterns_.clear();
114 for (ContentSettingsForOneType::const_iterator iter = settings.begin();
115 iter != settings.end(); ++iter) {
116 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
117 iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
118 iter->source != "preference") {
119 continue;
120 }
121
122 std::string url_pattern = iter->primary_pattern.ToString();
123 string16 name = UTF8ToUTF16(url_pattern);
124 GURL url(url_pattern);
125 notifiers->push_back(new message_center::Notifier(
126 url,
127 name,
128 notification_service->GetContentSetting(url) == CONTENT_SETTING_ALLOW));
129 patterns_[name] = iter->primary_pattern;
130 FaviconService::FaviconForURLParams favicon_params(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100131 profile, url, chrome::FAVICON | chrome::TOUCH_ICON,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000132 message_center::kSettingsIconSize);
133 // Note that favicon service obtains the favicon from history. This means
134 // that it will fail to obtain the image if there are no history data for
135 // that URL.
136 favicon_service->GetFaviconImageForURL(
137 favicon_params,
138 base::Bind(&MessageCenterSettingsController::OnFaviconLoaded,
139 base::Unretained(this), url),
140 favicon_tracker_.get());
141 }
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100142
143 // Screenshot notification feature is only for ChromeOS. See crbug.com/238358
144#if defined(OS_CHROMEOS)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100145 const string16 screenshot_name =
146 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
147 message_center::Notifier* const screenshot_notifier =
148 new message_center::Notifier(
149 message_center::Notifier::SCREENSHOT,
150 screenshot_name,
151 notification_service->IsSystemComponentEnabled(
152 message_center::Notifier::SCREENSHOT));
153 screenshot_notifier->icon =
154 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
155 IDR_SCREENSHOT_NOTIFICATION_ICON);
156 notifiers->push_back(screenshot_notifier);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100157#endif
158
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100159 if (comparator) {
160 std::sort(notifiers->begin() + app_count, notifiers->end(), *comparator);
161 } else {
162 std::sort(notifiers->begin() + app_count, notifiers->end(),
163 SimpleCompareNotifiers);
164 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000165}
166
167void MessageCenterSettingsController::SetNotifierEnabled(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100168 const Notifier& notifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 bool enabled) {
170 // TODO(mukai): Fix this for multi-profile.
171 Profile* profile = ProfileManager::GetDefaultProfile();
172 DesktopNotificationService* notification_service =
173 DesktopNotificationServiceFactory::GetForProfile(profile);
174
175 switch (notifier.type) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100176 case Notifier::APPLICATION:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000177 notification_service->SetExtensionEnabled(notifier.id, enabled);
178 break;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100179 case Notifier::WEB_PAGE: {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000180 ContentSetting default_setting =
181 notification_service->GetDefaultContentSetting(NULL);
182 DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
183 default_setting == CONTENT_SETTING_BLOCK ||
184 default_setting == CONTENT_SETTING_ASK);
185 if ((enabled && default_setting != CONTENT_SETTING_ALLOW) ||
186 (!enabled && default_setting == CONTENT_SETTING_ALLOW)) {
187 if (notifier.url.is_valid()) {
188 if (enabled)
189 notification_service->GrantPermission(notifier.url);
190 else
191 notification_service->DenyPermission(notifier.url);
192 } else {
193 LOG(ERROR) << "Invalid url pattern: " << notifier.url.spec();
194 }
195 } else {
196 std::map<string16, ContentSettingsPattern>::const_iterator iter =
197 patterns_.find(notifier.name);
198 if (iter != patterns_.end()) {
199 notification_service->ClearSetting(iter->second);
200 } else {
201 LOG(ERROR) << "Invalid url pattern: " << notifier.url.spec();
202 }
203 }
204 break;
205 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100206 case message_center::Notifier::SYSTEM_COMPONENT:
207 notification_service->SetSystemComponentEnabled(
208 notifier.system_component_type, enabled);
209 break;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000210 }
211}
212
213void MessageCenterSettingsController::OnNotifierSettingsClosing() {
214 delegate_ = NULL;
215 DCHECK(favicon_tracker_.get());
216 favicon_tracker_->TryCancelAll();
217 patterns_.clear();
218}
219
220void MessageCenterSettingsController::OnFaviconLoaded(
221 const GURL& url,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100222 const chrome::FaviconImageResult& favicon_result) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000223 if (!delegate_)
224 return;
225 delegate_->UpdateFavicon(url, favicon_result.image);
226}
227
228
229void MessageCenterSettingsController::SetAppImage(const std::string& id,
230 const gfx::ImageSkia& image) {
231 if (!delegate_)
232 return;
233 delegate_->UpdateIconImage(id, gfx::Image(image) );
234}