Decouple notification code from content module

This commit is contained in:
Cheng Zhao 2015-12-25 10:16:07 +08:00
parent 6f81d1e29f
commit 5b7c7be804
15 changed files with 316 additions and 139 deletions

View file

@ -5,45 +5,34 @@
#ifndef BROWSER_MAC_COCOA_NOTIFICATION_H_ #ifndef BROWSER_MAC_COCOA_NOTIFICATION_H_
#define BROWSER_MAC_COCOA_NOTIFICATION_H_ #define BROWSER_MAC_COCOA_NOTIFICATION_H_
#include <set>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "browser/notification.h" #include "browser/notification.h"
#include "content/public/browser/desktop_notification_delegate.h"
@class NotificationDelegate;
namespace brightray { namespace brightray {
class CocoaNotification : public Notification { class CocoaNotification : public Notification {
public: public:
static CocoaNotification* FromNSNotification( CocoaNotification(NotificationDelegate* delegate,
NSUserNotification* notification); NotificationPresenter* presenter);
CocoaNotification(
scoped_ptr<content::DesktopNotificationDelegate> delegate);
~CocoaNotification(); ~CocoaNotification();
void ShowNotification(const base::string16& title, void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const SkBitmap& icon) override; const SkBitmap& icon) override;
void DismissNotification() override; void Dismiss() override;
void NotifyDisplayed(); void NotifyDisplayed();
void NotifyClick(); void NotifyClick();
NSUserNotification* notification() const { return notification_; }
private: private:
static void Cleanup(); NotificationDelegate* delegate_;
scoped_ptr<content::DesktopNotificationDelegate> delegate_;
base::scoped_nsobject<NSUserNotification> notification_; base::scoped_nsobject<NSUserNotification> notification_;
static base::scoped_nsobject<NotificationDelegate> notification_delegate_;
static std::set<CocoaNotification*> notifications_;
DISALLOW_COPY_AND_ASSIGN(CocoaNotification); DISALLOW_COPY_AND_ASSIGN(CocoaNotification);
}; };

View file

@ -4,62 +4,35 @@
#include "browser/mac/cocoa_notification.h" #include "browser/mac/cocoa_notification.h"
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "browser/mac/notification_delegate.h" #include "browser/notification_delegate.h"
#include "browser/notification_presenter.h"
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
namespace brightray { namespace brightray {
// static // static
base::scoped_nsobject<NotificationDelegate> Notification* Notification::Create(NotificationDelegate* delegate,
CocoaNotification::notification_delegate_; NotificationPresenter* presenter) {
return new CocoaNotification(delegate, presenter);
// 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 CocoaNotification::CocoaNotification(NotificationDelegate* delegate,
void CocoaNotification::Cleanup() { NotificationPresenter* presenter)
NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil; : Notification(delegate, presenter) {
notification_delegate_.reset();
STLDeleteElements(&notifications_);
}
CocoaNotification::CocoaNotification(
scoped_ptr<content::DesktopNotificationDelegate> delegate)
: delegate_(delegate.Pass()) {
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() { CocoaNotification::~CocoaNotification() {
[NSUserNotificationCenter.defaultUserNotificationCenter if (notification_) {
removeDeliveredNotification:notification_]; [NSUserNotificationCenter.defaultUserNotificationCenter
notifications_.erase(this); removeDeliveredNotification:notification_];
}
} }
void CocoaNotification::ShowNotification(const base::string16& title, void CocoaNotification::Show(const base::string16& title,
const base::string16& body, const base::string16& body,
const SkBitmap& icon) { const SkBitmap& icon) {
notification_.reset([[NSUserNotification alloc] init]); notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)]; [notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)]; [notification_ setInformativeText:base::SysUTF16ToNSString(body)];
@ -75,17 +48,17 @@ void CocoaNotification::ShowNotification(const base::string16& title,
deliverNotification:notification_]; deliverNotification:notification_];
} }
void CocoaNotification::DismissNotification() { void CocoaNotification::Dismiss() {
delete this; Destroy();
} }
void CocoaNotification::NotifyDisplayed() { void CocoaNotification::NotifyDisplayed() {
delegate_->NotificationDisplayed(); delegate()->NotificationDisplayed();
} }
void CocoaNotification::NotifyClick() { void CocoaNotification::NotifyClick() {
delegate_->NotificationClick(); delegate()->NotificationClick();
delete this; Destroy();
} }
} // namespace brightray } // namespace brightray

View file

@ -7,8 +7,16 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface NotificationDelegate : NSObject<NSUserNotificationCenterDelegate> { namespace brightray {
class NotificationPresenterMac;
} }
@interface NotificationCenterDelegate :
NSObject<NSUserNotificationCenterDelegate> {
@private
brightray::NotificationPresenterMac* presenter_;
}
- (instancetype)initWithPresenter:(brightray::NotificationPresenterMac*)presenter;
@end @end
#endif // BROWSER_MAC_NOTIFICATION_DELEGATE_H_ #endif // BROWSER_MAC_NOTIFICATION_DELEGATE_H_

