Commit c0eba728 authored by Mohamed Adel's avatar Mohamed Adel Committed by Commit Bot

Adds a AlertNSNotificationService subclass

The purpose of this subclass is to move all specific API calls to their
appropriate subclass. This is being done as UNUserNotificationCenter is
going to be added to the XPC service so it needs to be able to support
both.

Bug: 1142497
Change-Id: I123fc0144f507c18ca30ae66c75129ab1410b7a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2498594Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Reviewed-by: default avatarRayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Mohamed Adel <adelm@google.com>
Cr-Commit-Position: refs/heads/master@{#822166}
parent 8a33ab1d
......@@ -457,7 +457,7 @@ getDisplayedAlertsForProfileId:(NSString*)profileId
crash_reporter::GetCrashpadClient().GetHandlerMachPort());
base::scoped_nsobject<CrXPCMachPort> xpcPort(
[[CrXPCMachPort alloc] initWithMachSendRight:std::move(exceptionPort)]);
[proxy setMachExceptionPort:xpcPort];
[proxy setUseUNNotification:NO machExceptionPort:xpcPort];
_setExceptionPort = YES;
}
......
......@@ -15,6 +15,8 @@ mac_app_bundle("alert_notification_xpc_service") {
sources = [
"alert_notification_service.h",
"alert_notification_service.mm",
"alert_nsnotification_service.h",
"alert_nsnotification_service.mm",
"notification_service_delegate.h",
"notification_service_delegate.mm",
"xpc_service_main.mm",
......
......@@ -13,8 +13,10 @@
// Implementation of the NotificationDelivery protocol that can display
// notifications of type alert.
@interface AlertNotificationService : NSObject<NotificationDelivery>
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler;
@interface AlertNotificationService : NSObject <NotificationDelivery>
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler
xpcConnection:(NSXPCConnection*)connection;
@end
#endif // CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_ALERT_NOTIFICATION_SERVICE_H_
......@@ -4,20 +4,15 @@
#import "chrome/browser/ui/cocoa/notifications/alert_notification_service.h"
#include <unistd.h>
#import "base/mac/scoped_nsobject.h"
#include "base/mac/scoped_nsobject.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#import "chrome/browser/ui/cocoa/notifications/notification_builder_mac.h"
#include "chrome/browser/ui/cocoa/notifications/notification_constants_mac.h"
#import "chrome/browser/ui/cocoa/notifications/alert_nsnotification_service.h"
#import "chrome/browser/ui/cocoa/notifications/xpc_transaction_handler.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
#include "third_party/crashpad/crashpad/client/crashpad_info.h"
#include "third_party/crashpad/crashpad/client/simple_string_dictionary.h"
@class NSUserNotificationCenter;
namespace {
crashpad::SimpleStringDictionary* GetCrashpadAnnotations() {
......@@ -33,7 +28,9 @@ crashpad::SimpleStringDictionary* GetCrashpadAnnotations() {
} // namespace
@implementation AlertNotificationService {
XPCTransactionHandler* _transactionHandler;
base::scoped_nsobject<XPCTransactionHandler> _transactionHandler;
base::scoped_nsobject<NSXPCConnection> _connection;
base::scoped_nsobject<NSObject<NotificationDelivery>> _notificationDelivery;
// Ensures that the XPC service has been configured for crash reporting.
// Other messages should not be sent to a new instance of the service
......@@ -43,14 +40,17 @@ crashpad::SimpleStringDictionary* GetCrashpadAnnotations() {
BOOL _didSetExceptionPort;
}
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler {
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler
xpcConnection:(NSXPCConnection*)connection {
if ((self = [super init])) {
_transactionHandler = handler;
_transactionHandler.reset([handler retain]);
_connection.reset([connection retain]);
}
return self;
}
- (void)setMachExceptionPort:(CrXPCMachPort*)port {
- (void)setUseUNNotification:(BOOL)useUNNotification
machExceptionPort:(CrXPCMachPort*)port {
base::mac::ScopedMachSendRight sendRight([port takeRight]);
if (!sendRight.is_valid()) {
NOTREACHED();
......@@ -62,6 +62,11 @@ crashpad::SimpleStringDictionary* GetCrashpadAnnotations() {
return;
}
[_transactionHandler setUseUNNotification:useUNNotification];
_notificationDelivery.reset([[AlertNSNotificationService alloc]
initWithTransactionHandler:_transactionHandler
xpcConnection:_connection]);
crashpad::CrashpadClient client;
_didSetExceptionPort = client.SetHandlerMachPort(std::move(sendRight));
DCHECK(_didSetExceptionPort);
......@@ -73,68 +78,35 @@ crashpad::SimpleStringDictionary* GetCrashpadAnnotations() {
- (void)deliverNotification:(NSDictionary*)notificationData {
DCHECK(_didSetExceptionPort);
DCHECK(_notificationDelivery);
base::scoped_nsobject<NotificationBuilder> builder(
[[NotificationBuilder alloc] initWithDictionary:notificationData]);
NSUserNotification* toast = [builder buildUserNotification];
[[NSUserNotificationCenter defaultUserNotificationCenter]
deliverNotification:toast];
[_transactionHandler openTransactionIfNeeded];
[_notificationDelivery deliverNotification:notificationData];
}
- (void)closeNotificationWithId:(NSString*)notificationId
withProfileId:(NSString*)profileId {
DCHECK(_didSetExceptionPort);
DCHECK(_notificationDelivery);
NSUserNotificationCenter* notificationCenter =
[NSUserNotificationCenter defaultUserNotificationCenter];
for (NSUserNotification* candidate in
[notificationCenter deliveredNotifications]) {
NSString* candidateId = [candidate.userInfo
objectForKey:notification_constants::kNotificationId];
NSString* candidateProfileId = [candidate.userInfo
objectForKey:notification_constants::kNotificationProfileId];
if ([candidateId isEqualToString:notificationId] &&
[profileId isEqualToString:candidateProfileId]) {
[notificationCenter removeDeliveredNotification:candidate];
[_transactionHandler closeTransactionIfNeeded];
break;
}
}
[_notificationDelivery closeNotificationWithId:notificationId
withProfileId:profileId];
}
- (void)closeAllNotifications {
DCHECK(_didSetExceptionPort);
DCHECK(_notificationDelivery);
[[NSUserNotificationCenter defaultUserNotificationCenter]
removeAllDeliveredNotifications];
[_transactionHandler closeTransactionIfNeeded];
[_notificationDelivery closeAllNotifications];
}
- (void)getDisplayedAlertsForProfileId:(NSString*)profileId
andIncognito:(BOOL)incognito
withReply:(void (^)(NSArray*))reply {
NSUserNotificationCenter* notificationCenter =
[NSUserNotificationCenter defaultUserNotificationCenter];
NSMutableArray* notificationIds = [NSMutableArray
arrayWithCapacity:[[notificationCenter deliveredNotifications] count]];
for (NSUserNotification* toast in
[notificationCenter deliveredNotifications]) {
NSString* candidateProfileId = [toast.userInfo
objectForKey:notification_constants::kNotificationProfileId];
BOOL incognitoNotification = [[toast.userInfo
objectForKey:notification_constants::kNotificationIncognito] boolValue];
if ([candidateProfileId isEqualToString:profileId] &&
incognito == incognitoNotification) {
[notificationIds
addObject:[toast.userInfo
objectForKey:notification_constants::kNotificationId]];
}
}
reply(notificationIds);
DCHECK(_notificationDelivery);
[_notificationDelivery getDisplayedAlertsForProfileId:profileId
andIncognito:incognito
withReply:reply];
}
@end
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_ALERT_NSNOTIFICATION_SERVICE_H_
#define CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_ALERT_NSNOTIFICATION_SERVICE_H_
#import <Foundation/Foundation.h>
#import "chrome/browser/ui/cocoa/notifications/notification_delivery.h"
@class XPCTransactionHandler;
// Implementation of the NotificationDelivery protocol that can display
// notifications of type alert. This uses the legacy NSUserNotificationCenter
// API and is meant for use on macOS versions 10.10 - 10.14. Versions 10.14 and
// above are meant to be supported using UNUserNotificationCenter.
@interface AlertNSNotificationService
: NSObject <NotificationDelivery, NSUserNotificationCenterDelegate>
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler
xpcConnection:(NSXPCConnection*)connection;
@end
#endif // CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_ALERT_NSNOTIFICATION_SERVICE_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/notifications/alert_nsnotification_service.h"
#import "base/mac/scoped_nsobject.h"
#include "base/notreached.h"
#import "chrome/browser/ui/cocoa/notifications/notification_builder_mac.h"
#include "chrome/browser/ui/cocoa/notifications/notification_constants_mac.h"
#import "chrome/browser/ui/cocoa/notifications/notification_response_builder_mac.h"
#import "chrome/browser/ui/cocoa/notifications/xpc_transaction_handler.h"
@class NSUserNotificationCenter;
@implementation AlertNSNotificationService {
base::scoped_nsobject<XPCTransactionHandler> _transactionHandler;
base::scoped_nsobject<NSXPCConnection> _connection;
}
- (instancetype)initWithTransactionHandler:(XPCTransactionHandler*)handler
xpcConnection:(NSXPCConnection*)connection {
if ((self = [super init])) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
_transactionHandler.reset([handler retain]);
_connection.reset([connection retain]);
}
return self;
}
- (void)dealloc {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
[super dealloc];
}
- (void)setUseUNNotification:(BOOL)useUNNotification
machExceptionPort:(CrXPCMachPort*)port {
NOTREACHED();
}
- (void)deliverNotification:(NSDictionary*)notificationData {
base::scoped_nsobject<NotificationBuilder> builder(
[[NotificationBuilder alloc] initWithDictionary:notificationData]);
NSUserNotification* toast = [builder buildUserNotification];
[[NSUserNotificationCenter defaultUserNotificationCenter]
deliverNotification:toast];
[_transactionHandler openTransactionIfNeeded];
}
- (void)closeNotificationWithId:(NSString*)notificationId
withProfileId:(NSString*)profileId {
NSUserNotificationCenter* notificationCenter =
[NSUserNotificationCenter defaultUserNotificationCenter];
for (NSUserNotification* candidate in
[notificationCenter deliveredNotifications]) {
NSString* candidateId = [candidate.userInfo
objectForKey:notification_constants::kNotificationId];
NSString* candidateProfileId = [candidate.userInfo
objectForKey:notification_constants::kNotificationProfileId];
if ([candidateId isEqualToString:notificationId] &&
[profileId isEqualToString:candidateProfileId]) {
[notificationCenter removeDeliveredNotification:candidate];
[_transactionHandler closeTransactionIfNeeded];
break;
}
}
}
- (void)closeAllNotifications {
[[NSUserNotificationCenter defaultUserNotificationCenter]
removeAllDeliveredNotifications];
[_transactionHandler closeTransactionIfNeeded];
}
- (void)getDisplayedAlertsForProfileId:(NSString*)profileId
andIncognito:(BOOL)incognito
withReply:(void (^)(NSArray*))reply {
NSUserNotificationCenter* notificationCenter =
[NSUserNotificationCenter defaultUserNotificationCenter];
NSArray* deliveredNotifications = [notificationCenter deliveredNotifications];
NSMutableArray* notificationIds =
[NSMutableArray arrayWithCapacity:[deliveredNotifications count]];
for (NSUserNotification* toast in deliveredNotifications) {
NSString* candidateProfileId = [toast.userInfo
objectForKey:notification_constants::kNotificationProfileId];
BOOL incognitoNotification = [[toast.userInfo
objectForKey:notification_constants::kNotificationIncognito] boolValue];
if ([candidateProfileId isEqualToString:profileId] &&
incognito == incognitoNotification) {
[notificationIds
addObject:[toast.userInfo
objectForKey:notification_constants::kNotificationId]];
}
}
reply(notificationIds);
}
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification*)notification {
NSDictionary* response =
[NotificationResponseBuilder buildActivatedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
}
// _NSUserNotificationCenterDelegatePrivate:
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDismissAlert:(NSUserNotification*)notification {
NSDictionary* response =
[NotificationResponseBuilder buildDismissedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
[_transactionHandler closeTransactionIfNeeded];
}
// _NSUserNotificationCenterDelegatePrivate:
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didRemoveDeliveredNotifications:(NSArray*)notifications {
for (NSUserNotification* notification in notifications) {
NSDictionary* response =
[NotificationResponseBuilder buildDismissedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
}
[_transactionHandler closeTransactionIfNeeded];
}
@end
......@@ -15,8 +15,11 @@
// Protocol for the XPC notification service.
@protocol NotificationDelivery
// Sets the Mach exception handler port to use for the XPCService.
- (void)setMachExceptionPort:(CrXPCMachPort*)port;
// Sets the Mach exception handler port to use for the XPCService, and sets
// which notification API to be used. This method must be called first before
// using the other methods in this protocol.
- (void)setUseUNNotification:(BOOL)useUNNotification
machExceptionPort:(CrXPCMachPort*)port;
// |notificationData| is generated using a NofiticationBuilder object.
- (void)deliverNotification:(NSDictionary*)notificationData;
......
......@@ -7,8 +7,7 @@
#import <Foundation/Foundation.h>
@interface ServiceDelegate
: NSObject<NSXPCListenerDelegate, NSUserNotificationCenterDelegate>
@interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
@end
#endif // CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_NOTIFICATION_SERVICE_DELEGATE_H_
......@@ -12,8 +12,6 @@
#import "chrome/browser/ui/cocoa/notifications/notification_response_builder_mac.h"
#import "chrome/browser/ui/cocoa/notifications/xpc_transaction_handler.h"
@class NSUserNotificationCenter;
@implementation ServiceDelegate {
// Helper to manage the XPC transaction reference count with respect to
// still-visible notifications.
......@@ -26,14 +24,12 @@
- (instancetype)init {
if ((self = [super init])) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
_transactionHandler.reset([[XPCTransactionHandler alloc] init]);
}
return self;
}
- (void)dealloc {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
[super dealloc];
}
......@@ -52,7 +48,8 @@
base::scoped_nsobject<AlertNotificationService> object(
[[AlertNotificationService alloc]
initWithTransactionHandler:_transactionHandler]);
initWithTransactionHandler:_transactionHandler
xpcConnection:newConnection]);
newConnection.exportedObject = object.get();
newConnection.remoteObjectInterface =
[NSXPCInterface interfaceWithProtocol:@protocol(NotificationReply)];
......@@ -62,32 +59,4 @@
return YES;
}
// NSUserNotificationCenterDelegate:
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification*)notification {
NSDictionary* response =
[NotificationResponseBuilder buildActivatedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
}
// _NSUserNotificationCenterDelegatePrivate:
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDismissAlert:(NSUserNotification*)notification {
NSDictionary* response =
[NotificationResponseBuilder buildDismissedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
[_transactionHandler closeTransactionIfNeeded];
}
// _NSUserNotificationCenterDelegatePrivate:
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didRemoveDeliveredNotifications:(NSArray*)notifications {
for (NSUserNotification* notification in notifications) {
NSDictionary* response =
[NotificationResponseBuilder buildDismissedDictionary:notification];
[[_connection remoteObjectProxy] notificationClick:response];
}
[_transactionHandler closeTransactionIfNeeded];
}
@end
......@@ -10,6 +10,9 @@
// Keeps track of whether a XPC transaction is opened.
@interface XPCTransactionHandler : NSObject
// Sets which API to use, NSUserNotificationCenter or UNUserNotificationCenter.
- (void)setUseUNNotification:(BOOL)useUNNotification;
// Only open a new transaction if one is not already opened.
- (void)openTransactionIfNeeded;
......
......@@ -5,19 +5,18 @@
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#include "base/notreached.h"
#import "chrome/browser/ui/cocoa/notifications/xpc_transaction_handler.h"
@class NSUserNotificationCenter;
@implementation XPCTransactionHandler {
bool _transactionOpen;
BOOL _transactionOpen;
BOOL _useUNNotification;
}
- (instancetype)init {
if ((self = [super init])) {
_transactionOpen = false;
}
return self;
- (void)setUseUNNotification:(BOOL)useUNNotification {
_useUNNotification = useUNNotification;
}
- (void)openTransactionIfNeeded {
......@@ -26,18 +25,23 @@
return;
}
xpc_transaction_begin();
_transactionOpen = true;
_transactionOpen = YES;
}
}
- (void)closeTransactionIfNeeded {
@synchronized(self) {
if (_useUNNotification) {
NOTIMPLEMENTED();
return;
}
NSUserNotificationCenter* notificationCenter =
[NSUserNotificationCenter defaultUserNotificationCenter];
NSUInteger showing = [[notificationCenter deliveredNotifications] count];
if (showing == 0 && _transactionOpen) {
xpc_transaction_end();
_transactionOpen = false;
_transactionOpen = NO;
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment