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

Side by Side Diff: chrome/browser/notifications/notification_ui_manager_mac.mm

Issue 1925803002: Rename NotificationUIManagerMac to NotificationPlatformBridgeMac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « chrome/browser/notifications/notification_ui_manager_mac.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/notifications/notification_ui_manager_mac.h"
6
7 #include <utility>
8
9 #include "base/mac/foundation_util.h"
10 #include "base/mac/mac_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/notifications/notification.h"
15 #include "chrome/browser/notifications/notification_display_service_factory.h"
16 #include "chrome/browser/notifications/persistent_notification_delegate.h"
17 #include "chrome/browser/notifications/platform_notification_service_impl.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util_mac.h"
22 #include "url/gurl.h"
23
24 @class NSUserNotification;
25 @class NSUserNotificationCenter;
26
27 // The mapping from web notifications to NsUserNotification works as follows
28
29 // notification#title in NSUserNotification.title
30 // notification#message in NSUserNotification.subtitle
31 // notification#context_message in NSUserNotification.informativeText
32 // notification#tag in NSUserNotification.identifier (10.9)
33 // notification#icon in NSUserNotification.contentImage (10.9)
34 // Site settings button is implemented as NSUserNotification's action button
35 // Not possible to implement:
36 // -notification.requireInteraction
37 // -The event associated to the close button
38
39 // TODO(miguelg) implement the following features
40 // - Sound names can be implemented by setting soundName in NSUserNotification
41 // NSUserNotificationDefaultSoundName gives you the platform default.
42
43 namespace {
44
45 // Keys in NSUserNotification.userInfo to map chrome notifications to
46 // native ones.
47 NSString* const kNotificationOriginKey = @"notification_origin";
48 NSString* const kNotificationPersistentIdKey = @"notification_persistent_id";
49
50 NSString* const kNotificationProfilePersistentIdKey =
51 @"notification_profile_persistent_id";
52 NSString* const kNotificationIncognitoKey = @"notification_incognito";
53
54 } // namespace
55
56 // static
57 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
58 return new NotificationUIManagerMac(
59 [NSUserNotificationCenter defaultUserNotificationCenter]);
60 }
61
62 // A Cocoa class that represents the delegate of NSUserNotificationCenter and
63 // can forward commands to C++.
64 @interface NotificationCenterDelegate
65 : NSObject<NSUserNotificationCenterDelegate> {
66 }
67 @end
68
69 // /////////////////////////////////////////////////////////////////////////////
70
71 NotificationUIManagerMac::NotificationUIManagerMac(
72 NSUserNotificationCenter* notification_center)
73 : delegate_([NotificationCenterDelegate alloc]),
74 notification_center_(notification_center) {
75 [notification_center_ setDelegate:delegate_.get()];
76 }
77
78 NotificationUIManagerMac::~NotificationUIManagerMac() {
79 [notification_center_ setDelegate:nil];
80
81 // TODO(miguelg) lift this restriction if possible.
82 [notification_center_ removeAllDeliveredNotifications];
83 }
84
85 void NotificationUIManagerMac::Display(const std::string& notification_id,
86 const std::string& profile_id,
87 bool incognito,
88 const Notification& notification) {
89 base::scoped_nsobject<NSUserNotification> toast(
90 [[NSUserNotification alloc] init]);
91 [toast setTitle:base::SysUTF16ToNSString(notification.title())];
92 [toast setSubtitle:base::SysUTF16ToNSString(notification.message())];
93
94 // TODO(miguelg): try to elide the origin perhaps See NSString
95 // stringWithFormat. It seems that the informativeText font is constant.
96 NSString* informative_text =
97 notification.context_message().empty()
98 ? base::SysUTF8ToNSString(notification.origin_url().spec())
99 : base::SysUTF16ToNSString(notification.context_message());
100 [toast setInformativeText:informative_text];
101
102 // Some functionality requires private APIs
103 // Icon
104 if ([toast respondsToSelector:@selector(_identityImage)] &&
105 !notification.icon().IsEmpty()) {
106 [toast setValue:notification.icon().ToNSImage() forKey:@"_identityImage"];
107 [toast setValue:@NO forKey:@"_identityImageHasBorder"];
108 }
109
110 // Buttons
111 if ([toast respondsToSelector:@selector(_showsButtons)]) {
112 [toast setValue:@YES forKey:@"_showsButtons"];
113 // A default close button label is provided by the platform but we
114 // explicitly override it in case the user decides to not
115 // use the OS language in Chrome.
116 [toast setOtherButtonTitle:l10n_util::GetNSString(
117 IDS_NOTIFICATION_BUTTON_CLOSE)];
118
119 // Display the Settings button as the action button if there either are no
120 // developer-provided action buttons, or the alternate action menu is not
121 // available on this Mac version. This avoids needlessly showing the menu.
122 if (notification.buttons().empty() ||
123 ![toast respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]) {
124 [toast setActionButtonTitle:l10n_util::GetNSString(
125 IDS_NOTIFICATION_BUTTON_SETTINGS)];
126 } else {
127 // Otherwise show the alternate menu, then show the developer actions and
128 // finally the settings one.
129 DCHECK(
130 [toast respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]);
131 DCHECK(
132 [toast respondsToSelector:@selector(_alternateActionButtonTitles)]);
133
134 [toast setActionButtonTitle:l10n_util::GetNSString(
135 IDS_NOTIFICATION_BUTTON_OPTIONS)];
136 [toast setValue:@YES
137 forKey:@"_alwaysShowAlternateActionMenu"];
138
139 NSMutableArray* buttons = [NSMutableArray arrayWithCapacity:3];
140 for (const auto& action : notification.buttons())
141 [buttons addObject:base::SysUTF16ToNSString(action.title)];
142 [buttons
143 addObject:l10n_util::GetNSString(IDS_NOTIFICATION_BUTTON_SETTINGS)];
144
145 [toast setValue:buttons forKey:@"_alternateActionButtonTitles"];
146 }
147 }
148
149 // Tag
150 if ([toast respondsToSelector:@selector(setIdentifier:)] &&
151 !notification.tag().empty()) {
152 [toast setValue:base::SysUTF8ToNSString(notification.tag())
153 forKey:@"identifier"];
154
155 // If renotify is needed, delete the notification with the same tag
156 // from the notification center before displaying this one.
157 if (notification.renotify()) {
158 NSUserNotificationCenter* notification_center =
159 [NSUserNotificationCenter defaultUserNotificationCenter];
160 for (NSUserNotification* existing_notification in
161 [notification_center deliveredNotifications]) {
162 NSString* identifier =
163 [existing_notification valueForKey:@"identifier"];
164 if ([identifier isEqual:base::SysUTF8ToNSString(notification.tag())]) {
165 [notification_center
166 removeDeliveredNotification:existing_notification];
167 break;
168 }
169 }
170 }
171 }
172
173 toast.get().userInfo = @{
174 kNotificationOriginKey :
175 base::SysUTF8ToNSString(notification.origin_url().spec()),
176 kNotificationPersistentIdKey : base::SysUTF8ToNSString(notification_id),
177 kNotificationProfilePersistentIdKey : base::SysUTF8ToNSString(profile_id),
178 kNotificationIncognitoKey : [NSNumber numberWithBool:incognito]
179 };
180
181 [notification_center_ deliverNotification:toast];
182 }
183
184 void NotificationUIManagerMac::Close(const std::string& profile_id,
185 const std::string& notification_id) {
186 NSString* candidate_id = base::SysUTF8ToNSString(notification_id);
187
188 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
189 for (NSUserNotification* toast in
190 [notification_center_ deliveredNotifications]) {
191 NSString* toast_id =
192 [toast.userInfo objectForKey:kNotificationPersistentIdKey];
193
194 NSString* persistent_profile_id =
195 [toast.userInfo objectForKey:kNotificationProfilePersistentIdKey];
196
197 if (toast_id == candidate_id &&
198 persistent_profile_id == current_profile_id) {
199 [notification_center_ removeDeliveredNotification:toast];
200 }
201 }
202 }
203
204 bool NotificationUIManagerMac::GetDisplayed(
205 const std::string& profile_id,
206 bool incognito,
207 std::set<std::string>* notifications) const {
208 DCHECK(notifications);
209 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
210 for (NSUserNotification* toast in
211 [notification_center_ deliveredNotifications]) {
212 NSString* toast_profile_id =
213 [toast.userInfo objectForKey:kNotificationProfilePersistentIdKey];
214 if (toast_profile_id == current_profile_id) {
215 notifications->insert(base::SysNSStringToUTF8(
216 [toast.userInfo objectForKey:kNotificationPersistentIdKey]));
217 }
218 }
219 return true;
220 }
221
222 bool NotificationUIManagerMac::SupportsNotificationCenter() const {
223 return true;
224 }
225
226 // /////////////////////////////////////////////////////////////////////////////
227
228 @implementation NotificationCenterDelegate
229 - (void)userNotificationCenter:(NSUserNotificationCenter*)center
230 didActivateNotification:(NSUserNotification*)notification {
231 std::string notificationOrigin = base::SysNSStringToUTF8(
232 [notification.userInfo objectForKey:kNotificationOriginKey]);
233 NSNumber* persistentNotificationId =
234 [notification.userInfo objectForKey:kNotificationPersistentIdKey];
235 NSString* persistentProfileId =
236 [notification.userInfo objectForKey:kNotificationProfilePersistentIdKey];
237 NSNumber* isIncognito =
238 [notification.userInfo objectForKey:kNotificationIncognitoKey];
239
240 GURL origin(notificationOrigin);
241
242 // Initialize operation and button index for the case where the
243 // notification itself was clicked.
244 PlatformNotificationServiceImpl::NotificationOperation operation =
245 PlatformNotificationServiceImpl::NOTIFICATION_CLICK;
246 int buttonIndex = -1;
247
248 // Determine whether the user clicked on a button, and if they did, whether it
249 // was a developer-provided button or the mandatory Settings button.
250 if (notification.activationType ==
251 NSUserNotificationActivationTypeActionButtonClicked) {
252 NSArray* alternateButtons = @[];
253 if ([notification
254 respondsToSelector:@selector(_alternateActionButtonTitles)]) {
255 alternateButtons =
256 [notification valueForKey:@"_alternateActionButtonTitles"];
257 }
258
259 bool multipleButtons = (alternateButtons.count > 0);
260
261 // No developer actions, just the settings button.
262 if (!multipleButtons) {
263 operation = PlatformNotificationServiceImpl::NOTIFICATION_SETTINGS;
264 buttonIndex = -1;
265 } else {
266 // 0 based array containing.
267 // Button 1
268 // Button 2 (optional)
269 // Settings
270 NSNumber* actionIndex =
271 [notification valueForKey:@"_alternateActionIndex"];
272 operation = (actionIndex.unsignedLongValue == alternateButtons.count - 1)
273 ? PlatformNotificationServiceImpl::NOTIFICATION_SETTINGS
274 : PlatformNotificationServiceImpl::NOTIFICATION_CLICK;
275 buttonIndex =
276 (actionIndex.unsignedLongValue == alternateButtons.count - 1)
277 ? -1
278 : actionIndex.intValue;
279 }
280 }
281
282 PlatformNotificationServiceImpl::GetInstance()
283 ->ProcessPersistentNotificationOperation(
284 operation, base::SysNSStringToUTF8(persistentProfileId),
285 [isIncognito boolValue], origin,
286 persistentNotificationId.longLongValue, buttonIndex);
287 }
288
289 - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
290 shouldPresentNotification:(NSUserNotification*)nsNotification {
291 // Always display notifications, regardless of whether the app is foreground.
292 return YES;
293 }
294
295 @end
OLDNEW
« no previous file with comments | « chrome/browser/notifications/notification_ui_manager_mac.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698