summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/mozab/bootstrap/MNSInit.cxx
blob: 09d665bde55f6e747e6df8ffd9eb12aab5779bb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "mozillasrc/MNSInclude.hxx"

#include "mozilla_nsinit.h"

#include "MNSInit.hxx"

#include <sal/types.h>
#include <osl/diagnose.h>
#include <osl/conditn.hxx>
#include <osl/file.hxx>
#include <rtl/bootstrap.hxx>

#include "MConfigAccess.hxx"
#include "mozillasrc/MNSDeclares.hxx"
#include <osl/thread.hxx>
#include "mozillasrc/MNSTerminateListener.hxx"

static nsIServiceManager*   sServiceManager = nsnull;
static sal_Int32            sInitCounter = 0;
static sal_Bool             s_bProfilePresentAfterInitialized = sal_False;

static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);

static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static oslThread m_Mozilla_UI_Thread;
static PRBool aLive=1;
static ::osl::Condition    m_aUI_Thread_Condition;

#define HACK_AROUND_THREADING_ISSUES
#define HACK_AROUND_NONREENTRANT_INITXPCOM

#ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
// XXX hack class to clean up XPCOM when this module is unloaded
static PRBool sXPCOMInitializedFlag = PR_FALSE;
#endif


extern "C" void NS_SetupRegistry();

 const PRUnichar* determineProfile( PRUnichar const* const* _pValidProfiles, const PRUint32 _nValidProfiles )
{
    // the fallback for the to-be-used user profile: the first profile
    const PRUnichar* pUsedProfile = *_pValidProfiles;

    // have a look what the configuration suggests as preferred profile
    // PRUnichar != sal_Unicode in mingw
    const PRUnichar* pPreferredProfile = reinterpret_cast_mingw_only< const PRUnichar* >( getUserProfile( ) );
    if ( pPreferredProfile && *pPreferredProfile )
    {
        PRUnichar const* const* pLoop = _pValidProfiles;
        PRUnichar const* const* pLoopEnd = pLoop + _nValidProfiles;
        for ( ; pLoop != pLoopEnd; ++pLoop )
        {
            // compare the current and the preferred profile
            // (by looping through the characters)
            const PRUnichar* pCurrent   = *pLoop;
            const PRUnichar* pPref      = pPreferredProfile;
            while ( *pCurrent && ( *pCurrent == *pPref ) )  // testing one of them against 0 is enough because of the second clause
            {
                ++pCurrent;
                ++pPref;
            }
            if ( *pCurrent == *pPref )
                // the are equal
                break;
        }

        if ( pLoop != pLoopEnd )
            pUsedProfile = *pLoop;
        return pUsedProfile;
    }
    else
        return NULL;
}


sal_Bool MNS_InitXPCOM(sal_Bool* aProfileExists)
{
    nsresult rv;
    OSL_TRACE( "IN : MNS_InitXPCOM()" );
    // Reentrant calls to this method do nothing except increment a counter

#ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
    // The first time, add another increment so that it'll be left until exit
    // for the final cleanup to happen
    sInitCounter++;
#endif // HACK_AROUND_NONREENTRANT_INITXPCOM

    // Initialise XPCOM
#ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
    // Can't call NS_InitXPCom more than once or things go boom!
    if (!sXPCOMInitializedFlag)
#endif
    {
        nsCOMPtr<nsILocalFile> binDir;
        // Note: if path3 construction fails, mozilla will default to using MOZILLA_FIVE_HOME in the NS_InitXPCOM2()
        rtl::OUString path1("$BRAND_BASE_DIR/program");
        rtl::Bootstrap::expandMacros(path1);
        rtl::OString path2;
        if ((osl::FileBase::getSystemPathFromFileURL(path1, path1) ==
             osl::FileBase::E_None) &&
            path1.convertToString(
                &path2, osl_getThreadTextEncoding(),
                (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
                 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
        {
            nsDependentCString sPath(path2.getStr());
            rv = NS_NewNativeLocalFile(sPath, PR_TRUE, getter_AddRefs(binDir));
            if (NS_FAILED(rv))
                return sal_False;
        }



    // Initialise XPCOM
    NS_InitXPCOM2(&sServiceManager, binDir, NULL);

//      if (!sServiceManager)
//          return sal_False;

#ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
        sXPCOMInitializedFlag = PR_TRUE;
#endif
    }


    // Create the Event Queue for the UI thread...
    //
    // If an event queue already exists for the thread, then
    // CreateThreadEventQueue(...) will fail...
    // CreateThread0ueue(...) will fail...
    nsCOMPtr<nsIEventQueueService> eventQService(
                do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv));
    if (NS_FAILED(rv))
      return NS_SUCCEEDED( rv ) ? sal_True : sal_False;

    eventQService->CreateThreadEventQueue();

//  nsCOMPtr<nsIObserver> mStartupNotifier = do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv);
//  if(NS_FAILED(rv))
//      return rv;
//  mStartupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);

#ifdef HACK_AROUND_THREADING_ISSUES
    // XXX force certain objects to be created on the main thread
    nsCOMPtr<nsIStringBundleService> sBundleService;
    sBundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv))
    {
        nsCOMPtr<nsIStringBundle> stringBundle;
        const char* propertyURL = "chrome://necko/locale/necko.properties";
        rv = sBundleService->CreateBundle(propertyURL,
                                          getter_AddRefs(stringBundle));
    }
#endif

    // Need to create a Pref Service
    nsCOMPtr< nsIPref > thePref = do_GetService( kPrefCID, &rv );
    if (NS_SUCCEEDED(rv) )
    {
        OSL_TRACE("Created an nsIPref i/f");
        thePref->ReadUserPrefs( nsnull );
        *aProfileExists = sal_True ;
        s_bProfilePresentAfterInitialized = sal_True;
    }
    OSL_TRACE( "OUT : MNS_InitXPCOM() - XPCOM Init" );

    return sal_True;
}

void MNS_XPCOM_EventLoop()
{
    OSL_TRACE( "IN : MNS_XPCOM_EventLoop()" );
    nsresult rv;
    nsCOMPtr<nsIEventQueue> eventQ;
    nsCOMPtr<nsIEventQueueService>  eventQService;
    rv=nsServiceManager::GetService(kEventQueueServiceCID,
                                 NS_GET_IID(nsIEventQueueService),
                                 getter_AddRefs(eventQService));

    if (NS_SUCCEEDED(rv))
    {
      rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD , getter_AddRefs(eventQ));
      if (NS_FAILED(rv))
      {
          rv = eventQService->CreateThreadEventQueue();
          if (NS_FAILED(rv))
            return ;
          else
            rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
      }
    }

    if (NS_FAILED(rv)) return ;

    PLEvent* event = nsnull;
    m_aUI_Thread_Condition.set(); //we are ready to recive event
    do
    {
        rv = eventQ->GetEvent(&event);
        if (NS_FAILED(rv))
            return ;
        if (event)
            eventQ->HandleEvent(event);
    }while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(20)) && aLive );

    eventQ->ProcessPendingEvents();
    OSL_TRACE( "OUT : MNS_XPCOM_EventLoop()" );
}

extern "C" void MNS_Mozilla_UI_Thread( void *arg )
{
    aLive=1;
    OSL_TRACE( "IN : MNS_Mozilla_UI_Thread()" );
    UI_Thread_ARGS * args = (UI_Thread_ARGS*) arg;
    sal_Bool* aProfileExists=args->bProfileExists;
    delete args;
    args=NULL;

    //Init xpcom
    if (!MNS_InitXPCOM(aProfileExists))
    {
        m_aUI_Thread_Condition.set(); // error happened
        return;
    }

    //do the mozilla event loop
    MNS_XPCOM_EventLoop();
    //we are interupted

    if (sServiceManager)
    {
        NS_RELEASE(sServiceManager);

    // Terminate XPCOM & cleanup
#ifndef HACK_AROUND_NONREENTRANT_INITXPCOM
        NS_ShutdownXPCOM(sServiceManager);
#endif
    }

    m_aUI_Thread_Condition.set();   //release all blocks

    OSL_TRACE( "OUT : MNS_Mozilla_UI_Thread()" );

}


sal_Bool MNS_Init(sal_Bool& aProfileExists)
{
    aProfileExists = sal_False ;

    OSL_TRACE( "IN : MNS_Init()" );
    // Reentrant calls to this method do nothing except increment a counter
    sInitCounter++;
    if (sInitCounter > 1) {
        OSL_TRACE( "IN : MNS_Init() wait for xpcom to be initted" );
        //wait for xpcom to be initted
        m_aUI_Thread_Condition.wait();

        OSL_TRACE( "OUT : MNS_Init() : counter = %d", sInitCounter );
        aProfileExists = s_bProfilePresentAfterInitialized;
        return sal_True;
    }

    UI_Thread_ARGS * args = new UI_Thread_ARGS;
    args->bProfileExists = &aProfileExists;

    m_aUI_Thread_Condition.reset();
    m_Mozilla_UI_Thread=osl_createThread(MNS_Mozilla_UI_Thread,
                                    (void*)args);
    if (!m_Mozilla_UI_Thread)
    {
        return sal_False;
    }

    //wait for xpcom to be initted
    m_aUI_Thread_Condition.wait();

    //Add Terminate Listener to XDesktop to get application exit event
    MNSTerminateListener::addTerminateListener();

    OSL_TRACE( "OUT : MNS_Init() - First Init" );

    return sal_True;
}

sal_Bool MNS_Term(sal_Bool aForce)
{
    // Reentrant calls to this method do nothing except decrement a counter
    OSL_TRACE( "IN : MNS_Term()" );
    if (!aForce && sInitCounter > 1)
    {
        --sInitCounter;
        OSL_TRACE( "OUT : MNS_Term() : counter = %d", sInitCounter );
        return sal_True;
    }
    sInitCounter = 0;

    aLive=0;

    //wait for xpcom to be finished
    TimeValue               timeValue = { 1, 0 };
    m_aUI_Thread_Condition.wait(&timeValue);


    OSL_TRACE( "OUT : MNS_Term() - Final Term" );
    return sal_True;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */