Index: chrome/browser/notifications/notification_platform_bridge_linux.cc |
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc |
index 6a0f8974c804f7e3ef7e9dbbef6546c7fc14068c..5e3a18b7cc8f6673baf312bd252ea9ed86cc2a64 100644 |
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc |
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc |
@@ -4,6 +4,8 @@ |
#include "chrome/browser/notifications/notification_platform_bridge_linux.h" |
+#include <algorithm> |
+ |
#include "base/memory/ptr_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "chrome/browser/notifications/notification.h" |
@@ -29,13 +31,42 @@ NotificationPlatformBridge* NotificationPlatformBridge::Create() { |
return new NotificationPlatformBridgeLinux(notification_proxy); |
} |
+NotificationPlatformBridgeLinux::NotificationData::NotificationData( |
+ const std::string& notification_id, |
+ const std::string& profile_id, |
+ bool is_incognito, |
+ NotificationPlatformBridgeLinux* platform_bridge) |
+ : notification_id(notification_id), |
+ profile_id(profile_id), |
+ is_incognito(is_incognito), |
+ platform_bridge(platform_bridge) {} |
+ |
+NotificationPlatformBridgeLinux::NotificationData::~NotificationData() { |
+ if (cancellable) |
+ g_cancellable_cancel(cancellable); |
Lei Zhang
2017/04/06 03:59:54
Thought this would need to be cancellable.get().
Tom (Use chromium acct)
2017/04/06 05:05:35
ScopedGObject has "operator T*() { return obj_; }"
|
+} |
+ |
+void OnNotifyComplete(GObject* source_object, |
+ GAsyncResult* result, |
+ gpointer user_data) { |
+ GDBusProxy* proxy = G_DBUS_PROXY(source_object); |
+ GVariant* value = g_dbus_proxy_call_finish(proxy, result, nullptr); |
+ if (!value) { |
+ // The message might have been cancelled, in which case |
+ // |user_data| points to a destroyed NotificationData. |
+ return; |
+ } |
+ auto* data = |
+ reinterpret_cast<NotificationPlatformBridgeLinux::NotificationData*>( |
+ user_data); |
+ data->platform_bridge->OnNotifyComplete(data, value); |
+} |
+ |
NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux( |
GDBusProxy* notification_proxy) |
: notification_proxy_(notification_proxy) {} |
-NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() { |
- g_object_unref(notification_proxy_); |
-} |
+NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() {} |
void NotificationPlatformBridgeLinux::Display( |
NotificationCommon::Type notification_type, |
@@ -43,20 +74,37 @@ void NotificationPlatformBridgeLinux::Display( |
const std::string& profile_id, |
bool is_incognito, |
const Notification& notification) { |
- // TODO(thomasanderson): Add a complete implementation. |
- g_dbus_proxy_call( |
- notification_proxy_, "Notify", |
- g_variant_new("(susssasa{sv}i)", "", 0, "", |
- base::UTF16ToUTF8(notification.title()).c_str(), |
- base::UTF16ToUTF8(notification.message()).c_str(), nullptr, |
- nullptr, -1), |
- G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr); |
+ NotificationData* data = FindNotificationData(notification_id, profile_id); |
+ if (data) { |
+ // Update an existing notification. |
+ if (data->dbus_id) { |
+ NotifyNow(data->dbus_id, notification_type, notification, nullptr, |
+ nullptr, nullptr); |
+ } else { |
+ data->update_type = notification_type; |
+ data->update_data.reset(new Notification(notification)); |
+ } |
+ } else { |
+ // Send the notification for the first time. |
+ data = |
+ new NotificationData(notification_id, profile_id, is_incognito, this); |
+ data->cancellable.reset(g_cancellable_new()); |
+ notifications_.emplace(data, std::unique_ptr<NotificationData>(data)); |
+ NotifyNow(0, notification_type, notification, data->cancellable, |
+ ::OnNotifyComplete, data); |
+ } |
} |
void NotificationPlatformBridgeLinux::Close( |
const std::string& profile_id, |
const std::string& notification_id) { |
- NOTIMPLEMENTED(); |
+ NotificationData* data = FindNotificationData(notification_id, profile_id); |
Lei Zhang
2017/04/06 03:59:54
Is this expected to never be NULL? i.e. We can saf
Tom (Use chromium acct)
2017/04/06 05:05:35
Probably not; added a nullptr check.
|
+ if (data->dbus_id) { |
+ CloseNow(data->dbus_id); |
+ notifications_.erase(data); |
+ } else { |
+ data->should_close = true; |
+ } |
} |
void NotificationPlatformBridgeLinux::GetDisplayed( |
@@ -65,3 +113,62 @@ void NotificationPlatformBridgeLinux::GetDisplayed( |
const DisplayedNotificationsCallback& callback) const { |
callback.Run(base::MakeUnique<std::set<std::string>>(), false); |
} |
+ |
+void NotificationPlatformBridgeLinux::OnNotifyComplete(NotificationData* data, |
+ GVariant* value) { |
+ data->cancellable.reset(nullptr); |
+ if (value && g_variant_is_of_type(value, G_VARIANT_TYPE("(u)"))) |
+ g_variant_get(value, "(u)", &data->dbus_id); |
+ |
+ if (!data->dbus_id) { |
+ // There was some sort of error with creating the notification. |
+ notifications_.erase(data); |
+ } else if (data->should_close) { |
+ CloseNow(data->dbus_id); |
+ notifications_.erase(data); |
+ } else if (data->update_data) { |
+ NotifyNow(data->dbus_id, data->update_type, *data->update_data, nullptr, |
+ nullptr, nullptr); |
+ data->update_data.reset(); |
+ } |
+} |
+ |
+void NotificationPlatformBridgeLinux::NotifyNow( |
+ uint32_t dbus_id, |
+ NotificationCommon::Type notification_type, |
+ const Notification& notification, |
+ GCancellable* cancellable, |
+ GAsyncReadyCallback callback, |
+ gpointer user_data) { |
+ // TODO(thomasanderson): Add a complete implementation. |
+ GVariant* parameters = g_variant_new( |
+ "(susssasa{sv}i)", "", dbus_id, "", |
+ base::UTF16ToUTF8(notification.title()).c_str(), |
+ base::UTF16ToUTF8(notification.message()).c_str(), nullptr, nullptr, -1); |
+ g_dbus_proxy_call(notification_proxy_, "Notify", parameters, |
+ G_DBUS_CALL_FLAGS_NONE, -1, cancellable, callback, |
+ user_data); |
+} |
+ |
+void NotificationPlatformBridgeLinux::CloseNow(uint32_t dbus_id) { |
+ g_dbus_proxy_call(notification_proxy_, "CloseNotification", |
+ g_variant_new("(u)", dbus_id), G_DBUS_CALL_FLAGS_NONE, -1, |
+ nullptr, nullptr, nullptr); |
+} |
+ |
+NotificationPlatformBridgeLinux::NotificationData* |
+NotificationPlatformBridgeLinux::FindNotificationData( |
+ const std::string& notification_id, |
+ const std::string& profile_id) { |
+ auto it = std::find_if( |
+ notifications_.begin(), notifications_.end(), |
+ [&](std::pair<NotificationData* const, std::unique_ptr<NotificationData>>& |
+ data) { |
+ return data.first->notification_id == notification_id && |
+ data.first->profile_id == profile_id; |
+ |
+ }); |
+ if (it == notifications_.end()) |
+ return nullptr; |
+ return it->first; |
+} |