From 862f3c21f60c3ae257b9c1361987382d9c189178 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Dec 2015 10:46:08 +0800 Subject: [PATCH] Load libnotify dynamically --- brightray/browser/linux/libnotify_loader.cc | 113 ++++++++++++++++++ brightray/browser/linux/libnotify_loader.h | 41 +++++++ .../linux/notification_presenter_linux.cc | 43 +++++-- .../linux/notification_presenter_linux.h | 6 +- brightray/filenames.gypi | 2 + 5 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 brightray/browser/linux/libnotify_loader.cc create mode 100644 brightray/browser/linux/libnotify_loader.h diff --git a/brightray/browser/linux/libnotify_loader.cc b/brightray/browser/linux/libnotify_loader.cc new file mode 100644 index 000000000000..ede4eeec670c --- /dev/null +++ b/brightray/browser/linux/libnotify_loader.cc @@ -0,0 +1,113 @@ +// This is generated file. Do not modify directly. +// Path to the code generator: tools/generate_library_loader/generate_library_loader.py . + +#include "browser/linux/libnotify_loader.h" + +#include + +LibNotifyLoader::LibNotifyLoader() : loaded_(false) { +} + +LibNotifyLoader::~LibNotifyLoader() { + CleanUp(loaded_); +} + +bool LibNotifyLoader::Load(const std::string& library_name) { + if (loaded_) + return false; + + library_ = dlopen(library_name.c_str(), RTLD_LAZY); + if (!library_) + return false; + + notify_is_initted = + reinterpret_castnotify_is_initted)>( + dlsym(library_, "notify_is_initted")); + notify_is_initted = &::notify_is_initted; + if (!notify_is_initted) { + CleanUp(true); + return false; + } + + notify_init = + reinterpret_castnotify_init)>( + dlsym(library_, "notify_init")); + notify_init = &::notify_init; + if (!notify_init) { + CleanUp(true); + return false; + } + + notify_notification_new = + reinterpret_castnotify_notification_new)>( + dlsym(library_, "notify_notification_new")); + notify_notification_new = &::notify_notification_new; + if (!notify_notification_new) { + CleanUp(true); + return false; + } + + notify_notification_add_action = + reinterpret_castnotify_notification_add_action)>( + dlsym(library_, "notify_notification_add_action")); + notify_notification_add_action = &::notify_notification_add_action; + if (!notify_notification_add_action) { + CleanUp(true); + return false; + } + + notify_notification_set_image_from_pixbuf = + reinterpret_castnotify_notification_set_image_from_pixbuf)>( + dlsym(library_, "notify_notification_set_image_from_pixbuf")); + notify_notification_set_image_from_pixbuf = &::notify_notification_set_image_from_pixbuf; + if (!notify_notification_set_image_from_pixbuf) { + CleanUp(true); + return false; + } + + notify_notification_set_timeout = + reinterpret_castnotify_notification_set_timeout)>( + dlsym(library_, "notify_notification_set_timeout")); + notify_notification_set_timeout = &::notify_notification_set_timeout; + if (!notify_notification_set_timeout) { + CleanUp(true); + return false; + } + + notify_notification_show = + reinterpret_castnotify_notification_show)>( + dlsym(library_, "notify_notification_show")); + notify_notification_show = &::notify_notification_show; + if (!notify_notification_show) { + CleanUp(true); + return false; + } + + notify_notification_close = + reinterpret_castnotify_notification_close)>( + dlsym(library_, "notify_notification_close")); + notify_notification_close = &::notify_notification_close; + if (!notify_notification_close) { + CleanUp(true); + return false; + } + + loaded_ = true; + return true; +} + +void LibNotifyLoader::CleanUp(bool unload) { + if (unload) { + dlclose(library_); + library_ = NULL; + } + loaded_ = false; + notify_is_initted = NULL; + notify_init = NULL; + notify_notification_new = NULL; + notify_notification_add_action = NULL; + notify_notification_set_image_from_pixbuf = NULL; + notify_notification_set_timeout = NULL; + notify_notification_show = NULL; + notify_notification_close = NULL; +} diff --git a/brightray/browser/linux/libnotify_loader.h b/brightray/browser/linux/libnotify_loader.h new file mode 100644 index 000000000000..6cf2853af2c6 --- /dev/null +++ b/brightray/browser/linux/libnotify_loader.h @@ -0,0 +1,41 @@ +// This is generated file. Do not modify directly. +// Path to the code generator: tools/generate_library_loader/generate_library_loader.py . + +#ifndef BRIGHTRAY_BROWSER_LINUX_LIBNOTIFY_LOADER_H_ +#define BRIGHTRAY_BROWSER_LINUX_LIBNOTIFY_LOADER_H_ + +#include + +#include + +class LibNotifyLoader { + public: + LibNotifyLoader(); + ~LibNotifyLoader(); + + bool Load(const std::string& library_name) + __attribute__((warn_unused_result)); + + bool loaded() const { return loaded_; } + + decltype(&::notify_is_initted) notify_is_initted; + decltype(&::notify_init) notify_init; + decltype(&::notify_notification_new) notify_notification_new; + decltype(&::notify_notification_add_action) notify_notification_add_action; + decltype(&::notify_notification_set_image_from_pixbuf) notify_notification_set_image_from_pixbuf; + decltype(&::notify_notification_set_timeout) notify_notification_set_timeout; + decltype(&::notify_notification_show) notify_notification_show; + decltype(&::notify_notification_close) notify_notification_close; + + private: + void CleanUp(bool unload); + + void* library_; + bool loaded_; + + // Disallow copy constructor and assignment operator. + LibNotifyLoader(const LibNotifyLoader&); + void operator=(const LibNotifyLoader&); +}; + +#endif // BRIGHTRAY_BROWSER_LINUX_LIBNOTIFY_LOADER_H_ diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 10e8dec765f7..253ec26fe0ca 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -10,11 +10,10 @@ #include "base/files/file_enumerator.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" +#include "common/application_info.h" #include "content/public/browser/desktop_notification_delegate.h" #include "content/public/common/platform_notification_data.h" -#include "common/application_info.h" -#include +#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" #include "third_party/skia/include/core/SkBitmap.h" namespace brightray { @@ -65,10 +64,12 @@ content::DesktopNotificationDelegate* GetDelegateFromNotification( // static NotificationPresenter* NotificationPresenter::Create() { - if (!notify_is_initted()) { - notify_init(GetApplicationName().c_str()); - } - return new NotificationPresenterLinux; + scoped_ptr presenter( + new NotificationPresenterLinux); + if (presenter->Init()) + return presenter.release(); + else + return nullptr; } NotificationPresenterLinux::NotificationPresenterLinux() @@ -81,6 +82,19 @@ NotificationPresenterLinux::~NotificationPresenterLinux() { 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, @@ -88,7 +102,8 @@ void NotificationPresenterLinux::ShowNotification( base::Closure* cancel_callback) { std::string title = base::UTF16ToUTF8(data.title); std::string body = base::UTF16ToUTF8(data.body); - NotifyNotification* notification = notify_notification_new(title.c_str(), body.c_str(), nullptr); + NotifyNotification* notification = libnotify_loader_.notify_notification_new( + title.c_str(), body.c_str(), nullptr); content::DesktopNotificationDelegate* delegate = delegate_ptr.release(); @@ -100,19 +115,21 @@ void NotificationPresenterLinux::ShowNotification( // Zen Nature" is difficult, we will test for the presence of the indicate // dbus service if (!UnityIsRunning()) { - notify_notification_add_action( + libnotify_loader_.notify_notification_add_action( notification, "default", "View", OnNotificationViewThunk, this, nullptr); } if (!icon.drawsNothing()) { GdkPixbuf* pixbuf = libgtk2ui::GdkPixbufFromSkBitmap(icon); - notify_notification_set_image_from_pixbuf(notification, pixbuf); - notify_notification_set_timeout(notification, NOTIFY_EXPIRES_DEFAULT); + 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; - notify_notification_show(notification, &error); + libnotify_loader_.notify_notification_show(notification, &error); if (error) { log_and_clear_error(error, "notify_notification_show"); g_object_unref(notification); @@ -131,7 +148,7 @@ void NotificationPresenterLinux::ShowNotification( void NotificationPresenterLinux::CancelNotification(NotifyNotification* notification) { GError* error = nullptr; - notify_notification_close(notification, &error); + libnotify_loader_.notify_notification_close(notification, &error); if (error) log_and_clear_error(error, "notify_notification_close"); diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index ddd79e4c2e8d..d70d1c468a00 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -6,11 +6,10 @@ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ -#include - #include #include "base/compiler_specific.h" +#include "browser/linux/libnotify_loader.h" #include "browser/notification_presenter.h" #include "ui/base/glib/glib_signal.h" @@ -21,6 +20,7 @@ class NotificationPresenterLinux : public NotificationPresenter { NotificationPresenterLinux(); ~NotificationPresenterLinux(); + bool Init(); void RemoveNotification(NotifyNotification *notification); private: @@ -38,6 +38,8 @@ class NotificationPresenterLinux : public NotificationPresenter { 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 diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 5b0fd733c998..91cb88876cce 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -61,6 +61,8 @@ 'browser/permission_manager.h', 'browser/platform_notification_service_impl.cc', 'browser/platform_notification_service_impl.h', + 'browser/linux/libnotify_loader.h', + 'browser/linux/libnotify_loader.cc', 'browser/linux/notification_presenter_linux.h', 'browser/linux/notification_presenter_linux.cc', 'browser/win/notification_presenter_win.h',