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