2 * Copyright 2019 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.
18 #include <dali/internal/accessibility/bridge/dbus.h>
20 #include <dali/internal/accessibility/bridge/accessibility-common.h>
28 #include <Ecore_Input.h>
31 #include <dali/public-api/dali-adaptor-common.h>
33 #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
37 #define EINA_TRUE static_cast< Eina_Bool >( 1 )
38 #define EINA_FALSE static_cast< Eina_Bool >( 0 )
40 //#define DBUS_DEBUG(...) do { DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); } while (0)
42 std::atomic< unsigned int > DBus::detail::CallId::LastId{0};
43 static std::function< void( const char*, size_t ) > debugPrinter;
44 static std::mutex debugLock;
46 thread_local std::string DBus::DBusServer::currentObjectPath;
47 thread_local DBusWrapper::ConnectionPtr DBus::DBusServer::currentConnection;
49 void DBus::setDebugPrinter( std::function< void( const char*, size_t ) > printer )
51 std::lock_guard< std::mutex > lock( debugLock );
52 debugPrinter = std::move( printer );
55 void DBus::debugPrint( const char* file, size_t line, const char* format, ... )
57 std::function< void( const char*, size_t ) > debugPrintFunc;
59 std::lock_guard< std::mutex > lock( debugLock );
62 debugPrintFunc = debugPrinter;
64 std::vector< char > buf( 4096 );
68 offset = snprintf( buf.data(), buf.size(), "%s:%u: ", file, static_cast< unsigned int >( line ) );
71 if( static_cast< size_t >( offset ) < buf.size() )
73 buf.resize( offset + 1 );
79 va_start( args, format );
80 int z = vsnprintf( buf.data() + offset, buf.size() - offset, format, args );
84 bool done = static_cast< size_t >( z ) + static_cast< size_t >( offset ) < buf.size();
85 buf.resize( static_cast< size_t >( z ) + static_cast< size_t >( offset ) );
89 debugPrintFunc( buf.data(), buf.size() );
92 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByName( const std::string& name )
94 return DBUS_W->eldbus_address_connection_get_impl( name );
97 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByType( ConnectionType connectionType )
99 return DBUS_W->eldbus_connection_get_impl(connectionType);
102 DBus::DBusClient::DBusClient( std::string busName, std::string pathName, std::string interfaceName, ConnectionType tp ) : DBusClient( std::move( busName ), std::move( pathName ), std::move( interfaceName ), getDBusConnectionByType( tp ) )
106 DBus::DBusClient::DBusClient( std::string busName, std::string pathName, std::string interfaceName, const DBusWrapper::ConnectionPtr &conn )
109 connectionState->connection = getDBusConnectionByType( ConnectionType::SESSION );
111 connectionState->connection = conn;
113 std::ostringstream o;
114 o << "bus = " << busName << " path = " << pathName << " connection = " << DBUS_W->eldbus_connection_unique_name_get_impl( connectionState->connection );
117 connectionState->object = DBUS_W->eldbus_object_get_impl( connectionState->connection, busName.c_str(), pathName.c_str() );
118 if( connectionState->object )
120 connectionState->proxy = DBUS_W->eldbus_proxy_get_impl( connectionState->object, interfaceName );
121 if( interfaceName != DBUS_INTERFACE_PROPERTIES )
123 connectionState->propertiesProxy = DBUS_W->eldbus_proxy_get_impl( connectionState->object, DBUS_INTERFACE_PROPERTIES );
127 connectionState->propertiesProxy = DBUS_W->eldbus_proxy_copy_impl( connectionState->proxy );
130 connectionInfo = std::make_shared< ConnectionInfo >();
131 connectionInfo->busName = std::move( busName );
132 connectionInfo->pathName = std::move( pathName );
133 connectionInfo->interfaceName = std::move( interfaceName );
136 DBus::DBusServer::DBusServer( ConnectionType tp ) : DBus::DBusServer( DBus::getDBusConnectionByType( tp ) )
140 DBus::DBusServer::DBusServer( const DBusWrapper::ConnectionPtr &conn )
143 connection = getDBusConnectionByType( ConnectionType::SESSION );
148 DBus::DBusInterfaceDescription::DBusInterfaceDescription( std::string interfaceName ) : interfaceName( std::move( interfaceName ) )
152 void DBus::DBusServer::addInterface( const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback )
154 DBUS_W->add_interface_impl( fallback, pathName, connection, destructorObject->destructors, dscr.interfaceName, dscr.methods, dscr.properties, dscr.signals );
157 std::string DBus::DBusServer::getBusName() const
159 return getConnectionName( connection );
162 std::string DBus::getConnectionName( const DBusWrapper::ConnectionPtr &c )
164 return DBUS_W->eldbus_connection_unique_name_get_impl( c );
167 bool DBus::DBusClient::getFromEinaValue(const _Eina_Value *v, void *dst)
169 return eina_value_get(const_cast<Eina_Value*>(v), dst);
173 static std::unique_ptr<DBusWrapper> InstalledWrapper;
175 struct DefaultDBusWrapper : public DBusWrapper {
176 constexpr static int ELDBUS_CALL_TIMEOUT = 1000;
178 DefaultDBusWrapper() {
180 ~DefaultDBusWrapper() {
182 #define DEFINE_GS(name, eldbus_name, unref_call) \
183 static eldbus_name *get(const std::shared_ptr<name> &a) { \
184 return static_cast<name ## Impl*>(a.get())->Value; \
186 static eldbus_name *release(const std::shared_ptr<name> &a) { \
187 auto z = static_cast<name ## Impl*>(a.get())->Value; \
188 static_cast<name ## Impl*>(a.get())->Value = nullptr; \
191 template <typename ... ARGS> static std::shared_ptr<name> create(const eldbus_name *v, ARGS && ... args) { \
192 return std::make_shared<name ## Impl>(const_cast<eldbus_name*>(v), std::forward<ARGS>(args)...); \
195 #define DEFINE_TYPE(name, eldbus_name, unref_call) \
196 struct name ## Impl : public name { \
197 eldbus_name *Value = nullptr; \
198 bool EraseOnExit = false; \
199 name ## Impl(eldbus_name *Value, bool EraseOnExit = false) : Value(Value), EraseOnExit(EraseOnExit) { } \
201 if (EraseOnExit && Value) { unref_call; } \
204 DEFINE_GS(name, eldbus_name, unref_call)
206 struct ConnectionImpl : public Connection {
207 Eldbus_Connection *Value = nullptr;
208 bool EraseOnExit = false;
209 ConnectionImpl(Eldbus_Connection *Value, bool EraseOnExit = false) : Value(Value), EraseOnExit(EraseOnExit) {
214 if (EraseOnExit && Value) {
215 eldbus_connection_unref( Value );
218 ecore_event_shutdown();
221 struct MessageIterImpl : public MessageIter {
222 Eldbus_Message_Iter *Value = nullptr, *Parent = nullptr;
223 bool EraseOnExit = false;
224 MessageIterImpl(Eldbus_Message_Iter *Value, Eldbus_Message_Iter *Parent, bool EraseOnExit = false) : Value(Value), Parent(Parent), EraseOnExit(EraseOnExit) { }
226 if (EraseOnExit && Value && Parent)
227 eldbus_message_iter_container_close(Parent, Value);
231 DEFINE_GS(Connection, Eldbus_Connection, )
232 DEFINE_GS(MessageIter, Eldbus_Message_Iter, )
233 DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref( Value ))
234 DEFINE_TYPE(Proxy, Eldbus_Proxy, )
235 DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref( Value ))
236 DEFINE_TYPE(Pending, Eldbus_Pending, )
237 DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
240 std::shared_ptr<Connection> eldbus_address_connection_get_impl(const std::string &addr) override {
242 auto p = eldbus_address_connection_get(addr.c_str());
243 auto w = create(p, true);
248 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
249 void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type src) override { \
250 eldbus_message_iter_arguments_append( get(it), #sig, src ); \
252 bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type &dst) override { \
253 return eldbus_message_iter_get_and_next( get(it), (#sig)[0], &dst ); \
256 eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
257 eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
258 eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
259 eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
260 eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
261 eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
262 eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
263 eldbus_message_iter_arguments_append_impl_basic(double, d)
265 #undef eldbus_message_iter_arguments_append_impl_basic
267 void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, bool src) override {
268 eldbus_message_iter_arguments_append( get(it), "b", src ? 1 : 0 );
270 bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, bool &dst) override {
272 auto z = eldbus_message_iter_get_and_next( get(it), 'b', &q );
276 void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, const std::string &src) override {
277 eldbus_message_iter_arguments_append( get(it), "s", src.c_str() );
279 bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, std::string &dst) override {
282 if( !eldbus_message_iter_get_and_next( iter, 's', &q ) )
284 if( !eldbus_message_iter_get_and_next( iter, 'o', &q ) )
290 void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, const ObjectPath &src) override {
291 eldbus_message_iter_arguments_append( get(it), "o", src.value.c_str() );
293 bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, ObjectPath &dst) override {
295 if( !eldbus_message_iter_get_and_next( get(it), 'o', &q ) )
301 MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) override {
302 auto z = eldbus_message_iter_container_new( get(it), type, !sig.empty() ? sig.c_str() : NULL );
303 return create(z, get(it), true);
305 MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) override {
306 Eldbus_Message_Iter* entry;
307 if (!eldbus_message_iter_get_and_next( get(it), type, &entry ) ) return {};
308 return create(entry, get(it), false);
310 MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &msg, bool) override {
311 return create(eldbus_message_iter_get(get(msg)), nullptr, false);
313 MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) {
314 return create(eldbus_proxy_method_call_new( get(proxy), funcName.c_str() ) );
316 MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override {
317 return create(eldbus_proxy_send_and_block(get(proxy), release(msg), ELDBUS_CALL_TIMEOUT) );
319 bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override {
320 const char *errname, *errmsg;
321 if( eldbus_message_error_get( get(msg), &errname, &errmsg ) ) {
328 std::string eldbus_message_signature_get_impl(const MessagePtr &msg) override {
329 return eldbus_message_signature_get(get(msg));
332 static void callAsyncCb( void* data, const Eldbus_Message *msg, Eldbus_Pending *pending )
334 auto d = static_cast< SendCallback* >( data );
335 (*d)( create(msg, false) );
337 static void pendingFreeCb( void* data, const void* )
339 auto d = static_cast< SendCallback* >( data );
342 static void listenerCallbackFree( void* data, const void* )
344 auto d = static_cast< std::function< void( const Eldbus_Message* msg ) >* >( data );
348 PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override {
349 auto cb = new SendCallback{ callback };
350 auto pending = eldbus_proxy_send( get(proxy), release(msg), callAsyncCb, cb, ELDBUS_CALL_TIMEOUT );
353 eldbus_pending_free_cb_add( pending, pendingFreeCb, cb );
359 return create(pending, false);
361 std::string eldbus_proxy_interface_get_impl(const ProxyPtr &proxy) override {
362 return eldbus_proxy_interface_get( get(proxy) );
364 static void listenerCallback( void* data, const Eldbus_Message* msg )
366 auto p = static_cast< std::function< void( const Eldbus_Message* msg ) >* >( data );
369 void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) override {
370 auto tmp = new std::function< void( const Eldbus_Message* msg ) >{
371 [cb](const Eldbus_Message* msg) {
372 cb(create(msg, false));
375 auto handler = eldbus_proxy_signal_handler_add( get(proxy), member.c_str(), listenerCallback, tmp );
377 eldbus_proxy_free_cb_add( get(proxy), listenerCallbackFree, tmp );
381 std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) override {
382 return eldbus_message_iter_signature_get( get(iter) );
384 MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) override {
385 return create(eldbus_message_method_return_new( get(msg) ) );
387 MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) override {
388 return create(eldbus_message_error_new( get(msg), err.c_str(), txt.c_str() ) );
390 PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) override {
391 return create(eldbus_connection_send( get(conn), get(msg), NULL, NULL, -1 ) );
393 MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) override {
394 return create(eldbus_message_signal_new( path.c_str(), iface.c_str(), name.c_str() ) );
396 MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) override {
397 return create(eldbus_message_ref( get(msg) ), true );
399 ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override {
400 Eldbus_Connection_Type eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
404 case ConnectionType::SYSTEM:
406 eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
409 case ConnectionType::SESSION:
411 eldbusType = ELDBUS_CONNECTION_TYPE_SESSION;
417 auto p = eldbus_connection_get( eldbusType );
418 auto w = create(p, true);
422 std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) override {
423 return eldbus_connection_unique_name_get( get(conn) );
425 ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) override {
426 return create(eldbus_object_get(get(conn), bus.c_str(), path.c_str() ), true );
428 ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) override {
429 return create(eldbus_proxy_get(get(obj), interface.c_str() ), false );
431 ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) override {
432 return create(get(ptr), false );
440 struct Implementation
442 Eldbus_Service_Interface_Desc dsc;
443 std::vector< std::vector< Eldbus_Arg_Info > > argsInfos;
444 std::vector< Eldbus_Method > methods;
445 std::vector< Eldbus_Signal > signals;
446 std::vector< Eldbus_Property > properties;
448 std::unordered_map< std::string, DBusWrapper::MethodInfo > methodsMap;
449 std::unordered_map< std::string, DBusWrapper::PropertyInfo > propertiesMap;
450 std::unordered_map< unsigned int, DBusWrapper::SignalInfo > signalsMap;
452 DBusWrapper::ConnectionWeakPtr connection;
455 static std::unordered_map< const Eldbus_Service_Interface*, std::unique_ptr< Implementation > > globalEntries;
456 static std::mutex globalEntriesMutex;
460 #define EINA_FALSE static_cast<Eina_Bool>(0)
461 #define EINA_TRUE static_cast<Eina_Bool>(1)
463 static Eina_Bool property_get_callback( const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter,
464 const Eldbus_Message* message, Eldbus_Message** error )
466 Implementation* impl = nullptr;
468 std::lock_guard< std::mutex > lock( globalEntriesMutex );
469 auto it = globalEntries.find( iface );
470 if( it != globalEntries.end() )
471 impl = it->second.get();
476 auto it = impl->propertiesMap.find( propertyName );
477 if( it == impl->propertiesMap.end() || !it->second.getCallback )
480 auto connection = impl->connection.lock();
484 DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
485 auto reply = it->second.getCallback( create(message, false), create(iter, nullptr, false) );
489 *error = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", reply.c_str() );
496 static Eldbus_Message* property_set_callback( const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter,
497 const Eldbus_Message* message )
499 Implementation* impl = nullptr;
501 std::lock_guard< std::mutex > lock( globalEntriesMutex );
502 auto it = globalEntries.find( iface );
503 if( it != globalEntries.end() )
504 impl = it->second.get();
508 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown interface" );
511 auto it = impl->propertiesMap.find( propertyName );
512 if( it == impl->propertiesMap.end() || !it->second.setCallback )
514 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown setter" );
517 auto connection = impl->connection.lock();
520 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Connection lost" );
524 DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
525 auto reply = it->second.setCallback( create(message, false), create(iter, nullptr, false) );
527 Eldbus_Message* ret = nullptr;
530 ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", reply.c_str() );
534 ret = eldbus_message_method_return_new( message );
539 static Eldbus_Message* method_callback( const Eldbus_Service_Interface* iface, const Eldbus_Message* message )
541 Implementation* impl = nullptr;
543 std::lock_guard< std::mutex > lock( globalEntriesMutex );
544 auto it = globalEntries.find( iface );
545 if( it != globalEntries.end() )
546 impl = it->second.get();
550 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown interface" );
553 std::string memberName = eldbus_message_member_get( message );
554 auto it = impl->methodsMap.find( memberName );
555 if( it == impl->methodsMap.end() )
557 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown method" );
560 auto connection = impl->connection.lock();
563 auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Connection lost" );
566 DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
567 auto reply = it->second.callback( create(message) );
568 return release(reply);
571 void add_interface_impl( bool fallback, const std::string& pathName,
572 const ConnectionPtr &connection,
573 std::vector<std::function<void()>> &destructors,
574 const std::string& interfaceName,
575 std::vector< MethodInfo >& dscrMethods,
576 std::vector< PropertyInfo >& dscrProperties,
577 std::vector< SignalInfo >& dscrSignals ) override
579 std::vector< Eldbus_Method > methods;
580 std::vector< Eldbus_Signal > signals;
581 std::vector< Eldbus_Property > properties;
582 std::vector< std::vector< Eldbus_Arg_Info > > argsInfos;
583 std::unordered_map< std::string, DBus::DBusInterfaceDescription::MethodInfo > methodsMap;
584 std::unordered_map< std::string, DBus::DBusInterfaceDescription::PropertyInfo > propertiesMap;
585 std::unordered_map< unsigned int, DBus::DBusInterfaceDescription::SignalInfo > signalsMap;
587 DBUS_DEBUG( "interface %s path %s on bus %s", interfaceName.c_str(), pathName.c_str(), DBus::getConnectionName( connection ).c_str() );
588 auto makeArgInfo = [&](const std::vector<std::pair<std::string, std::string>> &input) {
589 argsInfos.push_back({});
590 auto &dst = argsInfos.back();
591 for(auto &s : input) {
592 auto a = Strings.add(s.first);
593 auto b = Strings.add(s.second);
594 dst.push_back({ a, b });
596 dst.push_back({ nullptr, nullptr });
599 for( auto& ee : dscrMethods )
601 auto key = ee.memberName;
602 DBUS_DEBUG( "adding method %s", ee.memberName.c_str() );
603 for( auto& r : ee.in )
605 DBUS_DEBUG( "in %s '%s'", r.first.c_str(), r.second.c_str() );
607 for( auto& r : ee.out )
609 DBUS_DEBUG( "out %s '%s'", r.first.c_str(), r.second.c_str() );
611 auto& e = ( methodsMap[key] = std::move( ee ) );
612 methods.push_back( {} );
613 auto& m = methods.back();
614 m.member = e.memberName.c_str();
615 m.in = makeArgInfo(e.in);
616 m.out = makeArgInfo(e.out);
617 m.cb = method_callback;
620 for( auto& ee : dscrProperties )
622 auto key = ee.memberName;
623 DBUS_DEBUG( "adding property %s", ee.memberName.c_str() );
624 auto& e = ( propertiesMap[key] = std::move( ee ) );
625 properties.push_back( {} );
626 auto& m = properties.back();
627 m.name = e.memberName.c_str();
628 m.type = e.typeSignature.c_str();
629 m.get_func = e.getCallback ? property_get_callback : nullptr;
630 m.set_func = e.setCallback ? property_set_callback : nullptr;
634 dscrProperties.clear();
637 methods.push_back( {nullptr, nullptr, nullptr, nullptr, 0} );
638 signals.push_back( {nullptr, nullptr, 0} );
639 properties.push_back( {nullptr, nullptr, nullptr, nullptr, 0} );
641 auto impl = std::unique_ptr< Implementation >( new Implementation{
642 {interfaceName.c_str(),
648 std::move( argsInfos ),
649 std::move( methods ),
650 std::move( signals ),
651 std::move( properties ),
652 std::move( methodsMap ),
653 std::move( propertiesMap ),
654 std::move( signalsMap ),
658 std::lock_guard< std::mutex > lock( globalEntriesMutex );
659 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 );
661 globalEntries[v] = std::move( impl );
662 DBUS_DEBUG( "registering interface %p (%d)", v, fallback ? 1 : 0 );
663 destructors.push_back([=]() {
664 DBUS_DEBUG( "unregistering interface %p", v );
665 eldbus_service_interface_unregister( v );
666 std::lock_guard< std::mutex > lock( globalEntriesMutex );
667 globalEntries.erase( v );
671 static void listenerEventChangedCallback( void* data, Eldbus_Proxy* proxy EINA_UNUSED, void* event )
673 auto p = static_cast< std::function< void( Eldbus_Proxy_Event_Property_Changed* ) >* >( data );
674 ( *p )( static_cast< Eldbus_Proxy_Event_Property_Changed* >( event ) );
676 static void ProxyEventCallbackDelCb( void* data, const void *obj )
678 auto d = static_cast< std::function< void( Eldbus_Proxy_Event_Property_Changed* ) >* >( data );
681 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 {
682 auto callbackLambdaPtr = new std::function< void( Eldbus_Proxy_Event_Property_Changed *epc ) >{
683 [cb, name, interface]( Eldbus_Proxy_Event_Property_Changed *ev ) {
684 const char* ifc = eldbus_proxy_interface_get( ev->proxy );
685 if( ev->name && ev->name == name && ifc && interface == ifc )
691 eldbus_proxy_event_callback_add( p, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
692 listenerEventChangedCallback, callbackLambdaPtr );
693 eldbus_proxy_free_cb_add( p, ProxyEventCallbackDelCb, callbackLambdaPtr );
697 std::unordered_map< const Eldbus_Service_Interface*, std::unique_ptr< DefaultDBusWrapper::Implementation > > DefaultDBusWrapper::globalEntries;
698 std::mutex DefaultDBusWrapper::globalEntriesMutex;
700 DBusWrapper *DBusWrapper::Installed()
702 if (!InstalledWrapper)
703 InstalledWrapper.reset(new DefaultDBusWrapper);
704 return InstalledWrapper.get();
707 void DBusWrapper::Install(std::unique_ptr<DBusWrapper> w)
709 InstalledWrapper = std::move(w);
713 // struct TestDBusWrapper::ConnectionImpl : public TestDBusWrapper::Connection {
716 // TestDBusWrapper::TestDBusWrapper()
719 // connection = std::make_shared<ConnectionImpl>();
720 // testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "ScreenReaderEnabled", MethodType::Getter}] =
721 // testMethods[std::tuple<std::string, std::string, std::string, MethodType>{"/org/a11y/bus", "org.a11y.Status", "IsEnabled", MethodType::Getter}] =
722 // [this](const DBusWrapper::MessagePtr &m) -> MessagePtr {
723 // auto reply = newReplyMessage(m);
724 // Encode(reply, std::tuple<TestDBusWrapper::Variant<bool>>{ TestDBusWrapper::Variant<bool>{ false} });
728 // TestDBusWrapper::~TestDBusWrapper()
733 // TestDBusWrapper::ConnectionPtr TestDBusWrapper::eldbus_address_connection_get_impl(const std::string &addr)
735 // return connection;
738 // struct TestDBusWrapper::MessageIterImpl : public TestDBusWrapper::MessageIter {
742 // std::list<Element>::iterator it;
743 // MessageIterImpl(MessagePtr msg, Element *elem, bool write) : msg(std::move(msg)), elem(elem), write(write) {
744 // if (!write) it = elem->get<ElementList>().begin();
746 // MessageIterImpl(MessagePtr msg, Element *elem, bool write, std::list<Element>::iterator it) : msg(std::move(msg)), elem(elem), write(write), it(it) { }
748 // struct TestDBusWrapper::MessageImpl : public TestDBusWrapper::Message {
749 // std::string bus, path, interface, name;
751 // bool reply, error = false;
752 // std::string error_a, error_b;
754 // MessageImpl(std::string bus, std::string path, std::string interface, std::string name, bool reply) :
755 // bus(std::move(bus)), path(std::move(path)), interface(std::move(interface)), name(std::move(name)), data{ ElementList{} }, reply(reply) { }
756 // MessageImpl(std::string bus, std::string path, std::string interface, std::string name, std::string error_a, std::string error_b) :
757 // bus(std::move(bus)), path(std::move(path)), interface(std::move(interface)), name(std::move(name)), data{ ElementList{} },
758 // reply(true), error(true), error_a(std::move(error_a)), error_b(std::move(error_b)) { }
760 // struct TestDBusWrapper::ProxyImpl : public TestDBusWrapper::Proxy {
761 // std::string bus, path, interface;
762 // ProxyImpl(std::string bus, std::string path, std::string interface) : bus(std::move(bus)), path(std::move(path)), interface(std::move(interface)) { }
764 // struct TestDBusWrapper::ObjectImpl : public TestDBusWrapper::Object {
765 // std::string bus, path;
766 // ObjectImpl(std::string bus, std::string path) : bus(std::move(bus)), path(std::move(path)) { }
768 // #define DEFINE_TYPE(name) TestDBusWrapper::name ## Impl *TestDBusWrapper::get(const name ## Ptr &v) { return static_cast<name ## Impl*>(v.get()); }
769 // DEFINE_TYPE(Connection)
770 // DEFINE_TYPE(Proxy)
771 // DEFINE_TYPE(Object)
772 // DEFINE_TYPE(Message)
773 // DEFINE_TYPE(MessageIter)
774 // #undef DEFINE_TYPE
776 // template <typename T> void TestDBusWrapperAppendBasic(const TestDBusWrapper::MessageIterPtr &it, T src) {
777 // auto m = TestDBusWrapper::get(it);
778 // if (!m->write) throw TestDBusWrapper::error{};
779 // if (!m->elem->isContainer()) throw TestDBusWrapper::error{};
780 // m->elem->get<TestDBusWrapper::ElementList>().push_back(TestDBusWrapper::Element{ src });
782 // template <typename T> bool TestDBusWrapperGetBasicAndNext(const TestDBusWrapper::MessageIterPtr &it, T &src) {
783 // auto m = TestDBusWrapper::get(it);
784 // if (m->write) throw TestDBusWrapper::error{};
785 // if (!m->elem->isContainer()) return false;
786 // auto &lst = m->elem->get<TestDBusWrapper::ElementList>();
787 // if (m->it == lst.end()) return false;
788 // if (!m->it->is<T>()) return false;
789 // src = m->it->get<T>();
794 // #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
795 // void TestDBusWrapper::eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) { \
796 // TestDBusWrapperAppendBasic(it, src); \
798 // bool TestDBusWrapper::eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) { \
799 // return TestDBusWrapperGetBasicAndNext(it, dst); \
801 // #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
802 // eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
804 // eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
805 // eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
806 // eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
807 // eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
808 // eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
809 // eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
810 // eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
811 // eldbus_message_iter_arguments_append_impl_basic(double, d)
812 // eldbus_message_iter_arguments_append_impl_basic(bool, b)
813 // eldbus_message_iter_arguments_append_impl_basic_impl(const std::string &, std::string, s)
814 // eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath &, ObjectPath, o)
816 // #undef eldbus_message_iter_arguments_append_impl_basic
817 // #undef eldbus_message_iter_arguments_append_impl_basic_impl
819 // TestDBusWrapper::MessageIterPtr TestDBusWrapper::eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) {
821 // if (!m->write) throw error{};
822 // if (!m->elem->isContainer()) throw error{};
823 // auto &lst = m->elem->get<ElementList>();
824 // if (type == 'r' || type == 'e' || type == 'a' || type == 'v') {
825 // lst.push_back({ ElementList{}, type });
826 // return std::make_shared<MessageIterImpl>(MessageIterImpl{ m->msg, &lst.back(), true });
831 // TestDBusWrapper::MessageIterPtr TestDBusWrapper::eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) {
833 // if (m->write) throw error{};
834 // if (!m->elem->isContainer()) throw error{} << "not a container";
835 // auto &lst = m->elem->get<ElementList>();
836 // if (m->it == lst.end()) return {};
837 // if (m->it->signature() != type) return {};
838 // auto v = std::make_shared<MessageIterImpl>(MessageIterImpl{ m->msg, &*m->it, false });
843 // TestDBusWrapper::MessageIterPtr TestDBusWrapper::eldbus_message_iter_get_impl(const MessagePtr &it, bool write) {
845 // return std::make_shared<MessageIterImpl>(MessageIterImpl{ it, &m->data, write, m->data.get<ElementList>().begin() });
848 // bool TestDBusWrapper::completed(const MessageIterPtr &iter)
850 // auto m = get(iter);
851 // assert(!m->write);
852 // return m->it == m->elem->get<ElementList>().end();
855 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) {
856 // auto p = get(proxy);
857 // return std::make_shared<MessageImpl>(MessageImpl{
858 // p->bus, p->path, p->interface, funcName, false
861 // TestDBusWrapper::MessagePtr TestDBusWrapper::call(
862 // std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> &mp,
863 // const std::string &mpName, const MessagePtr &msg, MethodType type) {
864 // auto m = get(msg);
865 // auto findMethod = [&](std::string path, const std::string &iname, const std::string &name, MethodType type) {
866 // if (path.empty()) throw error{};
867 // if (path[0] != '/') {
868 // path = "/org/a11y/atspi/accessible/" + path;
871 // while(!path.empty()) {
872 // auto it = mp.find(std::tuple<std::string, std::string, std::string, MethodType> { path, iname, name, type });
873 // if (it != mp.end()) return it;
874 // auto index = path.rfind('/');
875 // if (index == std::string::npos) break;
876 // path.resize(index);
880 // std::string iname, name;
881 // if (type == MethodType::Method && m->interface == "org.freedesktop.DBus.Properties") {
882 // type = m->name == "Get" ? MethodType::Getter : MethodType::Setter;
883 // auto &lst = m->data.get<ElementList>();
884 // assert(lst.size() >= 2);
885 // iname = lst.front().get<std::string>();
887 // name = lst.front().get<std::string>();
891 // iname = m->interface;
894 // auto it = findMethod(m->path, iname, name, type);
895 // if (it == mp.end()) {
897 // if (type == MethodType::Method) mt = "MethodType::Method";
898 // else if (type == MethodType::Getter) mt = "MethodType::Getter";
899 // else if (type == MethodType::Setter) mt = "MethodType::Setter";
901 // throw error{} << "missing {\"" << m->path << "\", \"" << iname << "\", \"" << name << "\", " << mt << "} in " << mpName;
903 // DBus::DBusServer::CurrentObjectSetter setter{ connection, m->path };
904 // return it->second(msg);
906 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) {
907 // auto p = get(proxy);
908 // auto m = get(msg);
909 // assert(p->bus == m->bus);
910 // assert(p->path == m->path);
911 // assert(p->interface == m->interface);
912 // return call(testMethods, "testMethods", msg, MethodType::Method);
915 // bool TestDBusWrapper::eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) {
916 // auto m = get(msg);
917 // name = m->error_a;
918 // text = m->error_b;
921 // static void calculate_signature(std::ostringstream &ostr, TestDBusWrapper::Element &e)
923 // ostr << static_cast<char>(e.signature());
924 // if (e.isContainer()) {
926 // auto &lst = e.get<TestDBusWrapper::ElementList>();
927 // for(auto &q : lst) calculate_signature(ostr, q);
931 // std::string TestDBusWrapper::eldbus_message_signature_get_impl(const MessagePtr &msg) {
932 // auto m = get(msg);
933 // std::ostringstream ostr;
934 // for(auto &q : m->data.get<ElementList>())
935 // calculate_signature(ostr, q);
936 // return ostr.str();
938 // TestDBusWrapper::PendingPtr TestDBusWrapper::eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) {
939 // auto p = get(proxy);
940 // auto m = get(msg);
941 // assert(p->bus == m->bus);
942 // assert(p->path == m->path);
943 // assert(p->interface == m->interface);
944 // asyncCalls.push_back([this, msg, callback]() {
945 // auto r = call(testMethods, "testMethods", msg, MethodType::Method);
950 // std::string TestDBusWrapper::eldbus_proxy_interface_get_impl(const ProxyPtr &proxy) {
951 // auto p = get(proxy);
952 // return p->interface;
954 // void TestDBusWrapper::eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) {
955 // auto p = get(proxy);
956 // daliSignals[std::tuple<std::string, std::string, std::string> { p->path, p->interface, member }] = cb;
958 // std::string TestDBusWrapper::eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) {
959 // auto m = get(iter);
960 // if (m->write) throw error{};
961 // if (!m->elem->isContainer()) throw error{};
962 // std::ostringstream ostr;
963 // auto &lst = m->elem->get<ElementList>();
964 // for(auto it = m->it; it != lst.end(); ++it)
965 // calculate_signature(ostr, *it);
966 // return ostr.str();
968 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_message_method_return_new_impl( const MessagePtr &msg) {
969 // auto m = get(msg);
970 // return std::make_shared<MessageImpl>(MessageImpl{
971 // m->bus, m->path, m->interface, m->name, true
974 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) {
975 // auto m = get(msg);
976 // return std::make_shared<MessageImpl>(MessageImpl{
977 // m->bus, m->path, m->interface, m->name, err, txt
980 // TestDBusWrapper::PendingPtr TestDBusWrapper::eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) {
981 // call(testMethods, "testMethods", msg, MethodType::Method);
984 // std::shared_ptr<Eina_Value> TestDBusWrapper::createEinaValue(bool b) {
985 // Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_UCHAR);
986 // eina_value_set(value, b);
987 // return std::shared_ptr<Eina_Value>(value, [](Eina_Value *v) {
988 // eina_value_free(v);
991 // TestDBusWrapper::MessagePtr TestDBusWrapper::newMessage(const std::string &path, const std::string &interface, const std::string &name, bool reply) {
992 // return std::make_shared<MessageImpl>(MessageImpl{
993 // "bus", path, interface, name, reply
996 // TestDBusWrapper::MessagePtr TestDBusWrapper::newReplyMessage(const MessagePtr &msg) {
997 // auto m = get(msg);
998 // return newMessage(m->path, m->interface, m->name, true);
1000 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) {
1001 // return std::make_shared<MessageImpl>(MessageImpl{
1002 // "bus", path, iface, name, true
1005 // TestDBusWrapper::MessagePtr TestDBusWrapper::eldbus_message_ref_impl(const MessagePtr &msg) {
1008 // TestDBusWrapper::ConnectionPtr TestDBusWrapper::eldbus_connection_get_impl(ConnectionType type) {
1009 // return connection;
1011 // std::string TestDBusWrapper::eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) {
1014 // TestDBusWrapper::ObjectPtr TestDBusWrapper::eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) {
1015 // return std::make_shared<ObjectImpl>(ObjectImpl{
1019 // TestDBusWrapper::ProxyPtr TestDBusWrapper::eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) {
1020 // auto o = get(obj);
1021 // return std::make_shared<ProxyImpl>(ProxyImpl{ o->bus, o->path, interface });
1023 // TestDBusWrapper::ProxyPtr TestDBusWrapper::eldbus_proxy_copy_impl( const ProxyPtr &ptr) {
1026 // void TestDBusWrapper::add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const Eina_Value * ) > cb) {
1027 // auto p = get(proxy);
1028 // propertyChangeListeners[std::tuple<std::string, std::string, std::string>{ p->path, interface, name }] = cb;
1030 // void TestDBusWrapper::add_interface_impl( bool fallback, const std::string& path_,
1031 // const ConnectionPtr &connection,
1032 // std::vector<std::function<void()>> &destructors,
1033 // const std::string& interface,
1034 // std::vector< MethodInfo >& dscrMethods,
1035 // std::vector< PropertyInfo >& dscrProperties,
1036 // std::vector< SignalInfo >& dscrSignals ) {
1037 // std::string bus = "bus";
1038 // std::string path = path_;
1039 // while(!path.empty() && path.back() == '/') path.pop_back();
1040 // for(auto &m : dscrMethods) {
1041 // auto key = std::make_tuple( "/org/a11y/atspi/accessible" + path, interface, m.memberName, MethodType::Method );
1042 // daliMethods[key] = m.callback;
1044 // for(auto &m : dscrProperties) {
1045 // auto key = std::make_tuple( "/org/a11y/atspi/accessible" + path, interface, m.memberName, MethodType::Getter );
1046 // daliMethods[key] = [=](const MessagePtr &msg) -> MessagePtr {
1047 // auto ret = std::make_shared<MessageImpl>(MessageImpl{
1048 // "bus", path, interface, m.memberName, true
1050 // auto v = m.getCallback(msg, std::make_shared<MessageIterImpl>(MessageIterImpl{ ret, &ret->data, true }));
1051 // ret->error = !v.empty();
1052 // if (ret->error) {
1053 // ret->error_a = "call failed";
1054 // ret->error_b = std::move(v);
1058 // std::get<3>(key) = MethodType::Setter;
1059 // daliMethods[key] = [=](const MessagePtr &msg) -> MessagePtr {
1060 // auto v = m.setCallback(msg, std::make_shared<MessageIterImpl>(MessageIterImpl{ msg, &get(msg)->data, false }));
1061 // return v.empty() ? std::make_shared<MessageImpl>(MessageImpl{
1062 // "bus", path, interface, m.memberName, true,
1063 // }) : std::make_shared<MessageImpl>(MessageImpl{
1064 // "bus", path, interface, m.memberName, "call failed", v
1066 // // interface is probably wrong, due to retarded way properties are handlded by dbus
1069 // for(auto &m : dscrSignals) {
1070 // daliSignalsMap[std::tuple<std::string, std::string, unsigned int>{ "/org/a11y/atspi/accessible" + path, interface, m.uniqueId }] = m.memberName;