1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MNSInit.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include <MNSInclude.hxx>
35 #include "mozilla_nsinit.h"
37 #include <MNSInit.hxx>
39 #include <sal/types.h>
40 #include <osl/diagnose.h>
41 #include <osl/conditn.hxx>
42 #include <osl/file.hxx>
43 #include <rtl/bootstrap.hxx>
45 #ifndef CONNECTIVITY_MOZAB_MCONFIGACCESS_HXX
46 #include "MConfigAccess.hxx"
48 #include "MNSDeclares.hxx"
49 #include <osl/thread.hxx>
50 #include <MNSTerminateListener.hxx>
52 static nsIServiceManager
* sServiceManager
= nsnull
;
53 static sal_Int32 sInitCounter
= 0;
54 static sal_Bool s_bProfilePresentAfterInitialized
= sal_False
;
56 static NS_DEFINE_CID(kProfileCID
, NS_PROFILE_CID
);
57 static NS_DEFINE_CID(kPrefCID
, NS_PREF_CID
);
59 static NS_DEFINE_CID(kEventQueueServiceCID
, NS_EVENTQUEUESERVICE_CID
);
60 static oslThread m_Mozilla_UI_Thread
;
61 static PRBool aLive
=1;
62 static ::osl::Condition m_aUI_Thread_Condition
;
64 #define HACK_AROUND_THREADING_ISSUES
65 #define HACK_AROUND_NONREENTRANT_INITXPCOM
67 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
68 // XXX hack class to clean up XPCOM when this module is unloaded
69 static PRBool sXPCOMInitializedFlag
= PR_FALSE
;
73 extern "C" void NS_SetupRegistry();
75 const PRUnichar
* determineProfile( PRUnichar
const* const* _pValidProfiles
, const PRUint32 _nValidProfiles
)
77 // the fallback for the to-be-used user profile: the first profile
78 const PRUnichar
* pUsedProfile
= *_pValidProfiles
;
80 // have a look what the configuration suggests as preferred profile
81 // PRUnichar != sal_Unicode in mingw
82 const PRUnichar
* pPreferredProfile
= reinterpret_cast_mingw_only
< const PRUnichar
* >( getUserProfile( ) );
83 if ( pPreferredProfile
&& *pPreferredProfile
)
85 PRUnichar
const* const* pLoop
= _pValidProfiles
;
86 PRUnichar
const* const* pLoopEnd
= pLoop
+ _nValidProfiles
;
87 for ( ; pLoop
!= pLoopEnd
; ++pLoop
)
89 // compare the current and the preferred profile
90 // (by looping through the characters)
91 const PRUnichar
* pCurrent
= *pLoop
;
92 const PRUnichar
* pPref
= pPreferredProfile
;
93 while ( *pCurrent
&& ( *pCurrent
== *pPref
) ) // testing one of them against 0 is enough because of the second clause
98 if ( *pCurrent
== *pPref
)
103 if ( pLoop
!= pLoopEnd
)
104 pUsedProfile
= *pLoop
;
112 sal_Bool
MNS_InitXPCOM(sal_Bool
* aProfileExists
)
115 OSL_TRACE( "IN : MNS_InitXPCOM() \n" );
116 // Reentrant calls to this method do nothing except increment a counter
118 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
119 // The first time, add another increment so that it'll be left until exit
120 // for the final cleanup to happen
122 #endif // HACK_AROUND_NONREENTRANT_INITXPCOM
125 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
126 // Can't call NS_InitXPCom more than once or things go boom!
127 if (!sXPCOMInitializedFlag
)
130 nsCOMPtr
<nsILocalFile
> binDir
;
131 // Note: if path3 construction fails, mozilla will default to using MOZILLA_FIVE_HOME in the NS_InitXPCOM2()
134 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program")
136 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/program")
139 rtl::Bootstrap::expandMacros(path1
);
141 if ((osl::FileBase::getSystemPathFromFileURL(path1
, path1
) ==
142 osl::FileBase::E_None
) &&
143 path1
.convertToString(
144 &path2
, osl_getThreadTextEncoding(),
145 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
146 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
148 nsDependentCString
sPath(path2
.getStr());
149 rv
= NS_NewNativeLocalFile(sPath
, PR_TRUE
, getter_AddRefs(binDir
));
157 NS_InitXPCOM2(&sServiceManager
, binDir
, NULL
);
159 // if (!sServiceManager)
162 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
163 sXPCOMInitializedFlag
= PR_TRUE
;
168 // Create the Event Queue for the UI thread...
170 // If an event queue already exists for the thread, then
171 // CreateThreadEventQueue(...) will fail...
172 // CreateThread0ueue(...) will fail...
173 nsCOMPtr
<nsIEventQueueService
> eventQService(
174 do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID
, &rv
));
176 return NS_SUCCEEDED( rv
) ? sal_True
: sal_False
;
178 eventQService
->CreateThreadEventQueue();
180 // nsCOMPtr<nsIObserver> mStartupNotifier = do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv);
183 // mStartupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
185 #ifdef HACK_AROUND_THREADING_ISSUES
186 // XXX force certain objects to be created on the main thread
187 nsCOMPtr
<nsIStringBundleService
> sBundleService
;
188 sBundleService
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
);
189 if (NS_SUCCEEDED(rv
))
191 nsCOMPtr
<nsIStringBundle
> stringBundle
;
192 const char* propertyURL
= "chrome://necko/locale/necko.properties";
193 rv
= sBundleService
->CreateBundle(propertyURL
,
194 getter_AddRefs(stringBundle
));
198 // Need to create a Pref Service
199 nsCOMPtr
< nsIPref
> thePref
= do_GetService( kPrefCID
, &rv
);
200 if (NS_SUCCEEDED(rv
) )
202 OSL_TRACE("Created an nsIPref i/f\n");
203 thePref
->ReadUserPrefs( nsnull
);
204 *aProfileExists
= sal_True
;
205 s_bProfilePresentAfterInitialized
= sal_True
;
207 OSL_TRACE( "OUT : MNS_InitXPCOM() - XPCOM Init\n" );
212 void MNS_XPCOM_EventLoop()
214 OSL_TRACE( "IN : MNS_XPCOM_EventLoop() \n" );
216 nsCOMPtr
<nsIEventQueue
> eventQ
;
217 nsCOMPtr
<nsIEventQueueService
> eventQService
;
218 rv
=nsServiceManager::GetService(kEventQueueServiceCID
,
219 NS_GET_IID(nsIEventQueueService
),
220 getter_AddRefs(eventQService
));
222 if (NS_SUCCEEDED(rv
))
224 rv
= eventQService
->GetThreadEventQueue(NS_CURRENT_THREAD
, getter_AddRefs(eventQ
));
227 rv
= eventQService
->CreateThreadEventQueue();
231 rv
= eventQService
->GetThreadEventQueue(NS_CURRENT_THREAD
, getter_AddRefs(eventQ
));
235 if (NS_FAILED(rv
)) return ;
237 PLEvent
* event
= nsnull
;
238 m_aUI_Thread_Condition
.set(); //we are ready to recive event
241 rv
= eventQ
->GetEvent(&event
);
245 eventQ
->HandleEvent(event
);
246 }while ( PR_SUCCESS
== PR_Sleep( PR_MillisecondsToInterval(1)) && aLive
);
248 eventQ
->ProcessPendingEvents();
249 OSL_TRACE( "OUT : MNS_XPCOM_EventLoop() \n" );
252 extern "C" void MNS_Mozilla_UI_Thread( void *arg
)
255 OSL_TRACE( "IN : MNS_Mozilla_UI_Thread() \n" );
256 UI_Thread_ARGS
* args
= (UI_Thread_ARGS
*) arg
;
257 sal_Bool
* aProfileExists
=args
->bProfileExists
;
262 if (!MNS_InitXPCOM(aProfileExists
))
264 m_aUI_Thread_Condition
.set(); // error happened
268 //do the mozilla event loop
269 MNS_XPCOM_EventLoop();
274 NS_RELEASE(sServiceManager
);
276 // Terminate XPCOM & cleanup
277 #ifndef HACK_AROUND_NONREENTRANT_INITXPCOM
278 NS_ShutdownXPCOM(sServiceManager
);
282 m_aUI_Thread_Condition
.set(); //release all blocks
284 OSL_TRACE( "OUT : MNS_Mozilla_UI_Thread() \n" );
289 sal_Bool
MNS_Init(sal_Bool
& aProfileExists
)
291 aProfileExists
= sal_False
;
293 OSL_TRACE( "IN : MNS_Init() \n" );
294 // Reentrant calls to this method do nothing except increment a counter
296 if (sInitCounter
> 1) {
297 OSL_TRACE( "IN : MNS_Init() wait for xpcom to be initted \n" );
298 //wait for xpcom to be initted
299 m_aUI_Thread_Condition
.wait();
301 OSL_TRACE( "OUT : MNS_Init() : counter = %d\n", sInitCounter
);
302 aProfileExists
= s_bProfilePresentAfterInitialized
;
306 UI_Thread_ARGS
* args
= new UI_Thread_ARGS
;
307 args
->bProfileExists
= &aProfileExists
;
309 m_aUI_Thread_Condition
.reset();
310 m_Mozilla_UI_Thread
=osl_createThread(MNS_Mozilla_UI_Thread
,
312 if (!m_Mozilla_UI_Thread
)
317 //wait for xpcom to be initted
318 m_aUI_Thread_Condition
.wait();
320 //Add Terminate Listener to XDesktop to get application exit event
321 MNSTerminateListener::addTerminateListener();
323 OSL_TRACE( "OUT : MNS_Init() - First Init\n" );
328 sal_Bool
MNS_Term(sal_Bool aForce
)
330 // Reentrant calls to this method do nothing except decrement a counter
331 OSL_TRACE( "IN : MNS_Term() \n" );
332 if (!aForce
&& sInitCounter
> 1)
335 OSL_TRACE( "OUT : MNS_Term() : counter = %d\n", sInitCounter
);
342 //wait for xpcom to be finished
343 TimeValue timeValue
= { 1, 0 };
344 m_aUI_Thread_Condition
.wait(&timeValue
);
347 OSL_TRACE( "OUT : MNS_Term() - Final Term\n" );