Refactor the notification code

This commit is contained in:
Cheng Zhao 2015-12-24 21:55:18 +08:00
parent b4664ce897
commit 41084883cf
9 changed files with 281 additions and 191 deletions

View file

@ -0,0 +1,59 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef BROWSER_MAC_COCOA_NOTIFICATION_H_
#define BROWSER_MAC_COCOA_NOTIFICATION_H_
#include <set>
#import <Foundation/Foundation.h>
#include "base/mac/scoped_nsobject.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/public/browser/desktop_notification_delegate.h"
@class NotificationDelegate;
class SkBitmap;
namespace brightray {
class CocoaNotification {
public:
static CocoaNotification* FromNSNotification(
NSUserNotification* notification);
CocoaNotification(
scoped_ptr<content::DesktopNotificationDelegate> delegate);
~CocoaNotification();
void ShowNotification(const base::string16& title,
const base::string16& msg,
const SkBitmap& icon);
void DismissNotification();
void NotifyDisplayed();
void NotifyClick();
base::WeakPtr<CocoaNotification> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
static void Cleanup();
scoped_ptr<content::DesktopNotificationDelegate> delegate_;
base::scoped_nsobject<NSUserNotification> notification_;
base::WeakPtrFactory<CocoaNotification> weak_factory_;
static base::scoped_nsobject<NotificationDelegate> notification_delegate_;
static std::set<CocoaNotification*> notifications_;
DISALLOW_COPY_AND_ASSIGN(CocoaNotification);
};
} // namespace brightray
#endif // BROWSER_MAC_COCOA_NOTIFICATION_H_

View file

@ -0,0 +1,92 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "browser/mac/cocoa_notification.h"
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/mac/mac_util.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#include "browser/mac/notification_delegate.h"
#include "skia/ext/skia_utils_mac.h"
namespace brightray {
// static
base::scoped_nsobject<NotificationDelegate>
CocoaNotification::notification_delegate_;
// static
std::set<CocoaNotification*> CocoaNotification::notifications_;
// static
CocoaNotification* CocoaNotification::FromNSNotification(
NSUserNotification* ns_notification) {
for (CocoaNotification* notification : notifications_) {
if ([notification->notification_ isEqual:ns_notification])
return notification;
}
return nullptr;
}
// static
void CocoaNotification::Cleanup() {
NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil;
notification_delegate_.reset();
STLDeleteElements(&notifications_);
}
CocoaNotification::CocoaNotification(
scoped_ptr<content::DesktopNotificationDelegate> delegate)
: delegate_(delegate.Pass()),
weak_factory_(this) {
if (!notification_delegate_) {
notification_delegate_.reset([[NotificationDelegate alloc] init]);
NSUserNotificationCenter.defaultUserNotificationCenter.delegate =
notification_delegate_;
base::AtExitManager::RegisterTask(base::Bind(Cleanup));
}
notifications_.insert(this);
}
CocoaNotification::~CocoaNotification() {
[NSUserNotificationCenter.defaultUserNotificationCenter
removeDeliveredNotification:notification_];
notifications_.erase(this);
}
void CocoaNotification::ShowNotification(const base::string16& title,
const base::string16& body,
const SkBitmap& icon) {
notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)];
if ([notification_ respondsToSelector:@selector(setContentImage:)] &&
!icon.drawsNothing()) {
NSImage* image = gfx::SkBitmapToNSImageWithColorSpace(
icon, base::mac::GetGenericRGBColorSpace());
[notification_ setContentImage:image];
}
[NSUserNotificationCenter.defaultUserNotificationCenter
deliverNotification:notification_];
}
void CocoaNotification::DismissNotification() {
delete this;
}
void CocoaNotification::NotifyDisplayed() {
delegate_->NotificationDisplayed();
}
void CocoaNotification::NotifyClick() {
delegate_->NotificationClick();
delete this;
}
} // namespace brightray

View file

@ -0,0 +1,14 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef BROWSER_MAC_NOTIFICATION_DELEGATE_H_
#define BROWSER_MAC_NOTIFICATION_DELEGATE_H_
#import <Foundation/Foundation.h>
@interface NotificationDelegate : NSObject<NSUserNotificationCenterDelegate> {
}
@end
#endif // BROWSER_MAC_NOTIFICATION_DELEGATE_H_

View file

@ -0,0 +1,31 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "browser/mac/notification_delegate.h"
#include "browser/mac/cocoa_notification.h"
@implementation NotificationDelegate
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDeliverNotification:(NSUserNotification*)notif {
auto notification = brightray::CocoaNotification::FromNSNotification(notif);
if (notification)
notification->NotifyDisplayed();
}
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification *)notif {
auto notification = brightray::CocoaNotification::FromNSNotification(notif);
if (notification)
notification->NotifyClick();
}
- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
shouldPresentNotification:(NSUserNotification*)notification {
// Display notifications even if the app is active.
return YES;
}
@end

View file

@ -0,0 +1,31 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_
#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_
#include "browser/notification_presenter.h"
namespace brightray {
class NotificationPresenterMac : public NotificationPresenter {
public:
NotificationPresenterMac();
~NotificationPresenterMac();
// NotificationPresenter:
void ShowNotification(
const content::PlatformNotificationData&,
const SkBitmap& icon,
scoped_ptr<content::DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) override;
private:
DISALLOW_COPY_AND_ASSIGN(NotificationPresenterMac);
};
} // namespace brightray
#endif

View file

@ -0,0 +1,48 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#import "browser/mac/notification_presenter_mac.h"
#include "base/bind.h"
#include "browser/mac/cocoa_notification.h"
#include "content/public/common/platform_notification_data.h"
namespace brightray {
namespace {
void RemoveNotification(base::WeakPtr<CocoaNotification> notification) {
if (notification)
notification->DismissNotification();
}
} // namespace
NotificationPresenter* NotificationPresenter::Create() {
return new NotificationPresenterMac;
}
NotificationPresenterMac::NotificationPresenterMac() {
}
NotificationPresenterMac::~NotificationPresenterMac() {
}
void NotificationPresenterMac::ShowNotification(
const content::PlatformNotificationData& data,
const SkBitmap& icon,
scoped_ptr<content::DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) {
// This class manages itself.
auto notification = new CocoaNotification(delegate.Pass());
notification->ShowNotification(data.title, data.body, icon);
if (cancel_callback) {
*cancel_callback = base::Bind(
&RemoveNotification, notification->GetWeakPtr());
}
}
} // namespace brightray