Chromium Code Reviews| Index: chrome/browser/notifications/notification_platform_bridge_mac.mm |
| diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm |
| index e96756be9d07f2003944297157bc9d80f3a2cb7c..273a5f3a14ee411709f6dd57cca3a72723e89d00 100644 |
| --- a/chrome/browser/notifications/notification_platform_bridge_mac.mm |
| +++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm |
| @@ -6,6 +6,10 @@ |
| #include <utility> |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/command_line.h" |
| +#include "base/mac/bundle_locations.h" |
| #include "base/mac/foundation_util.h" |
| #include "base/mac/mac_util.h" |
| #include "base/strings/string_number_conversions.h" |
| @@ -20,8 +24,10 @@ |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/cocoa/notifications/notification_builder_mac.h" |
| +#import "chrome/browser/ui/cocoa/notifications/notification_delivery.h" |
| #include "chrome/browser/ui/cocoa/notifications/notification_constants_mac.h" |
| #import "chrome/browser/ui/cocoa/notifications/notification_response_builder_mac.h" |
| +#include "chrome/common/chrome_switches.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "components/url_formatter/elide_url.h" |
| #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h" |
| @@ -73,6 +79,23 @@ void ProfileLoadedCallback(NotificationCommon::Operation operation, |
| notification_id, action_index); |
| } |
| +// Loads the profile and process the Notification response |
| +void DoProcessNotificationResponse(NotificationCommon::Operation operation, |
| + NotificationCommon::Type type, |
| + const std::string& profile_id, |
| + bool incognito, |
| + const std::string& origin, |
| + const std::string& notification_id, |
| + int32_t button_index) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + ProfileManager* profileManager = g_browser_process->profile_manager(); |
|
Peter Beverloo
2016/07/19 17:31:40
nit: profile_manager
|
| + DCHECK(profileManager); |
| + |
| + profileManager->LoadProfile( |
| + profile_id, incognito, base::Bind(&ProfileLoadedCallback, operation, type, |
| + origin, notification_id, button_index)); |
| +} |
| + |
| } // namespace |
| // static |
| @@ -93,7 +116,9 @@ NotificationPlatformBridge* NotificationPlatformBridge::Create() { |
| NotificationPlatformBridgeMac::NotificationPlatformBridgeMac( |
| NSUserNotificationCenter* notification_center) |
| : delegate_([NotificationCenterDelegate alloc]), |
| - notification_center_(notification_center) { |
| + notification_center_(notification_center), |
| + notification_remote_dispatcher_( |
| + [[NotificationRemoteDispatcher alloc] init]) { |
| [notification_center_ setDelegate:delegate_.get()]; |
| } |
| @@ -101,6 +126,8 @@ NotificationPlatformBridgeMac::~NotificationPlatformBridgeMac() { |
| [notification_center_ setDelegate:nil]; |
| // TODO(miguelg) lift this restriction if possible. |
| + // But make sure the ones shown by the XPC service are actually |
|
Peter Beverloo
2016/07/19 17:31:40
Is this a continuation from the TODO on line 128?
|
| + // removed. |
| [notification_center_ removeAllDeliveredNotifications]; |
| } |
| @@ -141,6 +168,7 @@ void NotificationPlatformBridgeMac::Display( |
| // Tag |
| if (!notification.tag().empty()) { |
| [builder setTag:base::SysUTF8ToNSString(notification.tag())]; |
| + |
| // If renotify is needed, delete the notification with the same tag |
| // from the notification center before displaying this one. |
| // TODO(miguelg): This will need to work for alerts as well via XPC |
| @@ -167,9 +195,15 @@ void NotificationPlatformBridgeMac::Display( |
| [builder setProfileId:base::SysUTF8ToNSString(profile_id)]; |
| [builder setIncognito:incognito]; |
| [builder setNotificationType:[NSNumber numberWithInteger:notification_type]]; |
| - |
| - NSUserNotification* toast = [builder buildUserNotification]; |
| - [notification_center_ deliverNotification:toast]; |
| + if (notification.never_timeout() && |
|
Peter Beverloo
2016/07/19 17:31:40
nit:
// TODO(miguelg): Remove the command line
|
| + base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableNativeAlerts)) { |
| + NSDictionary* dict = [builder buildDictionary]; |
| + [notification_remote_dispatcher_ dispatchNotification:dict]; |
| + } else { |
| + NSUserNotification* toast = [builder buildUserNotification]; |
| + [notification_center_ deliverNotification:toast]; |
| + } |
| } |
| void NotificationPlatformBridgeMac::Close(const std::string& profile_id, |
| @@ -216,6 +250,41 @@ bool NotificationPlatformBridgeMac::SupportsNotificationCenter() const { |
| } |
| // static |
| +void NotificationPlatformBridgeMac::ProcessNotificationResponse( |
| + NSDictionary* notificationResponseData) { |
| + if (!NotificationPlatformBridgeMac::VerifyNotificationData( |
| + notificationResponseData)) |
|
Peter Beverloo
2016/07/19 17:31:40
nit: brackets around the return (this now is a mul
|
| + return; |
| + |
| + NSNumber* buttonIndex = [notificationResponseData |
| + objectForKey:notification_constants::kNotificationButtonIndex]; |
| + NSNumber* operation = [notificationResponseData |
| + objectForKey:notification_constants::kNotificationOperation]; |
| + |
| + std::string notificationOrigin = |
| + base::SysNSStringToUTF8([notificationResponseData |
| + objectForKey:notification_constants::kNotificationOrigin]); |
| + std::string notificationId = base::SysNSStringToUTF8([notificationResponseData |
| + objectForKey:notification_constants::kNotificationId]); |
| + std::string profileId = base::SysNSStringToUTF8([notificationResponseData |
| + objectForKey:notification_constants::kNotificationProfileId]); |
| + NSNumber* isIncognito = [notificationResponseData |
| + objectForKey:notification_constants::kNotificationIncognito]; |
| + NSNumber* notificationType = [notificationResponseData |
| + objectForKey:notification_constants::kNotificationType]; |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(DoProcessNotificationResponse, |
| + static_cast<NotificationCommon::Operation>( |
| + operation.unsignedIntValue), |
| + static_cast<NotificationCommon::Type>( |
| + notificationType.unsignedIntValue), |
| + profileId, [isIncognito boolValue], notificationOrigin, |
| + notificationId, buttonIndex.intValue)); |
| +} |
| + |
| +// static |
| bool NotificationPlatformBridgeMac::VerifyNotificationData( |
| NSDictionary* response) { |
| if (![response |
| @@ -288,40 +357,10 @@ bool NotificationPlatformBridgeMac::VerifyNotificationData( |
| @implementation NotificationCenterDelegate |
| - (void)userNotificationCenter:(NSUserNotificationCenter*)center |
| didActivateNotification:(NSUserNotification*)notification { |
| - NSDictionary* response = |
| + NSDictionary* notificationResponseData = |
| [NotificationResponseBuilder buildDictionary:notification]; |
| - if (!NotificationPlatformBridgeMac::VerifyNotificationData(response)) |
| - return; |
| - |
| - NSNumber* buttonIndex = |
| - [response objectForKey:notification_constants::kNotificationButtonIndex]; |
| - NSNumber* operation = |
| - [response objectForKey:notification_constants::kNotificationOperation]; |
| - |
| - std::string notificationOrigin = base::SysNSStringToUTF8( |
| - [response objectForKey:notification_constants::kNotificationOrigin]); |
| - NSString* notificationId = |
| - [response objectForKey:notification_constants::kNotificationId]; |
| - std::string persistentNotificationId = |
| - base::SysNSStringToUTF8(notificationId); |
| - std::string profileId = base::SysNSStringToUTF8( |
| - [response objectForKey:notification_constants::kNotificationProfileId]); |
| - NSNumber* isIncognito = |
| - [response objectForKey:notification_constants::kNotificationIncognito]; |
| - NSNumber* notificationType = |
| - [response objectForKey:notification_constants::kNotificationType]; |
| - |
| - ProfileManager* profileManager = g_browser_process->profile_manager(); |
| - DCHECK(profileManager); |
| - |
| - profileManager->LoadProfile( |
| - profileId, [isIncognito boolValue], |
| - base::Bind( |
| - &ProfileLoadedCallback, static_cast<NotificationCommon::Operation>( |
| - operation.unsignedIntValue), |
| - static_cast<NotificationCommon::Type>( |
| - notificationType.unsignedIntValue), |
| - notificationOrigin, persistentNotificationId, buttonIndex.intValue)); |
| + NotificationPlatformBridgeMac::ProcessNotificationResponse( |
| + notificationResponseData); |
| } |
| - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center |
| @@ -331,3 +370,51 @@ bool NotificationPlatformBridgeMac::VerifyNotificationData( |
| } |
| @end |
| + |
| +@implementation NotificationRemoteDispatcher |
| + |
| +@synthesize xpcConnection = _xpcConnection; |
| + |
| +- (instancetype)init { |
| + if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableNativeAlerts)) { |
| + _xpcConnection = [[NSXPCConnection alloc] |
| + initWithServiceName: |
| + [NSString |
| + stringWithFormat:notification_constants::kAlertXPCServiceName, |
| + [base::mac::OuterBundle() bundleIdentifier]]]; |
| + _xpcConnection.remoteObjectInterface = |
| + [NSXPCInterface interfaceWithProtocol:@protocol(NotificationDelivery)]; |
| + _xpcConnection.interruptionHandler = ^{ |
| + NSLog(@"connection interrupted: interruptionHandler: %@", _xpcConnection); |
| + // TODO(miguelg): perhaps add some UMA here. |
| + // We will be getting this handler both when the XPC server crashes or |
| + // when it decides to close the connection. |
| + }; |
| + _xpcConnection.invalidationHandler = ^{ |
| + NSLog(@"conn invalidationHandler %@", _xpcConnection); |
| + // This means that the connection should be recreated if it needs |
| + // to be used again. It should not really happen. |
| + DCHECK(false) << "XPC Connection invalidated"; |
| + }; |
| + |
| + _xpcConnection.exportedInterface = |
| + [NSXPCInterface interfaceWithProtocol:@protocol(NotificationReply)]; |
| + _xpcConnection.exportedObject = self; |
| + [_xpcConnection resume]; |
| + } |
| + |
| + return self; |
| +} |
| + |
| +- (void)dispatchNotification:(NSDictionary*)data { |
| + [[_xpcConnection remoteObjectProxy] deliverNotification:data]; |
| +} |
| + |
| +// NotificationReply implementation |
| +- (void)notificationClick:(NSDictionary*)notificationResponseData { |
| + NotificationPlatformBridgeMac::ProcessNotificationResponse( |
| + notificationResponseData); |
| +} |
| + |
| +@end |