1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include "svtaccessiblefactory.hxx"
27 #include <osl/module.h>
28 
29 // #define UNLOAD_ON_LAST_CLIENT_DYING
30     // this is not recommended currently. If enabled, the implementation will log
31     // the number of active clients, and unload the acc library when the last client
32     // goes away.
33     // Sounds like a good idea, unfortunately, there's no guarantee that all objects
34     // implemented in this library are already dead.
35     // Iow, just because an object implementing an XAccessible (implemented in this lib
36     // here) died, it's not said that everybody released all references to the
37     // XAccessibleContext used by this component, and implemented in the acc lib.
38     // So we cannot really unload the lib.
39     //
40     // Alternatively, if the lib would us own "usage counting", i.e. every component
41     // implemented therein would affect a static ref count, the acc lib could care
42     // for unloading itself.
43 
44 //........................................................................
45 namespace svt
46 {
47 //........................................................................
48 
49     using namespace ::com::sun::star::uno;
50     using namespace ::com::sun::star::awt;
51     using namespace ::com::sun::star::accessibility;
52 
53     namespace
54     {
55 #ifdef UNLOAD_ON_LAST_CLIENT_DYING
56         static oslInterlockedCount                      s_nAccessibleFactoryAccesss = 0;
57 #endif // UNLOAD_ON_LAST_CLIENT_DYING
58         static oslModule                                s_hAccessibleImplementationModule = NULL;
59         static GetSvtAccessibilityComponentFactory      s_pAccessibleFactoryFunc = NULL;
60         static ::rtl::Reference< IAccessibleFactory >   s_pFactory;
61 
62         //====================================================================
63         //= AccessibleDummyFactory
64         //====================================================================
65         class AccessibleDummyFactory : public IAccessibleFactory
66         {
67         public:
68             AccessibleDummyFactory();
69 
70         protected:
71             virtual ~AccessibleDummyFactory();
72 
73         private:
74             AccessibleDummyFactory( const AccessibleDummyFactory& );            // never implemented
75             AccessibleDummyFactory& operator=( const AccessibleDummyFactory& ); // never implemented
76 
77             oslInterlockedCount m_refCount;
78 
79         public:
80             // IReference
81 	        virtual oslInterlockedCount SAL_CALL acquire();
82 	        virtual oslInterlockedCount SAL_CALL release();
83 
84             // IAccessibleFactory
85             virtual IAccessibleTabListBox*
86                 createAccessibleTabListBox(
87 		            const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*rxParent*/,
88 		            SvHeaderTabListBox& /*rBox*/
89                 ) const
90             {
91                 return NULL;
92             }
93 
94             virtual IAccessibleBrowseBox*
95                 createAccessibleBrowseBox(
96                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_rxParent*/,
97                     IAccessibleTableProvider& /*_rBrowseBox*/
98 		        ) const
99             {
100                 return NULL;
101             }
102 
103 			virtual table::IAccessibleTableControl*
104                 createAccessibleTableControl(
105                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_rxParent*/,
106                     table::IAccessibleTable& /*_rTable*/
107 		        ) const
108             {
109                 return NULL;
110             }
111 
112             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
113 		        createAccessibleIconChoiceCtrl(
114                     SvtIconChoiceCtrl& /*_rIconCtrl*/,
115                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_xParent*/
116                 ) const
117             {
118                 return NULL;
119             }
120 
121             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
122 		        createAccessibleTabBar(
123                     TabBar& /*_rTabBar*/
124                 ) const
125             {
126                 return NULL;
127             }
128 
129             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
130 		        createAccessibleTextWindowContext(
131                     VCLXWindow* /*pVclXWindow*/, TextEngine& /*rEngine*/, TextView& /*rView*/, bool /*bCompoundControlChild*/
132                 ) const
133             {
134                 return NULL;
135             }
136 
137             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
138                 createAccessibleTreeListBox(
139                     SvTreeListBox& /*_rListBox*/,
140 				    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_xParent*/
141                 ) const
142             {
143                 return NULL;
144             }
145 
146             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
147                 createAccessibleBrowseBoxHeaderBar(
148                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*rxParent*/,
149                     IAccessibleTableProvider& /*_rOwningTable*/,
150                     AccessibleBrowseBoxObjType /*_eObjType*/
151                 ) const
152             {
153                 return NULL;
154             }
155 
156             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
157                 createAccessibleBrowseBoxTableCell(
158                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_rxParent*/,
159 				    IAccessibleTableProvider& /*_rBrowseBox*/,
160 				    const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& /*_xFocusWindow*/,
161 				    sal_Int32 /*_nRowId*/,
162 				    sal_uInt16 /*_nColId*/,
163                     sal_Int32 /*_nOffset*/
164                 ) const
165             {
166                 return NULL;
167             }
168 
169             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
170                 createAccessibleBrowseBoxHeaderCell(
171                     sal_Int32 /*_nColumnRowId*/,
172 				    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*rxParent*/,
173 				    IAccessibleTableProvider& /*_rBrowseBox*/,
174 				    const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& /*_xFocusWindow*/,
175 				    AccessibleBrowseBoxObjType  /*_eObjType*/
176                 ) const
177             {
178                 return NULL;
179             }
180 
181             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
182                 createAccessibleCheckBoxCell(
183                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*_rxParent*/,
184 				    IAccessibleTableProvider& /*_rBrowseBox*/,
185 				    const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& /*_xFocusWindow*/,
186 				    sal_Int32 /*_nRowPos*/,
187 				    sal_uInt16 /*_nColPos*/,
188 				    const TriState& /*_eState*/,
189 				    sal_Bool /*_bEnabled*/,
190 				    sal_Bool /*_bIsTriState*/
191                 ) const
192             {
193                 return NULL;
194             }
195 
196             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
197                 createEditBrowseBoxTableCellAccess(
198 			        const ::com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessible >& /*_rxParent*/,
199 			        const ::com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessible >& /*_rxControlAccessible*/,
200 			        const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& /*_rxFocusWindow*/,
201                     IAccessibleTableProvider& /*_rBrowseBox*/,
202 			        sal_Int32 /*_nRowPos*/,
203 			        sal_uInt16 /*_nColPos*/
204 		        ) const
205             {
206                 return NULL;
207             }
208 
209             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
210                 createAccessibleToolPanelDeck(
211                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*i_rAccessibleParent*/,
212                     ::svt::ToolPanelDeck& /*i_rPanelDeck*/
213                 )
214             {
215                 return NULL;
216             }
217             virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
218                 createAccessibleToolPanelTabBar(
219                     const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*i_rAccessibleParent*/,
220                     ::svt::IToolPanelDeck& /*i_rPanelDeck*/,
221                     ::svt::PanelTabBar& /*i_rTabBar*/
222                 )
223             {
224                 return NULL;
225             }
226         };
227 
228         //----------------------------------------------------------------
229         AccessibleDummyFactory::AccessibleDummyFactory()
230         {
231         }
232 
233         //----------------------------------------------------------------
234         AccessibleDummyFactory::~AccessibleDummyFactory()
235         {
236         }
237 
238         //----------------------------------------------------------------
239 	    oslInterlockedCount SAL_CALL AccessibleDummyFactory::acquire()
240         {
241             return osl_incrementInterlockedCount( &m_refCount );
242         }
243 
244 	    //----------------------------------------------------------------
245 	    oslInterlockedCount SAL_CALL AccessibleDummyFactory::release()
246         {
247             if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
248             {
249                 delete this;
250                 return 0;
251             }
252             return m_refCount;
253         }
254     }
255 
256     //====================================================================
257     //= AccessibleFactoryAccess
258     //====================================================================
259     //--------------------------------------------------------------------
260     AccessibleFactoryAccess::AccessibleFactoryAccess()
261         :m_bInitialized( false )
262     {
263     }
264 
265     //--------------------------------------------------------------------
266     extern "C" { static void SAL_CALL thisModule() {} }
267 
268     void AccessibleFactoryAccess::ensureInitialized()
269     {
270         if ( m_bInitialized )
271             return;
272 
273         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
274 
275 #ifdef UNLOAD_ON_LAST_CLIENT_DYING
276         if ( 1 == osl_incrementInterlockedCount( &s_nAccessibleFactoryAccesss ) )
277         {   // the first client
278 #endif // UNLOAD_ON_LAST_CLIENT_DYING
279             // load the library implementing the factory
280             if ( !s_pFactory.get() )
281             {
282                 const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii(
283                     SVLIBRARY( "acc" )
284                 );
285                 s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 );
286                 if ( s_hAccessibleImplementationModule != NULL )
287                 {
288                     const ::rtl::OUString sFactoryCreationFunc =
289                         ::rtl::OUString::createFromAscii( "getSvtAccessibilityComponentFactory" );
290                     s_pAccessibleFactoryFunc = (GetSvtAccessibilityComponentFactory)
291                         osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData );
292 
293                 }
294                 OSL_ENSURE( s_pAccessibleFactoryFunc, "ac_registerClient: could not load the library, or not retrieve the needed symbol!" );
295 
296                 // get a factory instance
297                 if ( s_pAccessibleFactoryFunc )
298                 {
299                     IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() );
300                     if ( pFactory )
301                     {
302                         s_pFactory = pFactory;
303                         pFactory->release();
304                     }
305                 }
306             }
307 
308             if ( !s_pFactory.get() )
309                 // the attempt to load the lib, or to create the factory, failed
310                 // -> fall back to a dummy factory
311                 s_pFactory = new AccessibleDummyFactory;
312 #ifdef UNLOAD_ON_LAST_CLIENT_DYING
313         }
314 #endif
315 
316         m_bInitialized = true;
317     }
318 
319     //--------------------------------------------------------------------
320     AccessibleFactoryAccess::~AccessibleFactoryAccess()
321     {
322         if ( m_bInitialized )
323         {
324             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
325 
326 #ifdef UNLOAD_ON_LAST_CLIENT_DYING
327             if( 0 == osl_decrementInterlockedCount( &s_nAccessibleFactoryAccesss ) )
328             {
329                 s_pFactory = NULL;
330                 s_pAccessibleFactoryFunc = NULL;
331                 if ( s_hAccessibleImplementationModule )
332                 {
333                     osl_unloadModule( s_hAccessibleImplementationModule );
334                     s_hAccessibleImplementationModule = NULL;
335                 }
336             }
337 #endif // UNLOAD_ON_LAST_CLIENT_DYING
338         }
339     }
340 
341     //--------------------------------------------------------------------
342     IAccessibleFactory& AccessibleFactoryAccess::getFactory()
343     {
344         ensureInitialized();
345         DBG_ASSERT( s_pFactory.is(), "AccessibleFactoryAccess::getFactory: at least a dummy factory should have been created!" );
346         return *s_pFactory;
347     }
348 
349 //........................................................................
350 }   // namespace svt
351 //........................................................................
352