~heikki-mantysaari/firefox-extensions/mozvoikko.upstream

« back to all changes in this revision

Viewing changes to src/mozVoikkoUtils.cpp

  • Committer: Heikki Mäntysaari
  • Date: 2008-12-16 16:26:09 UTC
  • Revision ID: heikki.mantysaari@linux.fi-20081216162609-c9nh3mpe99eud6n3
*import upstream source (v. 0.9.5)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 *
 
4
 * Copyright (C) 2007 Andris Pavenis <andris.pavenis@iki.fi>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 *
 
20
 * ***** END OF LICENSE BLOCK ***** */
 
21
 
 
22
#include "mozVoikkoUtils.hxx"
 
23
#include "mozVoikkoSpell.hxx"
 
24
#include <nsComponentManagerUtils.h>
 
25
#include <nsCOMPtr.h>
 
26
#include <nsICategoryManager.h>
 
27
#include <nsIConsoleService.h>
 
28
#include <nsIFile.h>
 
29
#include <nsILocalFile.h>
 
30
#include <nsIXULRuntime.h>
 
31
#include <nsServiceManagerUtils.h>
 
32
#include <nsStringAPI.h>
 
33
#include <prerror.h>
 
34
 
 
35
#if defined(__linux__)
 
36
 
 
37
const char *preloadLibNames[] =
 
38
{
 
39
    "libmalaga.so.7",
 
40
    "libvoikko.so.1"
 
41
};
 
42
 
 
43
const unsigned numPreloadedLibs = sizeof(preloadLibNames)/sizeof(*preloadLibNames);
 
44
 
 
45
const char * libvoikkoName = "libvoikko.so.1";
 
46
 
 
47
#elif defined(_WIN32)
 
48
 
 
49
 
 
50
const char *preloadLibNames[] =
 
51
{
 
52
    "iconv.dll",
 
53
    "intl.dll",
 
54
    "libglib-2.0-0.dll",
 
55
    "malaga.dll",
 
56
    "libvoikko-1.dll"
 
57
};
 
58
 
 
59
const unsigned numPreloadedLibs = sizeof(preloadLibNames)/sizeof(*preloadLibNames);
 
60
 
 
61
const char * libvoikkoName = "libvoikko-1.dll";
 
62
 
 
63
#else
 
64
 
 
65
#error Target OS not supported
 
66
 
 
67
#endif
 
68
 
 
69
#define CH(statement, errRetVal) do \
 
70
    { \
 
71
        nsresult rv = statement; \
 
72
        if (NS_FAILED(rv)) \
 
73
        { \
 
74
            logMessage("%s failed in %s at line %d: error code %X", \
 
75
                 #statement, __FILE__, __LINE__, (PRUint32)rv); \
 
76
            return errRetVal; \
 
77
        } \
 
78
    } while(false)
 
79
 
 
80
 
 
81
void logMessage(const char *fmt, ...)
 
82
{
 
83
    va_list args;
 
84
    va_start(args, fmt);
 
85
    char *msg = PR_vsmprintf(fmt, args);
 
86
    va_end(args);
 
87
 
 
88
    nsCOMPtr<nsIConsoleService> aConsoleService =
 
89
        do_GetService("@mozilla.org/consoleservice;1");
 
90
 
 
91
    if (aConsoleService)
 
92
    {
 
93
        nsCString tmp(msg);
 
94
        aConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(tmp).get());
 
95
    }
 
96
    else 
 
97
    {
 
98
        fputs(msg, stdout);
 
99
    }
 
100
    
 
101
    PR_Free(msg);
 
102
}
 
103
 
 
104
nsCString prGetErrorText(void)
 
105
{
 
106
    nsCString msg;
 
107
    PRInt32 len = PR_GetErrorTextLength();
 
108
    if (len > 0)
 
109
    {
 
110
        char *buffer = (char*)PR_Malloc(len);
 
111
        if (buffer)
 
112
        {
 
113
            PR_GetErrorText(buffer);
 
114
            msg = buffer;
 
115
            PR_Free(buffer);
 
116
        }
 
117
    }
 
118
 
 
119
    return msg;
 
120
}
 
121
 
 
122
nsresult checkLeafNameAndGetParent(nsIFile *file, nsIFile **parent,
 
123
    const nsACString &expectedLeafName)
 
