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

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

Powered by Google App Engine
This is Rietveld 408576698