| 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 |