OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |