Add internal api to support C#
[platform/core/api/notification.git] / notification-ex / dbus_event_listener.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <dlog.h>
18 #include <glib.h>
19 #include <unistd.h>
20
21 #include <string>
22 #include <list>
23
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"
30
31 #ifdef LOG_TAG
32 #undef LOG_TAG
33 #endif
34
35 #define LOG_TAG "NOTIFICATION_EX"
36 #define MAX_PACKAGE_STR_SIZE 512
37
38 using namespace std;
39 using namespace tizen_base;
40
41 namespace notification {
42
43 DBusEventListener::DBusEventListener(string path)
44     : impl_(new Impl(this, path)) {
45   LOGW("Created (%s)", path.c_str());
46 }
47
48 DBusEventListener::~DBusEventListener() {
49   LOGW("Destroyed");
50 }
51
52 DBusEventListener::Impl::~Impl() = default;
53
54 DBusEventListener::Impl::Impl(DBusEventListener* parent, string path)
55     : subscribe_id_(0), registration_id_(0), path_(path), parent_(parent) {
56   LOGI("Dbus_event_listener impl created");
57 }
58
59 void DBusEventListener::Impl::SignalCb(GDBusConnection* connection,
60                       const gchar* sender_name,
61                       const gchar* object_path,
62                       const gchar* interface_name,
63                       const gchar* signal_name,
64                       GVariant* parameters,
65                       void* user_data) {
66   DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
67   char* appid = nullptr;
68   GVariantIter *iter = nullptr;
69   char* event_info_raw = nullptr;
70   g_variant_get(parameters, "(ssa(s))", &appid, &event_info_raw, &iter);
71
72   LOGI("signal callback!! (%s)", appid);
73   string sender_appid = string(appid);
74   string cur_appid = util::GetAppId();
75   if (sender_appid == cur_appid)
76     return;
77   if ((!DBusConnectionManager::GetInst().IsDataProviderMaster(cur_appid)
78     && !DBusConnectionManager::GetInst().IsDataProviderMaster(sender_appid))
79     || (cur_appid == sender_appid))
80     return;
81
82   LOGE("%s : %s", cur_appid.c_str(), sender_appid.c_str());
83
84   char* raw = nullptr;
85   list<Bundle> ret_list;
86   while (g_variant_iter_loop(iter, "(s)", &raw) && raw != nullptr) {
87     Bundle ret(raw);
88     ret_list.emplace_back(ret);
89   }
90
91   Bundle b(event_info_raw);
92   EventInfo info(b);
93   dl->parent_->NotifyObserver(info, ret_list);
94 }
95
96 void DBusEventListener::Impl::OnMethodCall(
97     GDBusConnection *conn, const gchar *sender, const gchar *object_path,
98     const gchar *iface_name, const gchar *method_name,
99     GVariant *parameters, GDBusMethodInvocation *invocation,
100     gpointer user_data) {
101   LOGI("method_name[%s] sender[%s]", method_name, sender);
102   DBusEventListener::Impl* dl = static_cast<DBusEventListener::Impl*>(user_data);
103   GVariant *reply_body = NULL;
104   if (g_strcmp0(method_name, "Get") == 0) {
105     char* appid = NULL;
106     char* serialized = NULL;
107     g_variant_get(parameters, "(&s&s)", &appid, &serialized);
108
109     Bundle b(serialized);
110     EventInfo info(b);
111     list<Bundle> result = dl->parent_->NotifyObserver(info);
112     GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
113     for (auto& i : result) {
114       g_variant_builder_add(builder, "(s)",
115           reinterpret_cast<char*>(i.ToRaw().first.get()));
116     }
117     reply_body = g_variant_new("(a(s))", builder);
118     g_variant_builder_unref(builder);
119   } else if (g_strcmp0(method_name, "Count") == 0) {
120     char* appid = NULL;
121     char* serialized = NULL;
122     g_variant_get(parameters, "(&s&s)", &appid, &serialized);
123
124     Bundle b(serialized);
125     EventInfo info(b);
126     int num = dl->parent_->NotifyNumberRequest(info);
127     reply_body = g_variant_new("(i)", num);
128   }
129   g_dbus_method_invocation_return_value(invocation, reply_body);
130 }
131
132 int DBusEventListener::Impl::RegisterGDBusInterface() {
133   static const GDBusInterfaceVTable interface_vtable = {
134     OnMethodCall,
135     nullptr,
136     nullptr
137   };
138   static gchar introspection_xml[] =
139     "  <node>"
140     "  <interface name='org.tizen.notification_ex'>"
141     "        <method name='Get'>"
142     "          <arg type='s' name='appid' direction='in'/>"
143     "          <arg type='s' name='serialized' direction='in'/>"
144     "          <arg type='a(s)' name='noti_arr' direction='out'/>"
145     "        </method>"
146     "        <method name='Count'>"
147     "          <arg type='s' name='appid' direction='in'/>"
148     "          <arg type='s' name='serialized' direction='in'/>"
149     "          <arg type='i' name='num' direction='out'/>"
150     "        </method>"
151     "  </interface>"
152     "  </node>";
153   GError *error = NULL;
154   GDBusNodeInfo *introspection_data =
155       g_dbus_node_info_new_for_xml(introspection_xml, &error);
156   if (!introspection_data) {
157     LOGE("g_dbus_node_info_new_for_xml is failed.");
158     if (error != NULL) {
159       LOGE("g_dbus_node_info_new_for_xml err [%s]", error->message);
160       g_error_free(error);
161     }
162     return ERROR_IO_ERROR;
163   }
164
165   registration_id_ = g_dbus_connection_register_object(
166       DBusConnectionManager::GetInst().GetConnection(),
167       path_.c_str(), introspection_data->interfaces[0],
168       &interface_vtable, this, NULL, NULL);
169   g_dbus_node_info_unref(introspection_data);
170   if (registration_id_ == 0) {
171     LOGE("register object fail");
172     return ERROR_IO_ERROR;
173   }
174
175   LOGI("RegisterGDBusInterface success");
176   return ERROR_NONE;
177 }
178
179 void DBusEventListener::Impl::UnRegisterGDBusInterface() {
180   g_dbus_connection_unregister_object(
181         DBusConnectionManager::GetInst().GetConnection(),
182         registration_id_);
183 }
184
185 bool DBusEventListener::Impl::SubscribeSignal() {
186   subscribe_id_ = g_dbus_connection_signal_subscribe(
187                     DBusConnectionManager::GetInst().GetConnection(),
188                     NULL,
189                     DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
190                     NULL,
191                     path_.c_str(),
192                     NULL,
193                     G_DBUS_SIGNAL_FLAGS_NONE,
194                     SignalCb,
195                     this,
196                     NULL);
197   return subscribe_id_ > 0;
198 }
199
200 void DBusEventListener::Impl::UnSubscribeSignal() {
201   g_dbus_connection_signal_unsubscribe(
202       DBusConnectionManager::GetInst().GetConnection(), subscribe_id_);
203   subscribe_id_ = 0;
204 }
205
206 void DBusEventListener::RegisterObserver(IEventObserver* observer) {
207   if (impl_->subscribe_id_ == 0) {
208     impl_->SubscribeSignal();
209   } else {
210     impl_->UnSubscribeSignal();
211     impl_->SubscribeSignal();
212   }
213
214   if (impl_->registration_id_ == 0) {
215     impl_->RegisterGDBusInterface();
216   } else {
217     impl_->UnRegisterGDBusInterface();
218     impl_->RegisterGDBusInterface();
219   }
220   impl_->observer_ = observer;
221 }
222
223 void DBusEventListener::UnRegisterObserver(IEventObserver* observer) {
224   impl_->UnSubscribeSignal();
225   impl_->observer_ = NULL;
226 }
227
228 void DBusEventListener::NotifyObserver(
229     const IEventInfo& info, list<Bundle> serialized) {
230   impl_->observer_->OnEvent(info, serialized);
231 }
232
233 list<Bundle> DBusEventListener::NotifyObserver(const IEventInfo& info) {
234   return impl_->observer_->OnRequest(info);
235 }
236
237 int DBusEventListener::NotifyNumberRequest(const IEventInfo& info) {
238   return impl_->observer_->OnRequestNumber(info);
239 }
240
241 }  // namespace notification