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

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

Issue 2093953002: Introduce a new API to handle native notification clicks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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 2015 The Chromium Authors. All rights reserved. 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 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/notification_platform_bridge_mac.h" 5 #include "chrome/browser/notifications/notification_platform_bridge_mac.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
10 #include "base/mac/mac_util.h" 10 #include "base/mac/mac_util.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.h"
13 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/notifications/native_notification_display_service.h"
14 #include "chrome/browser/notifications/notification.h" 15 #include "chrome/browser/notifications/notification.h"
15 #include "chrome/browser/notifications/notification_display_service_factory.h" 16 #include "chrome/browser/notifications/notification_display_service_factory.h"
16 #include "chrome/browser/notifications/persistent_notification_delegate.h" 17 #include "chrome/browser/notifications/persistent_notification_delegate.h"
17 #include "chrome/browser/notifications/platform_notification_service_impl.h" 18 #include "chrome/browser/notifications/platform_notification_service_impl.h"
18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h" 20 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/ui/cocoa/notifications/notification_builder_mac.h" 21 #include "chrome/browser/ui/cocoa/notifications/notification_builder_mac.h"
21 #include "chrome/browser/ui/cocoa/notifications/notification_constants_mac.h" 22 #include "chrome/browser/ui/cocoa/notifications/notification_constants_mac.h"
22 #import "chrome/browser/ui/cocoa/notifications/notification_response_builder_mac .h" 23 #import "chrome/browser/ui/cocoa/notifications/notification_response_builder_mac .h"
23 #include "chrome/grit/generated_resources.h" 24 #include "chrome/grit/generated_resources.h"
(...skipping 15 matching lines...) Expand all
39 // notification#icon in NSUserNotification.contentImage (10.9) 40 // notification#icon in NSUserNotification.contentImage (10.9)
40 // Site settings button is implemented as NSUserNotification's action button 41 // Site settings button is implemented as NSUserNotification's action button
41 // Not possible to implement: 42 // Not possible to implement:
42 // -notification.requireInteraction 43 // -notification.requireInteraction
43 // -The event associated to the close button 44 // -The event associated to the close button
44 45
45 // TODO(miguelg) implement the following features 46 // TODO(miguelg) implement the following features
46 // - Sound names can be implemented by setting soundName in NSUserNotification 47 // - Sound names can be implemented by setting soundName in NSUserNotification
47 // NSUserNotificationDefaultSoundName gives you the platform default. 48 // NSUserNotificationDefaultSoundName gives you the platform default.
48 49
50 namespace {
51 // Callback to run once the profile has been loaded in order to perform a
52 // given |operation| in a notification.
53 void ProfileLoadedCallback(
54 notification_operation_common::NotificationOperation operation,
55 notification_operation_common::NotificationHandlerType notification_type,
56 const std::string& origin,
57 const std::string& notification_id,
58 int action_index,
59 Profile* profile) {
60 if (!profile) {
61 // TODO(miguelg): Add UMA for this condition.
62 // Perhaps propagate this through PersistentNotificationStatus.
63 LOG(WARNING) << "Profile not loaded correctly";
64 return;
65 }
66
67 NotificationDisplayService* display_service =
68 NotificationDisplayServiceFactory::GetForProfile(profile);
69
70 static_cast<NativeNotificationDisplayService*>(display_service)
71 ->ProcessNotificationOperation(operation, notification_type, origin,
72 notification_id, action_index);
73 }
74
75 } // namespace
49 76
50 // static 77 // static
51 NotificationPlatformBridge* NotificationPlatformBridge::Create() { 78 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
52 return new NotificationPlatformBridgeMac( 79 return new NotificationPlatformBridgeMac(
53 [NSUserNotificationCenter defaultUserNotificationCenter]); 80 [NSUserNotificationCenter defaultUserNotificationCenter]);
54 } 81 }
55 82
56 // A Cocoa class that represents the delegate of NSUserNotificationCenter and 83 // A Cocoa class that represents the delegate of NSUserNotificationCenter and
57 // can forward commands to C++. 84 // can forward commands to C++.
58 @interface NotificationCenterDelegate 85 @interface NotificationCenterDelegate
(...skipping 10 matching lines...) Expand all
69 [notification_center_ setDelegate:delegate_.get()]; 96 [notification_center_ setDelegate:delegate_.get()];
70 } 97 }
71 98
72 NotificationPlatformBridgeMac::~NotificationPlatformBridgeMac() { 99 NotificationPlatformBridgeMac::~NotificationPlatformBridgeMac() {
73 [notification_center_ setDelegate:nil]; 100 [notification_center_ setDelegate:nil];
74 101
75 // TODO(miguelg) lift this restriction if possible. 102 // TODO(miguelg) lift this restriction if possible.
76 [notification_center_ removeAllDeliveredNotifications]; 103 [notification_center_ removeAllDeliveredNotifications];
77 } 104 }
78 105
79 void NotificationPlatformBridgeMac::Display(const std::string& notification_id, 106 void NotificationPlatformBridgeMac::Display(
80 const std::string& profile_id, 107 notification_operation_common::NotificationHandlerType notification_type,
81 bool incognito, 108 const std::string& notification_id,
82 const Notification& notification) { 109 const std::string& profile_id,
110 bool incognito,
111 const Notification& notification) {
83 base::scoped_nsobject<NotificationBuilder> builder( 112 base::scoped_nsobject<NotificationBuilder> builder(
84 [[NotificationBuilder alloc] init]); 113 [[NotificationBuilder alloc] init]);
85 114
86 [builder setTitle:base::SysUTF16ToNSString(notification.title())]; 115 [builder setTitle:base::SysUTF16ToNSString(notification.title())];
87 [builder setContextMessage:base::SysUTF16ToNSString(notification.message())]; 116 [builder setContextMessage:base::SysUTF16ToNSString(notification.message())];
88 117
89 base::string16 subtitle = 118 base::string16 subtitle =
90 notification.context_message().empty() 119 notification.context_message().empty()
91 ? url_formatter::FormatOriginForSecurityDisplay( 120 ? url_formatter::FormatOriginForSecurityDisplay(
92 url::Origin(notification.origin_url()), 121 url::Origin(notification.origin_url()),
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 break; 157 break;
129 } 158 }
130 } 159 }
131 } 160 }
132 } 161 }
133 162
134 [builder setOrigin:base::SysUTF8ToNSString(notification.origin_url().spec())]; 163 [builder setOrigin:base::SysUTF8ToNSString(notification.origin_url().spec())];
135 [builder setNotificationId:base::SysUTF8ToNSString(notification_id)]; 164 [builder setNotificationId:base::SysUTF8ToNSString(notification_id)];
136 [builder setProfileId:base::SysUTF8ToNSString(profile_id)]; 165 [builder setProfileId:base::SysUTF8ToNSString(profile_id)];
137 [builder setIncognito:incognito]; 166 [builder setIncognito:incognito];
167 [builder setNotificationType:[NSNumber numberWithInteger:notification_type]];
138 168
139 NSUserNotification* toast = [builder buildUserNotification]; 169 NSUserNotification* toast = [builder buildUserNotification];
140 [notification_center_ deliverNotification:toast]; 170 [notification_center_ deliverNotification:toast];
141 } 171 }
142 172
143 void NotificationPlatformBridgeMac::Close(const std::string& profile_id, 173 void NotificationPlatformBridgeMac::Close(const std::string& profile_id,
144 const std::string& notification_id) { 174 const std::string& notification_id) {
145 NSString* candidate_id = base::SysUTF8ToNSString(notification_id); 175 NSString* candidate_id = base::SysUTF8ToNSString(notification_id);
146 176
147 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id); 177 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
148 for (NSUserNotification* toast in 178 for (NSUserNotification* toast in
149 [notification_center_ deliveredNotifications]) { 179 [notification_center_ deliveredNotifications]) {
150 NSString* toast_id = 180 NSString* toast_id =
151 [toast.userInfo objectForKey:notification_constants::kNotificationId]; 181 [toast.userInfo objectForKey:notification_constants::kNotificationId];
152
153 NSString* persistent_profile_id = [toast.userInfo 182 NSString* persistent_profile_id = [toast.userInfo
154 objectForKey:notification_constants::kNotificationProfileId]; 183 objectForKey:notification_constants::kNotificationProfileId];
155 184
156 if (toast_id == candidate_id && 185 if ([toast_id isEqualToString:candidate_id] &&
157 persistent_profile_id == current_profile_id) { 186 [persistent_profile_id isEqualToString:current_profile_id]) {
158 [notification_center_ removeDeliveredNotification:toast]; 187 [notification_center_ removeDeliveredNotification:toast];
159 } 188 }
160 } 189 }
161 } 190 }
162 191
163 bool NotificationPlatformBridgeMac::GetDisplayed( 192 bool NotificationPlatformBridgeMac::GetDisplayed(
164 const std::string& profile_id, 193 const std::string& profile_id,
165 bool incognito, 194 bool incognito,
166 std::set<std::string>* notifications) const { 195 std::set<std::string>* notifications) const {
167 DCHECK(notifications); 196 DCHECK(notifications);
168 197
169 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id); 198 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
170 for (NSUserNotification* toast in 199 for (NSUserNotification* toast in
171 [notification_center_ deliveredNotifications]) { 200 [notification_center_ deliveredNotifications]) {
172 NSString* toast_profile_id = [toast.userInfo 201 NSString* toast_profile_id = [toast.userInfo
173 objectForKey:notification_constants::kNotificationProfileId]; 202 objectForKey:notification_constants::kNotificationProfileId];
174 if (toast_profile_id == current_profile_id) { 203 if (toast_profile_id == current_profile_id) {
175 notifications->insert(base::SysNSStringToUTF8([toast.userInfo 204 notifications->insert(base::SysNSStringToUTF8([toast.userInfo
176 objectForKey:notification_constants::kNotificationId])); 205 objectForKey:notification_constants::kNotificationId]));
177 } 206 }
178 } 207 }
179 return true; 208 return true;
180 } 209 }
181 210
182 bool NotificationPlatformBridgeMac::SupportsNotificationCenter() const { 211 bool NotificationPlatformBridgeMac::SupportsNotificationCenter() const {
183 return true; 212 return true;
184 } 213 }
185 214
215 // static
216 bool NotificationPlatformBridgeMac::VerifyNotificationData(
217 NSDictionary* response) {
218 NSNumber* buttonIndex =
219 [response objectForKey:notification_constants::kNotificationButtonIndex];
220 NSNumber* operation =
221 [response objectForKey:notification_constants::kNotificationOperation];
222
223 std::string notificationOrigin = base::SysNSStringToUTF8(
224 [response objectForKey:notification_constants::kNotificationOrigin]);
225 NSString* notificationId =
226 [response objectForKey:notification_constants::kNotificationId];
227 NSString* profileId =
228 [response objectForKey:notification_constants::kNotificationProfileId];
229 NSNumber* notificationType =
230 [response objectForKey:notification_constants::kNotificationType];
231
232 if (buttonIndex.intValue < -1 ||
233 buttonIndex.intValue >=
234 static_cast<int>(blink::kWebNotificationMaxActions)) {
235 LOG(ERROR) << "Invalid number of buttons supplied " << buttonIndex.intValue;
236 return false;
237 }
238
239 if (operation.unsignedIntValue >
240 notification_operation_common::NOTIFICATION_OPERATION_MAX) {
241 LOG(ERROR) << operation.unsignedIntValue
242 << " Does not correspond to a valid operation.";
243 return false;
244 }
245
246 if (notificationId.length <= 0) {
247 LOG(ERROR) << "NotificationId not provided";
248 return false;
249 }
250
251 if (profileId.length <= 0) {
252 LOG(ERROR) << "ProfileId not provided";
253 return false;
254 }
255
256 if (notificationType.unsignedIntValue >
257 notification_operation_common::NOTIFICATION_HANDLER_TYPE_LAST) {
258 LOG(ERROR) << notificationType.unsignedIntValue
259 << " Does not correspond to a valid operation.";
260 return false;
261 }
262
263 return true;
264 }
265
186 // ///////////////////////////////////////////////////////////////////////////// 266 // /////////////////////////////////////////////////////////////////////////////
187 267
188 @implementation NotificationCenterDelegate 268 @implementation NotificationCenterDelegate
189 - (void)userNotificationCenter:(NSUserNotificationCenter*)center 269 - (void)userNotificationCenter:(NSUserNotificationCenter*)center
190 didActivateNotification:(NSUserNotification*)notification { 270 didActivateNotification:(NSUserNotification*)notification {
191 NSDictionary* response = 271 NSDictionary* response =
192 [NotificationResponseBuilder buildDictionary:notification]; 272 [NotificationResponseBuilder buildDictionary:notification];
193 273
274 if (!NotificationPlatformBridgeMac::VerifyNotificationData(response))
275 return;
276
194 NSNumber* buttonIndex = 277 NSNumber* buttonIndex =
195 [response objectForKey:notification_constants::kNotificationButtonIndex]; 278 [response objectForKey:notification_constants::kNotificationButtonIndex];
196 NSNumber* operation = 279 NSNumber* operation =
197 [response objectForKey:notification_constants::kNotificationOperation]; 280 [response objectForKey:notification_constants::kNotificationOperation];
198 281
199 std::string notificationOrigin = base::SysNSStringToUTF8( 282 std::string notificationOrigin = base::SysNSStringToUTF8(
200 [response objectForKey:notification_constants::kNotificationOrigin]); 283 [response objectForKey:notification_constants::kNotificationOrigin]);
201 NSString* notificationId = [notification.userInfo 284 NSString* notificationId =
202 objectForKey:notification_constants::kNotificationId]; 285 [response objectForKey:notification_constants::kNotificationId];
203 std::string persistentNotificationId = 286 std::string persistentNotificationId =
204 base::SysNSStringToUTF8(notificationId); 287 base::SysNSStringToUTF8(notificationId);
205 int64_t persistentId;
206 if (!base::StringToInt64(persistentNotificationId, &persistentId)) {
207 LOG(ERROR) << "Unable to convert notification ID: "
208 << persistentNotificationId << " to integer.";
209 return;
210 }
211 std::string profileId = base::SysNSStringToUTF8( 288 std::string profileId = base::SysNSStringToUTF8(
212 [response objectForKey:notification_constants::kNotificationProfileId]); 289 [response objectForKey:notification_constants::kNotificationProfileId]);
213 NSNumber* isIncognito = 290 NSNumber* isIncognito =
214 [response objectForKey:notification_constants::kNotificationIncognito]; 291 [response objectForKey:notification_constants::kNotificationIncognito];
292 NSNumber* notificationType =
293 [response objectForKey:notification_constants::kNotificationType];
215 294
216 GURL origin(notificationOrigin); 295 ProfileManager* profileManager = g_browser_process->profile_manager();
296 DCHECK(profileManager);
217 297
218 PlatformNotificationServiceImpl::GetInstance() 298 profileManager->LoadProfile(
219 ->ProcessPersistentNotificationOperation( 299 profileId, [isIncognito boolValue],
220 static_cast<PlatformNotificationServiceImpl::NotificationOperation>( 300 base::Bind(
221 operation.intValue), 301 &ProfileLoadedCallback,
222 profileId, [isIncognito boolValue], origin, persistentId, 302 static_cast<notification_operation_common::NotificationOperation>(
223 buttonIndex.intValue); 303 operation.unsignedIntValue),
304 static_cast<notification_operation_common::NotificationHandlerType>(
305 notificationType.unsignedIntValue),
306 notificationOrigin, persistentNotificationId, buttonIndex.intValue));
224 } 307 }
225 308
226 - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center 309 - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
227 shouldPresentNotification:(NSUserNotification*)nsNotification { 310 shouldPresentNotification:(NSUserNotification*)nsNotification {
228 // Always display notifications, regardless of whether the app is foreground. 311 // Always display notifications, regardless of whether the app is foreground.
229 return YES; 312 return YES;
230 } 313 }
231 314
232 @end 315 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698