From 41084883cfe9206f3d2f716df387d7e79a4d2641 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Dec 2015 21:55:18 +0800 Subject: [PATCH 1/8] Refactor the notification code --- brightray/browser/mac/cocoa_notification.h | 59 ++++++++ brightray/browser/mac/cocoa_notification.mm | 92 ++++++++++++ brightray/browser/mac/notification_delegate.h | 14 ++ .../browser/mac/notification_delegate.mm | 31 ++++ .../browser/mac/notification_presenter_mac.h | 31 ++++ .../browser/mac/notification_presenter_mac.mm | 48 +++++++ .../browser/notification_presenter_mac.h | 56 -------- .../browser/notification_presenter_mac.mm | 133 ------------------ brightray/filenames.gypi | 8 +- 9 files changed, 281 insertions(+), 191 deletions(-) create mode 100644 brightray/browser/mac/cocoa_notification.h create mode 100644 brightray/browser/mac/cocoa_notification.mm create mode 100644 brightray/browser/mac/notification_delegate.h create mode 100644 brightray/browser/mac/notification_delegate.mm create mode 100644 brightray/browser/mac/notification_presenter_mac.h create mode 100644 brightray/browser/mac/notification_presenter_mac.mm delete mode 100644 brightray/browser/notification_presenter_mac.h delete mode 100644 brightray/browser/notification_presenter_mac.mm diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h new file mode 100644 index 00000000000..c1a54678e24 --- /dev/null +++ b/brightray/browser/mac/cocoa_notification.h @@ -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 + +#import + +#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 delegate); + ~CocoaNotification(); + + void ShowNotification(const base::string16& title, + const base::string16& msg, + const SkBitmap& icon); + void DismissNotification(); + + void NotifyDisplayed(); + void NotifyClick(); + + base::WeakPtr GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + private: + static void Cleanup(); + + scoped_ptr delegate_; + base::scoped_nsobject notification_; + + base::WeakPtrFactory weak_factory_; + + static base::scoped_nsobject notification_delegate_; + static std::set notifications_; + + DISALLOW_COPY_AND_ASSIGN(CocoaNotification); +}; + +} // namespace brightray + +#endif // BROWSER_MAC_COCOA_NOTIFICATION_H_ diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm new file mode 100644 index 00000000000..5983cc48a08 --- /dev/null +++ b/brightray/browser/mac/cocoa_notification.mm @@ -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 +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; +} + +// static +void CocoaNotification::Cleanup() { + NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil; + notification_delegate_.reset(); + STLDeleteElements(¬ifications_); +} + +CocoaNotification::CocoaNotification( + scoped_ptr 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 diff --git a/brightray/browser/mac/notification_delegate.h b/brightray/browser/mac/notification_delegate.h new file mode 100644 index 00000000000..41acead8b11 --- /dev/null +++ b/brightray/browser/mac/notification_delegate.h @@ -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 + +@interface NotificationDelegate : NSObject { +} +@end + +#endif // BROWSER_MAC_NOTIFICATION_DELEGATE_H_ diff --git a/brightray/browser/mac/notification_delegate.mm b/brightray/browser/mac/notification_delegate.mm new file mode 100644 index 00000000000..6479eeb91dc --- /dev/null +++ b/brightray/browser/mac/notification_delegate.mm @@ -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 diff --git a/brightray/browser/mac/notification_presenter_mac.h b/brightray/browser/mac/notification_presenter_mac.h new file mode 100644 index 00000000000..9b2f61b7f03 --- /dev/null +++ b/brightray/browser/mac/notification_presenter_mac.h @@ -0,0 +1,31 @@ +// 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. + +#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 delegate, + base::Closure* cancel_callback) override; + + private: + DISALLOW_COPY_AND_ASSIGN(NotificationPresenterMac); +}; + +} // namespace brightray + +#endif diff --git a/brightray/browser/mac/notification_presenter_mac.mm b/brightray/browser/mac/notification_presenter_mac.mm new file mode 100644 index 00000000000..ead663bcbf8 --- /dev/null +++ b/brightray/browser/mac/notification_presenter_mac.mm @@ -0,0 +1,48 @@ +// 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. + +#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 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 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 diff --git a/brightray/browser/notification_presenter_mac.h b/brightray/browser/notification_presenter_mac.h deleted file mode 100644 index 768bf2b6f1a..00000000000 --- a/brightray/browser/notification_presenter_mac.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_ -#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_MAC_H_ - -#include "browser/notification_presenter.h" - -#include - -#import - -#include "base/mac/scoped_nsobject.h" - -@class BRYUserNotificationCenterDelegate; - -namespace brightray { - -class NotificationPresenterMac : public NotificationPresenter { - public: - NotificationPresenterMac(); - ~NotificationPresenterMac(); - - // NotificationPresenter: - void ShowNotification( - const content::PlatformNotificationData&, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) override; - - // Get the delegate accroding from the notification object. - content::DesktopNotificationDelegate* GetDelegateFromNotification( - NSUserNotification* notification); - - // Remove the notification object accroding to its delegate. - void RemoveNotification(content::DesktopNotificationDelegate* delegate); - - private: - void CancelNotification(content::DesktopNotificationDelegate* delegate); - - // 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> - NotificationsMap; - NotificationsMap notifications_map_; - - base::scoped_nsobject delegate_; -}; - -} // namespace brightray - -#endif diff --git a/brightray/browser/notification_presenter_mac.mm b/brightray/browser/notification_presenter_mac.mm deleted file mode 100644 index d7dfe015663..00000000000 --- a/brightray/browser/notification_presenter_mac.mm +++ /dev/null @@ -1,133 +0,0 @@ -// 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. - -#import "browser/notification_presenter_mac.h" - -#include "base/bind.h" -#include "base/stl_util.h" -#include "base/mac/mac_util.h" -#include "base/strings/sys_string_conversions.h" -#include "content/public/common/platform_notification_data.h" -#include "content/public/browser/desktop_notification_delegate.h" -#include "skia/ext/skia_utils_mac.h" - -@interface BRYUserNotificationCenterDelegate : NSObject { - @private - brightray::NotificationPresenterMac* presenter_; -} -- (instancetype)initWithNotificationPresenter:(brightray::NotificationPresenterMac*)presenter; -@end - -namespace brightray { - -namespace { - -} // namespace - -NotificationPresenter* NotificationPresenter::Create() { - return new NotificationPresenterMac; -} - -NotificationPresenterMac::NotificationPresenterMac() - : delegate_([[BRYUserNotificationCenterDelegate alloc] initWithNotificationPresenter:this]) { - NSUserNotificationCenter.defaultUserNotificationCenter.delegate = delegate_; -} - -NotificationPresenterMac::~NotificationPresenterMac() { - NSUserNotificationCenter.defaultUserNotificationCenter.delegate = nil; -} - -void NotificationPresenterMac::ShowNotification( - const content::PlatformNotificationData& data, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) { - auto notification = [[NSUserNotification alloc] init]; - notification.title = base::SysUTF16ToNSString(data.title); - notification.informativeText = base::SysUTF16ToNSString(data.body); - - if ([notification respondsToSelector:@selector(setContentImage:)] && !icon.drawsNothing()) - notification.contentImage = gfx::SkBitmapToNSImageWithColorSpace(icon, base::mac::GetGenericRGBColorSpace()); - - notifications_map_[delegate.get()].reset(notification); - [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:notification]; - - if (cancel_callback) - *cancel_callback = base::Bind( - &NotificationPresenterMac::CancelNotification, - base::Unretained(this), - delegate.release()); -} - -content::DesktopNotificationDelegate* NotificationPresenterMac::GetDelegateFromNotification( - NSUserNotification* notification) { - for (NotificationsMap::const_iterator it = notifications_map_.begin(); - it != notifications_map_.end(); ++it) - if ([it->second isEqual:notification]) - return it->first; - return NULL; -} - -void NotificationPresenterMac::RemoveNotification(content::DesktopNotificationDelegate* delegate) { - if (ContainsKey(notifications_map_, delegate)) { - delete delegate; - notifications_map_.erase(delegate); - } -} - -void NotificationPresenterMac::CancelNotification(content::DesktopNotificationDelegate* delegate) { - if (!ContainsKey(notifications_map_, delegate)) - return; - - // Notifications in -deliveredNotifications aren't the same objects we passed to - // -deliverNotification:, but they will respond YES to -isEqual:. - auto notification = notifications_map_[delegate]; - auto center = NSUserNotificationCenter.defaultUserNotificationCenter; - for (NSUserNotification* deliveredNotification in center.deliveredNotifications) - if ([notification isEqual:deliveredNotification]) { - [center removeDeliveredNotification:deliveredNotification]; - delegate->NotificationClosed(); - break; - } - - RemoveNotification(delegate); -} - -} // namespace brightray - -@implementation BRYUserNotificationCenterDelegate - -- (instancetype)initWithNotificationPresenter:(brightray::NotificationPresenterMac*)presenter { - self = [super init]; - if (!self) - return nil; - - presenter_ = presenter; - return self; -} - -- (void)userNotificationCenter:(NSUserNotificationCenter*)center - didDeliverNotification:(NSUserNotification*)notification { - auto delegate = presenter_->GetDelegateFromNotification(notification); - if (delegate) - delegate->NotificationDisplayed(); -} - -- (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. - return YES; -} - -@end diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 91cb88876cc..2f7ed8d3680 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -34,6 +34,12 @@ 'browser/mac/bry_application.mm', 'browser/mac/bry_inspectable_web_contents_view.h', '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_presenter_mac.h', + 'browser/mac/notification_presenter_mac.mm', 'browser/media/media_capture_devices_dispatcher.cc', 'browser/media/media_capture_devices_dispatcher.h', 'browser/media/media_stream_devices_controller.cc', @@ -55,8 +61,6 @@ 'browser/network_delegate.cc', 'browser/network_delegate.h', 'browser/notification_presenter.h', - 'browser/notification_presenter_mac.h', - 'browser/notification_presenter_mac.mm', 'browser/permission_manager.cc', 'browser/permission_manager.h', 'browser/platform_notification_service_impl.cc', From 9897f3aab04b5caa003e3fc19da5123a76eb6c88 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Dec 2015 22:06:41 +0800 Subject: [PATCH 2/8] Add an abstract Notification class --- brightray/browser/mac/cocoa_notification.h | 17 +++----- brightray/browser/mac/cocoa_notification.mm | 3 +- .../browser/mac/notification_presenter_mac.mm | 2 +- brightray/browser/notification.h | 39 +++++++++++++++++++ brightray/filenames.gypi | 1 + 5 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 brightray/browser/notification.h diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index c1a54678e24..3fefaa51712 100644 --- a/brightray/browser/mac/cocoa_notification.h +++ b/brightray/browser/mac/cocoa_notification.h @@ -10,16 +10,15 @@ #import #include "base/mac/scoped_nsobject.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" +#include "base/memory/scoped_ptr.h" +#include "browser/notification.h" #include "content/public/browser/desktop_notification_delegate.h" @class NotificationDelegate; -class SkBitmap; namespace brightray { -class CocoaNotification { +class CocoaNotification : public Notification { public: static CocoaNotification* FromNSNotification( NSUserNotification* notification); @@ -30,24 +29,18 @@ class CocoaNotification { void ShowNotification(const base::string16& title, const base::string16& msg, - const SkBitmap& icon); - void DismissNotification(); + const SkBitmap& icon) override; + void DismissNotification() override; void NotifyDisplayed(); void NotifyClick(); - base::WeakPtr GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - private: static void Cleanup(); scoped_ptr delegate_; base::scoped_nsobject notification_; - base::WeakPtrFactory weak_factory_; - static base::scoped_nsobject notification_delegate_; static std::set notifications_; diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm index 5983cc48a08..ceaf1f0d4cf 100644 --- a/brightray/browser/mac/cocoa_notification.mm +++ b/brightray/browser/mac/cocoa_notification.mm @@ -40,8 +40,7 @@ void CocoaNotification::Cleanup() { CocoaNotification::CocoaNotification( scoped_ptr delegate) - : delegate_(delegate.Pass()), - weak_factory_(this) { + : delegate_(delegate.Pass()) { if (!notification_delegate_) { notification_delegate_.reset([[NotificationDelegate alloc] init]); NSUserNotificationCenter.defaultUserNotificationCenter.delegate = diff --git a/brightray/browser/mac/notification_presenter_mac.mm b/brightray/browser/mac/notification_presenter_mac.mm index ead663bcbf8..fafde993a9f 100644 --- a/brightray/browser/mac/notification_presenter_mac.mm +++ b/brightray/browser/mac/notification_presenter_mac.mm @@ -13,7 +13,7 @@ namespace brightray { namespace { -void RemoveNotification(base::WeakPtr notification) { +void RemoveNotification(base::WeakPtr notification) { if (notification) notification->DismissNotification(); } diff --git a/brightray/browser/notification.h b/brightray/browser/notification.h new file mode 100644 index 00000000000..b629eda8fde --- /dev/null +++ b/brightray/browser/notification.h @@ -0,0 +1,39 @@ +// 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_H_ +#define BROWSER_NOTIFICATION_H_ + +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" + +class SkBitmap; + +namespace brightray { + +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; + + base::WeakPtr GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + protected: + virtual ~Notification() {} + + private: + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(Notification); +}; + +} // namespace brightray + +#endif // BROWSER_NOTIFICATION_H_ diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 2f7ed8d3680..e8d3b180091 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -61,6 +61,7 @@ 'browser/network_delegate.cc', 'browser/network_delegate.h', 'browser/notification_presenter.h', + 'browser/notification.h', 'browser/permission_manager.cc', 'browser/permission_manager.h', 'browser/platform_notification_service_impl.cc', From 6f81d1e29fca788f0f92c9d71a79c07d75d7d9ae Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Dec 2015 22:20:47 +0800 Subject: [PATCH 3/8] Expose NotificationPresenter to public --- brightray/browser/browser_client.cc | 28 +++++++++-- brightray/browser/browser_client.h | 7 +++ ...pl.cc => platform_notification_service.cc} | 46 ++++++------------- ...impl.h => platform_notification_service.h} | 30 +++++------- brightray/filenames.gypi | 4 +- 5 files changed, 57 insertions(+), 58 deletions(-) rename brightray/browser/{platform_notification_service_impl.cc => platform_notification_service.cc} (50%) rename brightray/browser/{platform_notification_service_impl.h => platform_notification_service.h} (67%) diff --git a/brightray/browser/browser_client.cc b/brightray/browser/browser_client.cc index 18b5fd855e2..465cbce4390 100644 --- a/brightray/browser/browser_client.cc +++ b/brightray/browser/browser_client.cc @@ -4,15 +4,19 @@ #include "browser/browser_client.h" +#include "base/path_service.h" #include "browser/browser_context.h" #include "browser/browser_main_parts.h" #include "browser/devtools_manager_delegate.h" #include "browser/media/media_capture_devices_dispatcher.h" -#include "browser/platform_notification_service_impl.h" - -#include "base/path_service.h" +#include "browser/notification_presenter.h" +#include "browser/platform_notification_service.h" #include "content/public/common/url_constants.h" +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif + namespace brightray { namespace { @@ -38,6 +42,20 @@ BrowserContext* BrowserClient::browser_context() { return browser_main_parts_->browser_context(); } +NotificationPresenter* BrowserClient::GetNotificationPresenter() { + #if defined(OS_WIN) + // Bail out if on Windows 7 or even lower, no operating will follow + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return nullptr; + #endif + + if (!notification_presenter_) { + // Create a new presenter if on OS X, Linux, or Windows 8+ + notification_presenter_.reset(NotificationPresenter::Create()); + } + return notification_presenter_.get(); +} + BrowserMainParts* BrowserClient::OverrideCreateBrowserMainParts( const content::MainFunctionParams&) { return new BrowserMainParts; @@ -65,7 +83,9 @@ content::MediaObserver* BrowserClient::GetMediaObserver() { } content::PlatformNotificationService* BrowserClient::GetPlatformNotificationService() { - return PlatformNotificationServiceImpl::GetInstance(); + if (!notification_service_) + notification_service_.reset(new PlatformNotificationService(this)); + return notification_service_.get(); } void BrowserClient::GetAdditionalAllowedSchemesForFileSystem( diff --git a/brightray/browser/browser_client.h b/brightray/browser/browser_client.h index 0612e56d255..bb6575c9b2b 100644 --- a/brightray/browser/browser_client.h +++ b/brightray/browser/browser_client.h @@ -13,6 +13,8 @@ namespace brightray { class BrowserContext; class BrowserMainParts; class NetLog; +class NotificationPresenter; +class PlatformNotificationService; class BrowserClient : public content::ContentBrowserClient { public: @@ -24,6 +26,8 @@ class BrowserClient : public content::ContentBrowserClient { BrowserContext* browser_context(); BrowserMainParts* browser_main_parts() { return browser_main_parts_; } + NotificationPresenter* GetNotificationPresenter(); + protected: // Subclasses should override this to provide their own BrowserMainParts // implementation. The lifetime of the returned instance is managed by the @@ -51,6 +55,9 @@ class BrowserClient : public content::ContentBrowserClient { NetLog net_log_; private: + scoped_ptr notification_service_; + scoped_ptr notification_presenter_; + DISALLOW_COPY_AND_ASSIGN(BrowserClient); }; diff --git a/brightray/browser/platform_notification_service_impl.cc b/brightray/browser/platform_notification_service.cc similarity index 50% rename from brightray/browser/platform_notification_service_impl.cc rename to brightray/browser/platform_notification_service.cc index 98c41b3bae1..a480771e8c8 100644 --- a/brightray/browser/platform_notification_service_impl.cc +++ b/brightray/browser/platform_notification_service.cc @@ -2,68 +2,48 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-CHROMIUM file. -#include "browser/platform_notification_service_impl.h" +#include "browser/platform_notification_service.h" +#include "browser/browser_client.h" #include "browser/notification_presenter.h" - #include "content/public/browser/desktop_notification_delegate.h" -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - namespace brightray { -// static -PlatformNotificationServiceImpl* -PlatformNotificationServiceImpl::GetInstance() { - return base::Singleton::get(); +PlatformNotificationService::PlatformNotificationService( + BrowserClient* browser_client) + : browser_client_(browser_client) { } -PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() {} -PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} +PlatformNotificationService::~PlatformNotificationService() {} -NotificationPresenter* PlatformNotificationServiceImpl::notification_presenter() { - #if defined(OS_WIN) - // Bail out if on Windows 7 or even lower, no operating will follow - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return nullptr; - #endif - - if (!notification_presenter_) { - // Create a new presenter if on OS X, Linux, or Windows 8+ - notification_presenter_.reset(NotificationPresenter::Create()); - } - return notification_presenter_.get(); -} - -blink::WebNotificationPermission PlatformNotificationServiceImpl::CheckPermissionOnUIThread( +blink::WebNotificationPermission PlatformNotificationService::CheckPermissionOnUIThread( content::BrowserContext* browser_context, const GURL& origin, int render_process_id) { return blink::WebNotificationPermissionAllowed; } -blink::WebNotificationPermission PlatformNotificationServiceImpl::CheckPermissionOnIOThread( +blink::WebNotificationPermission PlatformNotificationService::CheckPermissionOnIOThread( content::ResourceContext* resource_context, const GURL& origin, int render_process_id) { return blink::WebNotificationPermissionAllowed; } -void PlatformNotificationServiceImpl::DisplayNotification( +void PlatformNotificationService::DisplayNotification( content::BrowserContext* browser_context, const GURL& origin, const SkBitmap& icon, const content::PlatformNotificationData& notification_data, scoped_ptr delegate, base::Closure* cancel_callback) { - auto presenter = notification_presenter(); + auto presenter = browser_client_->GetNotificationPresenter(); if (presenter) presenter->ShowNotification(notification_data, icon, delegate.Pass(), cancel_callback); } -void PlatformNotificationServiceImpl::DisplayPersistentNotification( +void PlatformNotificationService::DisplayPersistentNotification( content::BrowserContext* browser_context, int64_t service_worker_registration_id, const GURL& origin, @@ -71,12 +51,12 @@ void PlatformNotificationServiceImpl::DisplayPersistentNotification( const content::PlatformNotificationData& notification_data) { } -void PlatformNotificationServiceImpl::ClosePersistentNotification( +void PlatformNotificationService::ClosePersistentNotification( content::BrowserContext* browser_context, int64_t persistent_notification_id) { } -bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( +bool PlatformNotificationService::GetDisplayedPersistentNotifications( content::BrowserContext* browser_context, std::set* displayed_notifications) { return false; diff --git a/brightray/browser/platform_notification_service_impl.h b/brightray/browser/platform_notification_service.h similarity index 67% rename from brightray/browser/platform_notification_service_impl.h rename to brightray/browser/platform_notification_service.h index 9b657d5395e..0c598965df4 100644 --- a/brightray/browser/platform_notification_service_impl.h +++ b/brightray/browser/platform_notification_service.h @@ -2,31 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-CHROMIUM file. -#ifndef BROWSER_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_ -#define BROWSER_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_ +#ifndef BROWSER_PLATFORM_NOTIFICATION_SERVICE_H_ +#define BROWSER_PLATFORM_NOTIFICATION_SERVICE_H_ -#include "base/memory/singleton.h" #include "content/public/browser/platform_notification_service.h" namespace brightray { -class NotificationPresenter; +class BrowserClient; -class PlatformNotificationServiceImpl +class PlatformNotificationService : public content::PlatformNotificationService { public: - // Returns the active instance of the service in the browser process. Safe to - // be called from any thread. - static PlatformNotificationServiceImpl* GetInstance(); - - NotificationPresenter* notification_presenter(); - - private: - friend struct base::DefaultSingletonTraits; - - PlatformNotificationServiceImpl(); - ~PlatformNotificationServiceImpl() override; + explicit PlatformNotificationService(BrowserClient* browser_client); + ~PlatformNotificationService() override; + protected: // content::PlatformNotificationService: blink::WebNotificationPermission CheckPermissionOnUIThread( content::BrowserContext* browser_context, @@ -56,11 +47,12 @@ class PlatformNotificationServiceImpl content::BrowserContext* browser_context, std::set* displayed_notifications) override; - scoped_ptr notification_presenter_; + private: + BrowserClient* browser_client_; - DISALLOW_COPY_AND_ASSIGN(PlatformNotificationServiceImpl); + DISALLOW_COPY_AND_ASSIGN(PlatformNotificationService); }; } // namespace brightray -#endif // BROWSER_PLATFORM_NOTIFICATION_SERVICE_IMPL_H_ +#endif // BROWSER_PLATFORM_NOTIFICATION_SERVICE_H_ diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index e8d3b180091..1e4868b7922 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -64,8 +64,8 @@ 'browser/notification.h', 'browser/permission_manager.cc', 'browser/permission_manager.h', - 'browser/platform_notification_service_impl.cc', - 'browser/platform_notification_service_impl.h', + 'browser/platform_notification_service.cc', + 'browser/platform_notification_service.h', 'browser/linux/libnotify_loader.h', 'browser/linux/libnotify_loader.cc', 'browser/linux/notification_presenter_linux.h', From 5b7c7be80440762e55f0c11759c197cf1e58d026 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Dec 2015 10:16:07 +0800 Subject: [PATCH 4/8] Decouple notification code from content module --- brightray/browser/mac/cocoa_notification.h | 29 +++----- brightray/browser/mac/cocoa_notification.mm | 67 ++++++------------- ...egate.h => notification_center_delegate.h} | 10 ++- ...ate.mm => notification_center_delegate.mm} | 18 +++-- .../browser/mac/notification_presenter_mac.h | 16 +++-- .../browser/mac/notification_presenter_mac.mm | 54 ++++++--------- brightray/browser/notification.cc | 27 ++++++++ brightray/browser/notification.h | 36 ++++++++-- brightray/browser/notification_delegate.h | 20 ++++++ .../browser/notification_delegate_adapter.cc | 33 +++++++++ .../browser/notification_delegate_adapter.h | 36 ++++++++++ brightray/browser/notification_presenter.cc | 31 +++++++++ brightray/browser/notification_presenter.h | 42 +++++++----- .../browser/platform_notification_service.cc | 27 ++++++-- brightray/filenames.gypi | 9 ++- 15 files changed, 316 insertions(+), 139 deletions(-) rename brightray/browser/mac/{notification_delegate.h => notification_center_delegate.h} (52%) rename brightray/browser/mac/{notification_delegate.mm => notification_center_delegate.mm} (62%) create mode 100644 brightray/browser/notification.cc create mode 100644 brightray/browser/notification_delegate.h create mode 100644 brightray/browser/notification_delegate_adapter.cc create mode 100644 brightray/browser/notification_delegate_adapter.h create mode 100644 brightray/browser/notification_presenter.cc diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index 3fefaa51712..027e8373de1 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 ceaf1f0d4cf..317211db049 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 41acead8b11..6bee83d411b 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 6479eeb91dc..53537bdc311 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 9b2f61b7f03..825a1dada23 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 fafde993a9f..a37e9182fc6 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 00000000000..6384737c21b --- /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 b629eda8fde..9bc4ac44225 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 00000000000..efecaa54010 --- /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 00000000000..da9a70aab39 --- /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 00000000000..b48c7376cb0 --- /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 00000000000..ad46e292a27 --- /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 6c1a66fc593..b3dac3005dc 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 a480771e8c8..0d3ecfc180b 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 1e4868b7922..4dc441d4b9e 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', From b091f27abfc2d280c667f512ce42ab2e17423217 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Dec 2015 11:05:48 +0800 Subject: [PATCH 5/8] win: Adapt to new Notification style --- brightray/browser/mac/cocoa_notification.h | 2 + brightray/browser/mac/cocoa_notification.mm | 1 + brightray/browser/notification.h | 2 + .../browser/platform_notification_service.cc | 2 +- .../browser/win/notification_presenter_win.cc | 23 +------ .../browser/win/notification_presenter_win.h | 12 +--- .../browser/win/windows_toast_notification.cc | 65 +++++++++++++------ .../browser/win/windows_toast_notification.h | 36 +++++----- 8 files changed, 72 insertions(+), 71 deletions(-) diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index 027e8373de1..9f967a5e5f9 100644 --- a/brightray/browser/mac/cocoa_notification.h +++ b/brightray/browser/mac/cocoa_notification.h @@ -19,8 +19,10 @@ class CocoaNotification : public Notification { NotificationPresenter* presenter); ~CocoaNotification(); + // Notification: void Show(const base::string16& title, const base::string16& msg, + const GURL& icon_url, const SkBitmap& icon) override; void Dismiss() override; diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm index 317211db049..4b24e10f52b 100644 --- a/brightray/browser/mac/cocoa_notification.mm +++ b/brightray/browser/mac/cocoa_notification.mm @@ -32,6 +32,7 @@ CocoaNotification::~CocoaNotification() { void CocoaNotification::Show(const base::string16& title, const base::string16& body, + const GURL& icon_url, const SkBitmap& icon) { notification_.reset([[NSUserNotification alloc] init]); [notification_ setTitle:base::SysUTF16ToNSString(title)]; diff --git a/brightray/browser/notification.h b/brightray/browser/notification.h index 9bc4ac44225..9d0deccbf45 100644 --- a/brightray/browser/notification.h +++ b/brightray/browser/notification.h @@ -8,6 +8,7 @@ #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +class GURL; class SkBitmap; namespace brightray { @@ -20,6 +21,7 @@ class Notification { // Shows the notification. virtual void Show(const base::string16& title, const base::string16& msg, + const GURL& icon_url, const SkBitmap& icon) = 0; // Closes the notification, this instance will be destroyed after the // notification gets closed. diff --git a/brightray/browser/platform_notification_service.cc b/brightray/browser/platform_notification_service.cc index 0d3ecfc180b..7d91ce5f2e4 100644 --- a/brightray/browser/platform_notification_service.cc +++ b/brightray/browser/platform_notification_service.cc @@ -57,7 +57,7 @@ void PlatformNotificationService::DisplayNotification( auto notification = presenter->CreateNotification(adapter.get()); if (notification) { ignore_result(adapter.release()); // it will release itself automatically. - notification->Show(data.title, data.body, icon); + notification->Show(data.title, data.body, data.icon, icon); *cancel_callback = base::Bind(&RemoveNotification, notification); } } diff --git a/brightray/browser/win/notification_presenter_win.cc b/brightray/browser/win/notification_presenter_win.cc index 29534d94bee..d3d4f7dc243 100644 --- a/brightray/browser/win/notification_presenter_win.cc +++ b/brightray/browser/win/notification_presenter_win.cc @@ -31,11 +31,6 @@ bool SaveIconToPath(const SkBitmap& bitmap, const base::FilePath& path) { return base::WriteFile(path, data, size) == size; } -void RemoveNotification(base::WeakPtr notification) { - if (notification) - notification->DismissNotification(); -} - } // namespace // static @@ -58,23 +53,7 @@ bool NotificationPresenterWin::Init() { return temp_dir_.CreateUniqueTempDir(); } -void NotificationPresenterWin::ShowNotification( - const content::PlatformNotificationData& data, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) { - // This class manages itself. - auto notification = new WindowsToastNotification(delegate.Pass()); - notification->ShowNotification( - data.title, data.body, SaveIconToFilesystem(icon, data.icon)); - - if (cancel_callback) { - *cancel_callback = base::Bind( - &RemoveNotification, notification->GetWeakPtr()); - } -} - -std::wstring NotificationPresenterWin::SaveIconToFilesystem( +base::string16 NotificationPresenterWin::SaveIconToFilesystem( const SkBitmap& icon, const GURL& origin) { std::string filename = base::MD5String(origin.spec()) + ".png"; base::FilePath path = temp_dir_.path().Append(base::UTF8ToUTF16(filename)); diff --git a/brightray/browser/win/notification_presenter_win.h b/brightray/browser/win/notification_presenter_win.h index 21152c9cab9..7bcf1a9909d 100644 --- a/brightray/browser/win/notification_presenter_win.h +++ b/brightray/browser/win/notification_presenter_win.h @@ -16,12 +16,12 @@ #ifndef BRIGHTRAY_BROWSER_WIN_NOTIFICATION_PRESENTER_WIN_H_ #define BRIGHTRAY_BROWSER_WIN_NOTIFICATION_PRESENTER_WIN_H_ -#include - #include "base/files/scoped_temp_dir.h" +#include "base/strings/string16.h" #include "browser/notification_presenter.h" class GURL; +class SkBitmap; namespace brightray { @@ -32,15 +32,9 @@ class NotificationPresenterWin : public NotificationPresenter { bool Init(); - void ShowNotification( - const content::PlatformNotificationData&, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) override; + base::string16 SaveIconToFilesystem(const SkBitmap& icon, const GURL& origin); private: - std::wstring SaveIconToFilesystem(const SkBitmap& icon, const GURL& origin); - base::ScopedTempDir temp_dir_; DISALLOW_COPY_AND_ASSIGN(NotificationPresenterWin); diff --git a/brightray/browser/win/windows_toast_notification.cc b/brightray/browser/win/windows_toast_notification.cc index f2d77edf677..050dff56935 100644 --- a/brightray/browser/win/windows_toast_notification.cc +++ b/brightray/browser/win/windows_toast_notification.cc @@ -8,9 +8,10 @@ #include #include "base/strings/utf_string_conversions.h" +#include "browser/notification_delegate.h" #include "browser/win/scoped_hstring.h" +#include "browser/win/notification_presenter_win.h" #include "common/application_info.h" -#include "content/public/browser/desktop_notification_delegate.h" using namespace ABI::Windows::Data::Xml::Dom; @@ -31,6 +32,12 @@ bool GetAppUserModelId(ScopedHString* app_id) { } // namespace +// static +Notification* Notification::Create(NotificationDelegate* delegate, + NotificationPresenter* presenter) { + return new WindowsToastNotification(delegate, presenter); +} + // static ComPtr WindowsToastNotification::toast_manager_; @@ -61,18 +68,25 @@ bool WindowsToastNotification::Initialize() { } WindowsToastNotification::WindowsToastNotification( - scoped_ptr delegate) - : delegate_(delegate.Pass()), - weak_factory_(this) { + NotificationDelegate* delegate, + NotificationPresenter* presenter) + : Notification(delegate, presenter) { } WindowsToastNotification::~WindowsToastNotification() { + // Remove the notification on exit, regardless whether it succeeds. + RemoveCallbacks(toast_notification_.Get()); + Dismiss(); } -void WindowsToastNotification::ShowNotification( - const std::wstring& title, - const std::wstring& msg, - const std::wstring& icon_path) { +void WindowsToastNotification::Show( + const base::string16& title, + const base::string16& msg, + const GURL& icon_url, + const SkBitmap& icon) { + auto presenter_win = static_cast(presenter()); + std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url); + ComPtr toast_xml; if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, &toast_xml))) return; @@ -97,25 +111,25 @@ void WindowsToastNotification::ShowNotification( if (FAILED(toast_notifier_->Show(toast_notification_.Get()))) return; - delegate_->NotificationDisplayed(); + delegate()->NotificationDisplayed(); } -void WindowsToastNotification::DismissNotification() { +void WindowsToastNotification::Dismiss() { toast_notifier_->Hide(toast_notification_.Get()); } void WindowsToastNotification::NotificationClicked() { - delegate_->NotificationClick(); - delete this; + delegate()->NotificationClick(); + Destroy(); } void WindowsToastNotification::NotificationDismissed() { - delegate_->NotificationClosed(); - delete this; + delegate()->NotificationClosed(); + Destroy(); } void WindowsToastNotification::NotificationFailed() { - delete this; + Destroy(); } bool WindowsToastNotification::GetToastXml( @@ -263,16 +277,27 @@ bool WindowsToastNotification::AppendTextToXml( return SUCCEEDED(node->AppendChild(text_node.Get(), &append_node)); } -bool WindowsToastNotification::SetupCallbacks(ABI::Windows::UI::Notifications::IToastNotification* toast) { - EventRegistrationToken activatedToken, dismissedToken, failedToken; +bool WindowsToastNotification::SetupCallbacks( + ABI::Windows::UI::Notifications::IToastNotification* toast) { event_handler_ = Make(this); - if (FAILED(toast->add_Activated(event_handler_.Get(), &activatedToken))) + if (FAILED(toast->add_Activated(event_handler_.Get(), &activated_token_))) return false; - if (FAILED(toast->add_Dismissed(event_handler_.Get(), &dismissedToken))) + if (FAILED(toast->add_Dismissed(event_handler_.Get(), &dismissed_token_))) return false; - return SUCCEEDED(toast->add_Failed(event_handler_.Get(), &failedToken)); + return SUCCEEDED(toast->add_Failed(event_handler_.Get(), &failed_token_)); +} + +bool WindowsToastNotification::RemoveCallbacks( + ABI::Windows::UI::Notifications::IToastNotification* toast) { + if (FAILED(toast->remove_Activated(activated_token_))) + return false; + + if (FAILED(toast->remove_Dismissed(dismissed_token_))) + return false; + + return SUCCEEDED(toast->remove_Failed(failed_token_)); } /* diff --git a/brightray/browser/win/windows_toast_notification.h b/brightray/browser/win/windows_toast_notification.h index a5c0a3d1d24..02e05666992 100644 --- a/brightray/browser/win/windows_toast_notification.h +++ b/brightray/browser/win/windows_toast_notification.h @@ -10,10 +10,7 @@ #include #include -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "content/public/browser/desktop_notification_delegate.h" -#include "content/public/common/platform_notification_data.h" +#include "browser/notification.h" using namespace Microsoft::WRL; @@ -31,23 +28,22 @@ using DesktopToastFailedEventHandler = ABI::Windows::Foundation::ITypedEventHandler; -class WindowsToastNotification { +class WindowsToastNotification : public Notification { public: - // Should be called before using this class. + // Should only be called by NotificationPresenterWin. static bool Initialize(); - WindowsToastNotification( - scoped_ptr delegate); + WindowsToastNotification(NotificationDelegate* delegate, + NotificationPresenter* presenter); ~WindowsToastNotification(); - void ShowNotification(const std::wstring& title, - const std::wstring& msg, - const std::wstring& icon_path); - void DismissNotification(); - - base::WeakPtr GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } + protected: + // Notification: + void Show(const base::string16& title, + const base::string16& msg, + const GURL& icon_url, + const SkBitmap& icon) override; + void Dismiss() override; private: friend class ToastEventHandler; @@ -76,16 +72,18 @@ class WindowsToastNotification { ABI::Windows::Data::Xml::Dom::IXmlNode* node, const std::wstring& text); bool SetupCallbacks(ABI::Windows::UI::Notifications::IToastNotification* toast); + bool RemoveCallbacks(ABI::Windows::UI::Notifications::IToastNotification* toast); static ComPtr toast_manager_; static ComPtr toast_notifier_; - scoped_ptr delegate_; + EventRegistrationToken activated_token_; + EventRegistrationToken dismissed_token_; + EventRegistrationToken failed_token_; + ComPtr event_handler_; ComPtr toast_notification_; - base::WeakPtrFactory weak_factory_; - DISALLOW_COPY_AND_ASSIGN(WindowsToastNotification); }; From c81bacc840a70009f50c2bf57d35b7e8b461bd1d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Dec 2015 11:12:25 +0800 Subject: [PATCH 6/8] mac: Emit closed when notification is dismissed --- brightray/browser/mac/cocoa_notification.mm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm index 4b24e10f52b..24174e226a9 100644 --- a/brightray/browser/mac/cocoa_notification.mm +++ b/brightray/browser/mac/cocoa_notification.mm @@ -24,10 +24,8 @@ CocoaNotification::CocoaNotification(NotificationDelegate* delegate, } CocoaNotification::~CocoaNotification() { - if (notification_) { - [NSUserNotificationCenter.defaultUserNotificationCenter - removeDeliveredNotification:notification_]; - } + [NSUserNotificationCenter.defaultUserNotificationCenter + removeDeliveredNotification:notification_]; } void CocoaNotification::Show(const base::string16& title, @@ -50,6 +48,9 @@ void CocoaNotification::Show(const base::string16& title, } void CocoaNotification::Dismiss() { + [NSUserNotificationCenter.defaultUserNotificationCenter + removeDeliveredNotification:notification_]; + delegate()->NotificationClosed(); Destroy(); } From 82cef446231a7b8fe5ed03690ce493954403db39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Dec 2015 11:17:35 +0800 Subject: [PATCH 7/8] win: Fire NotificationFailed when failed to show notification --- brightray/browser/notification_delegate.h | 3 ++ .../browser/win/windows_toast_notification.cc | 33 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/brightray/browser/notification_delegate.h b/brightray/browser/notification_delegate.h index efecaa54010..93512f71753 100644 --- a/brightray/browser/notification_delegate.h +++ b/brightray/browser/notification_delegate.h @@ -13,6 +13,9 @@ class NotificationDelegate : public content::DesktopNotificationDelegate { public: // The native Notification object is destroyed. virtual void NotificationDestroyed() {} + + // Failed to send the notification. + virtual void NotificationFailed() {} }; } // namespace brightray diff --git a/brightray/browser/win/windows_toast_notification.cc b/brightray/browser/win/windows_toast_notification.cc index 050dff56935..d08b888e4a8 100644 --- a/brightray/browser/win/windows_toast_notification.cc +++ b/brightray/browser/win/windows_toast_notification.cc @@ -74,9 +74,11 @@ WindowsToastNotification::WindowsToastNotification( } WindowsToastNotification::~WindowsToastNotification() { - // Remove the notification on exit, regardless whether it succeeds. - RemoveCallbacks(toast_notification_.Get()); - Dismiss(); + // Remove the notification on exit. + if (toast_notification_) { + RemoveCallbacks(toast_notification_.Get()); + Dismiss(); + } } void WindowsToastNotification::Show( @@ -88,28 +90,40 @@ void WindowsToastNotification::Show( std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url); ComPtr toast_xml; - if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, &toast_xml))) + if(FAILED(GetToastXml(toast_manager_.Get(), title, msg, icon_path, &toast_xml))) { + NotificationFailed(); return; + } ScopedHString toast_str( RuntimeClass_Windows_UI_Notifications_ToastNotification); - if (!toast_str.success()) + if (!toast_str.success()) { + NotificationFailed(); return; + } ComPtr toast_factory; if (FAILED(Windows::Foundation::GetActivationFactory(toast_str, - &toast_factory))) + &toast_factory))) { + NotificationFailed(); return; + } if (FAILED(toast_factory->CreateToastNotification(toast_xml.Get(), - &toast_notification_))) + &toast_notification_))) { + NotificationFailed(); return; + } - if (FAILED(SetupCallbacks(toast_notification_.Get()))) + if (FAILED(SetupCallbacks(toast_notification_.Get()))) { + NotificationFailed(); return; + } - if (FAILED(toast_notifier_->Show(toast_notification_.Get()))) + if (FAILED(toast_notifier_->Show(toast_notification_.Get()))) { + NotificationFailed(); return; + } delegate()->NotificationDisplayed(); } @@ -129,6 +143,7 @@ void WindowsToastNotification::NotificationDismissed() { } void WindowsToastNotification::NotificationFailed() { + delegate()->NotificationFailed(); Destroy(); } From 870e6a6f896318136e7c9e7b62c08e90e38c42a4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Dec 2015 11:52:19 +0800 Subject: [PATCH 8/8] linux: Adapt to new Notification style --- .../browser/linux/libnotify_notification.cc | 157 +++++++++++++++++ .../browser/linux/libnotify_notification.h | 46 +++++ .../linux/notification_presenter_linux.cc | 162 +----------------- .../linux/notification_presenter_linux.h | 33 +--- brightray/browser/mac/cocoa_notification.h | 1 - brightray/filenames.gypi | 2 + 6 files changed, 210 insertions(+), 191 deletions(-) create mode 100644 brightray/browser/linux/libnotify_notification.cc create mode 100644 brightray/browser/linux/libnotify_notification.h diff --git a/brightray/browser/linux/libnotify_notification.cc b/brightray/browser/linux/libnotify_notification.cc new file mode 100644 index 00000000000..98aa3ffd8a7 --- /dev/null +++ b/brightray/browser/linux/libnotify_notification.cc @@ -0,0 +1,157 @@ +// 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/linux/libnotify_notification.h" + +#include "base/files/file_enumerator.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "browser/notification_delegate.h" +#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" +#include "common/application_info.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace brightray { + +namespace { + +bool unity_has_result = false; +bool unity_result = false; + +bool UnityIsRunning() { + if (getenv("ELECTRON_USE_UBUNTU_NOTIFIER")) + return true; + + if (unity_has_result) + return unity_result; + + unity_has_result = true; + + // Look for the presence of libunity as our hint that we're under Ubuntu. + base::FileEnumerator enumerator(base::FilePath("/usr/lib"), + false, base::FileEnumerator::FILES); + base::FilePath haystack; + while (!((haystack = enumerator.Next()).empty())) { + if (base::StartsWith(haystack.value(), "/usr/lib/libunity-", + base::CompareCase::SENSITIVE)) { + unity_result = true; + break; + } + } + + return unity_result; +} + +void log_and_clear_error(GError* error, const char* context) { + LOG(ERROR) << context + << ": domain=" << error->domain + << " code=" << error->code + << " message=\"" << error->message << '"'; + g_error_free(error); +} + +} // namespace + +// static +Notification* Notification::Create(NotificationDelegate* delegate, + NotificationPresenter* presenter) { + return new LibnotifyNotification(delegate, presenter); +} + +// static +LibNotifyLoader LibnotifyNotification::libnotify_loader_; + +// static +bool LibnotifyNotification::Initialize() { + if (!libnotify_loader_.Load("libnotify.so.4") && + !libnotify_loader_.Load("libnotify.so.1") && + !libnotify_loader_.Load("libnotify.so")) { + return false; + } + if (!libnotify_loader_.notify_is_initted() && + !libnotify_loader_.notify_init(GetApplicationName().c_str())) { + return false; + } + return true; +} + +LibnotifyNotification::LibnotifyNotification(NotificationDelegate* delegate, + NotificationPresenter* presenter) + : Notification(delegate, presenter), + notification_(nullptr) { +} + +LibnotifyNotification::~LibnotifyNotification() { + g_object_unref(notification_); +} + +void LibnotifyNotification::Show(const base::string16& title, + const base::string16& body, + const GURL& icon_url, + const SkBitmap& icon) { + notification_ = libnotify_loader_.notify_notification_new( + base::UTF16ToUTF8(title).c_str(), + base::UTF16ToUTF8(body).c_str(), + nullptr); + + g_signal_connect( + notification_, "closed", G_CALLBACK(OnNotificationClosedThunk), this); + + // NB: On Unity, adding a notification action will cause the notification + // to display as a modal dialog box. Testing for distros that have "Unity + // Zen Nature" is difficult, we will test for the presence of the indicate + // dbus service + if (!UnityIsRunning()) { + libnotify_loader_.notify_notification_add_action( + notification_, "default", "View", OnNotificationViewThunk, this, + nullptr); + } + + if (!icon.drawsNothing()) { + GdkPixbuf* pixbuf = libgtk2ui::GdkPixbufFromSkBitmap(icon); + libnotify_loader_.notify_notification_set_image_from_pixbuf( + notification_, pixbuf); + libnotify_loader_.notify_notification_set_timeout( + notification_, NOTIFY_EXPIRES_DEFAULT); + g_object_unref(pixbuf); + } + + GError* error = nullptr; + libnotify_loader_.notify_notification_show(notification_, &error); + if (error) { + log_and_clear_error(error, "notify_notification_show"); + NotificationFailed(); + return; + } + + delegate()->NotificationDisplayed(); +} + +void LibnotifyNotification::Dismiss() { + GError* error = nullptr; + libnotify_loader_.notify_notification_close(notification_, &error); + if (error) { + log_and_clear_error(error, "notify_notification_close"); + Destroy(); + } +} + +void LibnotifyNotification::OnNotificationClosed( + NotifyNotification* notification) { + delegate()->NotificationClosed(); + Destroy(); +} + +void LibnotifyNotification::OnNotificationView( + NotifyNotification* notification, char* action) { + delegate()->NotificationClick(); + Destroy(); +} + +void LibnotifyNotification::NotificationFailed() { + delegate()->NotificationFailed(); + Destroy(); +} + +} // namespace brightray diff --git a/brightray/browser/linux/libnotify_notification.h b/brightray/browser/linux/libnotify_notification.h new file mode 100644 index 00000000000..be2f4280bc4 --- /dev/null +++ b/brightray/browser/linux/libnotify_notification.h @@ -0,0 +1,46 @@ +// 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_LINUX_LIBNOTIFY_NOTIFICATION_H_ +#define BROWSER_LINUX_LIBNOTIFY_NOTIFICATION_H_ + +#include "browser/linux/libnotify_loader.h" +#include "browser/notification.h" +#include "ui/base/glib/glib_signal.h" + +namespace brightray { + +class LibnotifyNotification : public Notification { + public: + LibnotifyNotification(NotificationDelegate* delegate, + NotificationPresenter* presenter); + virtual ~LibnotifyNotification(); + + static bool Initialize(); + + // Notification: + void Show(const base::string16& title, + const base::string16& msg, + const GURL& icon_url, + const SkBitmap& icon) override; + void Dismiss() override; + + private: + CHROMEG_CALLBACK_0(LibnotifyNotification, void, OnNotificationClosed, + NotifyNotification*); + CHROMEG_CALLBACK_1(LibnotifyNotification, void, OnNotificationView, + NotifyNotification*, char*); + + void NotificationFailed(); + + static LibNotifyLoader libnotify_loader_; + + NotifyNotification* notification_; + + DISALLOW_COPY_AND_ASSIGN(LibnotifyNotification); +}; + +} // namespace brightray + +#endif // BROWSER_LINUX_LIBNOTIFY_NOTIFICATION_H_ diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 253ec26fe0c..c846fca6659 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -5,175 +5,21 @@ #include "browser/linux/notification_presenter_linux.h" -#include "base/bind.h" -#include "base/logging.h" -#include "base/files/file_enumerator.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "common/application_info.h" -#include "content/public/browser/desktop_notification_delegate.h" -#include "content/public/common/platform_notification_data.h" -#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" -#include "third_party/skia/include/core/SkBitmap.h" +#include "browser/linux/libnotify_notification.h" namespace brightray { -namespace { - -bool unity_has_result = false; -bool unity_result = false; - -bool UnityIsRunning() { - if (getenv("ELECTRON_USE_UBUNTU_NOTIFIER")) - return true; - - if (unity_has_result) - return unity_result; - - unity_has_result = true; - - // Look for the presence of libunity as our hint that we're under Ubuntu. - base::FileEnumerator enumerator(base::FilePath("/usr/lib"), - false, base::FileEnumerator::FILES); - base::FilePath haystack; - while (!((haystack = enumerator.Next()).empty())) { - if (base::StartsWith(haystack.value(), "/usr/lib/libunity-", base::CompareCase::SENSITIVE)) { - unity_result = true; - break; - } - } - - return unity_result; -} - -void log_and_clear_error(GError* error, const char* context) { - LOG(ERROR) << context - << ": domain=" << error->domain - << " code=" << error->code - << " message=\"" << error->message << '"'; - g_error_free(error); -} - -content::DesktopNotificationDelegate* GetDelegateFromNotification( - NotifyNotification* notification) { - return static_cast( - g_object_get_data(G_OBJECT(notification), "delegate")); -} - -} // namespace - // static NotificationPresenter* NotificationPresenter::Create() { - scoped_ptr presenter( - new NotificationPresenterLinux); - if (presenter->Init()) - return presenter.release(); - else + if (!LibnotifyNotification::Initialize()) return nullptr; + return new NotificationPresenterLinux; } -NotificationPresenterLinux::NotificationPresenterLinux() - : notifications_(nullptr) { +NotificationPresenterLinux::NotificationPresenterLinux() { } NotificationPresenterLinux::~NotificationPresenterLinux() { - // unref any outstanding notifications, and then free the list. - if (notifications_) - g_list_free_full(notifications_, g_object_unref); -} - -bool NotificationPresenterLinux::Init() { - if (!libnotify_loader_.Load("libnotify.so.4") && - !libnotify_loader_.Load("libnotify.so.1") && - !libnotify_loader_.Load("libnotify.so")) { - return false; - } - if (!libnotify_loader_.notify_is_initted() && - !libnotify_loader_.notify_init(GetApplicationName().c_str())) { - return false; - } - return true; -} - -void NotificationPresenterLinux::ShowNotification( - const content::PlatformNotificationData& data, - const SkBitmap& icon, - scoped_ptr delegate_ptr, - base::Closure* cancel_callback) { - std::string title = base::UTF16ToUTF8(data.title); - std::string body = base::UTF16ToUTF8(data.body); - NotifyNotification* notification = libnotify_loader_.notify_notification_new( - title.c_str(), body.c_str(), nullptr); - - content::DesktopNotificationDelegate* delegate = delegate_ptr.release(); - - g_object_set_data_full(G_OBJECT(notification), "delegate", delegate, operator delete); - g_signal_connect(notification, "closed", G_CALLBACK(OnNotificationClosedThunk), this); - - // NB: On Unity, adding a notification action will cause the notification - // to display as a modal dialog box. Testing for distros that have "Unity - // Zen Nature" is difficult, we will test for the presence of the indicate - // dbus service - if (!UnityIsRunning()) { - libnotify_loader_.notify_notification_add_action( - notification, "default", "View", OnNotificationViewThunk, this, nullptr); - } - - if (!icon.drawsNothing()) { - GdkPixbuf* pixbuf = libgtk2ui::GdkPixbufFromSkBitmap(icon); - libnotify_loader_.notify_notification_set_image_from_pixbuf( - notification, pixbuf); - libnotify_loader_.notify_notification_set_timeout( - notification, NOTIFY_EXPIRES_DEFAULT); - g_object_unref(pixbuf); - } - - GError* error = nullptr; - libnotify_loader_.notify_notification_show(notification, &error); - if (error) { - log_and_clear_error(error, "notify_notification_show"); - g_object_unref(notification); - return; - } - - notifications_ = g_list_append(notifications_, notification); - delegate->NotificationDisplayed(); - - if (cancel_callback) - *cancel_callback = base::Bind( - &NotificationPresenterLinux::CancelNotification, - base::Unretained(this), - notification); -} - -void NotificationPresenterLinux::CancelNotification(NotifyNotification* notification) { - GError* error = nullptr; - libnotify_loader_.notify_notification_close(notification, &error); - if (error) - log_and_clear_error(error, "notify_notification_close"); - - GetDelegateFromNotification(notification)->NotificationClosed(); - DeleteNotification(notification); -} - -void NotificationPresenterLinux::DeleteNotification(NotifyNotification* notification) { - notifications_ = g_list_remove(notifications_, notification); - g_object_unref(notification); -} - -void NotificationPresenterLinux::OnNotificationClosed(NotifyNotification* notification) { - if (!notification) - return; - GetDelegateFromNotification(notification)->NotificationClosed(); - DeleteNotification(notification); -} - -void NotificationPresenterLinux::OnNotificationView( - NotifyNotification* notification, char* action) { - if (!notification) - return; - GetDelegateFromNotification(notification)->NotificationClick(); - DeleteNotification(notification); } } // namespace brightray diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index d70d1c468a0..ef436799484 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -6,12 +6,7 @@ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ -#include - -#include "base/compiler_specific.h" -#include "browser/linux/libnotify_loader.h" #include "browser/notification_presenter.h" -#include "ui/base/glib/glib_signal.h" namespace brightray { @@ -20,34 +15,8 @@ class NotificationPresenterLinux : public NotificationPresenter { NotificationPresenterLinux(); ~NotificationPresenterLinux(); - bool Init(); - void RemoveNotification(NotifyNotification *notification); - private: - // NotificationPresenter: - void ShowNotification( - const content::PlatformNotificationData&, - const SkBitmap& icon, - scoped_ptr delegate, - base::Closure* cancel_callback) override; - - void CancelNotification(NotifyNotification* notification); - void DeleteNotification(NotifyNotification* notification); - - CHROMEG_CALLBACK_0(NotificationPresenterLinux, void, OnNotificationClosed, NotifyNotification*); - CHROMEG_CALLBACK_1(NotificationPresenterLinux, void, OnNotificationView, NotifyNotification*, - char*); - - LibNotifyLoader libnotify_loader_; - - // A list of all open NotifyNotification objects. - // We do lookups here both by NotifyNotification object (when the user - // clicks a notification) and by the ID - // tuple (when the browser asks to dismiss a notification). So it's not - // a map. - // Entries in this list count as refs, so removal from this list should - // always go with g_object_unref(). - GList* notifications_; + DISALLOW_COPY_AND_ASSIGN(NotificationPresenterLinux); }; } // namespace brightray diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index 9f967a5e5f9..b1709568210 100644 --- a/brightray/browser/mac/cocoa_notification.h +++ b/brightray/browser/mac/cocoa_notification.h @@ -32,7 +32,6 @@ class CocoaNotification : public Notification { NSUserNotification* notification() const { return notification_; } private: - NotificationDelegate* delegate_; base::scoped_nsobject notification_; DISALLOW_COPY_AND_ASSIGN(CocoaNotification); diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 4dc441d4b9e..26c02679c05 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -73,6 +73,8 @@ 'browser/platform_notification_service.h', 'browser/linux/libnotify_loader.h', 'browser/linux/libnotify_loader.cc', + 'browser/linux/libnotify_notification.h', + 'browser/linux/libnotify_notification.cc', 'browser/linux/notification_presenter_linux.h', 'browser/linux/notification_presenter_linux.cc', 'browser/win/notification_presenter_win.h',