2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include "notification-ex/dbus_connection_manager.h"
25 #include "notification-ex/dbus_event_listener.h"
26 #include "notification-ex/dbus_event_listener_implementation.h"
27 #include "notification-ex/exception.h"
28 #include "notification-ex/ex_util.h"
29 #include "notification-ex/event_info_internal.h"
35 #define LOG_TAG "NOTIFICATION_EX"
36 #define MAX_PACKAGE_STR_SIZE 512
37 #define NORMAL_UID_BASE 5000
39 #define DBUS_NAME "org.freedesktop.DBus"
40 #define DBUS_OBJECT_PATH "/org/freedesktop/DBus"
41 #define DBUS_INTERFACE_NAME "org.freedesktop.DBus"
44 using namespace tizen_base;
46 namespace notification {
48 DBusEventListener::DBusEventListener(string path)
49 : impl_(new Impl(this, path)) {
50 LOGW("Created (%s)", path.c_str());
53 DBusEventListener::~DBusEventListener() {
57 DBusEventListener::Impl::~Impl() = default;
59 DBusEventListener::Impl::Impl(DBusEventListener* parent, string path)
60 : subscribe_id_(0), registration_id_(0), path_(path), parent_(parent) {
61 LOGI("Dbus_event_listener impl created");
64 uid_t DBusEventListener::Impl::GetSenderUid(GDBusConnection* connection,
65 const char* sender_name) {
66 GDBusMessage* msg = nullptr;
67 GDBusMessage* reply = nullptr;
68 GError* err = nullptr;
72 msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
73 DBUS_INTERFACE_NAME, "GetConnectionUnixUser");
75 LOGE("Failed to alloc new method call");
79 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
80 reply = g_dbus_connection_send_message_with_reply_sync(connection, msg,
81 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
85 LOGE("Failed to get uid [%s]", err->message);
91 body = g_dbus_message_get_body(reply);
92 g_variant_get(body, "(u)", &uid);
98 g_object_unref(reply);
103 pid_t DBusEventListener::Impl::GetSenderPid(GDBusConnection* connection,
104 const char* sender_name) {
105 GDBusMessage* msg = nullptr;
106 GDBusMessage* reply = nullptr;
107 GError* err = nullptr;
111 msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
112 DBUS_INTERFACE_NAME, "GetConnectionUnixProcessID");
114 LOGE("Failed to alloc new method call");
118 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
119 reply = g_dbus_connection_send_message_with_reply_sync(connection, msg,
120 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
123 if (err != nullptr) {
124 LOGE("Failed to get uid [%s]", err->message);
130 body = g_dbus_message_get_body(reply);
131 g_variant_get(body, "(u)", &pid);
137 g_object_unref(reply);
142 void DBusEventListener::Impl::SignalCb(GDBusConnection* connection,
143 const gchar* sender_name,
144 const gchar* object_path,
145 const gchar* interface_name,
146 const gchar* signal_name,
147 GVariant* parameters,
149 DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
150 char* appid = nullptr;
151 GVariantIter *iter = nullptr;
152 char* event_info_raw = nullptr;
153 g_variant_get(parameters, "(ssa(s))", &appid, &event_info_raw, &iter);
155 LOGI("signal callback!! (%s)", appid);
156 string sender_appid = string(appid);
157 string cur_appid = util::GetAppId();
158 if (sender_appid == cur_appid)
160 if ((!DBusConnectionManager::GetInst().IsDataProviderMaster(cur_appid)
161 && !DBusConnectionManager::GetInst().IsDataProviderMaster(sender_appid))
162 || (cur_appid == sender_appid))
165 LOGE("%s : %s", cur_appid.c_str(), sender_appid.c_str());
168 list<Bundle> ret_list;
169 while (g_variant_iter_loop(iter, "(s)", &raw) && raw != nullptr) {
171 ret_list.emplace_back(ret);
174 Bundle b(event_info_raw);
177 if (info.GetEventType() == EventInfo::Post
178 || info.GetEventType() == EventInfo::Update) {
179 uid_t uid = GetSenderUid(connection, sender_name);
180 if (uid >= NORMAL_UID_BASE) {
181 pid_t pid = GetSenderPid(connection, sender_name);
182 info.SetValidatedOwner(util::GetAppId(pid));
183 info.SetValidatedUid(uid);
187 dl->parent_->NotifyObserver(info, ret_list);
190 void DBusEventListener::Impl::OnMethodCall(
191 GDBusConnection *conn, const gchar *sender, const gchar *object_path,
192 const gchar *iface_name, const gchar *method_name,
193 GVariant *parameters, GDBusMethodInvocation *invocation,
194 gpointer user_data) {
195 LOGI("method_name[%s] sender[%s]", method_name, sender);
196 DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
197 GVariant *reply_body = NULL;
198 if (g_strcmp0(method_name, "Get") == 0) {
200 char* serialized = NULL;
201 g_variant_get(parameters, "(&s&s)", &appid, &serialized);
203 Bundle b(serialized);
205 list<Bundle> result = dl->parent_->NotifyObserver(info);
206 GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
207 for (auto& i : result) {
208 g_variant_builder_add(builder, "(s)",
209 reinterpret_cast<char*>(i.ToRaw().first.get()));
211 reply_body = g_variant_new("(a(s))", builder);
212 g_variant_builder_unref(builder);
213 } else if (g_strcmp0(method_name, "Count") == 0) {
215 char* serialized = NULL;
216 g_variant_get(parameters, "(&s&s)", &appid, &serialized);
218 Bundle b(serialized);
220 int num = dl->parent_->NotifyNumberRequest(info);
221 reply_body = g_variant_new("(i)", num);
223 g_dbus_method_invocation_return_value(invocation, reply_body);
226 int DBusEventListener::Impl::RegisterGDBusInterface() {
227 static const GDBusInterfaceVTable interface_vtable = {
232 static gchar introspection_xml[] =
234 " <interface name='org.tizen.notification_ex'>"
235 " <method name='Get'>"
236 " <arg type='s' name='appid' direction='in'/>"
237 " <arg type='s' name='serialized' direction='in'/>"
238 " <arg type='a(s)' name='noti_arr' direction='out'/>"
240 " <method name='Count'>"
241 " <arg type='s' name='appid' direction='in'/>"
242 " <arg type='s' name='serialized' direction='in'/>"
243 " <arg type='i' name='num' direction='out'/>"
247 GError *error = NULL;
248 GDBusNodeInfo *introspection_data =
249 g_dbus_node_info_new_for_xml(introspection_xml, &error);
250 if (!introspection_data) {
251 LOGE("g_dbus_node_info_new_for_xml is failed.");
253 LOGE("g_dbus_node_info_new_for_xml err [%s]", error->message);
256 return ERROR_IO_ERROR;
259 registration_id_ = g_dbus_connection_register_object(
260 DBusConnectionManager::GetInst().GetConnection(),
261 path_.c_str(), introspection_data->interfaces[0],
262 &interface_vtable, this, NULL, NULL);
263 g_dbus_node_info_unref(introspection_data);
264 if (registration_id_ == 0) {
265 LOGE("register object fail");
266 return ERROR_IO_ERROR;
269 LOGI("RegisterGDBusInterface success");
273 void DBusEventListener::Impl::UnRegisterGDBusInterface() {
274 g_dbus_connection_unregister_object(
275 DBusConnectionManager::GetInst().GetConnection(),
279 bool DBusEventListener::Impl::SubscribeSignal() {
280 subscribe_id_ = g_dbus_connection_signal_subscribe(
281 DBusConnectionManager::GetInst().GetConnection(),
283 DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
287 G_DBUS_SIGNAL_FLAGS_NONE,
291 return subscribe_id_ > 0;
294 void DBusEventListener::Impl::UnSubscribeSignal() {
295 g_dbus_connection_signal_unsubscribe(
296 DBusConnectionManager::GetInst().GetConnection(), subscribe_id_);
300 void DBusEventListener::RegisterObserver(IEventObserver* observer) {
301 if (impl_->subscribe_id_ == 0) {
302 impl_->SubscribeSignal();
304 impl_->UnSubscribeSignal();
305 impl_->SubscribeSignal();
308 if (impl_->registration_id_ == 0) {
309 impl_->RegisterGDBusInterface();
311 impl_->UnRegisterGDBusInterface();
312 impl_->RegisterGDBusInterface();
314 impl_->observer_ = observer;
317 void DBusEventListener::UnRegisterObserver(IEventObserver* observer) {
318 impl_->UnSubscribeSignal();
319 impl_->observer_ = NULL;
322 void DBusEventListener::NotifyObserver(
323 const IEventInfo& info, list<Bundle> serialized) {
324 impl_->observer_->OnEvent(info, serialized);
327 list<Bundle> DBusEventListener::NotifyObserver(const IEventInfo& info) {
328 return impl_->observer_->OnRequest(info);
331 int DBusEventListener::NotifyNumberRequest(const IEventInfo& info) {
332 return impl_->observer_->OnRequestNumber(info);
335 } // namespace notification