mac: Fix the notification presenter of new API.

This commit is contained in:
Cheng Zhao 2014-07-28 11:52:26 +08:00
parent e52a089ec2
commit f552dc7ba4
3 changed files with 93 additions and 108 deletions

View file

@ -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);
} }

View file

@ -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_;
}; };

View file

@ -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;
} }