Merge pull request #186 from atom/dlopen-notify

Load libnotify dynamically
This commit is contained in:
Cheng Zhao 2015-12-24 11:16:09 +08:00
commit 53e8c8841b
5 changed files with 190 additions and 15 deletions

View file

@ -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 <dlfcn.h>
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_cast<decltype(this->notify_is_initted)>(
dlsym(library_, "notify_is_initted"));
notify_is_initted = &::notify_is_initted;
if (!notify_is_initted) {
CleanUp(true);
return false;
}
notify_init =
reinterpret_cast<decltype(this->notify_init)>(
dlsym(library_, "notify_init"));
notify_init = &::notify_init;
if (!notify_init) {
CleanUp(true);
return false;
}
notify_notification_new =
reinterpret_cast<decltype(this->notify_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_cast<decltype(this->notify_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_cast<decltype(this->notify_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_cast<decltype(this->notify_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_cast<decltype(this->notify_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_cast<decltype(this->notify_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;
}

View file

@ -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 <string>
#include <libnotify/notify.h>
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_

View file

@ -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 <stdlib.h>
#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<NotificationPresenterLinux> 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");

View file

@ -6,11 +6,10 @@
#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_
#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_
#include <libnotify/notify.h>
#include <map>
#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 <process,view,notification> ID

View file

@ -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',