View file

@ -2,22 +2,32 @@
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "browser/mac/notification_delegate.h" #include "browser/mac/notification_center_delegate.h"
#include "browser/mac/cocoa_notification.h" #include "browser/mac/cocoa_notification.h"
#include "browser/mac/notification_presenter_mac.h"
@implementation NotificationDelegate @implementation NotificationCenterDelegate
- (instancetype)initWithPresenter:(brightray::NotificationPresenterMac*)presenter {
self = [super init];
if (!self)
return nil;
presenter_ = presenter;
return self;
}
- (void)userNotificationCenter:(NSUserNotificationCenter*)center - (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDeliverNotification:(NSUserNotification*)notif { didDeliverNotification:(NSUserNotification*)notif {
auto notification = brightray::CocoaNotification::FromNSNotification(notif); auto notification = presenter_->GetNotification(notif);
if (notification) if (notification)
notification->NotifyDisplayed(); notification->NotifyDisplayed();
} }
- (void)userNotificationCenter:(NSUserNotificationCenter*)center - (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification *)notif { didActivateNotification:(NSUserNotification *)notif {
auto notification = brightray::CocoaNotification::FromNSNotification(notif); auto notification = presenter_->GetNotification(notif);
if (notification) if (notification)
notification->NotifyClick(); notification->NotifyClick();
} }

View file

@ -6,23 +6,25 @@
#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_
#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_
#include "base/mac/scoped_nsobject.h"
#include "browser/mac/notification_center_delegate.h"
#include "browser/notification_presenter.h" #include "browser/notification_presenter.h"
namespace brightray { namespace brightray {
class CocoaNotification;
class NotificationPresenterMac : public NotificationPresenter { class NotificationPresenterMac : public NotificationPresenter {
public: public:
CocoaNotification* GetNotification(NSUserNotification* notif);
NotificationPresenterMac(); NotificationPresenterMac();
~NotificationPresenterMac(); ~NotificationPresenterMac();
// NotificationPresenter:
void ShowNotification(
const content::PlatformNotificationData&,
const SkBitmap& icon,
scoped_ptr<content::DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) override;
private: private:
base::scoped_nsobject<NotificationCenterDelegate>
notification_center_delegate_;
DISALLOW_COPY_AND_ASSIGN(NotificationPresenterMac); DISALLOW_COPY_AND_ASSIGN(NotificationPresenterMac);
}; };

View file

@ -1,48 +1,38 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright (c) 2015 GitHub, Inc.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved. // Use of this source code is governed by the MIT license that can be
// Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
// found in the LICENSE-CHROMIUM file.
#import "browser/mac/notification_presenter_mac.h" #include "browser/mac/notification_presenter_mac.h"
#include "base/bind.h"
#include "browser/mac/cocoa_notification.h" #include "browser/mac/cocoa_notification.h"
#include "content/public/common/platform_notification_data.h" #include "browser/mac/notification_center_delegate.h"
namespace brightray { namespace brightray {
namespace { // static
void RemoveNotification(base::WeakPtr<Notification> notification) {
if (notification)
notification->DismissNotification();
}
} // namespace
NotificationPresenter* NotificationPresenter::Create() { NotificationPresenter* NotificationPresenter::Create() {
return new NotificationPresenterMac; return new NotificationPresenterMac;
} }
NotificationPresenterMac::NotificationPresenterMac() { CocoaNotification* NotificationPresenterMac::GetNotification(
NSUserNotification* ns_notification) {
for (Notification* notification : notifications()) {
auto native_notification = static_cast<CocoaNotification*>(notification);
if ([native_notification->notification() isEqual:ns_notification])
return native_notification;
}
return nullptr;
}
NotificationPresenterMac::NotificationPresenterMac()
: notification_center_delegate_(
[[NotificationCenterDelegate alloc] initWithPresenter:this]) {
NSUserNotificationCenter.defaultUserNotificationCenter.delegate =
notification_center_delegate_;
} }
NotificationPresenterMac::~NotificationPresenterMac() { NotificationPresenterMac::~NotificationPresenterMac() {
} NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil;
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 } // namespace brightray

View file

@ -0,0 +1,27 @@
// 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/notification.h"
#include "browser/notification_delegate.h"
#include "browser/notification_presenter.h"
namespace brightray {
Notification::Notification(NotificationDelegate* delegate,
NotificationPresenter* presenter)
: delegate_(delegate),
presenter_(presenter),
weak_factory_(this) {
}
Notification::~Notification() {
delegate()->NotificationDestroyed();
}
void Notification::Destroy() {
presenter()->RemoveNotification(this);
}
} // namespace brightray

View file

@ -12,23 +12,45 @@ class SkBitmap;
namespace brightray { namespace brightray {
class NotificationDelegate;
class NotificationPresenter;
class Notification { class Notification {
public: public:
Notification() : weak_factory_(this) {} // Shows the notification.
virtual void Show(const base::string16& title,
virtual void ShowNotification(const base::string16& title, const base::string16& msg,
const base::string16& msg, const SkBitmap& icon) = 0;
const SkBitmap& icon) = 0; // Closes the notification, this instance will be destroyed after the
virtual void DismissNotification() = 0; // notification gets closed.
virtual void Dismiss() = 0;
base::WeakPtr<Notification> GetWeakPtr() { base::WeakPtr<Notification> GetWeakPtr() {
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
NotificationDelegate* delegate() const { return delegate_; }
NotificationPresenter* presenter() const { return presenter_; }
protected: protected:
virtual ~Notification() {} Notification(NotificationDelegate* delegate,
NotificationPresenter* presenter);
virtual ~Notification();
// delete this.
void Destroy();
private: private:
friend class NotificationPresenter;
// Can only be called by NotificationPresenter, the caller is responsible of
// freeing the returned instance.
static Notification* Create(NotificationDelegate* delegate,
NotificationPresenter* presenter);
NotificationDelegate* delegate_;
NotificationPresenter* presenter_;
base::WeakPtrFactory<Notification> weak_factory_; base::WeakPtrFactory<Notification> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Notification); DISALLOW_COPY_AND_ASSIGN(Notification);

View file

@ -0,0 +1,20 @@
// 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_NOTIFICATION_DELEGATE_H_
#define BROWSER_NOTIFICATION_DELEGATE_H_
#include "content/public/browser/desktop_notification_delegate.h"
namespace brightray {
class NotificationDelegate : public content::DesktopNotificationDelegate {
public:
// The native Notification object is destroyed.
virtual void NotificationDestroyed() {}
};
} // namespace brightray
#endif // BROWSER_NOTIFICATION_DELEGATE_H_

View file

@ -0,0 +1,33 @@
// 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/notification_delegate_adapter.h"
namespace brightray {
NotificationDelegateAdapter::NotificationDelegateAdapter(
scoped_ptr<content::DesktopNotificationDelegate> delegate)
: delegate_(delegate.Pass()) {
}
NotificationDelegateAdapter::~NotificationDelegateAdapter() {
}
void NotificationDelegateAdapter::NotificationDestroyed() {
delete this;
}
void NotificationDelegateAdapter::NotificationDisplayed() {
delegate_->NotificationDisplayed();
}
void NotificationDelegateAdapter::NotificationClosed() {
delegate_->NotificationClosed();
}
void NotificationDelegateAdapter::NotificationClick() {
delegate_->NotificationClick();
}
} // namespace brightray

View file

@ -0,0 +1,36 @@
// 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_NOTIFICATION_DELEGATE_ADAPTER_H_
#define BROWSER_NOTIFICATION_DELEGATE_ADAPTER_H_
#include "base/memory/scoped_ptr.h"
#include "browser/notification_delegate.h"
namespace brightray {
// Adapt the content::DesktopNotificationDelegate to NotificationDelegate.
class NotificationDelegateAdapter : public NotificationDelegate {
public:
explicit NotificationDelegateAdapter(
scoped_ptr<content::DesktopNotificationDelegate> delegate);
~NotificationDelegateAdapter() override;
// NotificationDelegate:
void NotificationDestroyed() override;
// content::DesktopNotificationDelegate:
void NotificationDisplayed() override;
void NotificationClosed() override;
void NotificationClick() override;
private:
scoped_ptr<content::DesktopNotificationDelegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(NotificationDelegateAdapter);
};
} // namespace brightray
#endif // BROWSER_NOTIFICATION_DELEGATE_ADAPTER_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/notification_presenter.h"
#include "browser/notification.h"
namespace brightray {
NotificationPresenter::NotificationPresenter() {
}
NotificationPresenter::~NotificationPresenter() {
for (Notification* notification : notifications_)
delete notification;
}
base::WeakPtr<Notification> NotificationPresenter::CreateNotification(
NotificationDelegate* delegate) {
Notification* notification = Notification::Create(delegate, this);
notifications_.insert(notification);
return notification->GetWeakPtr();
}
void NotificationPresenter::RemoveNotification(Notification* notification) {
notifications_.erase(notification);
delete notification;
}
} // namespace brightray

View file

@ -1,29 +1,41 @@
// 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 BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_H_ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_H_
#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_H_
#include "base/callback_forward.h" #include <set>
#include "base/memory/scoped_ptr.h"
class SkBitmap; #include "base/memory/weak_ptr.h"
namespace content {
class DesktopNotificationDelegate;
struct PlatformNotificationData;
}
namespace brightray { namespace brightray {
class Notification;
class NotificationDelegate;
class NotificationPresenter { class NotificationPresenter {
public: public:
virtual ~NotificationPresenter() {}
static NotificationPresenter* Create(); static NotificationPresenter* Create();
virtual void ShowNotification( virtual ~NotificationPresenter();
const content::PlatformNotificationData&,
const SkBitmap& icon, base::WeakPtr<Notification> CreateNotification(
scoped_ptr<content::DesktopNotificationDelegate> delegate, NotificationDelegate* delegate);
base::Closure* cancel_callback) = 0;
std::set<Notification*> notifications() const { return notifications_; }
protected:
NotificationPresenter();
private:
friend class Notification;
void RemoveNotification(Notification* notification);
std::set<Notification*> notifications_;
DISALLOW_COPY_AND_ASSIGN(NotificationPresenter);
}; };
} // namespace brightray } // namespace brightray

View file

@ -5,11 +5,22 @@
#include "browser/platform_notification_service.h" #include "browser/platform_notification_service.h"
#include "browser/browser_client.h" #include "browser/browser_client.h"
#include "browser/notification.h"
#include "browser/notification_delegate_adapter.h"
#include "browser/notification_presenter.h" #include "browser/notification_presenter.h"
#include "content/public/browser/desktop_notification_delegate.h" #include "content/public/common/platform_notification_data.h"
namespace brightray { namespace brightray {
namespace {
void RemoveNotification(base::WeakPtr<Notification> notification) {
if (notification)
notification->Dismiss();
}
} // namespace
PlatformNotificationService::PlatformNotificationService( PlatformNotificationService::PlatformNotificationService(
BrowserClient* browser_client) BrowserClient* browser_client)
: browser_client_(browser_client) { : browser_client_(browser_client) {
@ -35,12 +46,20 @@ void PlatformNotificationService::DisplayNotification(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const GURL& origin, const GURL& origin,
const SkBitmap& icon, const SkBitmap& icon,
const content::PlatformNotificationData& notification_data, const content::PlatformNotificationData& data,
scoped_ptr<content::DesktopNotificationDelegate> delegate, scoped_ptr<content::DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) { base::Closure* cancel_callback) {
auto presenter = browser_client_->GetNotificationPresenter(); auto presenter = browser_client_->GetNotificationPresenter();
if (presenter) if (!presenter)
presenter->ShowNotification(notification_data, icon, delegate.Pass(), cancel_callback); return;
scoped_ptr<NotificationDelegateAdapter> adapter(
new NotificationDelegateAdapter(delegate.Pass()));
auto notification = presenter->CreateNotification(adapter.get());
if (notification) {
ignore_result(adapter.release()); // it will release itself automatically.
notification->Show(data.title, data.body, icon);
*cancel_callback = base::Bind(&RemoveNotification, notification);
}
} }
void PlatformNotificationService::DisplayPersistentNotification( void PlatformNotificationService::DisplayPersistentNotification(

View file

@ -36,8 +36,8 @@
'browser/mac/bry_inspectable_web_contents_view.mm', 'browser/mac/bry_inspectable_web_contents_view.mm',
'browser/mac/cocoa_notification.h', 'browser/mac/cocoa_notification.h',
'browser/mac/cocoa_notification.mm', 'browser/mac/cocoa_notification.mm',
'browser/mac/notification_delegate.h', 'browser/mac/notification_center_delegate.h',
'browser/mac/notification_delegate.mm', 'browser/mac/notification_center_delegate.mm',
'browser/mac/notification_presenter_mac.h', 'browser/mac/notification_presenter_mac.h',
'browser/mac/notification_presenter_mac.mm', 'browser/mac/notification_presenter_mac.mm',
'browser/media/media_capture_devices_dispatcher.cc', 'browser/media/media_capture_devices_dispatcher.cc',
@ -60,7 +60,12 @@
'browser/net_log.h', 'browser/net_log.h',
'browser/network_delegate.cc', 'browser/network_delegate.cc',
'browser/network_delegate.h', 'browser/network_delegate.h',
'browser/notification_delegate.h',
'browser/notification_delegate_adapter.cc',
'browser/notification_delegate_adapter.h',
'browser/notification_presenter.cc',
'browser/notification_presenter.h', 'browser/notification_presenter.h',
'browser/notification.cc',
'browser/notification.h', 'browser/notification.h',
'browser/permission_manager.cc', 'browser/permission_manager.cc',
'browser/permission_manager.h', 'browser/permission_manager.h',