124
{
 
125
    nsresult rv;
 
126
    nsCString leafName;
 
127
 
 
128
    rv = file->GetNativeLeafName(leafName);
 
129
    NS_ENSURE_SUCCESS(rv, rv);
 
130
 
 
131
    if (leafName.Equals(expectedLeafName))
 
132
    {
 
133
        rv = file->GetParent(parent);
 
134
        NS_ENSURE_SUCCESS(rv, rv);
 
135
        return NS_OK;
 
136
    }
 
137
    else
 
138
        return NS_OK;
 
139
}
 
140
 
 
141
nsresult checkLeafNameAndGetParent(nsIFile *file, nsIFile **parent,
 
142
    const nsACString& expectedLeafName1, const nsACString &expectedLeafName2)
 
143
{
 
144
    nsresult rv;
 
145
    nsCString leafName;
 
146
 
 
147
    rv = file->GetNativeLeafName(leafName);
 
148
    NS_ENSURE_SUCCESS(rv, rv);
 
149
 
 
150
    if (leafName.Equals(expectedLeafName1) || leafName.Equals(expectedLeafName2))
 
151
    {
 
152
        rv = file->GetParent(parent);
 
153
        NS_ENSURE_SUCCESS(rv, rv);
 
154
        return NS_OK;
 
155
    }
 
156
    else
 
157
        return NS_OK;
 
158
}
 
159
 
 
160
nsresult findFileInSubdirectory(nsIFile *dir, nsIFile **result,
 
161
    const nsACString &subDirName, const nsACString &fileName)
 
162
{
 
163
    PRBool found;
 
164
    nsresult rv;
 
165
    nsCOMPtr<nsIFile> tmp;
 
166
 
 
167
    *result = nsnull;
 
168
 
 
169
    rv = dir->Clone(getter_AddRefs(tmp));
 
170
    NS_ENSURE_SUCCESS(rv, rv);
 
171
 
 
172
    rv = tmp->AppendNative(subDirName);
 
173
    NS_ENSURE_SUCCESS(rv, rv);
 
174
 
 
175
    rv = tmp->Exists(&found);
 
176
    NS_ENSURE_SUCCESS(rv, rv);
 
177
    if (!found)
 
178
        return NS_OK;
 
179
 
 
180
    rv = tmp->IsDirectory(&found);
 
181
    NS_ENSURE_SUCCESS(rv, rv);
 
182
    if (!found)
 
183
        return NS_OK;
 
184
 
 
185
    rv = tmp->AppendNative(fileName);
 
186
    NS_ENSURE_SUCCESS(rv, rv);
 
187
 
 
188
    rv = tmp->Exists(&found);
 
189
    NS_ENSURE_SUCCESS(rv, rv);
 
190
 
 
191
    rv = tmp->Clone(result);
 
192
    return rv;
 
193
}
 
194
 
 
195
nsresult getMozVoikkoLibrary(nsIFile **file)
 
196
{
 
197
    nsresult rv;
 
198
    char *mozVoikkoLibPathC;
 
199
  
 
200
    *file = nsnull;
 
201
 
 
202
    nsCOMPtr<nsICategoryManager> catMgr =
 
203
        do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
 
204
 
 
205
    if (!catMgr)
 
206
    {
 
207
        logMessage("Failed to get nsICategoryManager");
 
208
        return NS_ERROR_FAILURE;
 
209
    }
 
210
 
 
211
    rv = catMgr->GetCategoryEntry("spell-check-engine", MOZ_VOIKKOSPELL_CONTRACTID,
 
212
        &mozVoikkoLibPathC);
 
213
    if (NS_FAILED(rv)) 
 
214
    {
 
215
        logMessage("Failed to get category entry for mozVoikko");
 
216
        return rv;
 
217
    }
 
218
 
 
219
    nsCString path(mozVoikkoLibPathC);
 
220
 
 
221
    nsCOMPtr<nsILocalFile> mozVoikkoLib;
 
222
    mozVoikkoLib = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
 
223
    if (!mozVoikkoLib)
 
224
    {
 
225
        logMessage("Failed to create instance of nsILoclFile");
 
226
        return NS_ERROR_FAILURE;
 
227
    }
 
228
 
 
229
    rv = mozVoikkoLib->InitWithPath(NS_ConvertUTF8toUTF16(path));
 
230
    if (NS_FAILED(rv))
 
231
    {
 
232
        logMessage("Failed to set path for nsILocalFile");
 
233
        return rv;
 
234
    }
 
235
 
 
236
    rv = mozVoikkoLib->Clone(file);
 
237
    if (NS_FAILED(rv))
 
238
    { 
 
239
        logMessage("%s: Failed to clone nsIFile", __FUNCTION__);
 
240
        return rv;
 
241
    }
 
242
    
 
243
    return NS_OK;
 
244
}
 
245
 
 
246
nsresult getMozVoikkoBaseDirs(nsIFile **libDir, nsIFile **dataDir)
 
247
{
 
248
    nsresult rv;
 
249
    nsCOMPtr<nsIFile> mozVoikkoLibName;
 
250
    nsCOMPtr<nsIFile> currDir, parentDir;
 
251
    nsCOMPtr<nsIFile> tmpDir, tmpFile;
 
252
    nsCString leafName, tmp;
 
253
    nsCString shortTargetName;
 
254
    nsCString fullTargetName;
 
255
 
 
256
    // Get platform name (eg. WINNT_x86-msvc or Linux_x86_64-gcc3).
 
257
    // WARNING: not frozen interface nsIXULRuntime is being used.
 
258
    // String shortTargetName will contain only target OS name (like WINNT)
 
259
    // String fullTargetName will contain additionally XPCOMAPI_NAME
 
260
 
 
261
    nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/app-info;1", &rv);
 
262
 
 
263
    NS_ENSURE_SUCCESS(rv, rv);
 
264
 
 
265
    rv = runtime->GetOS(shortTargetName);
 
266
    NS_ENSURE_SUCCESS(rv, rv);
 
267
 
 
268
    fullTargetName = shortTargetName;
 
269
 
 
270
    rv = runtime->GetXPCOMABI(tmp);
 
271
    if (NS_SUCCEEDED(rv))
 
272
    {
 
273
        fullTargetName.Append("_");
 
274
        fullTargetName.Append(tmp);
 
275
    }
 
276
 
 
277
    // Get path of mozvoikko shared library.
 
278
    // mozVoikkoSpell::registerExtension() has saved it using nsICategory manager
 
279
    // when registrating the extension
 
280
    rv = getMozVoikkoLibrary(getter_AddRefs(mozVoikkoLibName));
 
281
    NS_ENSURE_SUCCESS(rv, rv);
 
282
 
 
283
    // Extract directory part
 
284
    rv = mozVoikkoLibName->GetParent(getter_AddRefs(currDir));
 
285
    NS_ENSURE_SUCCESS(rv, rv);
 
286
 
 
287
    rv = checkLeafNameAndGetParent(currDir, getter_AddRefs(parentDir),
 
288
        NS_LITERAL_CSTRING("components"));
 
289
    NS_ENSURE_SUCCESS(rv, rv);
 
290
    if (!parentDir)
 
291
        return NS_ERROR_FAILURE;
 
292
 
 
293
    currDir = parentDir;
 
294
 
 
295
    rv = findFileInSubdirectory(currDir, getter_AddRefs(tmpFile),
 
296
        NS_LITERAL_CSTRING("voikko"), NS_LITERAL_CSTRING("voikko-fi_FI.pro"));
 
297
    NS_ENSURE_SUCCESS(rv, rv);
 
298
    
 
299
    if (!tmpFile)
 
300
    {
 
301
        rv = checkLeafNameAndGetParent(currDir, getter_AddRefs(parentDir),
 
302
            shortTargetName, fullTargetName);
 
303
        NS_ENSURE_SUCCESS(rv, rv);
 
304
        if (parentDir)
 
305
        {
 
306
            currDir = parentDir;
 
307
 
 
308
            rv = checkLeafNameAndGetParent(currDir, getter_AddRefs(parentDir),
 
309
                NS_LITERAL_CSTRING("platform"));
 
310
            NS_ENSURE_SUCCESS(rv, rv);
 
311
 
 
312
            if (parentDir)
 
313
            {
 
314
                rv = findFileInSubdirectory(parentDir, getter_AddRefs(tmpFile),
 
315
                    NS_LITERAL_CSTRING("voikko"),
 
316
                    NS_LITERAL_CSTRING("voikko-fi_FI.pro"));
 
317
                NS_ENSURE_SUCCESS(rv, rv);
 
318
            }
 
319
        }
 
320
    }
 
321
 
 
322
    if (!tmpFile)
 
323
    {
 
324
        return NS_ERROR_FAILURE;
 
325
    }
 
326
 
 
327
    rv = tmpFile->GetParent(dataDir);
 
328
    NS_ENSURE_SUCCESS(rv, rv);
 
329
 
 
330
    rv = (*dataDir)->Clone(getter_AddRefs(tmpDir));
 
331
    NS_ENSURE_SUCCESS(rv, rv);
 
332
 
 
333
    rv = findFileInSubdirectory(tmpDir, getter_AddRefs(tmpFile), fullTargetName,
 
334
        nsCString(libvoikkoName));
 
335
    NS_ENSURE_SUCCESS(rv, rv);
 
336
 
 
337
    if (tmpFile)
 
338
    {
 
339
        rv = tmpFile->GetParent(libDir);
 
340
        return rv;
 
341
    }
 
342
 
 
343
    rv = findFileInSubdirectory(tmpDir, getter_AddRefs(tmpFile), shortTargetName,
 
344
        nsCString(libvoikkoName));
 
345
    NS_ENSURE_SUCCESS(rv, rv);
 
346
 
 
347
    if (tmpFile)
 
348
    {
 
349
        rv = tmpFile->GetParent(libDir);
 
350
        return rv;
 
351
    }
 
352
 
 
353
    return NS_ERROR_FAILURE;
 
354
}
 
