2 * Copyright (c) 2015 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
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.
17 #include "include/aul_app_com.h"
19 #include <bundle_cpp.h>
20 #include <bundle_internal.h>
26 #include "app_request.h"
29 #include "include/aul.h"
30 #include "include/aul_cmd.h"
33 using namespace aul::internal;
37 class AppComConnection {
39 AppComConnection(std::string endpoint, app_com_cb cb, void* user_data)
40 : endpoint_(std::move(endpoint)),
42 user_data_(user_data) {
45 ~AppComConnection() = default;
47 const std::string& GetEndpoint() const {
55 bool IsDisabled() const {
59 void Invoke(aul_app_com_result_e result, bundle* envelope) {
60 if (!disabled_ && cb_)
61 cb_(endpoint_.c_str(), result, envelope, user_data_);
65 bool disabled_ = false;
66 std::string endpoint_;
71 class AppComPermission {
73 AppComPermission() : option_(AUL_APP_COM_PUBLIC) {}
74 ~AppComPermission() {}
76 void SetPrivilege(std::string privilege) {
77 privilege_ = std::move(privilege);
80 void SetPropagationOption(aul_app_com_propagate_option_e option) {
84 const std::string& GetPrivilege() const {
88 aul_app_com_propagate_option_e GetPropagationOption() const {
93 std::string privilege_;
94 aul_app_com_propagate_option_e option_;
102 int Receive(bundle* b) {
103 const char* val = bundle_get_val(b, AUL_K_COM_ENDPOINT);
107 size_t result_size = 0;
108 aul_app_com_result_e* result = nullptr;
109 int ret = bundle_get_byte(b, AUL_K_COM_RESULT,
110 reinterpret_cast<void**>(&result), &result_size);
111 if (ret != BUNDLE_ERROR_NONE)
114 std::string endpoint(val);
116 std::lock_guard<std::recursive_mutex> lock(mutex_);
117 auto iter = conns_.begin();
118 while (iter != conns_.end()) {
121 if (conn->GetEndpoint() == endpoint)
122 conn->Invoke(*result, b);
128 AppComConnection* AddConnection(std::string endpoint, app_com_cb cb,
130 auto* conn = new (std::nothrow) AppComConnection(endpoint, cb, user_data);
134 std::lock_guard<std::recursive_mutex> lock(mutex_);
135 conns_.emplace_back(conn);
139 void RemoveConnection(AppComConnection* conn) {
140 std::lock_guard<std::recursive_mutex> lock(mutex_);
141 auto iter = conns_.begin();
142 while (iter != conns_.end()) {
143 if ((*iter).get() == conn) {
144 iter = conns_.erase(iter);
152 bool ExistConnection(const std::string& endpoint) {
153 std::lock_guard<std::recursive_mutex> lock(mutex_);
154 for (auto& conn : conns_) {
155 if (conn->GetEndpoint() == endpoint && !conn->IsDisabled())
162 bool ExistConnection(AppComConnection* conn) {
163 std::lock_guard<std::recursive_mutex> lock(mutex_);
164 if (conn->IsDisabled())
167 for (auto& i : conns_) {
175 std::recursive_mutex& GetMutex() const {
180 std::list<std::unique_ptr<AppComConnection>> conns_;
181 mutable std::recursive_mutex mutex_;
186 int AppComCreate(const char* endpoint,
187 aul_app_com_permission_h permission, app_com_cb callback, void* user_data,
188 bool sync, aul_app_com_connection_h* connection) {
189 if (endpoint == nullptr || callback == nullptr || connection == nullptr) {
190 _E("Invalid parameter");
194 if (!aul_is_initialized()) {
195 if (aul_launch_init(nullptr, nullptr) < 0)
196 return AUL_R_ENOINIT;
199 tizen_base::Bundle b { { AUL_K_COM_ENDPOINT, endpoint } };
201 auto* handle = static_cast<AppComPermission*>(permission);
202 auto option = handle->GetPropagationOption();
204 auto* p = reinterpret_cast<unsigned char*>(&option);
205 std::vector<unsigned char> bytes;
206 std::copy(p, p + sizeof(option), std::back_inserter(bytes));
207 b.Add(AUL_K_COM_PROPAGATE, bytes);
210 if (!handle->GetPrivilege().empty())
211 b.Add(AUL_K_COM_PRIVILEGE, handle->GetPrivilege());
214 int ret = AppRequest(APP_COM_CREATE, getuid())
216 .SendSimply(sync ? AUL_SOCK_NONE : AUL_SOCK_NOREPLY);
218 *connection = static_cast<aul_app_com_connection_h>(
219 context.AddConnection(endpoint, callback, user_data));
227 int app_com_recv(bundle* b) {
231 return context.Receive(b);
234 extern "C" API aul_app_com_permission_h aul_app_com_permission_create() {
235 auto* handle = new (std::nothrow) AppComPermission();
236 return static_cast<aul_app_com_permission_h>(handle);
239 extern "C" API void aul_app_com_permission_destroy(
240 aul_app_com_permission_h permission) {
241 if (permission == nullptr)
244 auto* handle = static_cast<AppComPermission*>(permission);
248 extern "C" API int aul_app_com_permission_set_propagation(
249 aul_app_com_permission_h permission,
250 aul_app_com_propagate_option_e option) {
251 if (permission == nullptr)
254 auto* handle = static_cast<AppComPermission*>(permission);
255 handle->SetPropagationOption(option);
259 extern "C" API int aul_app_com_permission_set_privilege(
260 aul_app_com_permission_h permission, const char* privilege) {
261 if (permission == nullptr || privilege == nullptr)
264 auto* handle = static_cast<AppComPermission*>(permission);
265 handle->SetPrivilege(privilege);
269 extern "C" API int aul_app_com_create(const char* endpoint,
270 aul_app_com_permission_h permission, app_com_cb callback,
271 void* user_data, aul_app_com_connection_h* connection) {
272 return AppComCreate(endpoint, permission, callback, user_data,
276 extern "C" API int aul_app_com_create_async(const char* endpoint,
277 aul_app_com_permission_h permission, app_com_cb callback,
278 void* user_data, aul_app_com_connection_h* connection) {
279 return AppComCreate(endpoint, permission, callback, user_data,
283 extern "C" API int aul_app_com_join(const char* endpoint, const char* filter,
284 app_com_cb callback, void* user_data,
285 aul_app_com_connection_h* connection) {
286 if (endpoint == nullptr || callback == nullptr || connection == nullptr) {
287 _E("Invalid parameter");
291 if (!aul_is_initialized()) {
292 if (aul_launch_init(nullptr, nullptr) < 0)
293 return AUL_R_ENOINIT;
296 tizen_base::Bundle b { { AUL_K_COM_ENDPOINT, endpoint } };
298 b.Add(AUL_K_COM_FILTER, filter);
300 int ret = AppRequest(APP_COM_JOIN, getuid())
304 *connection = static_cast<aul_app_com_connection_h>(
305 context.AddConnection(endpoint, callback, user_data));
311 extern "C" API int aul_app_com_send(const char* endpoint, bundle* envelope) {
312 if (endpoint == nullptr || envelope == nullptr)
315 std::string com_endpoint;
316 tizen_base::Bundle b(envelope, false, false);
317 bundle_type type = b.GetType(AUL_K_COM_ENDPOINT);
318 if (type != BUNDLE_TYPE_NONE) {
319 com_endpoint = b.GetString(AUL_K_COM_ENDPOINT);
320 b.Delete(AUL_K_COM_ENDPOINT);
323 b.Add(AUL_K_COM_ENDPOINT, endpoint);
325 int ret = AppRequest(APP_COM_SEND, getuid())
328 if (type != BUNDLE_TYPE_NONE) {
329 b.Delete(AUL_K_COM_ENDPOINT);
330 b.Add(AUL_K_COM_ENDPOINT, com_endpoint);
336 extern "C" API int aul_app_com_leave(aul_app_com_connection_h connection) {
337 if (connection == nullptr)
340 auto* conn = static_cast<AppComConnection*>(connection);
341 if (!context.ExistConnection(conn)) {
342 _E("Invalid parameter");
346 std::lock_guard<std::recursive_mutex> lock(context.GetMutex());
349 g_idle_add_full(G_PRIORITY_HIGH, [](gpointer user_data) -> gboolean {
350 auto* conn = static_cast<AppComConnection*>(user_data);
351 std::lock_guard<std::recursive_mutex> lock(context.GetMutex());
352 std::string endpoint = conn->GetEndpoint();
353 context.RemoveConnection(conn);
355 if (context.ExistConnection(endpoint))
356 return G_SOURCE_REMOVE;
358 tizen_base::Bundle b { { AUL_K_COM_ENDPOINT, endpoint } };
359 int ret = AppRequest(APP_COM_LEAVE, getuid())
363 _E("Failed to send leave request. error(%d)", ret);
365 return G_SOURCE_REMOVE;
366 }, connection, nullptr);