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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/notifications/notification_platform_bridge_linux.h" 5 #include "chrome/browser/notifications/notification_platform_bridge_linux.h"
6 6
7 #include <algorithm>
8
7 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/stl_util.h"
8 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/notifications/notification.h" 13 #include "chrome/browser/notifications/notification.h"
10 14
11 namespace { 15 namespace {
12 16
13 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; 17 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications";
14 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; 18 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications";
15 19
20 // Callback used by GLib when the "Notify" message completes for the
21 // first time.
22 void NotifyCompleteReceiver(GObject* source_object,
23 GAsyncResult* result,
24 gpointer user_data) {
25 GDBusProxy* proxy = G_DBUS_PROXY(source_object);
26 GVariant* value = g_dbus_proxy_call_finish(proxy, result, nullptr);
27 if (!value) {
28 // The message might have been cancelled, in which case
29 // |user_data| points to a destroyed NotificationData.
30 return;
31 }
32 auto* platform_bridge_linux = static_cast<NotificationPlatformBridgeLinux*>(
33 g_browser_process->notification_platform_bridge());
34 platform_bridge_linux->NotifyCompleteInternal(user_data, value);
35 }
36
16 } // namespace 37 } // namespace
17 38
18 // static 39 // static
19 NotificationPlatformBridge* NotificationPlatformBridge::Create() { 40 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
20 GDBusProxy* notification_proxy = g_dbus_proxy_new_for_bus_sync( 41 GDBusProxy* notification_proxy = g_dbus_proxy_new_for_bus_sync(
21 G_BUS_TYPE_SESSION, 42 G_BUS_TYPE_SESSION,
22 static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | 43 static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
23 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | 44 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
24 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START), 45 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START),
25 nullptr, kFreedesktopNotificationsName, kFreedesktopNotificationsPath, 46 nullptr, kFreedesktopNotificationsName, kFreedesktopNotificationsPath,
26 kFreedesktopNotificationsName, nullptr, nullptr); 47 kFreedesktopNotificationsName, nullptr, nullptr);
27 if (!notification_proxy) 48 if (!notification_proxy)
28 return nullptr; 49 return nullptr;
29 return new NotificationPlatformBridgeLinux(notification_proxy); 50 return new NotificationPlatformBridgeLinux(notification_proxy);
30 } 51 }
31 52
53 struct NotificationPlatformBridgeLinux::NotificationData {
54 NotificationData(const std::string& notification_id,
55 const std::string& profile_id,
56 bool is_incognito)
57 : notification_id(notification_id),
58 profile_id(profile_id),
59 is_incognito(is_incognito) {}
60
61 ~NotificationData() {
62 if (cancellable)
63 g_cancellable_cancel(cancellable);
64 }
65
66 // The ID used by the notification server. Will be 0 until the
67 // first "Notify" message completes.
68 uint32_t dbus_id = 0;
69
70 // Same parameters used by NotificationPlatformBridge::Display().
71 const std::string notification_id;
72 const std::string profile_id;
73 const bool is_incognito;
74
75 // Used to cancel the initial "Notify" message so we don't call
76 // NotificationPlatformBridgeLinux::NotifyCompleteInternal() with a
77 // destroyed Notification.
78 ScopedGObject<GCancellable> cancellable;
79
80 // If not null, the data to update the notification with once
81 // |dbus_id| becomes available.
82 std::unique_ptr<Notification> update_data;
83 NotificationCommon::Type update_type = NotificationCommon::TYPE_MAX;
84
85 // If true, indicates the notification should be closed once
86 // |dbus_id| becomes available.
87 bool should_close = false;
88 };
89
32 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux( 90 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux(
33 GDBusProxy* notification_proxy) 91 GDBusProxy* notification_proxy)
34 : notification_proxy_(notification_proxy) {} 92 : notification_proxy_(notification_proxy) {}
35 93
36 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() { 94 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() {}
37 g_object_unref(notification_proxy_);
38 }
39 95
40 void NotificationPlatformBridgeLinux::Display( 96 void NotificationPlatformBridgeLinux::Display(
41 NotificationCommon::Type notification_type, 97 NotificationCommon::Type notification_type,
42 const std::string& notification_id, 98 const std::string& notification_id,
43 const std::string& profile_id, 99 const std::string& profile_id,
44 bool is_incognito, 100 bool is_incognito,
45 const Notification& notification) { 101 const Notification& notification) {
46 // TODO(thomasanderson): Add a complete implementation. 102 NotificationData* data = FindNotificationData(notification_id, profile_id);
47 g_dbus_proxy_call( 103 if (data) {
48 notification_proxy_, "Notify", 104 // Update an existing notification.
49 g_variant_new("(susssasa{sv}i)", "", 0, "", 105 if (data->dbus_id) {
50 base::UTF16ToUTF8(notification.title()).c_str(), 106 NotifyNow(data->dbus_id, notification_type, notification, nullptr,
51 base::UTF16ToUTF8(notification.message()).c_str(), nullptr, 107 nullptr, nullptr);
52 nullptr, -1), 108 } else {
53 G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr); 109 data->update_type = notification_type;
110 data->update_data = base::MakeUnique<Notification>(notification);
111 }
112 } else {
113 // Send the notification for the first time.
114 data = new NotificationData(notification_id, profile_id, is_incognito);
115 data->cancellable.reset(g_cancellable_new());
116 notifications_.emplace(data, base::WrapUnique(data));
117 NotifyNow(0, notification_type, notification, data->cancellable,
118 NotifyCompleteReceiver, data);
119 }
54 } 120 }
55 121
56 void NotificationPlatformBridgeLinux::Close( 122 void NotificationPlatformBridgeLinux::Close(
57 const std::string& profile_id, 123 const std::string& profile_id,
58 const std::string& notification_id) { 124 const std::string& notification_id) {
59 NOTIMPLEMENTED(); 125 NotificationData* data = FindNotificationData(notification_id, profile_id);
126 if (!data)
127 return;
128 if (data->dbus_id) {
129 CloseNow(data->dbus_id);
130 notifications_.erase(data);
131 } else {
132 data->should_close = true;
133 }
60 } 134 }
61 135
62 void NotificationPlatformBridgeLinux::GetDisplayed( 136 void NotificationPlatformBridgeLinux::GetDisplayed(
63 const std::string& profile_id, 137 const std::string& profile_id,
64 bool incognito, 138 bool incognito,
65 const DisplayedNotificationsCallback& callback) const { 139 const DisplayedNotificationsCallback& callback) const {
66 callback.Run(base::MakeUnique<std::set<std::string>>(), false); 140 callback.Run(base::MakeUnique<std::set<std::string>>(), false);
67 } 141 }
142
143 void NotificationPlatformBridgeLinux::NotifyCompleteInternal(gpointer user_data,
144 GVariant* value) {
145 NotificationData* data = reinterpret_cast<NotificationData*>(user_data);
146 if (!base::ContainsKey(notifications_, data))
147 return;
148 data->cancellable.reset();
149 if (value && g_variant_is_of_type(value, G_VARIANT_TYPE("(u)")))
150 g_variant_get(value, "(u)", &data->dbus_id);
151
152 if (!data->dbus_id) {
153 // There was some sort of error with creating the notification.
154 notifications_.erase(data);
155 } else if (data->should_close) {
156 CloseNow(data->dbus_id);
157 notifications_.erase(data);
158 } else if (data->update_data) {
159 NotifyNow(data->dbus_id, data->update_type, *data->update_data, nullptr,
160 nullptr, nullptr);
161 data->update_data.reset();
162 }
163 }
164
165 void NotificationPlatformBridgeLinux::NotifyNow(
166 uint32_t dbus_id,
167 NotificationCommon::Type notification_type,
168 const Notification& notification,
169 GCancellable* cancellable,
170 GAsyncReadyCallback callback,
171 gpointer user_data) {
172 // TODO(thomasanderson): Add a complete implementation.
173 const std::string title = base::UTF16ToUTF8(notification.title());
174 const std::string message = base::UTF16ToUTF8(notification.message());
175 GVariant* parameters =
176 g_variant_new("(susssasa{sv}i)", "", dbus_id, "", title.c_str(),
177 message.c_str(), nullptr, nullptr, -1);
178 g_dbus_proxy_call(notification_proxy_, "Notify", parameters,
179 G_DBUS_CALL_FLAGS_NONE, -1, cancellable, callback,
180 user_data);
181 }
182
183 void NotificationPlatformBridgeLinux::CloseNow(uint32_t dbus_id) {
184 g_dbus_proxy_call(notification_proxy_, "CloseNotification",
185 g_variant_new("(u)", dbus_id), G_DBUS_CALL_FLAGS_NONE, -1,
186 nullptr, nullptr, nullptr);
187 }
188
189 NotificationPlatformBridgeLinux::NotificationData*
190 NotificationPlatformBridgeLinux::FindNotificationData(
191 const std::string& notification_id,
192 const std::string& profile_id) {
193 for (const auto& pair : notifications_) {
194 NotificationData* data = pair.first;
195 if (data->notification_id == notification_id &&
196 data->profile_id == profile_id) {
197 return data;
198 }
199 }
200
201 return nullptr;
202 }
OLDNEW
« 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