88ddbec7b9b15fe68748b85b47cd2be6c275a642
[platform/core/api/notification.git] / notification-ex / dbus_sender.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_sender.h"
26 #include "notification-ex/dbus_sender_implementation.h"
27 #include "notification-ex/event_info_internal.h"
28 #include "notification-ex/ex_util.h"
29
30 #ifdef LOG_TAG
31 #undef LOG_TAG
32 #endif
33
34 #define LOG_TAG "NOTIFICATION_EX"
35 #define MAX_PACKAGE_STR_SIZE 512
36
37 using namespace std;
38 using namespace tizen_base;
39 namespace notification {
40
41 DBusSender::DBusSender(string path) : impl_(new Impl(this, path)) {
42   LOGW("Created (%s)", path.c_str());
43 }
44
45 DBusSender::Impl::~Impl() = default;
46
47 DBusSender::Impl::Impl(DBusSender* parent, string path)
48     : path_(path), parent_(parent) {
49   LOGI("Dbus_sender impl created");
50 }
51
52 DBusSender::~DBusSender() {
53   LOGW("Destroyed");
54 }
55
56 bool DBusSender::Impl::EmitSignal(string bus_name, string signal_name,
57     GVariant* data) {
58   GError* err = NULL;
59   gboolean result = TRUE;
60
61   result = g_dbus_connection_emit_signal(
62               DBusConnectionManager::GetInst().GetConnection(),
63               bus_name.empty() ? NULL : bus_name.c_str(),
64               path_.c_str(),
65               DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
66               signal_name.c_str(), data, &err);
67   if (result == FALSE) {
68     LOGE("g_dbus_connection_emit_signal() is failed");
69     if (err != NULL) {
70       LOGE("g_dbus_connection_emit_signal() err : %s",
71         err->message);
72       g_error_free(err);
73     }
74   } else {
75     LOGI("Successfully emit signal to %s, %s, %s",
76       bus_name.c_str(), path_.c_str(), signal_name.c_str());
77   }
78   return result;
79 }
80
81 string DBusSender::Impl::GetBusName(string appid, string dest_appid) const {
82   if (!DBusConnectionManager::GetInst().IsDataProviderMaster(appid))
83     return DBusConnectionManager::GetInst().GetDataProviderMasterName();
84
85   return DBusConnectionManager::GetInst().GetBusName(dest_appid);
86 }
87
88 void DBusSender::Notify(const IEventInfo& info, list<Bundle> serialized,
89     string dest_appid) {
90   string signal_name = EventInfo::GetString(info.GetEventType());
91   string appid = util::GetAppId();
92
93   GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
94   for (auto& i : serialized) {
95     g_variant_builder_add(builder, "(s)",
96         reinterpret_cast<char*>(i.ToRaw().first.get()));
97   }
98
99   GVariant* data = g_variant_new("(ssa(s))",
100         appid.c_str(),
101         reinterpret_cast<char*>(info.Serialize().ToRaw().first.get()), builder);
102   string bus_name = impl_->GetBusName(appid, dest_appid);
103   LOGI("bus name %s, %s", dest_appid.c_str(), bus_name.c_str());
104   impl_->EmitSignal(bus_name, signal_name, data);
105   g_variant_builder_unref(builder);
106 }
107
108 GDBusMessage* DBusSender::Impl::MethodCall(string appid, string method_name,
109     Bundle serialized) {
110   GDBusMessage* msg = g_dbus_message_new_method_call(
111       DBusConnectionManager::GetInst().GetDataProviderMasterName().c_str(),
112       path_.c_str(),
113       DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
114       method_name.c_str());
115   if (!msg) {
116     LOGE("Can't allocate new method call");
117     return nullptr;
118   }
119
120   g_dbus_message_set_body(msg,
121       g_variant_new("(ss)",
122         appid.c_str(),
123         reinterpret_cast<char*>(serialized.ToRaw().first.get())
124       )
125   );
126
127   LOGI("send message !! (%s) (%s) (%s)",
128       path_.c_str(), method_name.c_str(), appid.c_str());
129
130   GError* err = nullptr;
131   GDBusMessage* reply = g_dbus_connection_send_message_with_reply_sync(
132       DBusConnectionManager::GetInst().GetConnection(), msg,
133       G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
134   if (err != NULL) {
135     LOGE("MethodCall, err[%s]", err->message);
136     if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
137       set_last_result(ERROR_PERMISSION_DENIED);
138     else
139       set_last_result(ERROR_IO_ERROR);
140     g_error_free(err);
141   }
142
143   return reply;
144 }
145
146 GDBusMessage* DBusSender::Impl::MethodCall(string appid, const IEventInfo& info,
147     list<Bundle> serialized) {
148   GDBusMessage* msg = g_dbus_message_new_method_call(
149       DBusConnectionManager::GetInst().GetDataProviderMasterName().c_str(),
150       path_.c_str(),
151       DBusConnectionManager::GetInst().GetInterfaceName().c_str(),
152       EventInfo::GetString(info.GetEventType()).c_str());
153   if (!msg) {
154     LOGE("Can't allocate new method call");
155     return nullptr;
156   }
157
158   GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
159   for (auto& i : serialized) {
160     g_variant_builder_add(builder, "(s)",
161         reinterpret_cast<char*>(i.ToRaw().first.get()));
162   }
163
164   g_dbus_message_set_body(msg,
165       g_variant_new("(ssa(s))",
166           appid.c_str(),
167           reinterpret_cast<char*>(info.Serialize().ToRaw().first.get()),
168           builder
169       )
170   );
171
172   LOGI("send message !! (%s) (%s) (%s)",
173       path_.c_str(), EventInfo::GetString(info.GetEventType()).c_str(), appid.c_str());
174
175   GError* err = nullptr;
176   GDBusMessage* reply = g_dbus_connection_send_message_with_reply_sync(
177       DBusConnectionManager::GetInst().GetConnection(), msg,
178       G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
179   if (err != NULL) {
180     LOGE("MethodCall, err[%s]", err->message);
181     if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
182       set_last_result(ERROR_PERMISSION_DENIED);
183     else
184       set_last_result(ERROR_IO_ERROR);
185     g_error_free(err);
186   }
187
188   g_variant_builder_unref(builder);
189   return reply;
190 }
191
192 int DBusSender::SendMessage(const IEventInfo& info, list<Bundle> serialized,
193     string dest_appid) {
194   string appid = info.GetOwner();
195   if (appid.length() == 0)
196     appid = util::GetAppId();
197
198   GDBusMessage* reply = impl_->MethodCall(appid, info, serialized);
199   if (!reply)
200     return ERROR_IO_ERROR;
201
202   int ret = ERROR_NONE;
203   GError* err = nullptr;
204   if (g_dbus_message_to_gerror(reply, &err)) {
205     LOGE("SendMessage got error %s", err->message);
206     if (err->code == G_DBUS_ERROR_ACCESS_DENIED) {
207       set_last_result(ERROR_PERMISSION_DENIED);
208       ret = ERROR_PERMISSION_DENIED;
209     } else {
210       set_last_result(ERROR_IO_ERROR);
211       ret = ERROR_IO_ERROR;
212     }
213     g_error_free(err);
214     return ret;
215   } else {
216     set_last_result(ERROR_NONE);
217   }
218
219   GVariant *reply_body = g_dbus_message_get_body(reply);
220   g_variant_get(reply_body, "(i)", &ret);
221   return ret;
222 }
223
224 std::list<Bundle> DBusSender::Request(const IEventInfo& info) {
225   string appid = info.GetOwner();
226   if (appid.length() == 0)
227     appid = util::GetAppId();
228
229   string method_name = EventInfo::GetString(info.GetEventType());
230   Bundle serialized = info.Serialize();
231
232   list<Bundle> ret_list;
233   GDBusMessage* reply = impl_->MethodCall(appid, method_name, serialized);
234   if (!reply)
235     return ret_list;
236
237   GError* err = nullptr;
238   if (g_dbus_message_to_gerror(reply, &err)) {
239     LOGE("Request got error %s", err->message);
240     if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
241       set_last_result(ERROR_PERMISSION_DENIED);
242     else
243       set_last_result(ERROR_IO_ERROR);
244
245     g_error_free(err);
246     return ret_list;
247   } else {
248     set_last_result(ERROR_NONE);
249   }
250
251   GVariant *reply_body = g_dbus_message_get_body(reply);
252   GVariantIter *iter = nullptr;
253   g_variant_get(reply_body, "(a(s))", &iter);
254   char* raw = nullptr;
255   while (g_variant_iter_loop(iter, "(s)", &raw) && raw != nullptr) {
256     Bundle ret(raw);
257     ret_list.emplace_back(ret);
258   }
259
260   return ret_list;
261 }
262
263 int DBusSender::RequestNumber(const IEventInfo& info) {
264   string appid = info.GetOwner();
265   if (appid.length() == 0)
266     appid = util::GetAppId();
267
268   string method_name = EventInfo::GetString(info.GetEventType());
269   Bundle serialized = info.Serialize();
270
271   GDBusMessage* reply = impl_->MethodCall(appid, method_name, serialized);
272   if (!reply)
273     return 0;
274
275   GError* err = nullptr;
276   if (g_dbus_message_to_gerror(reply, &err)) {
277     LOGE("RequestNumber got error %s", err->message);
278     if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
279       set_last_result(ERROR_PERMISSION_DENIED);
280     else
281       set_last_result(ERROR_IO_ERROR);
282
283     g_error_free(err);
284     return 0;
285   } else {
286     set_last_result(ERROR_NONE);
287   }
288
289   int num;
290   GVariant *reply_body = g_dbus_message_get_body(reply);
291   g_variant_get(reply_body, "(i)", &num);
292   return num;
293 }
294
295 }  // namespace notification