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