355
 
 
356
nsresult loadExtraLibraries(int numLibs, const char **names)
 
357
{
 
358
    nsresult rv;
 
359
    nsCOMPtr<nsIFile> base, baseDir;
 
360
    nsCString tmp;
 
361
 
 
362
    rv = getMozVoikkoLibrary(getter_AddRefs(base));
 
363
    if (NS_FAILED(rv))
 
364
        return rv; 
 
365
 
 
366
    base->GetParent(getter_AddRefs(baseDir));
 
367
 
 
368
    base->GetNativePath(tmp);
 
369
    logMessage("mozVoikko.so path is %s", tmp.get());
 
370
 
 
371
    baseDir->GetNativePath(tmp);
 
372
    logMessage("mozVoikko.so directory is %s", tmp.get());
 
373
 
 
374
    return NS_OK;
 
375
}
 
376
 
 
377
PreloadedLibraries::PreloadedLibraries(nsIFile *libDir, const char **names, unsigned numLibs) :
 
378
    ok(false), numLibs(numLibs), libraries(NULL)
 
379
{
 
380
    nsresult rv;
 
381
 
 
382
    libraries = new PRLibrary *[numLibs];
 
383
    if (!libraries)
 
384
        return;
 
385
 
 
386
    memset(libraries, 0, sizeof(PRLibrary*)*numLibs);
 
387
 
 
388
    for (unsigned i = 0; i < numLibs; i++)
 
389
    {
 
390
        PRBool exists;
 
391
        nsCOMPtr<nsIFile> libFile;
 
392
        nsCString libPath;
 
393
 
 
394
        rv = libDir->Clone(getter_AddRefs(libFile));
 
395
        if (NS_FAILED(rv))
 
396
            return;
 
397
 
 
398
        rv = libFile->AppendNative(nsCString(names[i]));
 
399
        if (NS_FAILED(rv))
 
400
            return;
 
401
 
 
402
        rv = libFile->GetNativePath(libPath);
 
403
        if (NS_FAILED(rv))
 
404
            return;
 
405
 
 
406
        rv = libFile->Exists(&exists);
 
407
        if (NS_FAILED(rv))
 
408
            return;
 
409
 
 
410
        if (exists)
 
411
        {
 
412
            libraries[i] = PR_LoadLibrary(libPath.get());
 
413
            if (!libraries[i])
 
414
            {
 
415
                logMessage("mozVoikko: failed to load library %s: %s",
 
416
                           libPath.get(), prGetErrorText().get());
 
417
                return;
 
418
            }
 
419
        }
 
420
        else
 
421
        {
 
422
            libraries[i] = nsnull;
 
423
        }
 
424
 
 
425
        logMessage("Loaded %s", libPath.get()); 
 
426
    }
 
427
 
 
428
    ok = true;
 
429
}
 
430
 
 
431
PreloadedLibraries::~PreloadedLibraries()
 
432
{
 
433
    if (libraries)
 
434
    {
 
435
        for (unsigned i = numLibs; i > 0; i--)
 
436
        {
 
437
            if (libraries[i-1])
 
438
                PR_UnloadLibrary(libraries[i-1]);
 
439
        }
 
440
 
 
441
        delete [] libraries;
 
442
    }
 
443
}