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 08fefce8bcc7e130114c3ca7f3e03986004b5f58..a1ce41b2846c018e31182d68784f655180b7e40e 100644 |
| --- a/chrome/browser/notifications/notification_platform_bridge_mac.mm |
| +++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm |
| @@ -6,8 +6,12 @@ |
| #include <utility> |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/mac/bundle_locations.h" |
| #include "base/mac/foundation_util.h" |
| #include "base/mac/mac_util.h" |
| +#include "base/mac/scoped_nsobject.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "chrome/browser/browser_process.h" |
| @@ -20,10 +24,14 @@ |
| #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/features.h" |
| +#include "chrome/grit/generated_resources.h" |
| #include "components/url_formatter/elide_url.h" |
| #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h" |
| +#include "ui/base/l10n/l10n_util_mac.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| @@ -71,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(); |
| + DCHECK(profileManager); |
| + |
| + profileManager->LoadProfile( |
| + profile_id, incognito, base::Bind(&ProfileLoadedCallback, operation, type, |
| + origin, notification_id, button_index)); |
| +} |
| + |
| } // namespace |
| // static |
| @@ -86,19 +111,30 @@ NotificationPlatformBridge* NotificationPlatformBridge::Create() { |
| } |
| @end |
| +// Interface to communicate with the Alert XPC service. |
| +@interface NotificationRemoteDispatcher : NSObject |
| + |
| +- (instancetype)init; |
|
Robert Sesek
2016/09/12 15:33:47
You don't have to re-declare init if there's no ar
Miguel Garcia
2016/09/12 16:57:59
Done.
|
| +- (void)dispatchNotification:(NSDictionary*)data; |
| + |
| +@end |
| + |
| // ///////////////////////////////////////////////////////////////////////////// |
| 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()]; |
| } |
| NotificationPlatformBridgeMac::~NotificationPlatformBridgeMac() { |
| [notification_center_ setDelegate:nil]; |
| - // TODO(miguelg) lift this restriction if possible. |
| + // TODO(miguelg) remove only alerts shown by the XPC service. |
| + // TODO(miguelg) do not remove banners if possible. |
| [notification_center_ removeAllDeliveredNotifications]; |
| } |
| @@ -139,6 +175,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 |
| @@ -166,8 +203,18 @@ void NotificationPlatformBridgeMac::Display( |
| [builder setIncognito:incognito]; |
| [builder setNotificationType:[NSNumber numberWithInteger:notification_type]]; |
| +#if BUILDFLAG(ENABLE_XPC_NOTIFICATIONS) |
| + if (notification.never_timeout()) { |
|
Robert Sesek
2016/09/12 15:33:47
This could use some commentary.
Miguel Garcia
2016/09/12 16:57:59
Done.
|
| + NSDictionary* dict = [builder buildDictionary]; |
| + [notification_remote_dispatcher_ dispatchNotification:dict]; |
| + } else { |
| + NSUserNotification* toast = [builder buildUserNotification]; |
| + [notification_center_ deliverNotification:toast]; |
| + } |
| +#else |
| NSUserNotification* toast = [builder buildUserNotification]; |
| [notification_center_ deliverNotification:toast]; |
| +#endif // ENABLE_XPC_NOTIFICATIONS |
| } |
| void NotificationPlatformBridgeMac::Close(const std::string& profile_id, |
| @@ -214,6 +261,39 @@ bool NotificationPlatformBridgeMac::SupportsNotificationCenter() const { |
| } |
| // static |
| +void NotificationPlatformBridgeMac::ProcessNotificationResponse( |
| + NSDictionary* response) { |
| + if (!NotificationPlatformBridgeMac::VerifyNotificationData(response)) |
| + return; |
| + |
| + NSNumber* buttonIndex = |
|
Robert Sesek
2016/09/12 15:33:47
under_score all these names
Miguel Garcia
2016/09/12 16:57:59
Done.
|
| + [response objectForKey:notification_constants::kNotificationButtonIndex]; |
| + NSNumber* operation = |
| + [response objectForKey:notification_constants::kNotificationOperation]; |
| + |
| + std::string notificationOrigin = base::SysNSStringToUTF8( |
| + [response objectForKey:notification_constants::kNotificationOrigin]); |
| + std::string notificationId = base::SysNSStringToUTF8( |
| + [response objectForKey:notification_constants::kNotificationId]); |
| + std::string profileId = base::SysNSStringToUTF8( |
| + [response objectForKey:notification_constants::kNotificationProfileId]); |
| + NSNumber* isIncognito = |
| + [response objectForKey:notification_constants::kNotificationIncognito]; |
| + NSNumber* notificationType = |
| + [response 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 |
| @@ -282,44 +362,13 @@ bool NotificationPlatformBridgeMac::VerifyNotificationData( |
| } |
| // ///////////////////////////////////////////////////////////////////////////// |
| - |
| @implementation NotificationCenterDelegate |
| - (void)userNotificationCenter:(NSUserNotificationCenter*)center |
| didActivateNotification:(NSUserNotification*)notification { |
| - NSDictionary* response = |
| + NSDictionary* notification_response = |
|
Robert Sesek
2016/09/12 15:33:47
but camelCase here ;-)
Miguel Garcia
2016/09/12 16:57:59
Done.
|
| [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( |
| + notification_response); |
| } |
| - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center |
| @@ -329,3 +378,54 @@ bool NotificationPlatformBridgeMac::VerifyNotificationData( |
| } |
| @end |
| + |
| +@implementation NotificationRemoteDispatcher { |
| + // The connection to the XPC server in charge of delivering alerts. |
| + base::scoped_nsobject<NSXPCConnection> xpcConnection_; |
| +} |
| + |
| +- (instancetype)init { |
| + if ((self = [super init])) { |
| +#if BUILDFLAG(ENABLE_XPC_NOTIFICATIONS) |
|
Robert Sesek
2016/09/12 15:33:47
Why not move this #if to be around the instantiati
Miguel Garcia
2016/09/12 16:57:59
I shied away from that because the instantiation w
|
| + xpcConnection_.reset([[NSXPCConnection alloc] |
| + initWithServiceName: |
| + [NSString |
| + stringWithFormat:notification_constants::kAlertXPCServiceName, |
| + [base::mac::OuterBundle() bundleIdentifier]]]); |
| + xpcConnection_.get().remoteObjectInterface = |
| + [NSXPCInterface interfaceWithProtocol:@protocol(NotificationDelivery)]; |
| + |
| + xpcConnection_.get().interruptionHandler = ^{ |
| + LOG(WARNING) << "connection interrupted: interruptionHandler: "; |
| + // 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_.get().invalidationHandler = ^{ |
| + LOG(WARNING) << "connection invalidationHandler received"; |
| + // 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_.get().exportedInterface = |
| + [NSXPCInterface interfaceWithProtocol:@protocol(NotificationReply)]; |
| + xpcConnection_.get().exportedObject = self; |
| + [xpcConnection_ resume]; |
| +#endif // ENABLE_XPC_NOTIFICATIONS |
| + } |
| + |
| + return self; |
| +} |
| + |
| +- (void)dispatchNotification:(NSDictionary*)data { |
| + [[xpcConnection_ remoteObjectProxy] deliverNotification:data]; |
| +} |
| + |
| +// NotificationReply implementation |
| +- (void)notificationClick:(NSDictionary*)notificationResponseData { |
| + NotificationPlatformBridgeMac::ProcessNotificationResponse( |
| + notificationResponseData); |
| +} |
| + |
| +@end |