Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Unified Diff: chrome/browser/notifications/notification_platform_bridge_linux.cc

Issue 2803873003: Linux native notifications: Support closing and updating notifications (Closed)
Patch Set: glib_signals.h -> glib_signal.h to fix gn gen --check Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..f19184ac8c78ff35c57e1baf256a8a3c2d51b8a0 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -4,8 +4,12 @@
#include "chrome/browser/notifications/notification_platform_bridge_linux.h"
+#include <algorithm>
+
#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification.h"
namespace {
@@ -13,6 +17,23 @@ namespace {
const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications";
const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications";
+// Callback used by GLib when the "Notify" message completes for the
+// first time.
+void NotifyCompleteReceiver(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* platform_bridge_linux = static_cast<NotificationPlatformBridgeLinux*>(
+ g_browser_process->notification_platform_bridge());
+ platform_bridge_linux->NotifyCompleteInternal(user_data, value);
+}
+
} // namespace
// static
@@ -29,13 +50,48 @@ NotificationPlatformBridge* NotificationPlatformBridge::Create() {
return new NotificationPlatformBridgeLinux(notification_proxy);
}
+struct NotificationPlatformBridgeLinux::NotificationData {
+ NotificationData(const std::string& notification_id,
+ const std::string& profile_id,
+ bool is_incognito)
+ : notification_id(notification_id),
+ profile_id(profile_id),
+ is_incognito(is_incognito) {}
+
+ ~NotificationData() {
+ if (cancellable)
+ g_cancellable_cancel(cancellable);
+ }
+
+ // The ID used by the notification server. Will be 0 until the
+ // first "Notify" message completes.
+ uint32_t dbus_id = 0;
+
+ // Same parameters used by NotificationPlatformBridge::Display().
+ const std::string notification_id;
+ const std::string profile_id;
+ const bool is_incognito;
+
+ // Used to cancel the initial "Notify" message so we don't call
+ // NotificationPlatformBridgeLinux::NotifyCompleteInternal() with a
+ // destroyed Notification.
+ ScopedGObject<GCancellable> cancellable;
+
+ // If not null, the data to update the notification with once
+ // |dbus_id| becomes available.
+ std::unique_ptr<Notification> update_data;
+ NotificationCommon::Type update_type = NotificationCommon::TYPE_MAX;
+
+ // If true, indicates the notification should be closed once
+ // |dbus_id| becomes available.
+ bool should_close = false;
+};
+
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 +99,38 @@ 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 = base::MakeUnique<Notification>(notification);
+ }
+ } else {
+ // Send the notification for the first time.
+ data = new NotificationData(notification_id, profile_id, is_incognito);
+ data->cancellable.reset(g_cancellable_new());
+ notifications_.emplace(data, base::WrapUnique(data));
+ NotifyNow(0, notification_type, notification, data->cancellable,
+ NotifyCompleteReceiver, data);
+ }
}
void NotificationPlatformBridgeLinux::Close(
const std::string& profile_id,
const std::string& notification_id) {
- NOTIMPLEMENTED();
+ NotificationData* data = FindNotificationData(notification_id, profile_id);
+ if (!data)
+ return;
+ if (data->dbus_id) {
+ CloseNow(data->dbus_id);
+ notifications_.erase(data);
+ } else {
+ data->should_close = true;
+ }
}
void NotificationPlatformBridgeLinux::GetDisplayed(
@@ -65,3 +139,64 @@ void NotificationPlatformBridgeLinux::GetDisplayed(
const DisplayedNotificationsCallback& callback) const {
callback.Run(base::MakeUnique<std::set<std::string>>(), false);
}
+
+void NotificationPlatformBridgeLinux::NotifyCompleteInternal(gpointer user_data,
+ GVariant* value) {
+ NotificationData* data = reinterpret_cast<NotificationData*>(user_data);
+ if (!base::ContainsKey(notifications_, data))
+ return;
+ data->cancellable.reset();
+ 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.
+ const std::string title = base::UTF16ToUTF8(notification.title());
+ const std::string message = base::UTF16ToUTF8(notification.message());
+ GVariant* parameters =
+ g_variant_new("(susssasa{sv}i)", "", dbus_id, "", title.c_str(),
+ 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) {
+ for (const auto& pair : notifications_) {
+ NotificationData* data = pair.first;
+ if (data->notification_id == notification_id &&
+ data->profile_id == profile_id) {
+ return data;
+ }
+ }
+
+ return nullptr;
+}
« no previous file with comments | « chrome/browser/notifications/notification_platform_bridge_linux.h ('k') | chrome/browser/ui/libgtkui/gtk_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698