[Tizen][ATSPI] Accessibility initial implementation
[platform/core/uifw/dali-adaptor.git] / dali / dali-bridge / src / BridgeBase.cpp
1 #include "BridgeBase.hpp"
2 #include <atomic>
3 #include <cstdlib>
4
5 using namespace Dali::Accessibility;
6
7 BridgeBase::BridgeBase()
8 {
9 }
10
11 BridgeBase::ForceUpResult BridgeBase::ForceUp()
12 {
13   if( Bridge::ForceUp() == ForceUpResult::alreadyUp )
14     return ForceUpResult::alreadyUp;
15   auto proxy = DBus::DBusClient{dbusLocators::atspi::BUS, dbusLocators::atspi::OBJ_PATH,
16                                 dbusLocators::atspi::BUS_INTERFACE, DBus::ConnectionType::SESSION};
17   auto addr = proxy.method< std::string() >( dbusLocators::atspi::GET_ADDRESS ).call();
18
19   if( !addr )
20     throw AccessibleError{std::string( "failed at call '" ) + dbusLocators::atspi::GET_ADDRESS +
21                           "': " + addr.getError().message};
22
23   con = std::make_shared< DBus::EldbusConnection >( eldbus_address_connection_get( std::get< 0 >( addr ).c_str() ) );
24   data->busName = DBus::getConnectionName( con );
25   data->root = &application;
26   dbusServer = {con};
27
28   {
29     DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Cache"};
30     AddFunctionToInterface( desc, "GetItems", &BridgeBase::GetItems );
31     dbusServer.addInterface( "/org/a11y/atspi/cache", desc );
32   }
33   {
34     DBus::DBusInterfaceDescription desc{"org.a11y.atspi.Application"};
35     AddGetSetPropertyToInterface( desc, "Id", &BridgeBase::IdGet, &BridgeBase::IdSet );
36     dbusServer.addInterface( ATSPI_PATH, desc );
37   }
38   return ForceUpResult::justStarted;
39 }
40
41 void BridgeBase::ForceDown()
42 {
43   Bridge::ForceDown();
44   dbusServer = {};
45   con = {};
46 }
47
48 const std::string& BridgeBase::GetBusName() const
49 {
50   static std::string empty;
51   return data ? data->busName : empty;
52 }
53
54 Accessible* BridgeBase::FindByPath( const std::string& name ) const
55 {
56   try
57   {
58     return Find( name );
59   }
60   catch( AccessibleError )
61   {
62     return nullptr;
63   }
64 }
65
66 void BridgeBase::SetApplicationChild( Accessible* root )
67 {
68   // for now you can set root only once.
69   // to set it multiple times you'd have to remove old one first, which usually involves
70   // a lot of messy events and cornercases (imagine old root becoming child of new-not-yet-announced one)
71   application.children.push_back( root );
72   SetIsOnRootLevel( root );
73 }
74
75 // Accessible *BridgeBase::getApplicationRoot() const
76 // {
77 //     return rootElement;
78 // }
79
80 std::string BridgeBase::StripPrefix( const std::string& path )
81 {
82   auto size = strlen( ATSPI_PATH );
83   return path.substr( size + 1 );
84 }
85
86 Accessible* BridgeBase::Find( const std::string& path ) const
87 {
88   if( path == "root" )
89     return &application;
90   char* p;
91   auto val = std::strtoll( path.c_str(), &p, 10 );
92   if( p == path.c_str() )
93     throw AccessibleError{"invalid path '" + path + "'"};
94   auto it = data->objects.find( val );
95   if( it == data->objects.end() )
96     throw AccessibleError{"unknown object '" + path + "'"};
97   return it->second;
98 }
99
100 Accessible* BridgeBase::Find( const Address& ptr ) const
101 {
102   assert( ptr.GetBus() == data->busName );
103   return Find( ptr.GetPath() );
104 }
105
106 Accessible* BridgeBase::FindSelf() const
107 {
108   auto pth = DBus::DBusServer::getCurrentObjectPath();
109   auto size = strlen( ATSPI_PATH );
110   if( pth.size() <= size )
111     throw AccessibleError{"invalid path '" + pth + "'"};
112   if( pth.substr( 0, size ) != ATSPI_PATH )
113     throw AccessibleError{"invalid path '" + pth + "'"};
114   if( pth[size] != '/' )
115     throw AccessibleError{"invalid path '" + pth + "'"};
116   return Find( StripPrefix( pth ) );
117 }
118
119 void BridgeBase::IdSet( int id )
120 {
121   this->id = id;
122 }
123 int BridgeBase::IdGet()
124 {
125   return this->id;
126 }
127
128 auto BridgeBase::GetItems() -> DBus::ValueOrError< std::vector< CacheElementType > >
129 {
130   auto root = &application;
131
132   std::vector< CacheElementType > res;
133
134   res.emplace_back( std::move( CreateCacheElement( root ) ) );
135   for( auto const& it : data->objects )
136     res.emplace_back( std::move( CreateCacheElement( it.second ) ) );
137
138   return res;
139 }
140
141 auto BridgeBase::CreateCacheElement( Accessible* item ) -> CacheElementType
142 {
143   if( !item )
144     return {};
145
146   auto root = &application;
147   auto parent = item->GetParent();
148
149   std::vector< Address > children;
150   for( auto i = 0u; i < item->GetChildCount(); ++i )
151   {
152     children.emplace_back( item->GetChildAtIndex( i )->GetAddress() );
153   }
154
155   return std::make_tuple(
156       item->GetAddress(),
157       root->GetAddress(),
158       parent->GetAddress(),
159       children,
160       item->GetInterfaces(),
161       item->GetName(),
162       item->GetRole(),
163       item->GetDescription(),
164       item->GetStates().GetRawData() );
165 }