VirtualBox

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

最後變更 在這個檔案從1是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.9 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 CFRelease(appBundle);
166 }
167 if (*buffer) return PR_TRUE;
168
169#elif defined(XP_UNIX)
170
171#if 0 /* we need .so location. */
172 // Actually we have a way on linux.
173 static volatile bool fPathSet = false;
174 static char szPath[MAXPATHLEN];
175 if (!fPathSet)
176 {
177 char buf2[MAXPATHLEN + 3];
178 buf2[0] = '\0';
179
180 /*
181 * Env.var. VBOX_XPCOM_HOME first.
182 */
183 char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
184 if (psz)
185 {
186 if (strlen(psz) < MAXPATHLEN)
187 {
188 if (!realpath(psz, buf2))
189 strcpy(buf2, psz);
190 strcat(buf2, "/x"); /* for the filename stripping */
191 }
192 }
193
194 /*
195 * The dynamic loader.
196 */
197 if (!buf2[0])
198 {
199 Dl_info DlInfo = {0};
200 if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo)
201 && DlInfo.dli_fname)
202 {
203 if (!realpath(DlInfo.dli_fname, buf2))
204 buf2[0] = '\0';
205 }
206 }
207
208 /*
209 * Executable location.
210 */
211 if (!buf2[0])
212 {
213 char buf[MAXPATHLEN];
214 int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
215 if (cchLink > 0 || cchLink != sizeof(buf) - 1)
216 {
217 buf[cchLink] = '\0';
218 if (!realpath(buf, buf2))
219 buf2[0] = '\0';
220 }
221 }
222
223 /*
224 * Copy to static buffer on success.
225 */
226 if (buf2[0])
227 {
228 char *p = strrchr(buf2, '/');
229 if (p)
230 {
231 p[p == buf2] = '\0';
232 #ifdef DEBUG
233 printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
234 #endif
235 strcpy(szPath, buf2);
236 fPathSet = true;
237 }
238 }
239 }
240 if (fPathSet)
241 {
242 strcpy(buffer, szPath);
243 return PR_TRUE;
244 }
245#endif
246
247 // In the absence of a good way to get the executable directory let
248 // us try this for unix:
249 // - if VBOX_XPCOM_HOME is defined, that is it
250 // - else give the current directory
251
252 // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
253 // a --with-default-mozilla-five-home=foo autoconf flag.
254 //
255 // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
256 // regardless of the environment. This makes it easier to write apps that
257 // embed mozilla without having to worry about setting up the environment
258 //
259 // We do this py putenv()ing the default value into the environment. Note that
260 // we only do this if it is not already set.
261#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
262 if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
263 {
264 putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
265 }
266#endif
267
268 char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
269
270 if (moz5 && *moz5)
271 {
272 if (!realpath(moz5, buffer))
273 strcpy(buffer, moz5);
274
275 return PR_TRUE;
276 }
277 else
278 {
279#if defined(DEBUG)
280 static PRBool firstWarning = PR_TRUE;
281
282 if(firstWarning) {
283 // Warn that VBOX_XPCOM_HOME not set, once.
284 printf("Warning: VBOX_XPCOM_HOME not set.\n");
285 firstWarning = PR_FALSE;
286 }
287#endif /* DEBUG */
288
289 // Fall back to current directory.
290 if (getcwd(buffer, MAXPATHLEN))
291 {
292 return PR_TRUE;
293 }
294 }
295
296#elif defined(XP_OS2)
297 PPIB ppib;
298 PTIB ptib;
299 char* p;
300 DosGetInfoBlocks( &ptib, &ppib);
301 DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer);
302 p = strrchr( buffer, '\\'); // XXX DBCS misery
303 if (p) {
304 *p = '\0';
305 return PR_TRUE;
306 }
307
308#elif defined(XP_BEOS)
309
310 char *moz5 = getenv("VBOX_XPCOM_HOME");
311 if (moz5)
312 {
313 strcpy(buffer, moz5);
314 return PR_TRUE;
315 }
316 else
317 {
318 int32 cookie = 0;
319 image_info info;
320 char *p;
321 *buffer = 0;
322 if(get_next_image_info(0, &cookie, &info) == B_OK)
323 {
324 strcpy(buffer, info.name);
325 if((p = strrchr(buffer, '/')) != 0)
326 {
327 *p = 0;
328
329 return PR_TRUE;
330 }
331 }
332 }
333
334#endif
335
336 return PR_FALSE;
337}
338
339/**
340 * the GRE location is stored in a static buffer so that we don't have
341 * to compute it multiple times.
342 */
343
344static char sGRELocation[MAXPATHLEN] = "";
345
346extern "C" char const *
347GRE_GetGREPath()
348{
349 // we've already done this...
350 if (*sGRELocation)
351 return sGRELocation;
352
353 char buffer[MAXPATHLEN];
354
355 // If the xpcom library exists in the current process directory,
356 // then we will not use any GRE. The assumption here is that the
357 // GRE is in the same directory as the executable.
358 if (GRE_GetCurrentProcessDirectory(buffer)) {
359 PRUint32 pathlen = strlen(buffer);
360 strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL);
361
362 struct stat libStat;
363 int statResult = stat(buffer, &libStat);
364
365 if (statResult != -1) {
366 //found our xpcom lib in the current process directory
367 buffer[pathlen] = '\0';
368 strcpy(sGRELocation, buffer);
369 return sGRELocation;
370 }
371 }
372
373 // if GRE_HOME is in the environment, use that GRE
374 const char* env = PR_GetEnv("GRE_HOME");
375 if (env && *env) {
376#if XP_UNIX
377 if (!realpath(env, sGRELocation))
378 strcpy(sGRELocation, env);
379#elif XP_WIN32
380 if (!_fullpath(sGRELocation, env, MAXPATHLEN))
381 strcpy(sGRELocation, env);
382#endif
383 // xxxbsmedberg: it would help that other platforms had a "make absolute" function
384 return sGRELocation;
385 }
386
387 // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
388 env = PR_GetEnv("USE_LOCAL_GRE");
389 if (env && *env)
390 return nsnull;
391
392#if XP_UNIX
393 // check in the HOME directory
394 env = PR_GetEnv("HOME");
395 if (env && *env) {
396 sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
397
398 if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) {
399 return sGRELocation;
400 }
401 }
402#endif
403
404 env = PR_GetEnv("MOZ_GRE_CONF");
405 if (env) {
406 if (GRE_GetPathFromConfigFile(env, sGRELocation)) {
407 return sGRELocation;
408 }
409 }
410
411#if XP_UNIX
412 // Look for a group of config files in /etc/gre.d/
413 if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) {
414 return sGRELocation;
415 }
416
417 // Look for a global /etc/gre.conf file
418 if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) {
419 return sGRELocation;
420 }
421#endif
422
423#if XP_WIN32
424 char szKey[256];
425 HKEY hRegKey = NULL;
426 DWORD dwLength = MAXPATHLEN;
427
428 // A couple of key points here:
429 // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
430 // us to have multiple versions of GREs on the same machine by having
431 // subkeys such as 1.0, 1.1, 2.0 etc. under it.
432 // 2. In this sample below we're looking for the location of GRE version 1.2
433 // i.e. we're compatible with GRE 1.2 and we're trying to find it's install
434 // location.
435 //
436 // Please see http://www.mozilla.org/projects/embedding/GRE.html for
437 // more info.
438 //
439 strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID);
440
441 if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
442 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
443 *sGRELocation = '\0';
444 }
445 ::RegCloseKey(hRegKey);
446
447 if (*sGRELocation)
448 return sGRELocation;
449 }
450
451 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
452 if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
453 *sGRELocation = '\0';
454 }
455 ::RegCloseKey(hRegKey);
456
457 if (*sGRELocation)
458 return sGRELocation;
459 }
460#endif
461
462 return nsnull;
463}
464
465PRBool
466GRE_GetPathFromConfigDir(const char* dirname, char* buffer)
467{
468 // Open the directory provided and try to read any files in that
469 // directory that end with .conf. We look for an entry that might
470 // point to the GRE that we're interested in.
471 PRDir *dir = PR_OpenDir(dirname);
472 if (!dir)
473 return nsnull;
474
475 PRBool found = PR_FALSE;
476 PRDirEntry *entry;
477
478 while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
479
480 // Only look for files that end in .conf
481 char *offset = PL_strrstr(entry->name, ".conf");
482 if (!offset)
483 continue;
484
485 if (offset != entry->name + strlen(entry->name) - 5)
486 continue;
487
488 nsEmbedCString fullPath;
489 NS_CStringAppendData(fullPath, dirname);
490 NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR);
491 NS_CStringAppendData(fullPath, entry->name);
492
493 found = GRE_GetPathFromConfigFile(fullPath.get(), buffer);
494 }
495
496 PR_CloseDir(dir);
497
498 return found;
499}
500
501PRBool
502GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer)
503{
504 *pathBuffer = '\0';
505 char buffer[1024];
506 FILE *cfg;
507 PRBool foundHeader = PR_FALSE;
508 PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1;
509
510 if((cfg=fopen(filename,"r"))==nsnull) {
511 return nsnull;
512 }
513
514 while (fgets(buffer, 1024, cfg) != nsnull) {
515 // skip over comment lines and blank lines
516 if (buffer[0] == '#' || buffer[0] == '\n') {
517 continue;
518 }
519
520 // we found a section heading, check to see if it is the one we are intersted in.
521 if (buffer[0] == '[') {
522 if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) {
523 foundHeader = PR_TRUE;
524 }
525 continue;
526 }
527
528 if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) {
529 strcpy(pathBuffer, buffer + 9);
530 // kill the line feed if any
531 PRInt32 len = strlen(pathBuffer);
532 len--;
533
534 if (pathBuffer[len] == '\n')
535 pathBuffer[len] = '\0';
536 break;
537 }
538 }
539 fclose(cfg);
540 return (*pathBuffer != '\0');
541}
542
543extern "C" nsresult
544GRE_GetGREDirectory(nsILocalFile* *_retval)
545{
546 NS_ENSURE_ARG_POINTER(_retval);
547 nsresult rv = NS_ERROR_FAILURE;
548
549 // Get the path of the GRE which is compatible with our embedding application
550 // from the registry
551
552 const char *pGREDir = GRE_GetGREPath();
553 if(pGREDir) {
554 nsCOMPtr<nsILocalFile> tempLocal;
555 nsEmbedCString leaf;
556 NS_CStringSetData(leaf, pGREDir);
557 rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal));
558
559 if (NS_SUCCEEDED(rv)) {
560 *_retval = tempLocal;
561 NS_ADDREF(*_retval);
562 }
563 }
564 return rv;
565}
566
567static char sXPCOMPath[MAXPATHLEN];
568
569extern "C" const char*
570GRE_GetXPCOMPath()
571{
572 const char* grePath = GRE_GetGREPath();
573
574 if (!grePath) {
575 grePath = PR_GetEnv("VBOX_XPCOM_HOME");
576 if (!grePath || !*grePath) {
577 return nsnull;
578 }
579 }
580
581 sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
582
583 return sXPCOMPath;
584}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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