| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | // Copyright (c) 2015 GitHub, Inc.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 20:01:11 +02:00
										 |  |  | #include "atom/browser/notifications/linux/libnotify_notification.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  | #include <set>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2017-06-23 20:39:42 +10:00
										 |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 20:01:11 +02:00
										 |  |  | #include "atom/browser/notifications/notification_delegate.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-24 12:49:10 +02:00
										 |  |  | #include "atom/common/application_info.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-19 20:51:43 +02:00
										 |  |  | #include "atom/common/platform_util.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | #include "base/files/file_enumerator.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  | #include "base/logging.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | #include "base/strings/string_util.h"
 | 
					
						
							|  |  |  | #include "base/strings/utf_string_conversions.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-12 09:33:06 +09:00
										 |  |  | #include "chrome/browser/ui/libgtkui/gtk_util.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 19:54:24 +09:00
										 |  |  | #include "chrome/browser/ui/libgtkui/skia_utils_gtk.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | #include "third_party/skia/include/core/SkBitmap.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 20:01:11 +02:00
										 |  |  | namespace atom { | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							| 
									
										
										
										
											2016-05-17 20:30:53 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-13 04:43:22 +02:00
										 |  |  | LibNotifyLoader libnotify_loader_; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  | const std::set<std::string>& GetServerCapabilities() { | 
					
						
							|  |  |  |   static std::set<std::string> caps; | 
					
						
							|  |  |  |   if (caps.empty()) { | 
					
						
							| 
									
										
										
										
											2018-04-17 15:41:47 -07:00
										 |  |  |     auto* capabilities = libnotify_loader_.notify_get_server_caps(); | 
					
						
							|  |  |  |     for (auto* l = capabilities; l != nullptr; l = l->next) | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  |       caps.insert(static_cast<const char*>(l->data)); | 
					
						
							|  |  |  |     g_list_free_full(capabilities, g_free); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return caps; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-14 18:24:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  | bool HasCapability(const std::string& capability) { | 
					
						
							|  |  |  |   return GetServerCapabilities().count(capability) != 0; | 
					
						
							| 
									
										
										
										
											2016-04-14 18:24:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-13 04:43:22 +02:00
										 |  |  | bool NotifierSupportsActions() { | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |   if (getenv("ELECTRON_USE_UBUNTU_NOTIFIER")) | 
					
						
							| 
									
										
										
										
											2016-04-13 04:43:22 +02:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  |   return HasCapability("actions"); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void log_and_clear_error(GError* error, const char* context) { | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |   LOG(ERROR) << context << ": domain=" << error->domain | 
					
						
							|  |  |  |              << " code=" << error->code << " message=\"" << error->message | 
					
						
							|  |  |  |              << '"'; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |   g_error_free(error); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // static
 | 
					
						
							|  |  |  | bool LibnotifyNotification::Initialize() { | 
					
						
							| 
									
										
										
										
											2016-05-17 20:30:53 +09:00
										 |  |  |   if (!libnotify_loader_.Load("libnotify.so.4") &&  // most common one
 | 
					
						
							|  |  |  |       !libnotify_loader_.Load("libnotify.so.5") && | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |       !libnotify_loader_.Load("libnotify.so.1") && | 
					
						
							|  |  |  |       !libnotify_loader_.Load("libnotify.so")) { | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  |     LOG(WARNING) << "Unable to find libnotify; notifications disabled"; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!libnotify_loader_.notify_is_initted() && | 
					
						
							| 
									
										
										
										
											2018-10-24 12:49:10 +02:00
										 |  |  |       !libnotify_loader_.notify_init(GetApplicationName().c_str())) { | 
					
						
							| 
									
										
										
										
											2018-02-20 07:53:10 -06:00
										 |  |  |     LOG(WARNING) << "Unable to initialize libnotify; notifications disabled"; | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LibnotifyNotification::LibnotifyNotification(NotificationDelegate* delegate, | 
					
						
							|  |  |  |                                              NotificationPresenter* presenter) | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |     : Notification(delegate, presenter), notification_(nullptr) {} | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | LibnotifyNotification::~LibnotifyNotification() { | 
					
						
							| 
									
										
										
										
											2016-10-25 19:02:06 +05:30
										 |  |  |   if (notification_) { | 
					
						
							|  |  |  |     g_signal_handlers_disconnect_by_data(notification_, this); | 
					
						
							|  |  |  |     g_object_unref(notification_); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-24 21:03:27 +10:00
										 |  |  | void LibnotifyNotification::Show(const NotificationOptions& options) { | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |   notification_ = libnotify_loader_.notify_notification_new( | 
					
						
							| 
									
										
										
										
											2017-06-24 21:03:27 +10:00
										 |  |  |       base::UTF16ToUTF8(options.title).c_str(), | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |       base::UTF16ToUTF8(options.msg).c_str(), nullptr); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |   g_signal_connect(notification_, "closed", | 
					
						
							|  |  |  |                    G_CALLBACK(OnNotificationClosedThunk), this); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-13 04:43:22 +02:00
										 |  |  |   // NB: On Unity and on any other DE using Notify-OSD, adding a notification
 | 
					
						
							|  |  |  |   // action will cause the notification to display as a modal dialog box.
 | 
					
						
							|  |  |  |   if (NotifierSupportsActions()) { | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |     libnotify_loader_.notify_notification_add_action( | 
					
						
							|  |  |  |         notification_, "default", "View", OnNotificationViewThunk, this, | 
					
						
							|  |  |  |         nullptr); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-24 21:03:27 +10:00
										 |  |  |   if (!options.icon.drawsNothing()) { | 
					
						
							|  |  |  |     GdkPixbuf* pixbuf = libgtkui::GdkPixbufFromSkBitmap(options.icon); | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |     libnotify_loader_.notify_notification_set_image_from_pixbuf(notification_, | 
					
						
							|  |  |  |                                                                 pixbuf); | 
					
						
							|  |  |  |     libnotify_loader_.notify_notification_set_timeout(notification_, | 
					
						
							|  |  |  |                                                       NOTIFY_EXPIRES_DEFAULT); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |     g_object_unref(pixbuf); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-24 21:03:27 +10:00
										 |  |  |   if (!options.tag.empty()) { | 
					
						
							|  |  |  |     GQuark id = g_quark_from_string(options.tag.c_str()); | 
					
						
							| 
									
										
										
										
											2016-04-13 06:08:35 +02:00
										 |  |  |     g_object_set(G_OBJECT(notification_), "id", id, NULL); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-14 18:31:02 +02:00
										 |  |  |   // Always try to append notifications.
 | 
					
						
							|  |  |  |   // Unique tags can be used to prevent this.
 | 
					
						
							|  |  |  |   if (HasCapability("append")) { | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  |     libnotify_loader_.notify_notification_set_hint_string(notification_, | 
					
						
							|  |  |  |                                                           "append", "true"); | 
					
						
							| 
									
										
										
										
											2016-04-14 18:31:02 +02:00
										 |  |  |   } else if (HasCapability("x-canonical-append")) { | 
					
						
							|  |  |  |     libnotify_loader_.notify_notification_set_hint_string( | 
					
						
							|  |  |  |         notification_, "x-canonical-append", "true"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-12 09:33:06 +09:00
										 |  |  |   // Send the desktop name to identify the application
 | 
					
						
							|  |  |  |   // The desktop-entry is the part before the .desktop
 | 
					
						
							| 
									
										
										
										
											2018-03-12 16:02:47 +09:00
										 |  |  |   std::string desktop_id; | 
					
						
							| 
									
										
										
										
											2018-10-19 20:51:43 +02:00
										 |  |  |   if (platform_util::GetDesktopName(&desktop_id)) { | 
					
						
							| 
									
										
										
										
											2018-03-12 09:33:06 +09:00
										 |  |  |     const std::string suffix{".desktop"}; | 
					
						
							|  |  |  |     if (base::EndsWith(desktop_id, suffix, | 
					
						
							|  |  |  |                        base::CompareCase::INSENSITIVE_ASCII)) { | 
					
						
							|  |  |  |       desktop_id.resize(desktop_id.size() - suffix.size()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     libnotify_loader_.notify_notification_set_hint_string( | 
					
						
							|  |  |  |         notification_, "desktop-entry", desktop_id.c_str()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |   GError* error = nullptr; | 
					
						
							|  |  |  |   libnotify_loader_.notify_notification_show(notification_, &error); | 
					
						
							|  |  |  |   if (error) { | 
					
						
							|  |  |  |     log_and_clear_error(error, "notify_notification_show"); | 
					
						
							|  |  |  |     NotificationFailed(); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 19:06:51 +10:00
										 |  |  |   if (delegate()) | 
					
						
							|  |  |  |     delegate()->NotificationDisplayed(); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void LibnotifyNotification::Dismiss() { | 
					
						
							| 
									
										
										
										
											2016-10-28 11:24:47 -07:00
										 |  |  |   if (!notification_) { | 
					
						
							|  |  |  |     Destroy(); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  |   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) { | 
					
						
							| 
									
										
										
										
											2016-04-15 16:14:13 +09:00
										 |  |  |   NotificationDismissed(); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:56:12 -04:00
										 |  |  | void LibnotifyNotification::OnNotificationView(NotifyNotification* notification, | 
					
						
							|  |  |  |                                                char* action) { | 
					
						
							| 
									
										
										
										
											2016-04-15 16:14:13 +09:00
										 |  |  |   NotificationClicked(); | 
					
						
							| 
									
										
										
										
											2015-12-25 11:52:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 20:01:11 +02:00
										 |  |  | }  // namespace atom
 |