1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/DebugOnly.h"
18 #define statvfs statfs
20 #include "sys/statvfs.h"
22 #endif // defined(ANDROID)
23 #endif // defined(XP_UNIX)
26 #include <linux/fadvise.h>
27 #endif // defined(XP_LINUX)
29 #if defined(XP_MACOSX)
31 #endif // defined(XP_MACOSX)
37 #define PATH_MAX MAX_PATH
39 #endif // defined(XP_WIN)
42 #include "jsfriendapi.h"
43 #include "BindingUtils.h"
45 // Used to provide information on the OS
47 #include "nsThreadUtils.h"
48 #include "nsIObserverService.h"
49 #include "nsIObserver.h"
50 #include "nsDirectoryServiceUtils.h"
51 #include "nsIXULRuntime.h"
52 #include "nsIPropertyBag2.h"
53 #include "nsXPCOMCIDInternal.h"
54 #include "nsServiceManagerUtils.h"
56 #include "nsAutoPtr.h"
57 #include "nsDirectoryServiceDefs.h"
58 #include "nsXULAppAPI.h"
59 #include "nsAppDirectoryServiceDefs.h"
60 #include "mozJSComponentLoader.h"
62 #include "OSFileConstants.h"
63 #include "nsIOSFileConstantsService.h"
64 #include "nsZipArchive.h"
66 #if defined(__DragonFly__) || defined(__FreeBSD__) \
67 || defined(__NetBSD__) || defined(__OpenBSD__)
72 * This module defines the basic libc constants (error numbers, open modes,
73 * etc.) used by OS.File and possibly other OS-bound JavaScript libraries.
79 // Use an anonymous namespace to hide the symbols and avoid any collision
80 // with, for instance, |extern bool gInitialized;|
83 * |true| if this module has been initialized, |false| otherwise
85 bool gInitialized
= false;
89 * The name of the directory holding all the libraries (libxpcom, libnss, etc.)
94 nsString localProfileDir
;
96 * The user's home directory
100 * The user's desktop directory, if there is one. Otherwise this is
101 * the same as homeDir.
105 * The user's 'application data' directory.
107 * HOME = Documents and Settings\$USER\Application Data
108 * UAppData = $HOME[\$vendor]\$name
112 * UAppData = $HOME/.[$vendor/]$name
116 * UAppData = $HOME/Library/Application Support/$name
118 nsString userApplicationDataDir
;
122 * The user's application data directory.
124 nsString winAppDataDir
;
126 * The programs subdirectory in the user's start menu directory.
128 nsString winStartMenuProgsDir
;
129 #endif // defined(XP_WIN)
131 #if defined(XP_MACOSX)
133 * The user's Library directory.
135 nsString macUserLibDir
;
137 * The Application directory, that stores applications installed in the
140 nsString macLocalApplicationsDir
;
142 * The user's trash directory.
144 nsString macTrashDir
;
145 #endif // defined(XP_MACOSX)
149 libDir
.SetIsVoid(true);
150 tmpDir
.SetIsVoid(true);
151 profileDir
.SetIsVoid(true);
152 localProfileDir
.SetIsVoid(true);
153 homeDir
.SetIsVoid(true);
154 desktopDir
.SetIsVoid(true);
155 userApplicationDataDir
.SetIsVoid(true);
158 winAppDataDir
.SetIsVoid(true);
159 winStartMenuProgsDir
.SetIsVoid(true);
160 #endif // defined(XP_WIN)
162 #if defined(XP_MACOSX)
163 macUserLibDir
.SetIsVoid(true);
164 macLocalApplicationsDir
.SetIsVoid(true);
165 macTrashDir
.SetIsVoid(true);
166 #endif // defined(XP_MACOSX)
171 * System directories.
173 Paths
* gPaths
= nullptr;
176 * (Unix) the umask, which goes in OS.Constants.Sys but
177 * can only be looked up (via the system-info service)
178 * on the main thread.
180 uint32_t gUserUmask
= 0;
184 * Return the path to one of the special directories.
186 * @param aKey The key to the special directory (e.g. "TmpD", "ProfD", ...)
187 * @param aOutPath The path to the special directory. In case of error,
188 * the string is set to void.
190 nsresult
GetPathToSpecialDir(const char *aKey
, nsString
& aOutPath
)
192 nsCOMPtr
<nsIFile
> file
;
193 nsresult rv
= NS_GetSpecialDirectory(aKey
, getter_AddRefs(file
));
194 if (NS_FAILED(rv
) || !file
) {
198 return file
->GetPath(aOutPath
);
202 * In some cases, OSFileConstants may be instantiated before the
203 * profile is setup. In such cases, |OS.Constants.Path.profileDir| and
204 * |OS.Constants.Path.localProfileDir| are undefined. However, we want
205 * to ensure that this does not break existing code, so that future
206 * workers spawned after the profile is setup have these constants.
208 * For this purpose, we register an observer to set |gPaths->profileDir|
209 * and |gPaths->localProfileDir| once the profile is setup.
211 class DelayedPathSetter MOZ_FINAL
: public nsIObserver
213 ~DelayedPathSetter() {}
218 DelayedPathSetter() {}
221 NS_IMPL_ISUPPORTS(DelayedPathSetter
, nsIObserver
)
224 DelayedPathSetter::Observe(nsISupports
*, const char * aTopic
, const char16_t
*)
226 if (gPaths
== nullptr) {
227 // Initialization of gPaths has not taken place, something is wrong,
228 // don't make things worse.
231 nsresult rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR
, gPaths
->profileDir
);
235 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR
, gPaths
->localProfileDir
);
244 * Perform the part of initialization that can only be
245 * executed on the main thread.
247 nsresult
InitOSFileConstants()
249 MOZ_ASSERT(NS_IsMainThread());
256 nsAutoPtr
<Paths
> paths(new Paths
);
258 // Initialize paths->libDir
259 nsCOMPtr
<nsIFile
> file
;
260 nsresult rv
= NS_GetSpecialDirectory(NS_XPCOM_LIBRARY_FILE
, getter_AddRefs(file
));
265 nsCOMPtr
<nsIFile
> libDir
;
266 rv
= file
->GetParent(getter_AddRefs(libDir
));
271 rv
= libDir
->GetPath(paths
->libDir
);
276 // Setup profileDir and localProfileDir immediately if possible (we
277 // assume that NS_APP_USER_PROFILE_50_DIR and
278 // NS_APP_USER_PROFILE_LOCAL_50_DIR are set simultaneously)
279 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR
, paths
->profileDir
);
280 if (NS_SUCCEEDED(rv
)) {
281 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR
, paths
->localProfileDir
);
284 // Otherwise, delay setup of profileDir/localProfileDir until they
287 nsCOMPtr
<nsIObserverService
> obsService
= do_GetService(NS_OBSERVERSERVICE_CONTRACTID
, &rv
);
291 nsRefPtr
<DelayedPathSetter
> pathSetter
= new DelayedPathSetter();
292 rv
= obsService
->AddObserver(pathSetter
, "profile-do-change", false);
298 // For other directories, ignore errors (they may be undefined on
299 // some platforms or in non-Firefox embeddings of Gecko).
301 GetPathToSpecialDir(NS_OS_TEMP_DIR
, paths
->tmpDir
);
302 GetPathToSpecialDir(NS_OS_HOME_DIR
, paths
->homeDir
);
303 GetPathToSpecialDir(NS_OS_DESKTOP_DIR
, paths
->desktopDir
);
304 GetPathToSpecialDir(XRE_USER_APP_DATA_DIR
, paths
->userApplicationDataDir
);
307 GetPathToSpecialDir(NS_WIN_APPDATA_DIR
, paths
->winAppDataDir
);
308 GetPathToSpecialDir(NS_WIN_PROGRAMS_DIR
, paths
->winStartMenuProgsDir
);
309 #endif // defined(XP_WIN)
311 #if defined(XP_MACOSX)
312 GetPathToSpecialDir(NS_MAC_USER_LIB_DIR
, paths
->macUserLibDir
);
313 GetPathToSpecialDir(NS_OSX_LOCAL_APPLICATIONS_DIR
, paths
->macLocalApplicationsDir
);
314 GetPathToSpecialDir(NS_MAC_TRASH_DIR
, paths
->macTrashDir
);
315 #endif // defined(XP_MACOSX)
317 gPaths
= paths
.forget();
319 // Get the umask from the system-info service.
320 // The property will always be present, but it will be zero on
322 nsCOMPtr
<nsIPropertyBag2
> infoService
=
323 do_GetService("@mozilla.org/system-info;1");
324 MOZ_ASSERT(infoService
, "Could not access the system information service");
325 rv
= infoService
->GetPropertyAsUint32(NS_LITERAL_STRING("umask"),
335 * Perform the cleaning up that can only be executed on the main thread.
337 void CleanupOSFileConstants()
339 MOZ_ASSERT(NS_IsMainThread());
344 gInitialized
= false;
350 * Define a simple read-only property holding an integer.
352 * @param name The name of the constant. Used both as the JS name for the
353 * constant and to access its value. Must be defined.
355 * Produces a |ConstantSpec|.
357 #define INT_CONSTANT(name) \
358 { #name, INT_TO_JSVAL(name) }
361 * Define a simple read-only property holding an unsigned integer.
363 * @param name The name of the constant. Used both as the JS name for the
364 * constant and to access its value. Must be defined.
366 * Produces a |ConstantSpec|.
368 #define UINT_CONSTANT(name) \
369 { #name, UINT_TO_JSVAL((name)) }
372 * End marker for ConstantSpec
374 #define PROP_END { nullptr, JS::UndefinedValue() }
377 // Define missing constants for Android
378 #if !defined(S_IRGRP)
391 #endif // !defined(S_IRGRP)
394 * The properties defined in libc.
396 * If you extend this list of properties, please
397 * separate categories ("errors", "open", etc.),
398 * keep properties organized by alphabetical order
399 * and #ifdef-away properties that are not portable.
401 static const dom::ConstantSpec gLibcProperties
[] =
403 // Arguments for open
404 INT_CONSTANT(O_APPEND
),
405 INT_CONSTANT(O_CREAT
),
406 #if defined(O_DIRECTORY)
407 INT_CONSTANT(O_DIRECTORY
),
408 #endif // defined(O_DIRECTORY)
409 #if defined(O_EVTONLY)
410 INT_CONSTANT(O_EVTONLY
),
411 #endif // defined(O_EVTONLY)
412 INT_CONSTANT(O_EXCL
),
413 #if defined(O_EXLOCK)
414 INT_CONSTANT(O_EXLOCK
),
415 #endif // defined(O_EXLOCK)
416 #if defined(O_LARGEFILE)
417 INT_CONSTANT(O_LARGEFILE
),
418 #endif // defined(O_LARGEFILE)
419 #if defined(O_NOFOLLOW)
420 INT_CONSTANT(O_NOFOLLOW
),
421 #endif // defined(O_NOFOLLOW)
422 #if defined(O_NONBLOCK)
423 INT_CONSTANT(O_NONBLOCK
),
424 #endif // defined(O_NONBLOCK)
425 INT_CONSTANT(O_RDONLY
),
426 INT_CONSTANT(O_RDWR
),
428 INT_CONSTANT(O_RSYNC
),
429 #endif // defined(O_RSYNC)
430 #if defined(O_SHLOCK)
431 INT_CONSTANT(O_SHLOCK
),
432 #endif // defined(O_SHLOCK)
433 #if defined(O_SYMLINK)
434 INT_CONSTANT(O_SYMLINK
),
435 #endif // defined(O_SYMLINK)
437 INT_CONSTANT(O_SYNC
),
438 #endif // defined(O_SYNC)
439 INT_CONSTANT(O_TRUNC
),
440 INT_CONSTANT(O_WRONLY
),
442 #if defined(AT_EACCESS)
443 INT_CONSTANT(AT_EACCESS
),
444 #endif //defined(AT_EACCESS)
445 #if defined(AT_FDCWD)
446 INT_CONSTANT(AT_FDCWD
),
447 #endif //defined(AT_FDCWD)
448 #if defined(AT_SYMLINK_NOFOLLOW)
449 INT_CONSTANT(AT_SYMLINK_NOFOLLOW
),
450 #endif //defined(AT_SYMLINK_NOFOLLOW)
452 #if defined(POSIX_FADV_SEQUENTIAL)
453 INT_CONSTANT(POSIX_FADV_SEQUENTIAL
),
454 #endif //defined(POSIX_FADV_SEQUENTIAL)
462 #endif // defined(F_OK)
465 INT_CONSTANT(S_IRGRP
),
466 INT_CONSTANT(S_IROTH
),
467 INT_CONSTANT(S_IRUSR
),
468 INT_CONSTANT(S_IRWXG
),
469 INT_CONSTANT(S_IRWXO
),
470 INT_CONSTANT(S_IRWXU
),
471 INT_CONSTANT(S_IWGRP
),
472 INT_CONSTANT(S_IWOTH
),
473 INT_CONSTANT(S_IWUSR
),
474 INT_CONSTANT(S_IXOTH
),
475 INT_CONSTANT(S_IXGRP
),
476 INT_CONSTANT(S_IXUSR
),
479 INT_CONSTANT(SEEK_CUR
),
480 INT_CONSTANT(SEEK_END
),
481 INT_CONSTANT(SEEK_SET
),
483 // fcntl command values
485 INT_CONSTANT(F_GETLK
),
486 INT_CONSTANT(F_SETLK
),
487 INT_CONSTANT(F_SETLKW
),
490 INT_CONSTANT(F_RDLCK
),
491 INT_CONSTANT(F_WRLCK
),
492 INT_CONSTANT(F_UNLCK
),
493 #endif // defined(XP_UNIX)
495 #if defined(COPYFILE_DATA)
496 INT_CONSTANT(COPYFILE_DATA
),
497 INT_CONSTANT(COPYFILE_EXCL
),
498 INT_CONSTANT(COPYFILE_XATTR
),
499 INT_CONSTANT(COPYFILE_STAT
),
500 INT_CONSTANT(COPYFILE_ACL
),
501 INT_CONSTANT(COPYFILE_MOVE
),
502 #endif // defined(COPYFILE_DATA)
505 INT_CONSTANT(EACCES
),
506 INT_CONSTANT(EAGAIN
),
508 INT_CONSTANT(EEXIST
),
509 INT_CONSTANT(EFAULT
),
511 INT_CONSTANT(EINVAL
),
513 INT_CONSTANT(EISDIR
),
514 #if defined(ELOOP) // not defined with VC9
516 #endif // defined(ELOOP)
517 INT_CONSTANT(EMFILE
),
518 INT_CONSTANT(ENAMETOOLONG
),
519 INT_CONSTANT(ENFILE
),
520 INT_CONSTANT(ENOENT
),
521 INT_CONSTANT(ENOMEM
),
522 INT_CONSTANT(ENOSPC
),
523 INT_CONSTANT(ENOTDIR
),
525 #if defined(EOPNOTSUPP) // not defined with VC 9
526 INT_CONSTANT(EOPNOTSUPP
),
527 #endif // defined(EOPNOTSUPP)
528 #if defined(EOVERFLOW) // not defined with VC 9
529 INT_CONSTANT(EOVERFLOW
),
530 #endif // defined(EOVERFLOW)
532 INT_CONSTANT(ERANGE
),
533 #if defined(ETIMEDOUT) // not defined with VC 9
534 INT_CONSTANT(ETIMEDOUT
),
535 #endif // defined(ETIMEDOUT)
536 #if defined(EWOULDBLOCK) // not defined with VC 9
537 INT_CONSTANT(EWOULDBLOCK
),
538 #endif // defined(EWOULDBLOCK)
541 #if defined(DT_UNKNOWN)
542 // Constants for |readdir|
543 INT_CONSTANT(DT_UNKNOWN
),
544 INT_CONSTANT(DT_FIFO
),
545 INT_CONSTANT(DT_CHR
),
546 INT_CONSTANT(DT_DIR
),
547 INT_CONSTANT(DT_BLK
),
548 INT_CONSTANT(DT_REG
),
549 INT_CONSTANT(DT_LNK
),
550 INT_CONSTANT(DT_SOCK
),
551 #endif // defined(DT_UNKNOWN)
554 // Constants for |stat|
555 INT_CONSTANT(S_IFMT
),
556 INT_CONSTANT(S_IFIFO
),
557 INT_CONSTANT(S_IFCHR
),
558 INT_CONSTANT(S_IFDIR
),
559 INT_CONSTANT(S_IFBLK
),
560 INT_CONSTANT(S_IFREG
),
561 INT_CONSTANT(S_IFLNK
),
562 INT_CONSTANT(S_IFSOCK
),
563 #endif // defined(S_IFIFO)
565 INT_CONSTANT(PATH_MAX
),
567 // Constants used to define data structures
569 // Many data structures have different fields/sizes/etc. on
570 // various OSes / versions of the same OS / platforms. For these
571 // data structures, we need to compute and export from C the size
572 // and, if necessary, the offset of fields, so as to be able to
573 // define the structure in JS.
576 // The size of |mode_t|.
577 { "OSFILE_SIZEOF_MODE_T", INT_TO_JSVAL(sizeof (mode_t
)) },
579 // The size of |gid_t|.
580 { "OSFILE_SIZEOF_GID_T", INT_TO_JSVAL(sizeof (gid_t
)) },
582 // The size of |uid_t|.
583 { "OSFILE_SIZEOF_UID_T", INT_TO_JSVAL(sizeof (uid_t
)) },
585 // The size of |time_t|.
586 { "OSFILE_SIZEOF_TIME_T", INT_TO_JSVAL(sizeof (time_t)) },
588 // The size of |fsblkcnt_t|.
589 { "OSFILE_SIZEOF_FSBLKCNT_T", INT_TO_JSVAL(sizeof (fsblkcnt_t
)) },
591 #if !defined(ANDROID)
592 // The size of |posix_spawn_file_actions_t|.
593 { "OSFILE_SIZEOF_POSIX_SPAWN_FILE_ACTIONS_T", INT_TO_JSVAL(sizeof (posix_spawn_file_actions_t
)) },
594 #endif // !defined(ANDROID)
596 // Defining |dirent|.
598 { "OSFILE_SIZEOF_DIRENT", INT_TO_JSVAL(sizeof (dirent
)) },
602 { "OSFILE_SIZEOF_FLOCK", INT_TO_JSVAL(sizeof (struct flock
)) },
603 { "OSFILE_OFFSETOF_FLOCK_L_START", INT_TO_JSVAL(offsetof (struct flock
, l_start
)) },
604 { "OSFILE_OFFSETOF_FLOCK_L_LEN", INT_TO_JSVAL(offsetof (struct flock
, l_len
)) },
605 { "OSFILE_OFFSETOF_FLOCK_L_PID", INT_TO_JSVAL(offsetof (struct flock
, l_pid
)) },
606 { "OSFILE_OFFSETOF_FLOCK_L_TYPE", INT_TO_JSVAL(offsetof (struct flock
, l_type
)) },
607 { "OSFILE_OFFSETOF_FLOCK_L_WHENCE", INT_TO_JSVAL(offsetof (struct flock
, l_whence
)) },
608 #endif // defined(XP_UNIX)
609 // Offset of field |d_name|.
610 { "OSFILE_OFFSETOF_DIRENT_D_NAME", INT_TO_JSVAL(offsetof (struct dirent
, d_name
)) },
611 // An upper bound to the length of field |d_name| of struct |dirent|.
612 // (may not be exact, depending on padding).
613 { "OSFILE_SIZEOF_DIRENT_D_NAME", INT_TO_JSVAL(sizeof (struct dirent
) - offsetof (struct dirent
, d_name
)) },
615 // Defining |timeval|.
616 { "OSFILE_SIZEOF_TIMEVAL", INT_TO_JSVAL(sizeof (struct timeval
)) },
617 { "OSFILE_OFFSETOF_TIMEVAL_TV_SEC", INT_TO_JSVAL(offsetof (struct timeval
, tv_sec
)) },
618 { "OSFILE_OFFSETOF_TIMEVAL_TV_USEC", INT_TO_JSVAL(offsetof (struct timeval
, tv_usec
)) },
620 #if defined(DT_UNKNOWN)
621 // Position of field |d_type| in |dirent|
622 // Not strictly posix, but seems defined on all platforms
624 { "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent
, d_type
)) },
625 #endif // defined(DT_UNKNOWN)
627 // Under MacOS X and BSDs, |dirfd| is a macro rather than a
628 // function, so we need a little help to get it to work
630 { "OSFILE_SIZEOF_DIR", INT_TO_JSVAL(sizeof (DIR)) },
632 { "OSFILE_OFFSETOF_DIR_DD_FD", INT_TO_JSVAL(offsetof (DIR, __dd_fd
)) },
637 { "OSFILE_SIZEOF_STAT", INT_TO_JSVAL(sizeof (struct stat
)) },
639 { "OSFILE_OFFSETOF_STAT_ST_MODE", INT_TO_JSVAL(offsetof (struct stat
, st_mode
)) },
640 { "OSFILE_OFFSETOF_STAT_ST_UID", INT_TO_JSVAL(offsetof (struct stat
, st_uid
)) },
641 { "OSFILE_OFFSETOF_STAT_ST_GID", INT_TO_JSVAL(offsetof (struct stat
, st_gid
)) },
642 { "OSFILE_OFFSETOF_STAT_ST_SIZE", INT_TO_JSVAL(offsetof (struct stat
, st_size
)) },
644 #if defined(HAVE_ST_ATIMESPEC)
645 { "OSFILE_OFFSETOF_STAT_ST_ATIME", INT_TO_JSVAL(offsetof (struct stat
, st_atimespec
)) },
646 { "OSFILE_OFFSETOF_STAT_ST_MTIME", INT_TO_JSVAL(offsetof (struct stat
, st_mtimespec
)) },
647 { "OSFILE_OFFSETOF_STAT_ST_CTIME", INT_TO_JSVAL(offsetof (struct stat
, st_ctimespec
)) },
649 { "OSFILE_OFFSETOF_STAT_ST_ATIME", INT_TO_JSVAL(offsetof (struct stat
, st_atime
)) },
650 { "OSFILE_OFFSETOF_STAT_ST_MTIME", INT_TO_JSVAL(offsetof (struct stat
, st_mtime
)) },
651 { "OSFILE_OFFSETOF_STAT_ST_CTIME", INT_TO_JSVAL(offsetof (struct stat
, st_ctime
)) },
652 #endif // defined(HAVE_ST_ATIME)
654 // Several OSes have a birthtime field. For the moment, supporting only Darwin.
655 #if defined(_DARWIN_FEATURE_64_BIT_INODE)
656 { "OSFILE_OFFSETOF_STAT_ST_BIRTHTIME", INT_TO_JSVAL(offsetof (struct stat
, st_birthtime
)) },
657 #endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
659 // Defining |statvfs|
661 { "OSFILE_SIZEOF_STATVFS", INT_TO_JSVAL(sizeof (struct statvfs
)) },
663 { "OSFILE_OFFSETOF_STATVFS_F_BSIZE", INT_TO_JSVAL(offsetof (struct statvfs
, f_bsize
)) },
664 { "OSFILE_OFFSETOF_STATVFS_F_BAVAIL", INT_TO_JSVAL(offsetof (struct statvfs
, f_bavail
)) },
666 #endif // defined(XP_UNIX)
670 // System configuration
672 // Under MacOSX, to avoid using deprecated functions that do not
673 // match the constants we define in this object (including
674 // |sizeof|/|offsetof| stuff, but not only), for a number of
675 // functions, we need to adapt the name of the symbols we are using,
676 // whenever macro _DARWIN_FEATURE_64_BIT_INODE is set. We export
677 // this value to be able to do so from JavaScript.
678 #if defined(_DARWIN_FEATURE_64_BIT_INODE)
679 { "_DARWIN_FEATURE_64_BIT_INODE", INT_TO_JSVAL(1) },
680 #endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
682 // Similar feature for Linux
683 #if defined(_STAT_VER)
684 INT_CONSTANT(_STAT_VER
),
685 #endif // defined(_STAT_VER)
693 * The properties defined in windows.h.
695 * If you extend this list of properties, please
696 * separate categories ("errors", "open", etc.),
697 * keep properties organized by alphabetical order
698 * and #ifdef-away properties that are not portable.
700 static const dom::ConstantSpec gWinProperties
[] =
702 // FormatMessage flags
703 INT_CONSTANT(FORMAT_MESSAGE_FROM_SYSTEM
),
704 INT_CONSTANT(FORMAT_MESSAGE_IGNORE_INSERTS
),
706 // The max length of paths
707 INT_CONSTANT(MAX_PATH
),
709 // CreateFile desired access
710 INT_CONSTANT(GENERIC_ALL
),
711 INT_CONSTANT(GENERIC_EXECUTE
),
712 INT_CONSTANT(GENERIC_READ
),
713 INT_CONSTANT(GENERIC_WRITE
),
715 // CreateFile share mode
716 INT_CONSTANT(FILE_SHARE_DELETE
),
717 INT_CONSTANT(FILE_SHARE_READ
),
718 INT_CONSTANT(FILE_SHARE_WRITE
),
720 // CreateFile creation disposition
721 INT_CONSTANT(CREATE_ALWAYS
),
722 INT_CONSTANT(CREATE_NEW
),
723 INT_CONSTANT(OPEN_ALWAYS
),
724 INT_CONSTANT(OPEN_EXISTING
),
725 INT_CONSTANT(TRUNCATE_EXISTING
),
727 // CreateFile attributes
728 INT_CONSTANT(FILE_ATTRIBUTE_ARCHIVE
),
729 INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY
),
730 INT_CONSTANT(FILE_ATTRIBUTE_NORMAL
),
731 INT_CONSTANT(FILE_ATTRIBUTE_READONLY
),
732 INT_CONSTANT(FILE_ATTRIBUTE_REPARSE_POINT
),
733 INT_CONSTANT(FILE_ATTRIBUTE_TEMPORARY
),
734 INT_CONSTANT(FILE_FLAG_BACKUP_SEMANTICS
),
736 // CreateFile error constant
737 { "INVALID_HANDLE_VALUE", INT_TO_JSVAL(INT_PTR(INVALID_HANDLE_VALUE
)) },
741 INT_CONSTANT(FILE_FLAG_DELETE_ON_CLOSE
),
743 // SetFilePointer methods
744 INT_CONSTANT(FILE_BEGIN
),
745 INT_CONSTANT(FILE_CURRENT
),
746 INT_CONSTANT(FILE_END
),
748 // SetFilePointer error constant
749 UINT_CONSTANT(INVALID_SET_FILE_POINTER
),
752 INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY
),
756 INT_CONSTANT(MOVEFILE_COPY_ALLOWED
),
757 INT_CONSTANT(MOVEFILE_REPLACE_EXISTING
),
759 // GetFileAttributes error constant
760 INT_CONSTANT(INVALID_FILE_ATTRIBUTES
),
762 // GetNamedSecurityInfo and SetNamedSecurityInfo constants
763 INT_CONSTANT(UNPROTECTED_DACL_SECURITY_INFORMATION
),
764 INT_CONSTANT(SE_FILE_OBJECT
),
765 INT_CONSTANT(DACL_SECURITY_INFORMATION
),
768 INT_CONSTANT(ERROR_INVALID_HANDLE
),
769 INT_CONSTANT(ERROR_ACCESS_DENIED
),
770 INT_CONSTANT(ERROR_DIR_NOT_EMPTY
),
771 INT_CONSTANT(ERROR_FILE_EXISTS
),
772 INT_CONSTANT(ERROR_ALREADY_EXISTS
),
773 INT_CONSTANT(ERROR_FILE_NOT_FOUND
),
774 INT_CONSTANT(ERROR_NO_MORE_FILES
),
775 INT_CONSTANT(ERROR_PATH_NOT_FOUND
),
776 INT_CONSTANT(ERROR_BAD_ARGUMENTS
),
777 INT_CONSTANT(ERROR_SHARING_VIOLATION
),
778 INT_CONSTANT(ERROR_NOT_SUPPORTED
),
782 #endif // defined(XP_WIN)
786 * Get a field of an object as an object.
788 * If the field does not exist, create it. If it exists but is not an
789 * object, throw a JS error.
791 JSObject
*GetOrCreateObjectProperty(JSContext
*cx
, JS::Handle
<JSObject
*> aObject
,
792 const char *aProperty
)
794 JS::Rooted
<JS::Value
> val(cx
);
795 if (!JS_GetProperty(cx
, aObject
, aProperty
, &val
)) {
798 if (!val
.isUndefined()) {
799 if (val
.isObject()) {
800 return &val
.toObject();
803 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
804 JSMSG_UNEXPECTED_TYPE
, aProperty
, "not an object");
807 return JS_DefineObject(cx
, aObject
, aProperty
, nullptr, JS::NullPtr(),
812 * Set a property of an object from a nsString.
814 * If the nsString is void (i.e. IsVoid is true), do nothing.
816 bool SetStringProperty(JSContext
*cx
, JS::Handle
<JSObject
*> aObject
, const char *aProperty
,
817 const nsString aValue
)
819 if (aValue
.IsVoid()) {
822 JSString
* strValue
= JS_NewUCStringCopyZ(cx
, aValue
.get());
823 NS_ENSURE_TRUE(strValue
, false);
824 JS::Rooted
<JS::Value
> valValue(cx
, STRING_TO_JSVAL(strValue
));
825 return JS_SetProperty(cx
, aObject
, aProperty
, valValue
);
829 * Define OS-specific constants.
831 * This function creates or uses JS object |OS.Constants| to store
834 bool DefineOSFileConstants(JSContext
*cx
, JS::Handle
<JSObject
*> global
)
836 MOZ_ASSERT(gInitialized
);
838 if (gPaths
== nullptr) {
839 // If an initialization error was ignored, we may end up with
840 // |gInitialized == true| but |gPaths == nullptr|. We cannot
841 // |MOZ_ASSERT| this, as this would kill precompile_cache.js,
842 // so we simply return an error.
843 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
844 JSMSG_CANT_OPEN
, "OSFileConstants", "initialization has failed");
848 JS::Rooted
<JSObject
*> objOS(cx
);
849 if (!(objOS
= GetOrCreateObjectProperty(cx
, global
, "OS"))) {
852 JS::Rooted
<JSObject
*> objConstants(cx
);
853 if (!(objConstants
= GetOrCreateObjectProperty(cx
, objOS
, "Constants"))) {
857 // Build OS.Constants.libc
859 JS::Rooted
<JSObject
*> objLibc(cx
);
860 if (!(objLibc
= GetOrCreateObjectProperty(cx
, objConstants
, "libc"))) {
863 if (!dom::DefineConstants(cx
, objLibc
, gLibcProperties
)) {
868 // Build OS.Constants.Win
870 JS::Rooted
<JSObject
*> objWin(cx
);
871 if (!(objWin
= GetOrCreateObjectProperty(cx
, objConstants
, "Win"))) {
874 if (!dom::DefineConstants(cx
, objWin
, gWinProperties
)) {
877 #endif // defined(XP_WIN)
879 // Build OS.Constants.Sys
881 JS::Rooted
<JSObject
*> objSys(cx
);
882 if (!(objSys
= GetOrCreateObjectProperty(cx
, objConstants
, "Sys"))) {
886 #if defined(MOZ_WIDGET_GONK)
887 JSString
* strVersion
= JS_NewStringCopyZ(cx
, "Gonk");
891 JS::Rooted
<JS::Value
> valVersion(cx
, STRING_TO_JSVAL(strVersion
));
892 if (!JS_SetProperty(cx
, objSys
, "Name", valVersion
)) {
896 nsCOMPtr
<nsIXULRuntime
> runtime
= do_GetService(XULRUNTIME_SERVICE_CONTRACTID
);
899 DebugOnly
<nsresult
> rv
= runtime
->GetOS(os
);
900 MOZ_ASSERT(NS_SUCCEEDED(rv
));
902 JSString
* strVersion
= JS_NewStringCopyZ(cx
, os
.get());
907 JS::Rooted
<JS::Value
> valVersion(cx
, STRING_TO_JSVAL(strVersion
));
908 if (!JS_SetProperty(cx
, objSys
, "Name", valVersion
)) {
912 #endif // defined(MOZ_WIDGET_GONK)
915 JS::Rooted
<JS::Value
> valDebug(cx
, JSVAL_TRUE
);
916 if (!JS_SetProperty(cx
, objSys
, "DEBUG", valDebug
)) {
921 dom::ConstantSpec umask_cs
[] = {
922 { "umask", UINT_TO_JSVAL(gUserUmask
) },
925 if (!dom::DefineConstants(cx
, objSys
, umask_cs
)) {
929 // Build OS.Constants.Path
931 JS::Rooted
<JSObject
*> objPath(cx
);
932 if (!(objPath
= GetOrCreateObjectProperty(cx
, objConstants
, "Path"))) {
937 // Note that we don't actually provide the full path, only the name of the
938 // library, which is sufficient to link to the library using js-ctypes.
940 #if defined(XP_MACOSX)
941 // Under MacOS X, for some reason, libxul is called simply "XUL",
942 // and we need to provide the full path.
944 libxul
.Append(gPaths
->libDir
);
945 libxul
.AppendLiteral("/XUL");
947 // On other platforms, libxul is a library "xul" with regular
948 // library prefix/suffix.
950 libxul
.AppendLiteral(DLL_PREFIX
);
951 libxul
.AppendLiteral("xul");
952 libxul
.AppendLiteral(DLL_SUFFIX
);
953 #endif // defined(XP_MACOSX)
955 if (!SetStringProperty(cx
, objPath
, "libxul", libxul
)) {
959 if (!SetStringProperty(cx
, objPath
, "libDir", gPaths
->libDir
)) {
963 if (!SetStringProperty(cx
, objPath
, "tmpDir", gPaths
->tmpDir
)) {
967 // Configure profileDir only if it is available at this stage
968 if (!gPaths
->profileDir
.IsVoid()
969 && !SetStringProperty(cx
, objPath
, "profileDir", gPaths
->profileDir
)) {
973 // Configure localProfileDir only if it is available at this stage
974 if (!gPaths
->localProfileDir
.IsVoid()
975 && !SetStringProperty(cx
, objPath
, "localProfileDir", gPaths
->localProfileDir
)) {
979 if (!SetStringProperty(cx
, objPath
, "homeDir", gPaths
->homeDir
)) {
983 if (!SetStringProperty(cx
, objPath
, "desktopDir", gPaths
->desktopDir
)) {
987 if (!SetStringProperty(cx
, objPath
, "userApplicationDataDir", gPaths
->userApplicationDataDir
)) {
992 if (!SetStringProperty(cx
, objPath
, "winAppDataDir", gPaths
->winAppDataDir
)) {
996 if (!SetStringProperty(cx
, objPath
, "winStartMenuProgsDir", gPaths
->winStartMenuProgsDir
)) {
999 #endif // defined(XP_WIN)
1001 #if defined(XP_MACOSX)
1002 if (!SetStringProperty(cx
, objPath
, "macUserLibDir", gPaths
->macUserLibDir
)) {
1006 if (!SetStringProperty(cx
, objPath
, "macLocalApplicationsDir", gPaths
->macLocalApplicationsDir
)) {
1010 if (!SetStringProperty(cx
, objPath
, "macTrashDir", gPaths
->macTrashDir
)) {
1013 #endif // defined(XP_MACOSX)
1015 // sqlite3 is linked from different places depending on the platform
1016 nsAutoString libsqlite3
;
1017 #if defined(ANDROID)
1018 // On Android, we use the system's libsqlite3
1019 libsqlite3
.AppendLiteral(DLL_PREFIX
);
1020 libsqlite3
.AppendLiteral("sqlite3");
1021 libsqlite3
.AppendLiteral(DLL_SUFFIX
);
1022 #elif defined(XP_WIN)
1023 // On Windows, for some reason, this is part of nss3.dll
1024 libsqlite3
.AppendLiteral(DLL_PREFIX
);
1025 libsqlite3
.AppendLiteral("nss3");
1026 libsqlite3
.AppendLiteral(DLL_SUFFIX
);
1028 // On other platforms, we link sqlite3 into libxul
1029 libsqlite3
= libxul
;
1030 #endif // defined(ANDROID) || defined(XP_WIN)
1032 if (!SetStringProperty(cx
, objPath
, "libsqlite3", libsqlite3
)) {
1039 NS_IMPL_ISUPPORTS(OSFileConstantsService
, nsIOSFileConstantsService
)
1041 OSFileConstantsService::OSFileConstantsService()
1043 MOZ_ASSERT(NS_IsMainThread());
1046 OSFileConstantsService::~OSFileConstantsService()
1048 mozilla::CleanupOSFileConstants();
1053 OSFileConstantsService::Init(JSContext
*aCx
)
1055 nsresult rv
= mozilla::InitOSFileConstants();
1056 if (NS_FAILED(rv
)) {
1060 mozJSComponentLoader
* loader
= mozJSComponentLoader::Get();
1061 JS::Rooted
<JSObject
*> targetObj(aCx
);
1062 rv
= loader
->FindTargetObject(aCx
, &targetObj
);
1063 NS_ENSURE_SUCCESS(rv
, rv
);
1065 if (!mozilla::DefineOSFileConstants(aCx
, targetObj
)) {
1066 return NS_ERROR_FAILURE
;
1072 } // namespace mozilla