[ATSPI] enhance "GetNeighbor" interface
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / dbus-tizen.cpp
1 /*
2  * Copyright 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 // CLASS HEADER
18 #include <dali/internal/accessibility/bridge/accessibility-common.h>
19 #include <dali/internal/accessibility/bridge/dbus.h>
20
21 // EXTERNAL INCLUDES
22 #include <iostream>
23 #include <mutex>
24 #include <sstream>
25
26 #include <Ecore_Input.h>
27 #include <Eldbus.h>
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/dali-adaptor-common.h>
31
32 #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
33
34 #undef EINA_FALSE
35 #undef EINA_TRUE
36 #define EINA_TRUE static_cast<Eina_Bool>(1)
37 #define EINA_FALSE static_cast<Eina_Bool>(0)
38
39 //#define DBUS_DEBUG(...) do { DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); } while (0)
40
41 std::atomic<unsigned int>                       DBus::detail::CallId::LastId{0};
42 static std::function<void(const char*, size_t)> debugPrinter;
43 static std::mutex                               debugLock;
44
45 thread_local std::string                DBus::DBusServer::currentObjectPath;
46 thread_local DBusWrapper::ConnectionPtr DBus::DBusServer::currentConnection;
47
48 void DBus::setDebugPrinter(std::function<void(const char*, size_t)> printer)
49 {
50   std::lock_guard<std::mutex> lock(debugLock);
51   debugPrinter = std::move(printer);
52 }
53
54 void DBus::debugPrint(const char* file, size_t line, const char* format, ...)
55 {
56   std::function<void(const char*, size_t)> debugPrintFunc;
57   {
58     std::lock_guard<std::mutex> lock(debugLock);
59     if(!debugPrinter)
60       return;
61     debugPrintFunc = debugPrinter;
62   }
63   std::vector<char> buf(4096);
64   int               offset;
65   while(true)
66   {
67     offset = snprintf(buf.data(), buf.size(), "%s:%u: ", file, static_cast<unsigned int>(line));
68     if(offset < 0)
69       return;
70     if(static_cast<size_t>(offset) < buf.size())
71       break;
72     buf.resize(offset + 1);
73   }
74
75   while(true)
76   {
77     va_list args;
78     va_start(args, format);
79     int z = vsnprintf(buf.data() + offset, buf.size() - offset, format, args);
80     va_end(args);
81     if(z < 0)
82       return;
83     bool done = static_cast<size_t>(z) + static_cast<size_t>(offset) < buf.size();
84     buf.resize(static_cast<size_t>(z) + static_cast<size_t>(offset));
85     if(done)
86       break;
87   }
88   debugPrintFunc(buf.data(), buf.size());
89 }
90
91 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByName(const std::string& name)
92 {
93   return DBUS_W->eldbus_address_connection_get_impl(name);
94 }
95
96 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByType(ConnectionType connectionType)
97 {
98   return DBUS_W->eldbus_connection_get_impl(connectionType);
99 }
100
101 DBus::DBusClient::DBusClient(std::string busName, std::string pathName, std::string interfaceName, ConnectionType tp)
102 : DBusClient(std::move(busName), std::move(pathName), std::move(interfaceName), getDBusConnectionByType(tp))
103 {
104 }
105
106 DBus::DBusClient::DBusClient(std::string busName, std::string pathName, std::string interfaceName, const DBusWrapper::ConnectionPtr& conn)
107 {
108   if(!conn)
109     connectionState->connection = getDBusConnectionByType(ConnectionType::SESSION);
110   else
111     connectionState->connection = conn;
112
113
114   if (!connectionState->connection)
115   {
116     DALI_LOG_ERROR("DBusClient connection is not ready\n");
117     return;
118   }
119
120   connectionState->object = DBUS_W->eldbus_object_get_impl(connectionState->connection, busName.c_str(), pathName.c_str());
121   if(connectionState->object)
122   {
123     connectionState->proxy = DBUS_W->eldbus_proxy_get_impl(connectionState->object, interfaceName);
124     if(interfaceName != DBUS_INTERFACE_PROPERTIES)
125     {
126       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_get_impl(connectionState->object, DBUS_INTERFACE_PROPERTIES);
127     }
128     else
129     {
130       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_copy_impl(connectionState->proxy);
131     }
132   }
133   connectionInfo                = std::make_shared<ConnectionInfo>();
134   connectionInfo->busName       = std::move(busName);
135   connectionInfo->pathName      = std::move(pathName);
136   connectionInfo->interfaceName = std::move(interfaceName);
137 }
138
139 DBus::DBusServer::DBusServer(ConnectionType tp)
140 : DBus::DBusServer(DBus::getDBusConnectionByType(tp))
141 {
142 }
143
144 DBus::DBusServer::DBusServer(const DBusWrapper::ConnectionPtr& conn)
145 {
146   if(!conn)
147     connection = getDBusConnectionByType(ConnectionType::SESSION);
148   else
149     connection = conn;
150 }
151
152 DBus::DBusInterfaceDescription::DBusInterfaceDescription(std::string interfaceName)
153 : interfaceName(std::move(interfaceName))
154 {
155 }
156
157 void DBus::DBusServer::addInterface(const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback)
158 {
159   DBUS_W->add_interface_impl(fallback, pathName, connection, destructorObject->destructors, dscr.interfaceName, dscr.methods, dscr.properties, dscr.signals);
160 }
161
162 std::string DBus::DBusServer::getBusName() const
163 {
164   return getConnectionName(connection);
165 }
166
167 std::string DBus::getConnectionName(const DBusWrapper::ConnectionPtr& c)
168 {
169   return DBUS_W->eldbus_connection_unique_name_get_impl(c);
170 }
171
172 bool DBus::DBusClient::getFromEinaValue(const _Eina_Value* v, void* dst)
173 {
174   return eina_value_get(const_cast<Eina_Value*>(v), dst);
175 }
176
177 static std::unique_ptr<DBusWrapper> InstalledWrapper;
178
179 struct DefaultDBusWrapper : public DBusWrapper
180 {
181   constexpr static int ELDBUS_CALL_TIMEOUT = 1000;
182
183   DefaultDBusWrapper()
184   {
185   }
186
187   ~DefaultDBusWrapper()
188   {
189   }
190
191 #define DEFINE_GS(name, eldbus_name, unref_call)                                                   \
192   static eldbus_name* get(const std::shared_ptr<name>& a)                                          \
193   {                                                                                                \
194     return static_cast<name##Impl*>(a.get())->Value;                                               \
195   }                                                                                                \
196   static eldbus_name* release(const std::shared_ptr<name>& a)                                      \
197   {                                                                                                \
198     auto z                                   = static_cast<name##Impl*>(a.get())->Value;           \
199     static_cast<name##Impl*>(a.get())->Value = nullptr;                                            \
200     return z;                                                                                      \
201   }                                                                                                \
202   template<typename... ARGS>                                                                       \
203   static std::shared_ptr<name> create(const eldbus_name* v, ARGS&&... args)                        \
204   {                                                                                                \
205     return std::make_shared<name##Impl>(const_cast<eldbus_name*>(v), std::forward<ARGS>(args)...); \
206   }
207
208 #define DEFINE_TYPE(name, eldbus_name, unref_call)                                     \
209   struct name##Impl : public name                                                      \
210   {                                                                                    \
211     eldbus_name* Value       = nullptr;                                                \
212     bool         EraseOnExit = false;                                                  \
213     name##Impl(eldbus_name* Value, bool EraseOnExit = false): Value(Value),            \
214                                                               EraseOnExit(EraseOnExit) \
215     {                                                                                  \
216     }                                                                                  \
217     ~name##Impl()                                                                      \
218     {                                                                                  \
219       if(EraseOnExit && Value)                                                         \
220       {                                                                                \
221         unref_call;                                                                    \
222       }                                                                                \
223     }                                                                                  \
224   };                                                                                   \
225   DEFINE_GS(name, eldbus_name, unref_call)
226
227   struct ConnectionImpl : public Connection
228   {
229     Eldbus_Connection* Value       = nullptr;
230     bool               EraseOnExit = false;
231     ConnectionImpl(Eldbus_Connection* Value, bool EraseOnExit = false)
232     : Value(Value),
233       EraseOnExit(EraseOnExit)
234     {
235       ecore_event_init();
236       eldbus_init();
237     }
238
239     ~ConnectionImpl()
240     {
241       if(EraseOnExit && Value)
242       {
243         eldbus_connection_unref(Value);
244       }
245       eldbus_shutdown();
246       ecore_event_shutdown();
247     }
248   };
249
250   struct MessageIterImpl : public MessageIter
251   {
252     Eldbus_Message_Iter *Value = nullptr, *Parent = nullptr;
253     bool                 EraseOnExit = false;
254     MessageIterImpl(Eldbus_Message_Iter* Value, Eldbus_Message_Iter* Parent, bool EraseOnExit = false)
255     : Value(Value),
256       Parent(Parent),
257       EraseOnExit(EraseOnExit)
258     {
259     }
260
261     ~MessageIterImpl()
262     {
263       if(EraseOnExit && Value && Parent)
264       {
265         eldbus_message_iter_container_close(Parent, Value);
266       }
267     }
268   };
269
270   DEFINE_GS(Connection, Eldbus_Connection, )
271   DEFINE_GS(MessageIter, Eldbus_Message_Iter, )
272   DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref(Value))
273   DEFINE_TYPE(Proxy, Eldbus_Proxy, )
274   DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref(Value))
275   DEFINE_TYPE(Pending, Eldbus_Pending, )
276   DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
277 #undef DEFINE_TYPE
278
279   std::shared_ptr<Connection> eldbus_address_connection_get_impl(const std::string& addr) override
280   {
281     eldbus_init();
282     auto p = eldbus_address_connection_get(addr.c_str());
283     auto w = create(p, true);
284     eldbus_shutdown();
285     return w;
286   }
287
288 #define eldbus_message_iter_arguments_append_impl_basic(type, sig)                            \
289   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, type src) override \
290   {                                                                                           \
291     eldbus_message_iter_arguments_append(get(it), #sig, src);                                 \
292   }                                                                                           \
293   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, type& dst) override    \
294   {                                                                                           \
295     return eldbus_message_iter_get_and_next(get(it), (#sig)[0], &dst);                        \
296   }
297
298   // clang-format off
299   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
300   eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
301   eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
302   eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
303   eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
304   eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
305   eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
306   eldbus_message_iter_arguments_append_impl_basic(double, d)
307   // clang-format on
308
309 #undef eldbus_message_iter_arguments_append_impl_basic
310
311                   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, bool src) override
312   {
313     eldbus_message_iter_arguments_append(get(it), "b", src ? 1 : 0);
314   }
315
316   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, bool& dst) override
317   {
318     unsigned char q;
319     auto          z = eldbus_message_iter_get_and_next(get(it), 'b', &q);
320     dst             = q != 0;
321     return z;
322   }
323
324   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, const std::string& src) override
325   {
326     eldbus_message_iter_arguments_append(get(it), "s", src.c_str());
327   }
328
329   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, std::string& dst) override
330   {
331     auto        iter = get(it);
332     const char* q;
333     if(!eldbus_message_iter_get_and_next(iter, 's', &q))
334     {
335       if(!eldbus_message_iter_get_and_next(iter, 'o', &q))
336       {
337         return false;
338       }
339     }
340     dst = q;
341     return true;
342   }
343
344   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, const ObjectPath& src) override
345   {
346     eldbus_message_iter_arguments_append(get(it), "o", src.value.c_str());
347   }
348
349   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, ObjectPath& dst) override
350   {
351     const char* q;
352     if(!eldbus_message_iter_get_and_next(get(it), 'o', &q))
353     {
354       return false;
355     }
356     dst.value = q;
357     return true;
358   }
359
360   MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr& it, int type, const std::string& sig) override
361   {
362     auto z = eldbus_message_iter_container_new(get(it), type, !sig.empty() ? sig.c_str() : NULL);
363     return create(z, get(it), true);
364   }
365
366   MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr& it, int type) override
367   {
368     Eldbus_Message_Iter* entry;
369     if(!eldbus_message_iter_get_and_next(get(it), type, &entry))
370     {
371       return {};
372     }
373     return create(entry, get(it), false);
374   }
375
376   MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr& msg, bool) override
377   {
378     return create(eldbus_message_iter_get(get(msg)), nullptr, false);
379   }
380
381   MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr& proxy, const std::string& funcName)
382   {
383     return create(eldbus_proxy_method_call_new(get(proxy), funcName.c_str()));
384   }
385
386   MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr& proxy, const MessagePtr& msg) override
387   {
388     return create(eldbus_proxy_send_and_block(get(proxy), release(msg), ELDBUS_CALL_TIMEOUT));
389   }
390
391   bool eldbus_message_error_get_impl(const MessagePtr& msg, std::string& name, std::string& text) override
392   {
393     const char *errname, *errmsg;
394     if(eldbus_message_error_get(get(msg), &errname, &errmsg))
395     {
396       name = errname;
397       text = errmsg;
398       return true;
399     }
400     return false;
401   }
402
403   std::string eldbus_message_signature_get_impl(const MessagePtr& msg) override
404   {
405     return eldbus_message_signature_get(get(msg));
406   }
407
408   static void callAsyncCb(void* data, const Eldbus_Message* msg, Eldbus_Pending* pending)
409   {
410     auto d = static_cast<SendCallback*>(data);
411     (*d)(create(msg, false));
412   }
413
414   static void pendingFreeCb(void* data, const void*)
415   {
416     auto d = static_cast<SendCallback*>(data);
417     delete d;
418   }
419
420   static void listenerCallbackFree(void* data, const void*)
421   {
422     auto d = static_cast<std::function<void(const Eldbus_Message* msg)>*>(data);
423     delete d;
424   }
425
426   PendingPtr eldbus_proxy_send_impl(const ProxyPtr& proxy, const MessagePtr& msg, const SendCallback& callback) override
427   {
428     auto cb      = new SendCallback{callback};
429     auto pending = eldbus_proxy_send(get(proxy), release(msg), callAsyncCb, cb, ELDBUS_CALL_TIMEOUT);
430     if(pending)
431     {
432       eldbus_pending_free_cb_add(pending, pendingFreeCb, cb);
433     }
434     else
435     {
436       delete cb;
437     }
438     return create(pending, false);
439   }
440
441   std::string eldbus_proxy_interface_get_impl(const ProxyPtr& proxy) override
442   {
443     return eldbus_proxy_interface_get(get(proxy));
444   }
445
446   static void listenerCallback(void* data, const Eldbus_Message* msg)
447   {
448     auto p = static_cast<std::function<void(const Eldbus_Message* msg)>*>(data);
449     (*p)(msg);
450   }
451
452   void eldbus_proxy_signal_handler_add_impl(const ProxyPtr& proxy, const std::string& member, const std::function<void(const MessagePtr&)>& cb) override
453   {
454     auto tmp = new std::function<void(const Eldbus_Message* msg)>{
455       [cb](const Eldbus_Message* msg) {
456         cb(create(msg, false));
457       }};
458     auto handler = eldbus_proxy_signal_handler_add(get(proxy), member.c_str(), listenerCallback, tmp);
459     if(handler)
460     {
461       eldbus_proxy_free_cb_add(get(proxy), listenerCallbackFree, tmp);
462     }
463     else
464     {
465       delete tmp;
466     }
467   }
468
469   std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr& iter) override
470   {
471     return eldbus_message_iter_signature_get(get(iter));
472   }
473
474   MessagePtr eldbus_message_method_return_new_impl(const MessagePtr& msg) override
475   {
476     return create(eldbus_message_method_return_new(get(msg)));
477   }
478
479   MessagePtr eldbus_message_error_new_impl(const MessagePtr& msg, const std::string& err, const std::string& txt) override
480   {
481     return create(eldbus_message_error_new(get(msg), err.c_str(), txt.c_str()));
482   }
483
484   PendingPtr eldbus_connection_send_impl(const ConnectionPtr& conn, const MessagePtr& msg) override
485   {
486     return create(eldbus_connection_send(get(conn), get(msg), NULL, NULL, -1));
487   }
488
489   MessagePtr eldbus_message_signal_new_impl(const std::string& path, const std::string& iface, const std::string& name) override
490   {
491     return create(eldbus_message_signal_new(path.c_str(), iface.c_str(), name.c_str()));
492   }
493
494   MessagePtr eldbus_message_ref_impl(const MessagePtr& msg) override
495   {
496     return create(eldbus_message_ref(get(msg)), true);
497   }
498
499   ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override
500   {
501     Eldbus_Connection_Type eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
502
503     switch(type)
504     {
505       case ConnectionType::SYSTEM:
506       {
507         eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
508         break;
509       }
510       case ConnectionType::SESSION:
511       {
512         eldbusType = ELDBUS_CONNECTION_TYPE_SESSION;
513         break;
514       }
515     }
516
517     auto p = eldbus_connection_get(eldbusType);
518     if (!p)
519     {
520       DALI_LOG_ERROR("cannot get dbus connection\n");
521       return NULL;
522     }
523     auto w = create(p, true);
524     return w;
525   }
526
527   std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr& conn) override
528   {
529     return eldbus_connection_unique_name_get(get(conn));
530   }
531
532   ObjectPtr eldbus_object_get_impl(const ConnectionPtr& conn, const std::string& bus, const std::string& path) override
533   {
534     return create(eldbus_object_get(get(conn), bus.c_str(), path.c_str()), true);
535   }
536
537   ProxyPtr eldbus_proxy_get_impl(const ObjectPtr& obj, const std::string& interface) override
538   {
539     return create(eldbus_proxy_get(get(obj), interface.c_str()), false);
540   }
541
542   ProxyPtr eldbus_proxy_copy_impl(const ProxyPtr& ptr) override
543   {
544     return create(get(ptr), false);
545   }
546
547   struct Implementation
548   {
549     Eldbus_Service_Interface_Desc             dsc;
550     std::vector<std::vector<Eldbus_Arg_Info>> argsInfos;
551     std::vector<Eldbus_Method>                methods;
552     std::vector<Eldbus_Signal>                signals;
553     std::vector<Eldbus_Property>              properties;
554
555     std::unordered_map<std::string, DBusWrapper::MethodInfo>   methodsMap;
556     std::unordered_map<std::string, DBusWrapper::PropertyInfo> propertiesMap;
557     std::unordered_map<unsigned int, DBusWrapper::SignalInfo>  signalsMap;
558
559     DBusWrapper::ConnectionWeakPtr connection;
560   };
561
562   static std::unordered_map<const Eldbus_Service_Interface*, std::unique_ptr<Implementation>> globalEntries;
563   static std::mutex                                                                           globalEntriesMutex;
564
565 #undef EINA_FALSE
566 #undef EINA_TRUE
567 #define EINA_FALSE static_cast<Eina_Bool>(0)
568 #define EINA_TRUE static_cast<Eina_Bool>(1)
569
570   static Eina_Bool property_get_callback(const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter, const Eldbus_Message* message, Eldbus_Message** error)
571   {
572     Implementation* impl = nullptr;
573     {
574       std::lock_guard<std::mutex> lock(globalEntriesMutex);
575       auto                        it = globalEntries.find(iface);
576       if(it != globalEntries.end())
577       {
578         impl = it->second.get();
579       }
580     }
581     if(!impl)
582     {
583       return EINA_FALSE;
584     }
585
586     auto it = impl->propertiesMap.find(propertyName);
587     if(it == impl->propertiesMap.end() || !it->second.getCallback)
588     {
589       return EINA_FALSE;
590     }
591
592     auto connection = impl->connection.lock();
593     if(!connection)
594     {
595       return EINA_FALSE;
596     }
597
598     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
599     auto                                  reply = it->second.getCallback(create(message, false), create(iter, nullptr, false));
600     if(!reply.empty())
601     {
602       if(error)
603       {
604         *error = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", reply.c_str());
605       }
606       return EINA_FALSE;
607     }
608
609     return EINA_TRUE;
610   }
611
612   static Eldbus_Message* property_set_callback(const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter, const Eldbus_Message* message)
613   {
614     Implementation* impl = nullptr;
615     {
616       std::lock_guard<std::mutex> lock(globalEntriesMutex);
617       auto                        it = globalEntries.find(iface);
618       if(it != globalEntries.end())
619       {
620         impl = it->second.get();
621       }
622     }
623     if(!impl)
624     {
625       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown interface");
626       return ret;
627     }
628     auto it = impl->propertiesMap.find(propertyName);
629     if(it == impl->propertiesMap.end() || !it->second.setCallback)
630     {
631       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown setter");
632       return ret;
633     }
634     auto connection = impl->connection.lock();
635     if(!connection)
636     {
637       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Connection lost");
638       return ret;
639     }
640
641     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
642     auto                                  reply = it->second.setCallback(create(message, false), create(iter, nullptr, false));
643
644     Eldbus_Message* ret = nullptr;
645     if(!reply.empty())
646     {
647       ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", reply.c_str());
648     }
649     else
650     {
651       ret = eldbus_message_method_return_new(message);
652     }
653     return ret;
654   }
655
656   static Eldbus_Message* method_callback(const Eldbus_Service_Interface* iface, const Eldbus_Message* message)
657   {
658     Implementation* impl = nullptr;
659     {
660       std::lock_guard<std::mutex> lock(globalEntriesMutex);
661       auto                        it = globalEntries.find(iface);
662       if(it != globalEntries.end())
663         impl = it->second.get();
664     }
665     if(!impl)
666     {
667       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown interface");
668       return ret;
669     }
670     std::string memberName = eldbus_message_member_get(message);
671     auto        it         = impl->methodsMap.find(memberName);
672     if(it == impl->methodsMap.end())
673     {
674       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown method");
675       return ret;
676     }
677     auto connection = impl->connection.lock();
678     if(!connection)
679     {
680       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Connection lost");
681       return ret;
682     }
683     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
684     auto                                  reply = it->second.callback(create(message));
685     return release(reply);
686   }
687
688   void add_interface_impl(bool                                fallback,
689                           const std::string&                  pathName,
690                           const ConnectionPtr&                connection,
691                           std::vector<std::function<void()>>& destructors,
692                           const std::string&                  interfaceName,
693                           std::vector<MethodInfo>&            dscrMethods,
694                           std::vector<PropertyInfo>&          dscrProperties,
695                           std::vector<SignalInfo>&            dscrSignals) override
696   {
697     std::vector<Eldbus_Method>                                                    methods;
698     std::vector<Eldbus_Signal>                                                    signals;
699     std::vector<Eldbus_Property>                                                  properties;
700     std::vector<std::vector<Eldbus_Arg_Info>>                                     argsInfos;
701     std::unordered_map<std::string, DBus::DBusInterfaceDescription::MethodInfo>   methodsMap;
702     std::unordered_map<std::string, DBus::DBusInterfaceDescription::PropertyInfo> propertiesMap;
703     std::unordered_map<unsigned int, DBus::DBusInterfaceDescription::SignalInfo>  signalsMap;
704
705     DBUS_DEBUG("interface %s path %s on bus %s", interfaceName.c_str(), pathName.c_str(), DBus::getConnectionName(connection).c_str());
706     auto makeArgInfo = [&](const std::vector<std::pair<std::string, std::string>>& input) {
707       argsInfos.push_back({});
708       auto& dst = argsInfos.back();
709       for(auto& s : input)
710       {
711         auto a = Strings.add(s.first);
712         auto b = Strings.add(s.second);
713         dst.push_back({a, b});
714       }
715       dst.push_back({nullptr, nullptr});
716       return dst.data();
717     };
718     for(auto& ee : dscrMethods)
719     {
720       auto key = ee.memberName;
721       DBUS_DEBUG("adding method %s", ee.memberName.c_str());
722       for(auto& r : ee.in)
723       {
724         DBUS_DEBUG("in %s '%s'", r.first.c_str(), r.second.c_str());
725       }
726       for(auto& r : ee.out)
727       {
728         DBUS_DEBUG("out %s '%s'", r.first.c_str(), r.second.c_str());
729       }
730       auto& e = (methodsMap[key] = std::move(ee));
731       methods.push_back({});
732       auto& m  = methods.back();
733       m.member = e.memberName.c_str();
734       m.in     = makeArgInfo(e.in);
735       m.out    = makeArgInfo(e.out);
736       m.cb     = method_callback;
737       m.flags  = 0;
738     }
739     for(auto& ee : dscrProperties)
740     {
741       auto key = ee.memberName;
742       DBUS_DEBUG("adding property %s", ee.memberName.c_str());
743       auto& e = (propertiesMap[key] = std::move(ee));
744       properties.push_back({});
745       auto& m    = properties.back();
746       m.name     = e.memberName.c_str();
747       m.type     = e.typeSignature.c_str();
748       m.get_func = e.getCallback ? property_get_callback : nullptr;
749       m.set_func = e.setCallback ? property_set_callback : nullptr;
750       m.flags    = 0;
751     }
752     dscrMethods.clear();
753     dscrProperties.clear();
754     dscrSignals.clear();
755
756     methods.push_back({nullptr, nullptr, nullptr, nullptr, 0});
757     signals.push_back({nullptr, nullptr, 0});
758     properties.push_back({nullptr, nullptr, nullptr, nullptr, 0});
759
760     auto impl = std::unique_ptr<Implementation>(new Implementation{
761       {interfaceName.c_str(),
762        methods.data(),
763        signals.data(),
764        properties.data(),
765        nullptr,
766        nullptr},
767       std::move(argsInfos),
768       std::move(methods),
769       std::move(signals),
770       std::move(properties),
771       std::move(methodsMap),
772       std::move(propertiesMap),
773       std::move(signalsMap),
774       connection});
775
776     {
777       std::lock_guard<std::mutex> lock(globalEntriesMutex);
778       auto                        v = fallback ? eldbus_service_interface_fallback_register(get(connection), pathName.c_str(), &impl->dsc) : eldbus_service_interface_register(get(connection), pathName.c_str(), &impl->dsc);
779       assert(v);
780       globalEntries[v] = std::move(impl);
781       DBUS_DEBUG("registering interface %p (%d)", v, fallback ? 1 : 0);
782       destructors.push_back([=]() {
783         DBUS_DEBUG("unregistering interface %p", v);
784         {
785           std::lock_guard<std::mutex> lock(globalEntriesMutex);
786           globalEntries.erase(v);
787         }
788         eldbus_service_interface_unregister(v);
789       });
790     }
791   }
792
793   static void listenerEventChangedCallback(void* data, Eldbus_Proxy* proxy EINA_UNUSED, void* event)
794   {
795     auto p = static_cast<std::function<void(Eldbus_Proxy_Event_Property_Changed*)>*>(data);
796     (*p)(static_cast<Eldbus_Proxy_Event_Property_Changed*>(event));
797   }
798
799   static void ProxyEventCallbackDelCb(void* data, const void* obj)
800   {
801     auto d = static_cast<std::function<void(Eldbus_Proxy_Event_Property_Changed*)>*>(data);
802     delete d;
803   }
804
805   void add_property_changed_event_listener_impl(const ProxyPtr& proxy, const std::string& interface, const std::string& name, std::function<void(const Eina_Value*)> cb) override
806   {
807     auto callbackLambdaPtr = new std::function<void(Eldbus_Proxy_Event_Property_Changed * epc)>{
808       [cb, name, interface](Eldbus_Proxy_Event_Property_Changed* ev) {
809         const char* ifc = eldbus_proxy_interface_get(ev->proxy);
810         if(ev->name && ev->name == name && ifc && interface == ifc)
811         {
812           cb(ev->value);
813         }
814       }};
815     auto p = get(proxy);
816     eldbus_proxy_event_callback_add(p, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, listenerEventChangedCallback, callbackLambdaPtr);
817     eldbus_proxy_free_cb_add(p, ProxyEventCallbackDelCb, callbackLambdaPtr);
818   }
819 };
820
821 std::unordered_map<const Eldbus_Service_Interface*, std::unique_ptr<DefaultDBusWrapper::Implementation>> DefaultDBusWrapper::globalEntries;
822 std::mutex                                                                                               DefaultDBusWrapper::globalEntriesMutex;
823
824 DBusWrapper* DBusWrapper::Installed()
825 {
826   if(!InstalledWrapper)
827   {
828     InstalledWrapper.reset(new DefaultDBusWrapper);
829   }
830   return InstalledWrapper.get();
831 }
832
833 void DBusWrapper::Install(std::unique_ptr<DBusWrapper> w)
834 {
835   InstalledWrapper = std::move(w);
836 }