1 // Copyright 2020 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "wrt/src/browser/wrt_ipc.h"
7 #include "wrt/src/base/dlog_util.h"
11 #define WRT_DBUS_NAME "org.tizen.wrt"
12 #define WRT_DBUS_PATH "/org/tizen/wrt"
14 InterProcessCommunication::Message::Message(DBusConnection* connection,
16 InterProcessCommunication* ipc)
17 : connection_(connection), message_(message), ipc_(ipc) {}
19 const char* InterProcessCommunication::Message::Sender() const {
20 return dbus_message_get_sender(message_);
23 void InterProcessCommunication::Message::CloseDBusConnection() const {
24 LOG(INFO) << "Listen() will be ended and close dbus connection.";
26 ipc_->will_close_ = true;
30 void InterProcessCommunication::Message::Reply(const char* argument) const {
32 LOG(ERROR) << "connection_ is not valid";
35 DBusMessage* reply = dbus_message_new_method_return(message_);
36 dbus_message_append_args(reply, DBUS_TYPE_STRING, &argument, DBUS_TYPE_INVALID);
37 dbus_connection_send(connection_, reply, nullptr);
38 dbus_message_unref(reply);
41 InterProcessCommunication::InterProcessCommunication(bool is_daemon) {
43 dbus_error_init(&error);
45 connection_ = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
47 LOG(ERROR) << "DBus connection error : " << error.message;
48 dbus_error_free(&error);
52 int result = dbus_bus_request_name(connection_, WRT_DBUS_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
53 if (dbus_error_is_set(&error)) {
54 LOG(ERROR) << "Fail to request name : " << error.message;
55 dbus_error_free(&error);
58 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
59 LOG(ERROR) << "Fail to become owner";
65 void InterProcessCommunication::CloseDbus() {
67 if (!message_handlers_.empty())
68 dbus_connection_remove_filter(connection_, OnMessage, this);
69 dbus_connection_close(connection_);
70 dbus_connection_unref(connection_);
71 connection_ = nullptr;
75 InterProcessCommunication::~InterProcessCommunication() {
80 DBusHandlerResult InterProcessCommunication::OnMessage(DBusConnection* connection, DBusMessage* message, void* user_data) {
81 int type = dbus_message_get_type(message);
82 if (type != DBUS_MESSAGE_TYPE_METHOD_CALL) {
83 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
86 std::string interface = dbus_message_get_interface(message);
87 if (interface != WRT_DBUS_NAME) {
88 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
91 std::string member = dbus_message_get_member(message);
92 auto* ipc = reinterpret_cast<InterProcessCommunication*>(user_data);
93 if (!ipc || !ipc->connection_) {
94 LOG(ERROR) << "ipc or connection_ is not valid";
95 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
97 auto iterator = ipc->message_handlers_.find(member);
98 if (iterator != ipc->message_handlers_.end()) {
100 dbus_error_init(&error);
101 char* argument = nullptr;
102 if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &argument, DBUS_TYPE_INVALID)) {
103 LOG(ERROR) << "dbus message reply is not valid";
104 dbus_error_free(&error);
107 auto& handler = iterator->second;
108 handler(member.c_str(), argument, Message(ipc->connection_, message, ipc));
111 return DBUS_HANDLER_RESULT_HANDLED;
114 void InterProcessCommunication::AddMessageHandler(const char* type, MessageHandler handler) {
115 if (message_handlers_.empty()) {
116 if (!dbus_connection_add_filter(connection_, OnMessage, this, nullptr)) {
117 LOG(ERROR) << "Fail to add message handler";
121 message_handlers_[type] = handler;
124 void InterProcessCommunication::SetExitOnDisconnect(bool exit_on_disconnect) {
125 dbus_connection_set_exit_on_disconnect(connection_, exit_on_disconnect);
128 void InterProcessCommunication::Listen() {
129 while (dbus_connection_read_write_dispatch(connection_, 500)) {
136 DBusMessage* InterProcessCommunication::InternalSendMessage(const char* receiver, const char* type, const char* argument, bool need_reply) {
138 LOG(ERROR) << "connection_ is not valid";
141 DBusMessage* message = dbus_message_new_method_call(receiver, WRT_DBUS_PATH, WRT_DBUS_NAME, type);
143 LOG(ERROR) << "Fail to create dbus message";
147 if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &argument, DBUS_TYPE_INVALID)) {
148 LOG(ERROR) << "Fail to append dbus message argument";
153 dbus_error_init(&error);
155 DBusMessage* reply = dbus_connection_send_with_reply_and_block(connection_, message, -1, &error);
156 dbus_message_unref(message);
158 LOG(ERROR) << "Fail to receive dbus message reply";
159 dbus_error_free(&error);
164 dbus_connection_send(connection_, message, nullptr);
165 dbus_connection_flush(connection_);
167 if (dbus_error_is_set(&error)) {
168 LOG(ERROR) << "Fail to send message : " << error.message;
169 dbus_error_free(&error);
176 bool InterProcessCommunication::SendMessage(const char* type, const char* argument) {
177 return SendMessage(WRT_DBUS_NAME, type, argument);
180 bool InterProcessCommunication::SendMessage(const char* receiver, const char* type, const char* argument) {
181 DBusMessage* message = InternalSendMessage(receiver, type, argument, false);
185 dbus_message_unref(message);
189 bool InterProcessCommunication::SendMessageAndWaitReply(const char* type, const char* argument, std::string& reply_argument) {
190 return SendMessageAndWaitReply(WRT_DBUS_NAME, type, argument, reply_argument);
193 bool InterProcessCommunication::SendMessageAndWaitReply(const char* receiver, const char* type, const char* argument, std::string& reply_argument) {
194 DBusMessage* reply = InternalSendMessage(receiver, type, argument, true);
199 if (dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_ERROR) {
201 dbus_error_init(&error);
202 char* buffer = nullptr;
203 if (!dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &buffer, DBUS_TYPE_INVALID)) {
204 LOG(ERROR) << "dbus message reply is not valid";
205 dbus_error_free(&error);
208 reply_argument = buffer;
210 dbus_message_unref(reply);
214 bool InterProcessCommunication::HasDbusOwner(const char* dbus_name) {
216 LOG(ERROR) << "connection_ is not valid";
221 dbus_error_init(&err);
223 bool exist = dbus_bus_name_has_owner(connection_, dbus_name, &err);
224 if (dbus_error_is_set(&err)) {
225 LOG(ERROR) << "dbus error : " << err.message;
226 dbus_error_free(&err);