mac: Fix the notification presenter of new API.
This commit is contained in:
parent
e52a089ec2
commit
f552dc7ba4
3 changed files with 93 additions and 108 deletions
|
@ -70,7 +70,7 @@ void BrowserClient::ShowDesktopNotification(
|
||||||
content::DesktopNotificationDelegate* delegate,
|
content::DesktopNotificationDelegate* delegate,
|
||||||
base::Closure* cancel_callback) {
|
base::Closure* cancel_callback) {
|
||||||
auto presenter = notification_presenter();
|
auto presenter = notification_presenter();
|
||||||
if (!presenter)
|
if (presenter)
|
||||||
presenter->ShowNotification(params, delegate, cancel_callback);
|
presenter->ShowNotification(params, delegate, cancel_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,27 @@ class NotificationPresenterMac : public NotificationPresenter {
|
||||||
|
|
||||||
virtual void ShowNotification(
|
virtual void ShowNotification(
|
||||||
const content::ShowDesktopNotificationHostMsgParams&,
|
const content::ShowDesktopNotificationHostMsgParams&,
|
||||||
int render_process_id,
|
content::DesktopNotificationDelegate* delegate,
|
||||||
int render_view_id) OVERRIDE;
|
base::Closure* cancel_callback) OVERRIDE;
|
||||||
virtual void CancelNotification(
|
|
||||||
int render_process_id,
|
// Get the delegate accroding from the notification object.
|
||||||
int render_view_id,
|
content::DesktopNotificationDelegate* GetDelegateFromNotification(
|
||||||
int notification_id) OVERRIDE;
|
NSUserNotification* notification);
|
||||||
|
|
||||||
|
// Remove the notification object accroding to its delegate.
|
||||||
|
void RemoveNotification(content::DesktopNotificationDelegate* delegate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<std::string, base::scoped_nsobject<NSUserNotification>>
|
void CancelNotification(content::DesktopNotificationDelegate* delegate);
|
||||||
NotificationMap;
|
|
||||||
NotificationMap notification_map_;
|
// The userInfo of NSUserNotification can not store pointers (because they are
|
||||||
|
// not in property list), so we have to track them in a C++ map.
|
||||||
|
// Also notice that the delegate acts as "ID" or "Key", because it is certain
|
||||||
|
// that each notification has a unique delegate.
|
||||||
|
typedef std::map<content::DesktopNotificationDelegate*, base::scoped_nsobject<NSUserNotification>>
|
||||||
|
NotificationsMap;
|
||||||
|
NotificationsMap notifications_map_;
|
||||||
|
|
||||||
base::scoped_nsobject<BRYUserNotificationCenterDelegate> delegate_;
|
base::scoped_nsobject<BRYUserNotificationCenterDelegate> delegate_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,146 +5,121 @@
|
||||||
|
|
||||||
#import "browser/notification_presenter_mac.h"
|
#import "browser/notification_presenter_mac.h"
|
||||||
|
|
||||||
#import "base/strings/stringprintf.h"
|
#include "base/bind.h"
|
||||||
#import "base/strings/sys_string_conversions.h"
|
#include "base/stl_util.h"
|
||||||
#import "content/public/browser/render_view_host.h"
|
#include "base/strings/sys_string_conversions.h"
|
||||||
#import "content/public/common/show_desktop_notification_params.h"
|
#include "content/public/browser/desktop_notification_delegate.h"
|
||||||
|
#include "content/public/common/show_desktop_notification_params.h"
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface BRYUserNotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate>
|
@interface BRYUserNotificationCenterDelegate : NSObject<NSUserNotificationCenterDelegate> {
|
||||||
|
@private
|
||||||
|
brightray::NotificationPresenterMac* presenter_;
|
||||||
|
}
|
||||||
|
- (instancetype)initWithNotificationPresenter:(brightray::NotificationPresenterMac*)presenter;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
namespace brightray {
|
namespace brightray {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
NSString * const kRenderProcessIDKey = @"RenderProcessID";
|
} // namespace
|
||||||
NSString * const kRenderViewIDKey = @"RenderViewID";
|
|
||||||
NSString * const kNotificationIDKey = @"NotificationID";
|
|
||||||
|
|
||||||
struct NotificationID {
|
|
||||||
NotificationID(
|
|
||||||
int render_process_id,
|
|
||||||
int render_view_id,
|
|
||||||
int notification_id)
|
|
||||||
: render_process_id(render_process_id),
|
|
||||||
render_view_id(render_view_id),
|
|
||||||
notification_id(notification_id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationID(NSUserNotification* notification)
|
|
||||||
: render_process_id([[notification.userInfo objectForKey:kRenderProcessIDKey] intValue]),
|
|
||||||
render_view_id([[notification.userInfo objectForKey:kRenderViewIDKey] intValue]),
|
|
||||||
notification_id([[notification.userInfo objectForKey:kNotificationIDKey] intValue]) {
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetID() {
|
|
||||||
return base::StringPrintf("%d:%d:%d", render_process_id, render_view_id, notification_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
NSDictionary* GetUserInfo() {
|
|
||||||
return @{
|
|
||||||
kRenderProcessIDKey: @(render_process_id),
|
|
||||||
kRenderViewIDKey: @(render_view_id),
|
|
||||||
kNotificationIDKey: @(notification_id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
int render_process_id;
|
|
||||||
int render_view_id;
|
|
||||||
int notification_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
base::scoped_nsobject<NSUserNotification> CreateUserNotification(
|
|
||||||
const content::ShowDesktopNotificationHostMsgParams& params,
|
|
||||||
int render_process_id,
|
|
||||||
int render_view_id) {
|
|
||||||
auto notification = [[NSUserNotification alloc] init];
|
|
||||||
notification.title = base::SysUTF16ToNSString(params.title);
|
|
||||||
notification.informativeText = base::SysUTF16ToNSString(params.body);
|
|
||||||
notification.userInfo = NotificationID(render_process_id, render_view_id, params.notification_id).GetUserInfo();
|
|
||||||
|
|
||||||
return base::scoped_nsobject<NSUserNotification>(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationPresenter* NotificationPresenter::Create() {
|
NotificationPresenter* NotificationPresenter::Create() {
|
||||||
return new NotificationPresenterMac;
|
return new NotificationPresenterMac;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationPresenterMac::NotificationPresenterMac()
|
NotificationPresenterMac::NotificationPresenterMac()
|
||||||
: delegate_([[BRYUserNotificationCenterDelegate alloc] init]) {
|
: delegate_([[BRYUserNotificationCenterDelegate alloc] initWithNotificationPresenter:this]) {
|
||||||
NSUserNotificationCenter.defaultUserNotificationCenter.delegate = delegate_;
|
NSUserNotificationCenter.defaultUserNotificationCenter.delegate = delegate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationPresenterMac::~NotificationPresenterMac() {
|
NotificationPresenterMac::~NotificationPresenterMac() {
|
||||||
|
NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationPresenterMac::ShowNotification(
|
void NotificationPresenterMac::ShowNotification(
|
||||||
const content::ShowDesktopNotificationHostMsgParams& params,
|
const content::ShowDesktopNotificationHostMsgParams& params,
|
||||||
int render_process_id,
|
content::DesktopNotificationDelegate* delegate,
|
||||||
int render_view_id) {
|
base::Closure* cancel_callback) {
|
||||||
auto notification = CreateUserNotification(params, render_process_id, render_view_id);
|
auto notification = [[NSUserNotification alloc] init];
|
||||||
notification_map_.insert(std::make_pair(NotificationID(notification).GetID(), notification));
|
notification.title = base::SysUTF16ToNSString(params.title);
|
||||||
|
notification.informativeText = base::SysUTF16ToNSString(params.body);
|
||||||
|
|
||||||
|
notifications_map_[delegate].reset(notification);
|
||||||
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:notification];
|
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:notification];
|
||||||
|
|
||||||
|
if (cancel_callback)
|
||||||
|
*cancel_callback = base::Bind(
|
||||||
|
&NotificationPresenterMac::CancelNotification,
|
||||||
|
base::Unretained(this),
|
||||||
|
delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationPresenterMac::CancelNotification(
|
content::DesktopNotificationDelegate* NotificationPresenterMac::GetDelegateFromNotification(
|
||||||
int render_process_id,
|
NSUserNotification* notification) {
|
||||||
int render_view_id,
|
for (NotificationsMap::const_iterator it = notifications_map_.begin();
|
||||||
int notification_id) {
|
it != notifications_map_.end(); ++it)
|
||||||
auto found = notification_map_.find(NotificationID(render_process_id, render_view_id, notification_id).GetID());
|
if ([it->second isEqual:notification])
|
||||||
if (found == notification_map_.end())
|
return it->first;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationPresenterMac::RemoveNotification(content::DesktopNotificationDelegate* delegate) {
|
||||||
|
if (ContainsKey(notifications_map_, delegate))
|
||||||
|
notifications_map_.erase(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationPresenterMac::CancelNotification(content::DesktopNotificationDelegate* delegate) {
|
||||||
|
if (!ContainsKey(notifications_map_, delegate))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto notification = found->second;
|
|
||||||
|
|
||||||
notification_map_.erase(found);
|
|
||||||
|
|
||||||
// Notifications in -deliveredNotifications aren't the same objects we passed to
|
// Notifications in -deliveredNotifications aren't the same objects we passed to
|
||||||
// -deliverNotification:, but they will respond YES to -isEqual:.
|
// -deliverNotification:, but they will respond YES to -isEqual:.
|
||||||
|
auto notification = notifications_map_[delegate];
|
||||||
auto center = NSUserNotificationCenter.defaultUserNotificationCenter;
|
auto center = NSUserNotificationCenter.defaultUserNotificationCenter;
|
||||||
for (NSUserNotification* deliveredNotification in center.deliveredNotifications) {
|
for (NSUserNotification* deliveredNotification in center.deliveredNotifications)
|
||||||
if (![notification isEqual:deliveredNotification])
|
if ([notification isEqual:deliveredNotification]) {
|
||||||
continue;
|
[center removeDeliveredNotification:deliveredNotification];
|
||||||
[center removeDeliveredNotification:deliveredNotification];
|
delegate->NotificationClosed(false);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
NotificationID ID(notification);
|
RemoveNotification(delegate);
|
||||||
auto host = content::RenderViewHost::FromID(ID.render_process_id, ID.render_view_id);
|
|
||||||
if (!host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
host->DesktopNotificationPostClose(ID.notification_id, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace brightray
|
||||||
|
|
||||||
@implementation BRYUserNotificationCenterDelegate
|
@implementation BRYUserNotificationCenterDelegate
|
||||||
|
|
||||||
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification {
|
- (instancetype)initWithNotificationPresenter:(brightray::NotificationPresenterMac*)presenter {
|
||||||
brightray::NotificationID ID(notification);
|
self = [super init];
|
||||||
|
if (!self)
|
||||||
|
return nil;
|
||||||
|
|
||||||
auto host = content::RenderViewHost::FromID(ID.render_process_id, ID.render_view_id);
|
presenter_ = presenter;
|
||||||
if (!host)
|
return self;
|
||||||
return;
|
|
||||||
|
|
||||||
host->DesktopNotificationPostDisplay(ID.notification_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
|
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
|
||||||
brightray::NotificationID ID(notification);
|
didDeliverNotification:(NSUserNotification*)notification {
|
||||||
|
auto delegate = presenter_->GetDelegateFromNotification(notification);
|
||||||
auto host = content::RenderViewHost::FromID(ID.render_process_id, ID.render_view_id);
|
if (delegate)
|
||||||
if (!host)
|
delegate->NotificationDisplayed();
|
||||||
return;
|
|
||||||
|
|
||||||
host->DesktopNotificationPostClick(ID.notification_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
|
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
|
||||||
|
didActivateNotification:(NSUserNotification *)notification {
|
||||||
|
auto delegate = presenter_->GetDelegateFromNotification(notification);
|
||||||
|
if (delegate) {
|
||||||
|
delegate->NotificationClick();
|
||||||
|
presenter_->RemoveNotification(delegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
|
||||||
|
shouldPresentNotification:(NSUserNotification*)notification {
|
||||||
// Display notifications even if the app is active.
|
// Display notifications even if the app is active.
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue