VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp@ 31232

最後變更 在這個檔案從31232是 608,由 vboxsync 提交於 18 年 前

worked around weird mac crash starting tstAPI.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 16.1 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corp.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Sean Su <[email protected]>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39#include "nsBuildID.h"
40
41#include "nsEmbedString.h"
42#include "nsXPCOMPrivate.h"
43#include "nsXPCOMGlue.h"
44#include "nsILocalFile.h"
45#include "nsIDirectoryService.h"
46#include "nsDirectoryServiceDefs.h"
47#include "nsCOMPtr.h"
48
49#include "nspr.h"
50#include "plstr.h"
51
52#ifdef XP_WIN32
53#include <windows.h>
54#include <stdlib.h>
55#elif defined(XP_OS2)
56#define INCL_DOS
57#include <os2.h>
58#include <stdlib.h>
59#include <stdio.h>
60#include "prenv.h"
61#elif defined(XP_MACOSX)
62#include <Processes.h>
63#include <CFBundle.h>
64#elif defined(XP_UNIX)
65#include <unistd.h>
66#include <stdlib.h>
67#include <sys/param.h>
68#include <dlfcn.h>
69#include "prenv.h"
70#elif defined(XP_BEOS)
71#include <FindDirectory.h>
72#include <Path.h>
73#include <unistd.h>
74#include <stdlib.h>
75#include <sys/param.h>
76#include <OS.h>
77#include <image.h>
78#include "prenv.h"
79#endif
80
81#include <sys/stat.h>
82
83#include "nsGREDirServiceProvider.h"
84
85PRBool GRE_GetCurrentProcessDirectory(char* buffer);
86PRBool GRE_GetPathFromConfigDir(const char* dirname, char* buffer);
87PRBool GRE_GetPathFromConfigFile(const char* dirname, char* buffer);
88
89//*****************************************************************************
90// nsGREDirServiceProvider::nsISupports
91//*****************************************************************************
92
93NS_IMPL_ISUPPORTS1(nsGREDirServiceProvider, nsIDirectoryServiceProvider)
94
95//*****************************************************************************
96// nsGREDirServiceProvider::nsIDirectoryServiceProvider
97//*****************************************************************************
98
99NS_IMETHODIMP
100nsGREDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
101{
102 *_retval = nsnull;
103 *persistant = PR_TRUE;
104
105 //---------------------------------------------------------------
106 // Note that by returning a valid localFile's for NS_GRE_DIR,
107 // your app is indicating to XPCOM that it found a GRE version
108 // with which it's compatible with and intends to be "run against"
109 // that GRE.
110 //
111 // Please see http://www.mozilla.org/projects/embedding/GRE.html
112 // for more info on GRE.
113 //---------------------------------------------------------------
114 if(strcmp(prop, NS_GRE_DIR) == 0)
115 {
116 nsILocalFile* lfile = nsnull;
117 nsresult rv = GRE_GetGREDirectory(&lfile);
118 *_retval = lfile;
119 return rv;
120 }
121
122 return NS_ERROR_FAILURE;
123}
124
125//*****************************************************************************
126// Implementations from nsXPCOMGlue.h and helper functions.
127//*****************************************************************************
128
129PRBool
130GRE_GetCurrentProcessDirectory(char* buffer)
131{
132 *buffer = '\0';
133
134#ifdef XP_WIN
135 if ( ::GetModuleFileName(0, buffer, MAXPATHLEN) ) {
136 // chop of the executable name by finding the rightmost backslash
137 char* lastSlash = PL_strrchr(buffer, '\\');
138 if (lastSlash) {
139 *(lastSlash) = '\0';
140 return PR_TRUE;
141 }
142 }
143
144#elif defined(XP_MACOSX)
145 // Works even if we're not bundled.
146 CFBundleRef appBundle = CFBundleGetMainBundle();
147 if (appBundle != nsnull)
148 {
149 CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
150 if (bundleURL != nsnull)
151 {
152 CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
153 if (parentURL)
154 {
155 CFStringRef path = CFURLCopyFileSystemPath(parentURL, kCFURLPOSIXPathStyle);
156 if (path)
157 {
158 CFStringGetCString(path, buffer, MAXPATHLEN, kCFStringEncodingUTF8);
159 CFRelease(path);
160 }
161 CFRelease(parentURL);
162 }
163 CFRelease(bundleURL);
164 }
165#if 0 /* bird: Causes crashes in objc_msgSend() later if released. I dunno why really.
166 Something could be seriously screwed up somewhere else, but this'll have
167 to do for now. (appBundle isn't released in the other place it's used.) */
168 CFRelease(appBundle);
169#endif
170 }
171 if (*buffer) return PR_TRUE;
172
173#elif defined(XP_UNIX)
174
175#if 0 /* we need .so location. */
176 // Actually we have a way on linux.
177 static volatile bool fPathSet = false;
178 static char szPath[MAXPATHLEN];
179 if (!fPathSet)
180 {
181 char buf2[MAXPATHLEN + 3];
182 buf2[0] = '\0';
183
184 /*
185 * Env.var. VBOX_XPCOM_HOME first.
186 */
187 char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
188 if (psz)
189 {
190 if (strlen(psz) < MAXPATHLEN)
191 {
192 if (!realpath(psz, buf2))
193 strcpy(buf2, psz);
194 strcat(buf2, "/x"); /* for the filename stripping */
195 }
196 }
197
198 /*
199 * The dynamic loader.
200 */
201 if (!buf2[0])
202 {
203 Dl_info DlInfo = {0};
204 if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo)
205 && DlInfo.dli_fname)
206 {
207 if (!realpath(DlInfo.dli_fname, buf2))
208 buf2[0] = '\0';
209 }
210 }
211
212 /*
213 * Executable location.
214 */
215 if (!buf2[0])
216 {
217 char buf[MAXPATHLEN];
218 int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
219 if (cchLink > 0 || cchLink != sizeof(buf) - 1)
220 {
221 buf[cchLink] = '\0';
222 if (!realpath(buf, buf2))
223 buf2[0] = '\0';
224 }
225 }
226
227 /*
228 * Copy to static buffer on success.
229 */
230 if (buf2[0])
231 {
232 char *p = strrchr(buf2, '/');
233 if (p)
234 {
235 p[p == buf2] = '\0';
236 #ifdef DEBUG
237 printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
238 #endif
239 strcpy(szPath, buf2);
240 fPathSet = true;
241 }
242 }
243 }
244 if (fPathSet)
245 {
246 strcpy(buffer, szPath);
247 return PR_TRUE;
248 }
249#endif
250
251 // In the absence of a good way to get the executable directory let
252 // us try this for unix:
253 // - if VBOX_XPCOM_HOME is defined, that is it
254 // - else give the current directory
255
256 // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
257 // a --with-default-mozilla-five-home=foo autoconf flag.
258 //
259 // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
260 // regardless of the environment. This makes it easier to write apps that
261 // embed mozilla without having to worry about setting up the environment
262 //
263 // We do this py putenv()ing the default value into the environment. Note that
264 // we only do this if it is not already set.
265#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
266 if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
267 {
268 putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
269 }
270#endif
271
272 char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
273
274 if (moz5 && *moz5)
275 {
276 if (!realpath(moz5, buffer))
277 strcpy(buffer, moz5);
278
279 return PR_TRUE;
280 }
281 else
282 {
283#if defined(DEBUG)
284 static PRBool firstWarning = PR_TRUE;
285
286 if(firstWarning) {
287 // Warn that VBOX_XPCOM_HOME not set, once.
288 printf("Warning: VBOX_XPCOM_HOME not set.\n");
289 firstWarning = PR_FALSE;
290 }
291#endif /* DEBUG */
292
293 // Fall back to current directory.
294 if (getcwd(buffer, MAXPATHLEN))
295 {
296 return PR_TRUE;
297 }
298 }
299
300#elif defined(XP_OS2)
301 PPIB ppib;
302 PTIB ptib;
303 char* p;
304 DosGetInfoBlocks( &ptib, &ppib);
305 DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer);
306 p = strrchr( buffer, '\\'); // XXX DBCS misery
307 if (p) {
308 *p = '\0';
309 return PR_TRUE;
310 }
311
312#elif defined(XP_BEOS)
313
314 char *moz5 = getenv("VBOX_XPCOM_HOME");
315 if (moz5)
316 {
317 strcpy(buffer, moz5);
318 return PR_TRUE;
319 }
320 else
321 {
322 int32 cookie = 0;
323 image_info info;
324 char *p;
325 *buffer = 0;
326 if(get_next_image_info(0, &cookie, &info) == B_OK)
327 {
328 strcpy(buffer, info.name);
329 if((p = strrchr(buffer, '/')) != 0)
330 {
331 *p = 0;
332
333 return PR_TRUE;
334 }
335 }
336 }
337
338#endif
339
340 return PR_FALSE;
341}
342
343/**
344 * the GRE location is stored in a static buffer so that we don't have
345 * to compute it multiple times.
346 */
347
348static char sGRELocation[MAXPATHLEN] = "";
349
350extern "C" char const *
351GRE_GetGREPath()
352{
353 // we've already done this...
354 if (*sGRELocation)
355 return sGRELocation;
356
357 char buffer[MAXPATHLEN];
358
359 // If the xpcom library exists in the current process directory,
360 // then we will not use any GRE. The assumption here is that the
361 // GRE is in the same directory as the executable.
362 if (GRE_GetCurrentProcessDirectory(buffer)) {
363 PRUint32 pathlen = strlen(buffer);
364 strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL);
365
366 struct stat libStat;
367 int statResult = stat(buffer, &libStat);
368
369 if (statResult != -1) {
370 //found our xpcom lib in the current process directory
371 buffer[pathlen] = '\0';
372 strcpy(sGRELocation, buffer);
373 return sGRELocation;
374 }
375 }
376
377 // if GRE_HOME is in the environment, use that GRE
378 const char* env = PR_GetEnv("GRE_HOME");
379 if (env && *env) {
380#if XP_UNIX
381 if (!realpath(env, sGRELocation))
382 strcpy(sGRELocation, env);
383#elif XP_WIN32
384 if (!_fullpath(sGRELocation, env, MAXPATHLEN))
385 strcpy(sGRELocation, env);
386#endif
387 // xxxbsmedberg: it would help that other platforms had a "make absolute" function
388 return sGRELocation;
389 }
390
391 // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
392 env = PR_GetEnv("USE_LOCAL_GRE");
393 if (env && *env)
394 return nsnull;
395
396#if XP_UNIX
397 // check in the HOME directory
398 env = PR_GetEnv("HOME");
399 if (env && *env) {
400 sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
401
402 if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) {
403 return sGRELocation;
404 }
405 }
406#endif
407
408 env = PR_GetEnv("MOZ_GRE_CONF");
409 if (env) {
410 if (GRE_GetPathFromConfigFile(env, sGRELocation)) {
411 return sGRELocation;
412 }
413 }
414
415#if XP_UNIX
416 // Look for a group of config files in /etc/gre.d/
417 if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) {
418 return sGRELocation;
419 }
420
421 // Look for a global /etc/gre.conf file
422 if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) {
423 return sGRELocation;
424 }
425#endif
426
427#if XP_WIN32
428 char szKey[256];
429 HKEY hRegKey = NULL;
430 DWORD dwLength = MAXPATHLEN;
431
432 // A couple of key points here:
433 // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
434 // us to have multiple versions of GREs on the same machine by having
435 // subkeys such as 1.0, 1.1, 2.0 etc. under it.
436 // 2. In this sample below we're looking for the location of GRE version 1.2
437 // i.e. we're compatible with GRE 1.2 and we're trying to find it's install
438 // location.
439 //
440 // Please see http://www.mozilla.org/projects/embedding/GRE.html for
441 // more info.
442 //
443 strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID);
444
445 if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
446 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
447 *sGRELocation = '\0';
448 }
449 ::RegCloseKey(hRegKey);
450
451 if (*sGRELocation)
452 return sGRELocation;
453 }
454
455 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
456 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
457 *sGRELocation = '\0';
458 }
459 ::RegCloseKey(hRegKey);
460
461 if (*sGRELocation)
462 return sGRELocation;
463 }
464#endif
465
466 return nsnull;
467}
468
469PRBool
470GRE_GetPathFromConfigDir(const char* dirname, char* buffer)
471{
472 // Open the directory provided and try to read any files in that
473 // directory that end with .conf. We look for an entry that might
474 // point to the GRE that we're interested in.
475 PRDir *dir = PR_OpenDir(dirname);
476 if (!dir)
477 return nsnull;
478
479 PRBool found = PR_FALSE;
480 PRDirEntry *entry;
481
482 while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
483
484 // Only look for files that end in .conf
485 char *offset = PL_strrstr(entry->name, ".conf");
486 if (!offset)
487 continue;
488
489 if (offset != entry->name + strlen(entry->name) - 5)
490 continue;
491
492 nsEmbedCString fullPath;
493 NS_CStringAppendData(fullPath, dirname);
494 NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR);
495 NS_CStringAppendData(fullPath, entry->name);
496
497 found = GRE_GetPathFromConfigFile(fullPath.get(), buffer);
498 }
499
500 PR_CloseDir(dir);
501
502 return found;
503}
504
505PRBool
506GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer)
507{
508 *pathBuffer = '\0';
509 char buffer[1024];
510 FILE *cfg;
511 PRBool foundHeader = PR_FALSE;
512 PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1;
513
514 if((cfg=fopen(filename,"r"))==nsnull) {
515 return nsnull;
516 }
517
518 while (fgets(buffer, 1024, cfg) != nsnull) {
519 // skip over comment lines and blank lines
520 if (buffer[0] == '#' || buffer[0] == '\n') {
521 continue;
522 }
523
524 // we found a section heading, check to see if it is the one we are intersted in.
525 if (buffer[0] == '[') {
526 if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) {
527 foundHeader = PR_TRUE;
528 }
529 continue;
530 }
531
532 if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) {
533 strcpy(pathBuffer, buffer + 9);
534 // kill the line feed if any
535 PRInt32 len = strlen(pathBuffer);
536 len--;
537
538 if (pathBuffer[len] == '\n')
539 pathBuffer[len] = '\0';
540 break;
541 }
542 }
543 fclose(cfg);
544 return (*pathBuffer != '\0');
545}
546
547extern "C" nsresult
548GRE_GetGREDirectory(nsILocalFile* *_retval)
549{
550 NS_ENSURE_ARG_POINTER(_retval);
551 nsresult rv = NS_ERROR_FAILURE;
552
553 // Get the path of the GRE which is compatible with our embedding application
554 // from the registry
555
556 const char *pGREDir = GRE_GetGREPath();
557 if(pGREDir) {
558 nsCOMPtr<nsILocalFile> tempLocal;
559 nsEmbedCString leaf;
560 NS_CStringSetData(leaf, pGREDir);
561 rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal));
562
563 if (NS_SUCCEEDED(rv)) {
564 *_retval = tempLocal;
565 NS_ADDREF(*_retval);
566 }
567 }
568 return rv;
569}
570
571static char sXPCOMPath[MAXPATHLEN];
572
573extern "C" const char*
574GRE_GetXPCOMPath()
575{
576 const char* grePath = GRE_GetGREPath();
577
578 if (!grePath) {
579 grePath = PR_GetEnv("VBOX_XPCOM_HOME");
580 if (!grePath || !*grePath) {
581 return nsnull;
582 }
583 }
584
585 sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
586
587 return sXPCOMPath;
588}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette