From a82e9f30ed9041d90eb4bf38cadebf6d0c48a652 Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Wed, 18 Dec 2013 15:02:49 -0600 Subject: [PATCH 1/8] use libnotify to pop up notifications on Linux --- brightray/brightray.gyp | 4 +- brightray/browser/browser_client.cc | 2 +- .../linux/notification_presenter_linux.cc | 125 ++++++++++++++++++ .../linux/notification_presenter_linux.h | 36 +++++ 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 brightray/browser/linux/notification_presenter_linux.cc create mode 100644 brightray/browser/linux/notification_presenter_linux.h diff --git a/brightray/brightray.gyp b/brightray/brightray.gyp index 1781172b970..a4baef81f6f 100644 --- a/brightray/brightray.gyp +++ b/brightray/brightray.gyp @@ -64,6 +64,8 @@ 'browser/notification_presenter.h', 'browser/notification_presenter_mac.h', 'browser/notification_presenter_mac.mm', + 'browser/linux/notification_presenter_linux.h', + 'browser/linux/notification_presenter_linux.cc', 'browser/url_request_context_getter.cc', 'browser/url_request_context_getter.h', 'browser/win/devtools_window.cc', @@ -93,7 +95,7 @@ 'libraries': [ '<(brightray_source_root)/<(libchromiumcontent_library_dir)/libchromiumcontent.so', '-lpthread', - '. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE-CHROMIUM file. + +#include "browser/linux/notification_presenter_linux.h" + +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/common/show_desktop_notification_params.h" +#include "common/application_info.h" + +#include + +namespace brightray { + +namespace { + +struct NotificationID { + NotificationID( + int render_process_id, + int render_view_id, + int notification_id) + : render_process_id(render_process_id), + render_view_id(render_view_id), + notification_id(notification_id) { + } + + std::string GetID() { + return base::StringPrintf("%d:%d:%d", render_process_id, render_view_id, notification_id); + } + + int render_process_id; + int render_view_id; + int notification_id; +}; + +void log_and_clear_error(GError *error, const char *context) { + if (error) { + LOG(ERROR) << context << ": domain=" << error->domain << " code=" << error->code << " message=\"" << error->message << "\""; + g_error_free(error); + } +} + +void closed_cb(NotifyNotification *notification, NotificationID *ID) { + auto host = content::RenderViewHost::FromID(ID->render_process_id, ID->render_view_id); + if (host) host->DesktopNotificationPostClick(ID->notification_id); +} + +NotifyNotification *CreateUserNotification( + const content::ShowDesktopNotificationHostMsgParams& params, + int render_process_id, + int render_view_id) { + std::string title = base::UTF16ToUTF8(params.title); + std::string body = base::UTF16ToUTF8(params.body); + NotifyNotification *notification = notify_notification_new(title.c_str(), body.c_str(), NULL); + + return notification; +} + +} + +NotificationPresenter* NotificationPresenter::Create() { + if (!notify_is_initted()) { + notify_init(GetApplicationName().c_str()); + } + return new NotificationPresenterLinux; +} + +void NotificationPresenterLinux::ShowNotification( + const content::ShowDesktopNotificationHostMsgParams& params, + int render_process_id, + int render_view_id) { + DLOG(INFO) << "ShowNotification: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << params.notification_id + << " title=\"" << params.title << '"' + << " body=\"" << params.body << '"'; + NotifyNotification *notification = CreateUserNotification(params, render_process_id, render_view_id); + NotificationID ID(render_process_id, render_view_id, params.notification_id); + std::pair p = notification_map_.insert(std::make_pair(ID.GetID(), notification)); + + g_signal_connect(notification, "closed", G_CALLBACK(closed_cb), new NotificationID(ID)); // FIXME: closure to free it + + GError *error = NULL; + notify_notification_show(notification, &error); + log_and_clear_error(error, "notify_notification_show"); + + auto host = content::RenderViewHost::FromID(ID.render_process_id, ID.render_view_id); + if (!host) + return; + + host->DesktopNotificationPostDisplay(ID.notification_id); +} + +void NotificationPresenterLinux::CancelNotification( + int render_process_id, + int render_view_id, + int notification_id) { + DLOG(INFO) << "CancelNotification: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << notification_id; + + auto found = notification_map_.find(NotificationID(render_process_id, render_view_id, notification_id).GetID()); + if (found == notification_map_.end()) + return; + + auto notification = found->second; + + notification_map_.erase(found); + + GError *error = NULL; + notify_notification_close(notification, &error); + log_and_clear_error(error, "notify_notification_close"); + + NotificationID ID(render_process_id, render_view_id, notification_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + if (!host) + return; + + host->DesktopNotificationPostClose(ID.notification_id, false); +} + +} diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h new file mode 100644 index 00000000000..b3d77dc63e6 --- /dev/null +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -0,0 +1,36 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 Patrick Reynolds . 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_LINUX_H_ +#define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ + +#include "base/compiler_specific.h" +#include "browser/notification_presenter.h" + +#include + +#include + +namespace brightray { + +class NotificationPresenterLinux : public NotificationPresenter { + public: + virtual void ShowNotification( + const content::ShowDesktopNotificationHostMsgParams&, + int render_process_id, + int render_view_id) OVERRIDE; + virtual void CancelNotification( + int render_process_id, + int render_view_id, + int notification_id) OVERRIDE; + + private: + typedef std::map NotificationMap; + NotificationMap notification_map_; +}; + +} // namespace brightray + +#endif From 272b3c30d3258db597eb66d262e18155b916df8f Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Wed, 18 Dec 2013 23:05:19 -0600 Subject: [PATCH 2/8] free notifications properly --- .../linux/notification_presenter_linux.cc | 124 ++++++++++-------- .../linux/notification_presenter_linux.h | 8 +- 2 files changed, 78 insertions(+), 54 deletions(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 56746bbf162..6848ce5111c 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -17,24 +17,9 @@ namespace brightray { namespace { -struct NotificationID { - NotificationID( - int render_process_id, - int render_view_id, - int notification_id) - : render_process_id(render_process_id), - render_view_id(render_view_id), - notification_id(notification_id) { - } - - std::string GetID() { - return base::StringPrintf("%d:%d:%d", render_process_id, render_view_id, notification_id); - } - - int render_process_id; - int render_view_id; - int notification_id; -}; +const char *kRenderProcessIDKey = "RenderProcessID"; +const char *kRenderViewIDKey = "RenderViewID"; +const char *kNotificationIDKey = "NotificationID"; void log_and_clear_error(GError *error, const char *context) { if (error) { @@ -43,20 +28,28 @@ void log_and_clear_error(GError *error, const char *context) { } } -void closed_cb(NotifyNotification *notification, NotificationID *ID) { - auto host = content::RenderViewHost::FromID(ID->render_process_id, ID->render_view_id); - if (host) host->DesktopNotificationPostClick(ID->notification_id); +void closed_cb(NotifyNotification *notification, NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); + LOG(INFO) << "closed_cb: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << notification_id + << " reason=" << notify_notification_get_closed_reason(notification); + obj->RemoveNotification(notification); } -NotifyNotification *CreateUserNotification( - const content::ShowDesktopNotificationHostMsgParams& params, - int render_process_id, - int render_view_id) { - std::string title = base::UTF16ToUTF8(params.title); - std::string body = base::UTF16ToUTF8(params.body); - NotifyNotification *notification = notify_notification_new(title.c_str(), body.c_str(), NULL); - - return notification; +void action_cb(NotifyNotification *notification, const char *action, NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); + LOG(INFO) << "action_cb: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << notification_id + << " action=\"" << action << '"'; + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + if (host) host->DesktopNotificationPostClick(notification_id); + obj->RemoveNotification(notification); } } @@ -68,58 +61,85 @@ NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterLinux; } +NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(NULL) { } + +NotificationPresenterLinux::~NotificationPresenterLinux() { + if (notifications_) { + for (GList *p = notifications_; p != NULL; p = p->next) { + g_object_unref(G_OBJECT(p->data)); + } + g_list_free(notifications_); + } +} + void NotificationPresenterLinux::ShowNotification( const content::ShowDesktopNotificationHostMsgParams& params, int render_process_id, int render_view_id) { - DLOG(INFO) << "ShowNotification: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << params.notification_id - << " title=\"" << params.title << '"' - << " body=\"" << params.body << '"'; - NotifyNotification *notification = CreateUserNotification(params, render_process_id, render_view_id); - NotificationID ID(render_process_id, render_view_id, params.notification_id); - std::pair p = notification_map_.insert(std::make_pair(ID.GetID(), notification)); + LOG(INFO) << "ShowNotification: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << params.notification_id + << " title=\"" << params.title << '"' + << " body=\"" << params.body << '"'; - g_signal_connect(notification, "closed", G_CALLBACK(closed_cb), new NotificationID(ID)); // FIXME: closure to free it + std::string title = base::UTF16ToUTF8(params.title); + std::string body = base::UTF16ToUTF8(params.body); + NotifyNotification *notification = notify_notification_new(title.c_str(), body.c_str(), NULL); + g_object_set_data(G_OBJECT(notification), kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); + g_object_set_data(G_OBJECT(notification), kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); + g_object_set_data(G_OBJECT(notification), kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); + g_signal_connect(notification, "closed", G_CALLBACK(closed_cb), this); + notify_notification_add_action(notification, "default", "View", (NotifyActionCallback)action_cb, this, NULL); + + notifications_ = g_list_append(notifications_, notification); GError *error = NULL; notify_notification_show(notification, &error); log_and_clear_error(error, "notify_notification_show"); - auto host = content::RenderViewHost::FromID(ID.render_process_id, ID.render_view_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; - host->DesktopNotificationPostDisplay(ID.notification_id); + host->DesktopNotificationPostDisplay(params.notification_id); } void NotificationPresenterLinux::CancelNotification( int render_process_id, int render_view_id, int notification_id) { - DLOG(INFO) << "CancelNotification: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << notification_id; + LOG(INFO) << "CancelNotification: process=" << render_process_id + << " view=" << render_view_id + << " notification=" << notification_id; - auto found = notification_map_.find(NotificationID(render_process_id, render_view_id, notification_id).GetID()); - if (found == notification_map_.end()) + NotifyNotification *notification = NULL; + for (GList *p = notifications_; p != NULL; p = p->next) { + if (render_process_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kRenderProcessIDKey)) + && render_view_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kRenderViewIDKey)) + && notification_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kNotificationIDKey))) { + notification = (NotifyNotification*)p->data; + notifications_ = g_list_delete_link(notifications_, p); + break; + } + } + if (!notification) return; - auto notification = found->second; - - notification_map_.erase(found); - GError *error = NULL; notify_notification_close(notification, &error); log_and_clear_error(error, "notify_notification_close"); + g_object_unref(notification); - NotificationID ID(render_process_id, render_view_id, notification_id); auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; - host->DesktopNotificationPostClose(ID.notification_id, false); + host->DesktopNotificationPostClose(notification_id, false); +} + +void NotificationPresenterLinux::RemoveNotification(NotifyNotification *former_notification) { + notifications_ = g_list_remove(notifications_, former_notification); + g_object_unref(former_notification); } } diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index b3d77dc63e6..4b6344cfbe7 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -17,6 +17,9 @@ namespace brightray { class NotificationPresenterLinux : public NotificationPresenter { public: + NotificationPresenterLinux(); + ~NotificationPresenterLinux(); + virtual void ShowNotification( const content::ShowDesktopNotificationHostMsgParams&, int render_process_id, @@ -26,9 +29,10 @@ class NotificationPresenterLinux : public NotificationPresenter { int render_view_id, int notification_id) OVERRIDE; + void RemoveNotification(NotifyNotification *former_notification); + private: - typedef std::map NotificationMap; - NotificationMap notification_map_; + GList *notifications_; }; } // namespace brightray From 04d5ed25d82481a7d7a11092aeb289e68915644d Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Wed, 18 Dec 2013 23:13:33 -0600 Subject: [PATCH 3/8] call PostClose when notification closed by click --- brightray/browser/linux/notification_presenter_linux.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 6848ce5111c..f4be61af006 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -32,6 +32,8 @@ void closed_cb(NotifyNotification *notification, NotificationPresenterLinux *obj int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + if (host) host->DesktopNotificationPostClose(notification_id, false); LOG(INFO) << "closed_cb: process=" << render_process_id << " view=" << render_view_id << " notification=" << notification_id From c6424672f572ff644082b08edf86f8d87503ec34 Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Wed, 18 Dec 2013 23:14:08 -0600 Subject: [PATCH 4/8] comments and cleanup --- .../linux/notification_presenter_linux.cc | 37 ++++++------------- .../linux/notification_presenter_linux.h | 9 ++++- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index f4be61af006..4081b2bd54e 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -28,27 +28,21 @@ void log_and_clear_error(GError *error, const char *context) { } } -void closed_cb(NotifyNotification *notification, NotificationPresenterLinux *obj) { +void NotificationClosedCallback(NotifyNotification *notification, NotificationPresenterLinux *obj) { int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClose(notification_id, false); - LOG(INFO) << "closed_cb: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << notification_id - << " reason=" << notify_notification_get_closed_reason(notification); obj->RemoveNotification(notification); } -void action_cb(NotifyNotification *notification, const char *action, NotificationPresenterLinux *obj) { +void NotificationViewCallback(NotifyNotification *notification, const char *action, NotificationPresenterLinux *obj) { int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); - LOG(INFO) << "action_cb: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << notification_id - << " action=\"" << action << '"'; + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClick(notification_id); obj->RemoveNotification(notification); @@ -66,6 +60,7 @@ NotificationPresenter* NotificationPresenter::Create() { NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(NULL) { } NotificationPresenterLinux::~NotificationPresenterLinux() { + // unref any outstanding notifications, and then free the list. if (notifications_) { for (GList *p = notifications_; p != NULL; p = p->next) { g_object_unref(G_OBJECT(p->data)); @@ -78,20 +73,16 @@ void NotificationPresenterLinux::ShowNotification( const content::ShowDesktopNotificationHostMsgParams& params, int render_process_id, int render_view_id) { - LOG(INFO) << "ShowNotification: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << params.notification_id - << " title=\"" << params.title << '"' - << " body=\"" << params.body << '"'; - std::string title = base::UTF16ToUTF8(params.title); std::string body = base::UTF16ToUTF8(params.body); NotifyNotification *notification = notify_notification_new(title.c_str(), body.c_str(), NULL); g_object_set_data(G_OBJECT(notification), kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); g_object_set_data(G_OBJECT(notification), kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); g_object_set_data(G_OBJECT(notification), kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); - g_signal_connect(notification, "closed", G_CALLBACK(closed_cb), this); - notify_notification_add_action(notification, "default", "View", (NotifyActionCallback)action_cb, this, NULL); + g_signal_connect(notification, "closed", + G_CALLBACK(NotificationClosedCallback), this); + notify_notification_add_action(notification, "default", "View", + (NotifyActionCallback)NotificationViewCallback, this, NULL); notifications_ = g_list_append(notifications_, notification); @@ -110,10 +101,6 @@ void NotificationPresenterLinux::CancelNotification( int render_process_id, int render_view_id, int notification_id) { - LOG(INFO) << "CancelNotification: process=" << render_process_id - << " view=" << render_view_id - << " notification=" << notification_id; - NotifyNotification *notification = NULL; for (GList *p = notifications_; p != NULL; p = p->next) { if (render_process_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kRenderProcessIDKey)) @@ -139,9 +126,9 @@ void NotificationPresenterLinux::CancelNotification( host->DesktopNotificationPostClose(notification_id, false); } -void NotificationPresenterLinux::RemoveNotification(NotifyNotification *former_notification) { - notifications_ = g_list_remove(notifications_, former_notification); - g_object_unref(former_notification); +void NotificationPresenterLinux::RemoveNotification(NotifyNotification *notification) { + notifications_ = g_list_remove(notifications_, notification); + g_object_unref(notification); } } diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index 4b6344cfbe7..4433147c93a 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -29,9 +29,16 @@ class NotificationPresenterLinux : public NotificationPresenter { int render_view_id, int notification_id) OVERRIDE; - void RemoveNotification(NotifyNotification *former_notification); + void RemoveNotification(NotifyNotification *notification); private: + // 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_; }; From ef6d5dbf4e46debcc0b8ba088d25916e2e98a12f Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Wed, 18 Dec 2013 23:20:00 -0600 Subject: [PATCH 5/8] authorship --- brightray/browser/linux/notification_presenter_linux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 4081b2bd54e..be1d2bc9eb4 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -1,5 +1,5 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Copyright (c) 2013 Adam Roben . All rights reserved. +// Copyright (c) 2013 Patrick Reynolds . All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-CHROMIUM file. From 4e31c0011d150d186d5eafad56d267fd2a595535 Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Thu, 19 Dec 2013 13:06:05 -0600 Subject: [PATCH 6/8] keep cpplint happy, mostly about line length --- .../linux/notification_presenter_linux.cc | 81 ++++++++++++------- .../linux/notification_presenter_linux.h | 7 +- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index be1d2bc9eb4..3796ab8dd30 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -3,6 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-CHROMIUM file. +#include + #include "browser/linux/notification_presenter_linux.h" #include "base/strings/stringprintf.h" @@ -11,8 +13,6 @@ #include "content/public/common/show_desktop_notification_params.h" #include "common/application_info.h" -#include - namespace brightray { namespace { @@ -23,32 +23,45 @@ const char *kNotificationIDKey = "NotificationID"; void log_and_clear_error(GError *error, const char *context) { if (error) { - LOG(ERROR) << context << ": domain=" << error->domain << " code=" << error->code << " message=\"" << error->message << "\""; + LOG(ERROR) << context + << ": domain=" << error->domain + << " code=" << error->code + << " message=\"" << error->message << '"'; g_error_free(error); } } -void NotificationClosedCallback(NotifyNotification *notification, NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); +void NotificationClosedCallback(NotifyNotification *notification, + NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); - auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = + content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClose(notification_id, false); obj->RemoveNotification(notification); } -void NotificationViewCallback(NotifyNotification *notification, const char *action, NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); +void NotificationViewCallback(NotifyNotification *notification, + const char *action, NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); - auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = + content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClick(notification_id); obj->RemoveNotification(notification); } -} +} // namespace NotificationPresenter* NotificationPresenter::Create() { if (!notify_is_initted()) { @@ -57,7 +70,8 @@ NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterLinux; } -NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(NULL) { } +NotificationPresenterLinux::NotificationPresenterLinux() + : notifications_(NULL) { } NotificationPresenterLinux::~NotificationPresenterLinux() { // unref any outstanding notifications, and then free the list. @@ -75,10 +89,14 @@ void NotificationPresenterLinux::ShowNotification( int render_view_id) { std::string title = base::UTF16ToUTF8(params.title); std::string body = base::UTF16ToUTF8(params.body); - NotifyNotification *notification = notify_notification_new(title.c_str(), body.c_str(), NULL); - g_object_set_data(G_OBJECT(notification), kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); - g_object_set_data(G_OBJECT(notification), kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); - g_object_set_data(G_OBJECT(notification), kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); + NotifyNotification *notification = + notify_notification_new(title.c_str(), body.c_str(), NULL); + g_object_set_data(G_OBJECT(notification), + kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); + g_object_set_data(G_OBJECT(notification), + kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); + g_object_set_data(G_OBJECT(notification), + kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); g_signal_connect(notification, "closed", G_CALLBACK(NotificationClosedCallback), this); notify_notification_add_action(notification, "default", "View", @@ -90,7 +108,8 @@ void NotificationPresenterLinux::ShowNotification( notify_notification_show(notification, &error); log_and_clear_error(error, "notify_notification_show"); - auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = + content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; @@ -103,10 +122,16 @@ void NotificationPresenterLinux::CancelNotification( int notification_id) { NotifyNotification *notification = NULL; for (GList *p = notifications_; p != NULL; p = p->next) { - if (render_process_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kRenderProcessIDKey)) - && render_view_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kRenderViewIDKey)) - && notification_id == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(p->data), kNotificationIDKey))) { - notification = (NotifyNotification*)p->data; + int obj_render_process_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); + int obj_render_view_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); + int obj_notification_id = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); + if (render_process_id == obj_render_process_id + && render_view_id == obj_render_view_id + && notification_id == obj_notification_id) { + notification = reinterpret_cast(p->data); notifications_ = g_list_delete_link(notifications_, p); break; } @@ -119,16 +144,18 @@ void NotificationPresenterLinux::CancelNotification( log_and_clear_error(error, "notify_notification_close"); g_object_unref(notification); - auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = + content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; host->DesktopNotificationPostClose(notification_id, false); } -void NotificationPresenterLinux::RemoveNotification(NotifyNotification *notification) { +void NotificationPresenterLinux::RemoveNotification( + NotifyNotification *notification) { notifications_ = g_list_remove(notifications_, notification); g_object_unref(notification); } -} +} // namespace brightray diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index 4433147c93a..0f52fd55fdd 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -6,13 +6,12 @@ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_PRESENTER_LINUX_H_ +#include +#include + #include "base/compiler_specific.h" #include "browser/notification_presenter.h" -#include - -#include - namespace brightray { class NotificationPresenterLinux : public NotificationPresenter { From 8d2b392f07b1f467d0d9f3fee0fa6fc7685e6805 Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Thu, 19 Dec 2013 13:39:37 -0600 Subject: [PATCH 7/8] undo some ugly line wrapping --- .../linux/notification_presenter_linux.cc | 94 +++++++------------ 1 file changed, 36 insertions(+), 58 deletions(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 3796ab8dd30..3544dbc4bed 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -31,34 +31,25 @@ void log_and_clear_error(GError *error, const char *context) { } } -void NotificationClosedCallback(NotifyNotification *notification, - NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); +void NotificationClosedCallback(NotifyNotification *noti, NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); - auto host = - content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClose(notification_id, false); - obj->RemoveNotification(notification); + obj->RemoveNotification(noti); } -void NotificationViewCallback(NotifyNotification *notification, - const char *action, NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); +void NotificationViewCallback(NotifyNotification *noti, const char *action, + NotificationPresenterLinux *obj) { + int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); + int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); + int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); - auto host = - content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClick(notification_id); - obj->RemoveNotification(notification); + obj->RemoveNotification(noti); } } // namespace @@ -70,8 +61,7 @@ NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterLinux; } -NotificationPresenterLinux::NotificationPresenterLinux() - : notifications_(NULL) { } +NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(NULL) { } NotificationPresenterLinux::~NotificationPresenterLinux() { // unref any outstanding notifications, and then free the list. @@ -89,27 +79,22 @@ void NotificationPresenterLinux::ShowNotification( int render_view_id) { std::string title = base::UTF16ToUTF8(params.title); std::string body = base::UTF16ToUTF8(params.body); - NotifyNotification *notification = - notify_notification_new(title.c_str(), body.c_str(), NULL); - g_object_set_data(G_OBJECT(notification), - kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); - g_object_set_data(G_OBJECT(notification), - kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); - g_object_set_data(G_OBJECT(notification), - kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); - g_signal_connect(notification, "closed", + NotifyNotification *noti = notify_notification_new(title.c_str(), body.c_str(), NULL); + g_object_set_data(G_OBJECT(noti), kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); + g_object_set_data(G_OBJECT(noti), kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); + g_object_set_data(G_OBJECT(noti), kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); + g_signal_connect(noti, "closed", G_CALLBACK(NotificationClosedCallback), this); - notify_notification_add_action(notification, "default", "View", + notify_notification_add_action(noti, "default", "View", (NotifyActionCallback)NotificationViewCallback, this, NULL); - notifications_ = g_list_append(notifications_, notification); + notifications_ = g_list_append(notifications_, noti); GError *error = NULL; - notify_notification_show(notification, &error); + notify_notification_show(noti, &error); log_and_clear_error(error, "notify_notification_show"); - auto host = - content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; @@ -120,42 +105,35 @@ void NotificationPresenterLinux::CancelNotification( int render_process_id, int render_view_id, int notification_id) { - NotifyNotification *notification = NULL; + NotifyNotification *noti = NULL; for (GList *p = notifications_; p != NULL; p = p->next) { - int obj_render_process_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderProcessIDKey)); - int obj_render_view_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kRenderViewIDKey)); - int obj_notification_id = GPOINTER_TO_INT( - g_object_get_data(G_OBJECT(notification), kNotificationIDKey)); - if (render_process_id == obj_render_process_id - && render_view_id == obj_render_view_id - && notification_id == obj_notification_id) { - notification = reinterpret_cast(p->data); + int rpid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); + int rvid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); + int nid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); + if (render_process_id == rpid && render_view_id == rvid && notification_id == nid) { + noti = reinterpret_cast(p->data); notifications_ = g_list_delete_link(notifications_, p); break; } } - if (!notification) + if (!noti) return; GError *error = NULL; - notify_notification_close(notification, &error); + notify_notification_close(noti, &error); log_and_clear_error(error, "notify_notification_close"); - g_object_unref(notification); + g_object_unref(noti); - auto host = - content::RenderViewHost::FromID(render_process_id, render_view_id); + auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (!host) return; host->DesktopNotificationPostClose(notification_id, false); } -void NotificationPresenterLinux::RemoveNotification( - NotifyNotification *notification) { - notifications_ = g_list_remove(notifications_, notification); - g_object_unref(notification); +void NotificationPresenterLinux::RemoveNotification(NotifyNotification *noti) { + notifications_ = g_list_remove(notifications_, noti); + g_object_unref(noti); } } // namespace brightray From 967e8170f505de84afdb1fcbc4d2722fa8534b0a Mon Sep 17 00:00:00 2001 From: Patrick Reynolds Date: Thu, 19 Dec 2013 16:01:01 -0600 Subject: [PATCH 8/8] brevity and style --- .../linux/notification_presenter_linux.cc | 71 +++++++++++-------- .../linux/notification_presenter_linux.h | 6 +- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/brightray/browser/linux/notification_presenter_linux.cc b/brightray/browser/linux/notification_presenter_linux.cc index 3544dbc4bed..06a9d0d42d0 100644 --- a/brightray/browser/linux/notification_presenter_linux.cc +++ b/brightray/browser/linux/notification_presenter_linux.cc @@ -22,19 +22,28 @@ const char *kRenderViewIDKey = "RenderViewID"; const char *kNotificationIDKey = "NotificationID"; void log_and_clear_error(GError *error, const char *context) { - if (error) { - LOG(ERROR) << context - << ": domain=" << error->domain - << " code=" << error->code - << " message=\"" << error->message << '"'; - g_error_free(error); - } + if (!error) return; + + LOG(ERROR) << context + << ": domain=" << error->domain + << " code=" << error->code + << " message=\"" << error->message << '"'; + g_error_free(error); } +int GetObjectInt(NotifyNotification *noti, const char *key) { + return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), key)); +} + +void SetObjectInt(NotifyNotification *noti, const char *key, int value) { + g_object_set_data(G_OBJECT(noti), key, GINT_TO_POINTER(value)); +} + + void NotificationClosedCallback(NotifyNotification *noti, NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); + int render_process_id = GetObjectInt(noti, kRenderProcessIDKey); + int render_view_id = GetObjectInt(noti, kRenderViewIDKey); + int notification_id = GetObjectInt(noti, kNotificationIDKey); auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClose(notification_id, false); @@ -43,9 +52,9 @@ void NotificationClosedCallback(NotifyNotification *noti, NotificationPresenterL void NotificationViewCallback(NotifyNotification *noti, const char *action, NotificationPresenterLinux *obj) { - int render_process_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); - int render_view_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); - int notification_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); + int render_process_id = GetObjectInt(noti, kRenderProcessIDKey); + int render_view_id = GetObjectInt(noti, kRenderViewIDKey); + int notification_id = GetObjectInt(noti, kNotificationIDKey); auto host = content::RenderViewHost::FromID(render_process_id, render_view_id); if (host) host->DesktopNotificationPostClick(notification_id); @@ -61,16 +70,16 @@ NotificationPresenter* NotificationPresenter::Create() { return new NotificationPresenterLinux; } -NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(NULL) { } +NotificationPresenterLinux::NotificationPresenterLinux() : notifications_(nullptr) { } NotificationPresenterLinux::~NotificationPresenterLinux() { // unref any outstanding notifications, and then free the list. - if (notifications_) { - for (GList *p = notifications_; p != NULL; p = p->next) { - g_object_unref(G_OBJECT(p->data)); - } - g_list_free(notifications_); + if (!notifications_) return; + + for (GList *p = notifications_; p != nullptr; p = p->next) { + g_object_unref(G_OBJECT(p->data)); } + g_list_free(notifications_); } void NotificationPresenterLinux::ShowNotification( @@ -79,18 +88,18 @@ void NotificationPresenterLinux::ShowNotification( int render_view_id) { std::string title = base::UTF16ToUTF8(params.title); std::string body = base::UTF16ToUTF8(params.body); - NotifyNotification *noti = notify_notification_new(title.c_str(), body.c_str(), NULL); - g_object_set_data(G_OBJECT(noti), kRenderProcessIDKey, GINT_TO_POINTER(render_process_id)); - g_object_set_data(G_OBJECT(noti), kRenderViewIDKey, GINT_TO_POINTER(render_view_id)); - g_object_set_data(G_OBJECT(noti), kNotificationIDKey, GINT_TO_POINTER(params.notification_id)); + NotifyNotification *noti = notify_notification_new(title.c_str(), body.c_str(), nullptr); + SetObjectInt(noti, kRenderProcessIDKey, render_process_id); + SetObjectInt(noti, kRenderViewIDKey, render_view_id); + SetObjectInt(noti, kNotificationIDKey, params.notification_id); g_signal_connect(noti, "closed", G_CALLBACK(NotificationClosedCallback), this); notify_notification_add_action(noti, "default", "View", - (NotifyActionCallback)NotificationViewCallback, this, NULL); + (NotifyActionCallback)NotificationViewCallback, this, nullptr); notifications_ = g_list_append(notifications_, noti); - GError *error = NULL; + GError *error = nullptr; notify_notification_show(noti, &error); log_and_clear_error(error, "notify_notification_show"); @@ -105,11 +114,11 @@ void NotificationPresenterLinux::CancelNotification( int render_process_id, int render_view_id, int notification_id) { - NotifyNotification *noti = NULL; - for (GList *p = notifications_; p != NULL; p = p->next) { - int rpid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderProcessIDKey)); - int rvid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kRenderViewIDKey)); - int nid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(noti), kNotificationIDKey)); + NotifyNotification *noti = nullptr; + for (GList *p = notifications_; p != nullptr; p = p->next) { + int rpid = GetObjectInt(noti, kRenderProcessIDKey); + int rvid = GetObjectInt(noti, kRenderViewIDKey); + int nid = GetObjectInt(noti, kNotificationIDKey); if (render_process_id == rpid && render_view_id == rvid && notification_id == nid) { noti = reinterpret_cast(p->data); notifications_ = g_list_delete_link(notifications_, p); @@ -119,7 +128,7 @@ void NotificationPresenterLinux::CancelNotification( if (!noti) return; - GError *error = NULL; + GError *error = nullptr; notify_notification_close(noti, &error); log_and_clear_error(error, "notify_notification_close"); g_object_unref(noti); diff --git a/brightray/browser/linux/notification_presenter_linux.h b/brightray/browser/linux/notification_presenter_linux.h index 0f52fd55fdd..dc868917e36 100644 --- a/brightray/browser/linux/notification_presenter_linux.h +++ b/brightray/browser/linux/notification_presenter_linux.h @@ -19,6 +19,9 @@ class NotificationPresenterLinux : public NotificationPresenter { NotificationPresenterLinux(); ~NotificationPresenterLinux(); + void RemoveNotification(NotifyNotification *notification); + + private: virtual void ShowNotification( const content::ShowDesktopNotificationHostMsgParams&, int render_process_id, @@ -28,9 +31,6 @@ class NotificationPresenterLinux : public NotificationPresenter { int render_view_id, int notification_id) OVERRIDE; - void RemoveNotification(NotifyNotification *notification); - - private: // 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