diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index 3fefaa51712e..027e8373de19 100644 --- a/brightray/browser/mac/cocoa_notification.h +++ b/brightray/browser/mac/cocoa_notification.h @@ -5,45 +5,34 @@ #ifndef BROWSER_MAC_COCOA_NOTIFICATION_H_ #define BROWSER_MAC_COCOA_NOTIFICATION_H_ -#include - #import #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "browser/notification.h" -#include "content/public/browser/desktop_notification_delegate.h" - -@class NotificationDelegate; namespace brightray { class CocoaNotification : public Notification { public: - static CocoaNotification* FromNSNotification( - NSUserNotification* notification); - - CocoaNotification( - scoped_ptr delegate); + CocoaNotification(NotificationDelegate* delegate, + NotificationPresenter* presenter); ~CocoaNotification(); - void ShowNotification(const base::string16& title, - const base::string16& msg, - const SkBitmap& icon) override; - void DismissNotification() override; + void Show(const base::string16& title, + const base::string16& msg, + const SkBitmap& icon) override; + void Dismiss() override; void NotifyDisplayed(); void NotifyClick(); + NSUserNotification* notification() const { return notification_; } + private: - static void Cleanup(); - - scoped_ptr delegate_; + NotificationDelegate* delegate_; base::scoped_nsobject notification_; - static base::scoped_nsobject notification_delegate_; - static std::set notifications_; - DISALLOW_COPY_AND_ASSIGN(CocoaNotification); }; diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm index ceaf1f0d4cf5..317211db049c 100644 --- a/brightray/browser/mac/cocoa_notification.mm +++ b/brightray/browser/mac/cocoa_notification.mm @@ -4,62 +4,35 @@ #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 "browser/notification_delegate.h" +#include "browser/notification_presenter.h" #include "skia/ext/skia_utils_mac.h" namespace brightray { // static -base::scoped_nsobject -CocoaNotification::notification_delegate_; - -// static -std::set CocoaNotification::notifications_; - -// static -CocoaNotification* CocoaNotification::FromNSNotification( - NSUserNotification* ns_notification) { - for (CocoaNotification* notification : notifications_) { - if ([notification->notification_ isEqual:ns_notification]) - return notification; - } - return nullptr; +Notification* Notification::Create(NotificationDelegate* delegate, + NotificationPresenter* presenter) { + return new CocoaNotification(delegate, presenter); } -// static -void CocoaNotification::Cleanup() { - NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil; - notification_delegate_.reset(); - STLDeleteElements(¬ifications_); -} - -CocoaNotification::CocoaNotification( - scoped_ptr 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(NotificationDelegate* delegate, + NotificationPresenter* presenter) + : Notification(delegate, presenter) { } CocoaNotification::~CocoaNotification() { - [NSUserNotificationCenter.defaultUserNotificationCenter - removeDeliveredNotification:notification_]; - notifications_.erase(this); + if (notification_) { + [NSUserNotificationCenter.defaultUserNotificationCenter + removeDeliveredNotification:notification_]; + } } -void CocoaNotification::ShowNotification(const base::string16& title, - const base::string16& body, - const SkBitmap& icon) { +void CocoaNotification::Show(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)]; @@ -75,17 +48,17 @@ void CocoaNotification::ShowNotification(const base::string16& title, deliverNotification:notification_]; } -void CocoaNotification::DismissNotification() { - delete this; +void CocoaNotification::Dismiss() { + Destroy(); } void CocoaNotification::NotifyDisplayed() { - delegate_->NotificationDisplayed(); + delegate()->NotificationDisplayed(); } void CocoaNotification::NotifyClick() { - delegate_->NotificationClick(); - delete this; + delegate()->NotificationClick(); + Destroy(); } } // namespace brightray diff --git a/brightray/browser/mac/notification_delegate.h b/brightray/browser/mac/notification_center_delegate.h similarity index 52% rename from brightray/browser/mac/notification_delegate.h rename to brightray/browser/mac/notification_center_delegate.h index 41acead8b117..6bee83d411b4 100644 --- a/brightray/browser/mac/notification_delegate.h +++ b/brightray/browser/mac/notification_center_delegate.h @@ -7,8 +7,16 @@ #import -@interface NotificationDelegate : NSObject { +namespace brightray { +class NotificationPresenterMac; } + +@interface NotificationCenterDelegate : + NSObject { + @private + brightray::NotificationPresenterMac* presenter_; +} +- (instancetype)initWithPresenter:(brightray::NotificationPresenterMac*)presenter; @end #endif // BROWSER_MAC_NOTIFICATION_DELEGATE_H_ diff --git a/brightray/browser/mac/notification_delegate.mm b/brightray/browser/mac/notification_center_delegate.mm similarity index 62% rename from brightray/browser/mac/notification_delegate.mm rename to brightray/browser/mac/notification_center_delegate.mm index 6479eeb91dcc..53537bdc311a 100644 --- a/brightray/browser/mac/notification_delegate.mm +++ b/brightray/browser/mac/notification_center_delegate.mm @@ -2,22 +2,32 @@ // 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/notification_center_delegate.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 didDeliverNotification:(NSUserNotification*)notif { - auto notification = brightray::CocoaNotification::FromNSNotification(notif); + auto notification = presenter_->GetNotification(notif); if (notification) notification->NotifyDisplayed(); } - (void)userNotificationCenter:(NSUserNotificationCenter*)center didActivateNotification:(NSUserNotification *)notif { - auto notification = brightray::CocoaNotification::FromNSNotification(notif); + auto notification = presenter_->GetNotification(notif); if (notification) notification->NotifyClick(); } diff --git a/brightray/browser/mac/notification_presenter_mac.h b/brightray/browser/mac/notification_presenter_mac.h index 9b2f61b7f03b..825a1dada233 100644 --- a/brightray/browser/mac/notification_presenter_mac.h +++ b/brightray/browser/mac/notification_presenter_mac.h @@ -6,23 +6,25 @@ #ifndef 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" namespace brightray { +class CocoaNotification; + class NotificationPresenterMac : public NotificationPresenter { public: + CocoaNotification* GetNotification(NSUserNotification* notif); + NotificationPresenterMac(); ~NotificationPresenterMac(); - // NotificationPresenter: - void ShowNotification( - const content::PlatformNotificationData&, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) override; - private: + base::scoped_nsobject + notification_center_delegate_; + DISALLOW_COPY_AND_ASSIGN(NotificationPresenterMac); }; diff --git a/brightray/browser/mac/notification_presenter_mac.mm b/brightray/browser/mac/notification_presenter_mac.mm index fafde993a9f8..a37e9182fc6e 100644 --- a/brightray/browser/mac/notification_presenter_mac.mm +++ b/brightray/browser/mac/notification_presenter_mac.mm @@ -1,48 +1,38 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Copyright (c) 2013 Adam Roben . All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE 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 "content/public/common/platform_notification_data.h" +#include "browser/mac/notification_center_delegate.h" namespace brightray { -namespace { - -void RemoveNotification(base::WeakPtr notification) { - if (notification) - notification->DismissNotification(); -} - -} // namespace - +// static NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterMac; } -NotificationPresenterMac::NotificationPresenterMac() { +CocoaNotification* NotificationPresenterMac::GetNotification( + NSUserNotification* ns_notification) { + for (Notification* notification : notifications()) { + auto native_notification = static_cast(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() { -} - -void NotificationPresenterMac::ShowNotification( - const content::PlatformNotificationData& data, - const SkBitmap& icon, - scoped_ptr 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()); - } + NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil; } } // namespace brightray diff --git a/brightray/browser/notification.cc b/brightray/browser/notification.cc new file mode 100644 index 000000000000..6384737c21bf --- /dev/null +++ b/brightray/browser/notification.cc @@ -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 diff --git a/brightray/browser/notification.h b/brightray/browser/notification.h index b629eda8fde4..9bc4ac44225c 100644 --- a/brightray/browser/notification.h +++ b/brightray/browser/notification.h @@ -12,23 +12,45 @@ class SkBitmap; namespace brightray { +class NotificationDelegate; +class NotificationPresenter; + class Notification { public: - Notification() : weak_factory_(this) {} - - virtual void ShowNotification(const base::string16& title, - const base::string16& msg, - const SkBitmap& icon) = 0; - virtual void DismissNotification() = 0; + // Shows the notification. + virtual void Show(const base::string16& title, + const base::string16& msg, + const SkBitmap& icon) = 0; + // Closes the notification, this instance will be destroyed after the + // notification gets closed. + virtual void Dismiss() = 0; base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } + NotificationDelegate* delegate() const { return delegate_; } + NotificationPresenter* presenter() const { return presenter_; } + protected: - virtual ~Notification() {} + Notification(NotificationDelegate* delegate, + NotificationPresenter* presenter); + virtual ~Notification(); + + // delete this. + void Destroy(); 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 weak_factory_; DISALLOW_COPY_AND_ASSIGN(Notification); diff --git a/brightray/browser/notification_delegate.h b/brightray/browser/notification_delegate.h new file mode 100644 index 000000000000..efecaa540105 --- /dev/null +++ b/brightray/browser/notification_delegate.h @@ -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_ diff --git a/brightray/browser/notification_delegate_adapter.cc b/brightray/browser/notification_delegate_adapter.cc new file mode 100644 index 000000000000..da9a70aab391 --- /dev/null +++ b/brightray/browser/notification_delegate_adapter.cc @@ -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 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 diff --git a/brightray/browser/notification_delegate_adapter.h b/brightray/browser/notification_delegate_adapter.h new file mode 100644 index 000000000000..b48c7376cb00 --- /dev/null +++ b/brightray/browser/notification_delegate_adapter.h @@ -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 delegate); + ~NotificationDelegateAdapter() override; + + // NotificationDelegate: + void NotificationDestroyed() override; + + // content::DesktopNotificationDelegate: + void NotificationDisplayed() override; + void NotificationClosed() override; + void NotificationClick() override; + + private: + scoped_ptr delegate_; + + DISALLOW_COPY_AND_ASSIGN(NotificationDelegateAdapter); +}; + +} // namespace brightray + +#endif // BROWSER_NOTIFICATION_DELEGATE_ADAPTER_H_ diff --git a/brightray/browser/notification_presenter.cc b/brightray/browser/notification_presenter.cc new file mode 100644 index 000000000000..ad46e292a272 --- /dev/null +++ b/brightray/browser/notification_presenter.cc @@ -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 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 diff --git a/brightray/browser/notification_presenter.h b/brightray/browser/notification_presenter.h index 6c1a66fc5931..b3dac3005dcb 100644 --- a/brightray/browser/notification_presenter.h +++ b/brightray/browser/notification_presenter.h @@ -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_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_H_ -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" +#include -class SkBitmap; - -namespace content { -class DesktopNotificationDelegate; -struct PlatformNotificationData; -} +#include "base/memory/weak_ptr.h" namespace brightray { +class Notification; +class NotificationDelegate; + class NotificationPresenter { public: - virtual ~NotificationPresenter() {} - static NotificationPresenter* Create(); - virtual void ShowNotification( - const content::PlatformNotificationData&, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) = 0; + virtual ~NotificationPresenter(); + + base::WeakPtr CreateNotification( + NotificationDelegate* delegate); + + std::set notifications() const { return notifications_; } + + protected: + NotificationPresenter(); + + private: + friend class Notification; + + void RemoveNotification(Notification* notification); + + std::set notifications_; + + DISALLOW_COPY_AND_ASSIGN(NotificationPresenter); }; } // namespace brightray diff --git a/brightray/browser/platform_notification_service.cc b/brightray/browser/platform_notification_service.cc index a480771e8c8a..0d3ecfc180ba 100644 --- a/brightray/browser/platform_notification_service.cc +++ b/brightray/browser/platform_notification_service.cc @@ -5,11 +5,22 @@ #include "browser/platform_notification_service.h" #include "browser/browser_client.h" +#include "browser/notification.h" +#include "browser/notification_delegate_adapter.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 { + +void RemoveNotification(base::WeakPtr notification) { + if (notification) + notification->Dismiss(); +} + +} // namespace + PlatformNotificationService::PlatformNotificationService( BrowserClient* browser_client) : browser_client_(browser_client) { @@ -35,12 +46,20 @@ void PlatformNotificationService::DisplayNotification( content::BrowserContext* browser_context, const GURL& origin, const SkBitmap& icon, - const content::PlatformNotificationData& notification_data, + const content::PlatformNotificationData& data, scoped_ptr delegate, base::Closure* cancel_callback) { auto presenter = browser_client_->GetNotificationPresenter(); - if (presenter) - presenter->ShowNotification(notification_data, icon, delegate.Pass(), cancel_callback); + if (!presenter) + return; + scoped_ptr 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( diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 1e4868b79224..4dc441d4b9e0 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -36,8 +36,8 @@ 'browser/mac/bry_inspectable_web_contents_view.mm', 'browser/mac/cocoa_notification.h', 'browser/mac/cocoa_notification.mm', - 'browser/mac/notification_delegate.h', - 'browser/mac/notification_delegate.mm', + 'browser/mac/notification_center_delegate.h', + 'browser/mac/notification_center_delegate.mm', 'browser/mac/notification_presenter_mac.h', 'browser/mac/notification_presenter_mac.mm', 'browser/media/media_capture_devices_dispatcher.cc', @@ -60,7 +60,12 @@ 'browser/net_log.h', 'browser/network_delegate.cc', '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.cc', 'browser/notification.h', 'browser/permission_manager.cc', 'browser/permission_manager.h',