2 * Copyright (c) 2020 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.
22 #include "theme/dbus/request_broker.h"
23 #include "theme/utils/logging.h"
27 const char kDbusBusName[] = "org.tizen.ThemeManager";
28 const char kDbusInterfaceName[] = "org.tizen.ThemeManager";
29 const char kDbusObjectPath[] = "/org/tizen/ThemeManager";
30 const char kDBusMethodSendData[] = "SendData";
32 tizen_base::Bundle ErrorResultBundle() {
34 b.Add(ttm::dbus::kCmdResultKey, "error");
43 void RequestBroker::OnReceiveDbusMethod(GDBusConnection* connection,
44 const gchar* sender, const gchar* object_path, const gchar* interface_name,
45 const gchar* method_name, GVariant* parameters,
46 GDBusMethodInvocation* invocation, gpointer user_data) {
47 GVariant* reply_body = nullptr;
49 char* serialized = nullptr;
50 g_variant_get(parameters, "(i&s)", &command, &serialized);
52 Command cmd = static_cast<Command>(command);
53 tizen_base::Bundle b(serialized);
55 auto it = filters_.find(cmd);
56 if (it == filters_.end()) {
57 LOG(ERROR) << "UnKnown command";
58 g_dbus_method_invocation_return_value(invocation, nullptr);
62 tizen_base::Bundle result = it->second.GetHandler()->OnRequest(cmd, b);
63 reply_body = g_variant_new("(s)", result.ToRaw().first.get());
64 g_dbus_method_invocation_return_value(invocation, reply_body);
67 bool RequestBroker::Init() {
68 GError* error = nullptr;
69 connection_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
70 if (connection_ == nullptr) {
71 if (error != nullptr) {
72 LOG(ERROR) << "Failed to get dbus [" << error->message << "]";
81 RequestBroker& RequestBroker::GetInst() {
82 static RequestBroker sBroker;
83 if (sBroker.connection_ == nullptr)
88 GDBusConnection* RequestBroker::GetConnection() {
92 int RequestBroker::RegisterRequestFilter(RequestFilter filter) {
93 filters_.emplace(filter.GetCmd(), filter);
97 bool RequestBroker::EmitSignal(std::string signal_name,
98 Command cmd, tizen_base::Bundle data) {
99 GError* err = nullptr;
100 gboolean result = TRUE;
101 GVariant *serialized = nullptr;
103 serialized = g_variant_new("(is)", static_cast<int>(cmd),
104 reinterpret_cast<char*>(data.ToRaw().first.get()));
106 result = g_dbus_connection_emit_signal(connection_,
107 nullptr, kDbusObjectPath, kDbusInterfaceName, signal_name.c_str(),
109 if (result == FALSE) {
110 LOG(ERROR) << "g_dbus_connection_emit_signal() is failed";
111 if (err != nullptr) {
112 LOG(ERROR) << "g_dbus_connection_emit_signal() err : " << err->message;
116 LOG(INFO) << "Successfully emit signal";
121 bool RequestBroker::Listen() {
122 const GDBusInterfaceVTable interface_vtable = {
123 [](GDBusConnection* connection, const gchar* sender,
124 const gchar* object_path, const gchar* interface_name,
125 const gchar* method_name, GVariant* parameters,
126 GDBusMethodInvocation* invocation, gpointer user_data) {
127 reinterpret_cast<RequestBroker*>(user_data)->OnReceiveDbusMethod(
128 connection, sender, object_path, interface_name, method_name,
129 parameters, invocation, user_data);
134 gchar introspection_xml[] =
136 " <interface name='org.tizen.ThemeManager'>"
137 " <method name='SendData'>"
138 " <arg type='i' name='command' direction='in'/>"
139 " <arg type='s' name='serialized' direction='in'/>"
140 " <arg type='s' name='serialized' direction='out'/>"
144 GError* error = nullptr;
145 GDBusNodeInfo* introspection_data =
146 g_dbus_node_info_new_for_xml(introspection_xml, &error);
147 if (introspection_data == nullptr) {
148 LOG(ERROR) << "g_dbus_node_info_new_for_xml is failed";
149 if (error != nullptr) {
150 LOG(ERROR) << "g_dbus_node_info_new_for_xml err ["
151 << error->message << "]";
157 registration_id_ = g_dbus_connection_register_object(
158 connection_, kDbusObjectPath, introspection_data->interfaces[0],
159 &interface_vtable, this, nullptr, nullptr);
160 g_dbus_node_info_unref(introspection_data);
161 if (registration_id_ == 0) {
162 LOG(ERROR) << "register object fail";
166 int owner_id = g_bus_own_name_on_connection(connection_,
167 kDbusBusName, G_BUS_NAME_OWNER_FLAGS_NONE,
168 nullptr, nullptr, nullptr, nullptr);
170 g_object_unref(connection_);
171 LOG(ERROR) << "g_bus_own_name_on_connection error";
178 bool RequestBroker::Subscribe() {
179 subscribe_id_ = g_dbus_connection_signal_subscribe(connection_, nullptr,
180 kDbusInterfaceName, nullptr, kDbusObjectPath, nullptr,
181 G_DBUS_SIGNAL_FLAGS_NONE,
182 [](GDBusConnection* connection, const gchar* sender_name,
183 const gchar* object_path, const gchar* interface_name,
184 const gchar* signal_name, GVariant* parameters, void* user_data) {
185 RequestBroker* broker = static_cast<RequestBroker*>(user_data);
186 char* serialized = nullptr;
188 g_variant_get(parameters, "(i&s)", &command, &serialized);
190 Command cmd = static_cast<Command>(command);
191 tizen_base::Bundle b(serialized);
193 auto it = broker->filters_.find(cmd);
194 if (it == broker->filters_.end())
197 tizen_base::Bundle result = it->second.GetHandler()->OnRequest(cmd, b);
201 return subscribe_id_ > 0;
204 tizen_base::Bundle RequestBroker::SendData(Command cmd,
205 tizen_base::Bundle& data) {
206 GError* err = nullptr;
207 GDBusMessage* msg = g_dbus_message_new_method_call(kDbusInterfaceName,
208 kDbusObjectPath, kDbusInterfaceName, kDBusMethodSendData);
209 if (msg == nullptr) {
210 LOG(ERROR) << "Can't allocate new method call";
211 return ErrorResultBundle();
213 g_dbus_message_set_body(msg,
214 g_variant_new("(is)",
215 static_cast<int>(cmd),
216 reinterpret_cast<char*>(data.ToRaw().first.get())));
218 GDBusMessage* reply = g_dbus_connection_send_message_with_reply_sync(
219 connection_, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE,
220 -1, nullptr, nullptr, &err);
221 if (reply == nullptr) {
222 LOG(ERROR) << "g_dbus_connection_send_message_with_reply_sync() is failed";
224 LOG(ERROR) << "error[" << err->message << "]";
227 return ErrorResultBundle();
229 GVariant* reply_body = g_dbus_message_get_body(reply);
230 if (reply_body == nullptr) {
231 LOG(ERROR) << "g_dbus_message_get_body() is failed";
232 return ErrorResultBundle();
235 char* serialized = nullptr;
236 g_variant_get(reply_body, "(&s)", &serialized);
237 tizen_base::Bundle result(serialized);
241 void RequestBroker::SendDataAsync(Command cmd, tizen_base::Bundle& data) {
242 GDBusMessage* msg = g_dbus_message_new_method_call(
243 kDbusBusName, kDbusObjectPath, kDbusInterfaceName, kDBusMethodSendData);
244 if (msg == nullptr) {
245 LOG(ERROR) << "Can't allocate new method call";
249 g_dbus_message_set_body(msg, g_variant_new("(is)", static_cast<int>(cmd),
250 reinterpret_cast<char*>(data.ToRaw().first.get())));
252 std::pair<Command, RequestBroker*> param = std::make_pair(cmd, this);
254 g_dbus_connection_send_message_with_reply(connection_, msg,
255 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr,
256 [](GObject* source_object, GAsyncResult* res, gpointer user_data) {
258 static_cast<std::pair<Command, RequestBroker*>*>(user_data);
259 GDBusConnection* conn =
260 reinterpret_cast<GDBusConnection*>(source_object);
261 GError* err = nullptr;
262 GDBusMessage* reply =
263 g_dbus_connection_send_message_with_reply_finish(conn, res, &err);
264 if (reply == nullptr) {
265 LOG(ERROR) << "No reply. err["
266 << (err ? err->message : "Unknown") << "]";
270 char* serialized = nullptr;
272 GVariant* reply_body = g_dbus_message_get_body(reply);
273 g_variant_get(reply_body, "(&s)", &serialized);
274 RequestBroker* broker = param->second;
275 tizen_base::Bundle b(serialized);
276 g_object_unref(reply);
278 auto it = broker->filters_.find(param->first);
279 if (it == broker->filters_.end())
281 it->second.GetHandler()->OnRequest(Command::RESULT, b);