1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/DebugOnly.h"
18 # include "sys/stat.h"
19 # if defined(XP_LINUX)
21 # define statvfs statfs
22 # define f_frsize f_bsize
24 # include "sys/statvfs.h"
25 # endif // defined(XP_LINUX)
26 # if !defined(ANDROID)
27 # include "sys/wait.h"
29 # endif // !defined(ANDROID)
30 #endif // defined(XP_UNIX)
33 # include <linux/fadvise.h>
34 #endif // defined(XP_LINUX)
36 #if defined(XP_MACOSX)
37 # include "copyfile.h"
38 #endif // defined(XP_MACOSX)
45 # define PATH_MAX MAX_PATH
48 #endif // defined(XP_WIN)
51 #include "jsfriendapi.h"
52 #include "BindingUtils.h"
54 // Used to provide information on the OS
56 #include "nsThreadUtils.h"
57 #include "nsIObserverService.h"
58 #include "nsIObserver.h"
59 #include "nsDirectoryServiceUtils.h"
60 #include "nsIXULRuntime.h"
61 #include "nsIPropertyBag2.h"
62 #include "nsXPCOMCIDInternal.h"
63 #include "nsServiceManagerUtils.h"
65 #include "nsSystemInfo.h"
66 #include "nsDirectoryServiceDefs.h"
67 #include "nsXULAppAPI.h"
68 #include "nsAppDirectoryServiceDefs.h"
69 #include "mozJSComponentLoader.h"
71 #include "mozilla/ClearOnShutdown.h"
72 #include "mozilla/StaticPtr.h"
73 #include "mozilla/UniquePtr.h"
75 #include "OSFileConstants.h"
76 #include "nsIOSFileConstantsService.h"
77 #include "nsZipArchive.h"
79 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
81 # define __dd_fd dd_fd
85 * This module defines the basic libc constants (error numbers, open modes,
86 * etc.) used by OS.File and possibly other OS-bound JavaScript libraries.
93 StaticRefPtr
<OSFileConstantsService
> gInstance
;
95 } // anonymous namespace
97 struct OSFileConstantsService::Paths
{
99 * The name of the directory holding all the libraries (libxpcom, libnss,
105 nsString localProfileDir
;
108 libDir
.SetIsVoid(true);
109 tmpDir
.SetIsVoid(true);
110 profileDir
.SetIsVoid(true);
111 localProfileDir
.SetIsVoid(true);
116 * Return the path to one of the special directories.
118 * @param aKey The key to the special directory (e.g. "TmpD", "ProfD", ...)
119 * @param aOutPath The path to the special directory. In case of error,
120 * the string is set to void.
122 nsresult
GetPathToSpecialDir(const char* aKey
, nsString
& aOutPath
) {
123 nsCOMPtr
<nsIFile
> file
;
124 nsresult rv
= NS_GetSpecialDirectory(aKey
, getter_AddRefs(file
));
125 if (NS_FAILED(rv
) || !file
) {
129 return file
->GetPath(aOutPath
);
133 * In some cases, OSFileConstants may be instantiated before the
134 * profile is setup. In such cases, |OS.Constants.Path.profileDir| and
135 * |OS.Constants.Path.localProfileDir| are undefined. However, we want
136 * to ensure that this does not break existing code, so that future
137 * workers spawned after the profile is setup have these constants.
139 * For this purpose, we register an observer to set |mPaths->profileDir|
140 * and |mPaths->localProfileDir| once the profile is setup.
143 OSFileConstantsService::Observe(nsISupports
*, const char* aTopic
,
146 // Initialization has not taken place, something is wrong,
147 // don't make things worse.
152 GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR
, mPaths
->profileDir
);
156 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR
,
157 mPaths
->localProfileDir
);
166 * Perform the part of initialization that can only be
167 * executed on the main thread.
169 nsresult
OSFileConstantsService::InitOSFileConstants() {
170 MOZ_ASSERT(NS_IsMainThread());
175 UniquePtr
<Paths
> paths(new Paths
);
177 // Initialize paths->libDir
178 nsCOMPtr
<nsIFile
> file
;
180 NS_GetSpecialDirectory(NS_XPCOM_LIBRARY_FILE
, getter_AddRefs(file
));
185 nsCOMPtr
<nsIFile
> libDir
;
186 rv
= file
->GetParent(getter_AddRefs(libDir
));
191 rv
= libDir
->GetPath(paths
->libDir
);
196 // Setup profileDir and localProfileDir immediately if possible (we
197 // assume that NS_APP_USER_PROFILE_50_DIR and
198 // NS_APP_USER_PROFILE_LOCAL_50_DIR are set simultaneously)
199 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR
, paths
->profileDir
);
200 if (NS_SUCCEEDED(rv
)) {
201 rv
= GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR
,
202 paths
->localProfileDir
);
205 // Otherwise, delay setup of profileDir/localProfileDir until they
208 nsCOMPtr
<nsIObserverService
> obsService
=
209 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
, &rv
);
213 rv
= obsService
->AddObserver(this, "profile-do-change", false);
219 GetPathToSpecialDir(NS_OS_TEMP_DIR
, paths
->tmpDir
);
221 mPaths
= std::move(paths
);
223 // Get the umask from the system-info service.
224 // The property will always be present, but it will be zero on
226 // nsSystemInfo::gUserUmask is initialized by NS_InitXPCOM so we don't need
227 // to initialize the service.
228 mUserUmask
= nsSystemInfo::gUserUmask
;
235 * Define a simple read-only property holding an integer.
237 * @param name The name of the constant. Used both as the JS name for the
238 * constant and to access its value. Must be defined.
240 * Produces a |ConstantSpec|.
242 #define INT_CONSTANT(name) \
243 { #name, JS::Int32Value(name) }
246 * Define a simple read-only property holding an unsigned integer.
248 * @param name The name of the constant. Used both as the JS name for the
249 * constant and to access its value. Must be defined.
251 * Produces a |ConstantSpec|.
253 #define UINT_CONSTANT(name) \
254 { #name, JS::NumberValue(name) }
257 * End marker for ConstantSpec
260 { nullptr, JS::UndefinedValue() }
262 // Define missing constants for Android
263 #if !defined(S_IRGRP)
264 # define S_IXOTH 0001
265 # define S_IWOTH 0002
266 # define S_IROTH 0004
267 # define S_IRWXO 0007
268 # define S_IXGRP 0010
269 # define S_IWGRP 0020
270 # define S_IRGRP 0040
271 # define S_IRWXG 0070
272 # define S_IXUSR 0100
273 # define S_IWUSR 0200
274 # define S_IRUSR 0400
275 # define S_IRWXU 0700
276 #endif // !defined(S_IRGRP)
279 * The properties defined in libc.
281 * If you extend this list of properties, please
282 * separate categories ("errors", "open", etc.),
283 * keep properties organized by alphabetical order
284 * and #ifdef-away properties that are not portable.
286 static const dom::ConstantSpec gLibcProperties
[] = {
287 // Arguments for open
288 INT_CONSTANT(O_APPEND
),
289 #if defined(O_CLOEXEC)
290 INT_CONSTANT(O_CLOEXEC
),
291 #endif // defined(O_CLOEXEC)
292 INT_CONSTANT(O_CREAT
),
293 #if defined(O_DIRECTORY)
294 INT_CONSTANT(O_DIRECTORY
),
295 #endif // defined(O_DIRECTORY)
296 #if defined(O_EVTONLY)
297 INT_CONSTANT(O_EVTONLY
),
298 #endif // defined(O_EVTONLY)
299 INT_CONSTANT(O_EXCL
),
300 #if defined(O_EXLOCK)
301 INT_CONSTANT(O_EXLOCK
),
302 #endif // defined(O_EXLOCK)
303 #if defined(O_LARGEFILE)
304 INT_CONSTANT(O_LARGEFILE
),
305 #endif // defined(O_LARGEFILE)
306 #if defined(O_NOFOLLOW)
307 INT_CONSTANT(O_NOFOLLOW
),
308 #endif // defined(O_NOFOLLOW)
309 #if defined(O_NONBLOCK)
310 INT_CONSTANT(O_NONBLOCK
),
311 #endif // defined(O_NONBLOCK)
312 INT_CONSTANT(O_RDONLY
),
313 INT_CONSTANT(O_RDWR
),
315 INT_CONSTANT(O_RSYNC
),
316 #endif // defined(O_RSYNC)
317 #if defined(O_SHLOCK)
318 INT_CONSTANT(O_SHLOCK
),
319 #endif // defined(O_SHLOCK)
320 #if defined(O_SYMLINK)
321 INT_CONSTANT(O_SYMLINK
),
322 #endif // defined(O_SYMLINK)
324 INT_CONSTANT(O_SYNC
),
325 #endif // defined(O_SYNC)
326 INT_CONSTANT(O_TRUNC
),
327 INT_CONSTANT(O_WRONLY
),
329 #if defined(FD_CLOEXEC)
330 INT_CONSTANT(FD_CLOEXEC
),
331 #endif // defined(FD_CLOEXEC)
333 #if defined(AT_EACCESS)
334 INT_CONSTANT(AT_EACCESS
),
335 #endif // defined(AT_EACCESS)
336 #if defined(AT_FDCWD)
337 INT_CONSTANT(AT_FDCWD
),
338 #endif // defined(AT_FDCWD)
339 #if defined(AT_SYMLINK_NOFOLLOW)
340 INT_CONSTANT(AT_SYMLINK_NOFOLLOW
),
341 #endif // defined(AT_SYMLINK_NOFOLLOW)
343 #if defined(POSIX_FADV_SEQUENTIAL)
344 INT_CONSTANT(POSIX_FADV_SEQUENTIAL
),
345 #endif // defined(POSIX_FADV_SEQUENTIAL)
353 #endif // defined(F_OK)
356 INT_CONSTANT(S_IRGRP
),
357 INT_CONSTANT(S_IROTH
),
358 INT_CONSTANT(S_IRUSR
),
359 INT_CONSTANT(S_IRWXG
),
360 INT_CONSTANT(S_IRWXO
),
361 INT_CONSTANT(S_IRWXU
),
362 INT_CONSTANT(S_IWGRP
),
363 INT_CONSTANT(S_IWOTH
),
364 INT_CONSTANT(S_IWUSR
),
365 INT_CONSTANT(S_IXOTH
),
366 INT_CONSTANT(S_IXGRP
),
367 INT_CONSTANT(S_IXUSR
),
370 INT_CONSTANT(SEEK_CUR
),
371 INT_CONSTANT(SEEK_END
),
372 INT_CONSTANT(SEEK_SET
),
376 INT_CONSTANT(POLLERR
),
377 INT_CONSTANT(POLLHUP
),
378 INT_CONSTANT(POLLIN
),
379 INT_CONSTANT(POLLNVAL
),
380 INT_CONSTANT(POLLOUT
),
383 # if defined(WNOHANG)
384 INT_CONSTANT(WNOHANG
),
385 # endif // defined(WNOHANG)
387 // fcntl command values
388 INT_CONSTANT(F_GETLK
),
389 INT_CONSTANT(F_SETFD
),
390 INT_CONSTANT(F_SETFL
),
391 INT_CONSTANT(F_SETLK
),
392 INT_CONSTANT(F_SETLKW
),
395 INT_CONSTANT(F_RDLCK
),
396 INT_CONSTANT(F_WRLCK
),
397 INT_CONSTANT(F_UNLCK
),
400 # if defined(SPLICE_F_MOVE)
401 INT_CONSTANT(SPLICE_F_MOVE
),
402 # endif // defined(SPLICE_F_MOVE)
403 # if defined(SPLICE_F_NONBLOCK)
404 INT_CONSTANT(SPLICE_F_NONBLOCK
),
405 # endif // defined(SPLICE_F_NONBLOCK)
406 # if defined(SPLICE_F_MORE)
407 INT_CONSTANT(SPLICE_F_MORE
),
408 # endif // defined(SPLICE_F_MORE)
409 # if defined(SPLICE_F_GIFT)
410 INT_CONSTANT(SPLICE_F_GIFT
),
411 # endif // defined(SPLICE_F_GIFT)
412 #endif // defined(XP_UNIX)
414 #if defined(COPYFILE_DATA)
415 INT_CONSTANT(COPYFILE_DATA
),
416 INT_CONSTANT(COPYFILE_EXCL
),
417 INT_CONSTANT(COPYFILE_XATTR
),
418 INT_CONSTANT(COPYFILE_STAT
),
419 INT_CONSTANT(COPYFILE_ACL
),
420 INT_CONSTANT(COPYFILE_MOVE
),
421 #endif // defined(COPYFILE_DATA)
424 INT_CONSTANT(EACCES
),
425 INT_CONSTANT(EAGAIN
),
427 INT_CONSTANT(EEXIST
),
428 INT_CONSTANT(EFAULT
),
430 INT_CONSTANT(EINVAL
),
433 INT_CONSTANT(EISDIR
),
434 #if defined(ELOOP) // not defined with VC9
436 #endif // defined(ELOOP)
437 INT_CONSTANT(EMFILE
),
438 INT_CONSTANT(ENAMETOOLONG
),
439 INT_CONSTANT(ENFILE
),
440 INT_CONSTANT(ENOENT
),
441 INT_CONSTANT(ENOMEM
),
442 INT_CONSTANT(ENOSPC
),
443 INT_CONSTANT(ENOTDIR
),
445 #if defined(EOPNOTSUPP) // not defined with VC 9
446 INT_CONSTANT(EOPNOTSUPP
),
447 #endif // defined(EOPNOTSUPP)
448 #if defined(EOVERFLOW) // not defined with VC 9
449 INT_CONSTANT(EOVERFLOW
),
450 #endif // defined(EOVERFLOW)
452 INT_CONSTANT(ERANGE
),
453 #if defined(ETIMEDOUT) // not defined with VC 9
454 INT_CONSTANT(ETIMEDOUT
),
455 #endif // defined(ETIMEDOUT)
456 #if defined(EWOULDBLOCK) // not defined with VC 9
457 INT_CONSTANT(EWOULDBLOCK
),
458 #endif // defined(EWOULDBLOCK)
461 #if defined(DT_UNKNOWN)
462 // Constants for |readdir|
463 INT_CONSTANT(DT_UNKNOWN
),
464 INT_CONSTANT(DT_FIFO
),
465 INT_CONSTANT(DT_CHR
),
466 INT_CONSTANT(DT_DIR
),
467 INT_CONSTANT(DT_BLK
),
468 INT_CONSTANT(DT_REG
),
469 INT_CONSTANT(DT_LNK
),
470 INT_CONSTANT(DT_SOCK
),
471 #endif // defined(DT_UNKNOWN)
474 // Constants for |stat|
475 INT_CONSTANT(S_IFMT
),
476 INT_CONSTANT(S_IFIFO
),
477 INT_CONSTANT(S_IFCHR
),
478 INT_CONSTANT(S_IFDIR
),
479 INT_CONSTANT(S_IFBLK
),
480 INT_CONSTANT(S_IFREG
),
481 INT_CONSTANT(S_IFLNK
),
482 INT_CONSTANT(S_IFSOCK
),
483 #endif // defined(S_IFIFO)
485 INT_CONSTANT(PATH_MAX
),
487 // Constants used to define data structures
489 // Many data structures have different fields/sizes/etc. on
490 // various OSes / versions of the same OS / platforms. For these
491 // data structures, we need to compute and export from C the size
492 // and, if necessary, the offset of fields, so as to be able to
493 // define the structure in JS.
496 // The size of |mode_t|.
497 {"OSFILE_SIZEOF_MODE_T", JS::Int32Value(sizeof(mode_t
))},
499 // The size of |gid_t|.
500 {"OSFILE_SIZEOF_GID_T", JS::Int32Value(sizeof(gid_t
))},
502 // The size of |uid_t|.
503 {"OSFILE_SIZEOF_UID_T", JS::Int32Value(sizeof(uid_t
))},
505 // The size of |time_t|.
506 {"OSFILE_SIZEOF_TIME_T", JS::Int32Value(sizeof(time_t))},
508 // The size of |fsblkcnt_t|.
509 {"OSFILE_SIZEOF_FSBLKCNT_T", JS::Int32Value(sizeof(fsblkcnt_t
))},
511 # if !defined(ANDROID)
512 // The size of |posix_spawn_file_actions_t|.
513 {"OSFILE_SIZEOF_POSIX_SPAWN_FILE_ACTIONS_T",
514 JS::Int32Value(sizeof(posix_spawn_file_actions_t
))},
515 # endif // !defined(ANDROID)
517 // Defining |dirent|.
519 {"OSFILE_SIZEOF_DIRENT", JS::Int32Value(sizeof(dirent
))},
522 # if defined(XP_UNIX)
523 {"OSFILE_SIZEOF_FLOCK", JS::Int32Value(sizeof(struct flock
))},
524 {"OSFILE_OFFSETOF_FLOCK_L_START",
525 JS::Int32Value(offsetof(struct flock
, l_start
))},
526 {"OSFILE_OFFSETOF_FLOCK_L_LEN",
527 JS::Int32Value(offsetof(struct flock
, l_len
))},
528 {"OSFILE_OFFSETOF_FLOCK_L_PID",
529 JS::Int32Value(offsetof(struct flock
, l_pid
))},
530 {"OSFILE_OFFSETOF_FLOCK_L_TYPE",
531 JS::Int32Value(offsetof(struct flock
, l_type
))},
532 {"OSFILE_OFFSETOF_FLOCK_L_WHENCE",
533 JS::Int32Value(offsetof(struct flock
, l_whence
))},
534 # endif // defined(XP_UNIX)
535 // Offset of field |d_name|.
536 {"OSFILE_OFFSETOF_DIRENT_D_NAME",
537 JS::Int32Value(offsetof(struct dirent
, d_name
))},
538 // An upper bound to the length of field |d_name| of struct |dirent|.
539 // (may not be exact, depending on padding).
540 {"OSFILE_SIZEOF_DIRENT_D_NAME",
541 JS::Int32Value(sizeof(struct dirent
) - offsetof(struct dirent
, d_name
))},
543 // Defining |timeval|.
544 {"OSFILE_SIZEOF_TIMEVAL", JS::Int32Value(sizeof(struct timeval
))},
545 {"OSFILE_OFFSETOF_TIMEVAL_TV_SEC",
546 JS::Int32Value(offsetof(struct timeval
, tv_sec
))},
547 {"OSFILE_OFFSETOF_TIMEVAL_TV_USEC",
548 JS::Int32Value(offsetof(struct timeval
, tv_usec
))},
550 # if defined(DT_UNKNOWN)
551 // Position of field |d_type| in |dirent|
552 // Not strictly posix, but seems defined on all platforms
554 {"OSFILE_OFFSETOF_DIRENT_D_TYPE",
555 JS::Int32Value(offsetof(struct dirent
, d_type
))},
556 # endif // defined(DT_UNKNOWN)
558 // Under MacOS X and BSDs, |dirfd| is a macro rather than a
559 // function, so we need a little help to get it to work
561 {"OSFILE_SIZEOF_DIR", JS::Int32Value(sizeof(DIR))},
563 {"OSFILE_OFFSETOF_DIR_DD_FD", JS::Int32Value(offsetof(DIR, __dd_fd
))},
568 {"OSFILE_SIZEOF_STAT", JS::Int32Value(sizeof(struct stat
))},
570 {"OSFILE_OFFSETOF_STAT_ST_MODE",
571 JS::Int32Value(offsetof(struct stat
, st_mode
))},
572 {"OSFILE_OFFSETOF_STAT_ST_UID",
573 JS::Int32Value(offsetof(struct stat
, st_uid
))},
574 {"OSFILE_OFFSETOF_STAT_ST_GID",
575 JS::Int32Value(offsetof(struct stat
, st_gid
))},
576 {"OSFILE_OFFSETOF_STAT_ST_SIZE",
577 JS::Int32Value(offsetof(struct stat
, st_size
))},
579 # if defined(HAVE_ST_ATIMESPEC)
580 {"OSFILE_OFFSETOF_STAT_ST_ATIME",
581 JS::Int32Value(offsetof(struct stat
, st_atimespec
))},
582 {"OSFILE_OFFSETOF_STAT_ST_MTIME",
583 JS::Int32Value(offsetof(struct stat
, st_mtimespec
))},
584 {"OSFILE_OFFSETOF_STAT_ST_CTIME",
585 JS::Int32Value(offsetof(struct stat
, st_ctimespec
))},
587 {"OSFILE_OFFSETOF_STAT_ST_ATIME",
588 JS::Int32Value(offsetof(struct stat
, st_atime
))},
589 {"OSFILE_OFFSETOF_STAT_ST_MTIME",
590 JS::Int32Value(offsetof(struct stat
, st_mtime
))},
591 {"OSFILE_OFFSETOF_STAT_ST_CTIME",
592 JS::Int32Value(offsetof(struct stat
, st_ctime
))},
593 # endif // defined(HAVE_ST_ATIME)
595 // Several OSes have a birthtime field. For the moment, supporting only Darwin.
596 # if defined(_DARWIN_FEATURE_64_BIT_INODE)
597 {"OSFILE_OFFSETOF_STAT_ST_BIRTHTIME",
598 JS::Int32Value(offsetof(struct stat
, st_birthtime
))},
599 # endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
601 // Defining |statvfs|
603 {"OSFILE_SIZEOF_STATVFS", JS::Int32Value(sizeof(struct statvfs
))},
605 {"OSFILE_OFFSETOF_STATVFS_F_FRSIZE",
606 JS::Int32Value(offsetof(struct statvfs
, f_frsize
))},
607 {"OSFILE_OFFSETOF_STATVFS_F_BAVAIL",
608 JS::Int32Value(offsetof(struct statvfs
, f_bavail
))},
610 #endif // defined(XP_UNIX)
612 // System configuration
614 // Under MacOSX, to avoid using deprecated functions that do not
615 // match the constants we define in this object (including
616 // |sizeof|/|offsetof| stuff, but not only), for a number of
617 // functions, we need to adapt the name of the symbols we are using,
618 // whenever macro _DARWIN_FEATURE_64_BIT_INODE is set. We export
619 // this value to be able to do so from JavaScript.
620 #if defined(_DARWIN_FEATURE_64_BIT_INODE)
621 {"_DARWIN_FEATURE_64_BIT_INODE", JS::Int32Value(1)},
622 #endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
624 // Similar feature for Linux
625 #if defined(_STAT_VER)
626 INT_CONSTANT(_STAT_VER
),
627 #endif // defined(_STAT_VER)
633 * The properties defined in windows.h.
635 * If you extend this list of properties, please
636 * separate categories ("errors", "open", etc.),
637 * keep properties organized by alphabetical order
638 * and #ifdef-away properties that are not portable.
640 static const dom::ConstantSpec gWinProperties
[] = {
641 // FormatMessage flags
642 INT_CONSTANT(FORMAT_MESSAGE_FROM_SYSTEM
),
643 INT_CONSTANT(FORMAT_MESSAGE_IGNORE_INSERTS
),
645 // The max length of paths
646 INT_CONSTANT(MAX_PATH
),
648 // CreateFile desired access
649 INT_CONSTANT(GENERIC_ALL
),
650 INT_CONSTANT(GENERIC_EXECUTE
),
651 INT_CONSTANT(GENERIC_READ
),
652 INT_CONSTANT(GENERIC_WRITE
),
654 // CreateFile share mode
655 INT_CONSTANT(FILE_SHARE_DELETE
),
656 INT_CONSTANT(FILE_SHARE_READ
),
657 INT_CONSTANT(FILE_SHARE_WRITE
),
659 // CreateFile creation disposition
660 INT_CONSTANT(CREATE_ALWAYS
),
661 INT_CONSTANT(CREATE_NEW
),
662 INT_CONSTANT(OPEN_ALWAYS
),
663 INT_CONSTANT(OPEN_EXISTING
),
664 INT_CONSTANT(TRUNCATE_EXISTING
),
666 // CreateFile attributes
667 INT_CONSTANT(FILE_ATTRIBUTE_ARCHIVE
),
668 INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY
),
669 INT_CONSTANT(FILE_ATTRIBUTE_HIDDEN
),
670 INT_CONSTANT(FILE_ATTRIBUTE_NORMAL
),
671 INT_CONSTANT(FILE_ATTRIBUTE_READONLY
),
672 INT_CONSTANT(FILE_ATTRIBUTE_REPARSE_POINT
),
673 INT_CONSTANT(FILE_ATTRIBUTE_SYSTEM
),
674 INT_CONSTANT(FILE_ATTRIBUTE_TEMPORARY
),
675 INT_CONSTANT(FILE_FLAG_BACKUP_SEMANTICS
),
677 // CreateFile error constant
678 {"INVALID_HANDLE_VALUE", JS::Int32Value(INT_PTR(INVALID_HANDLE_VALUE
))},
681 INT_CONSTANT(FILE_FLAG_DELETE_ON_CLOSE
),
683 // SetFilePointer methods
684 INT_CONSTANT(FILE_BEGIN
),
685 INT_CONSTANT(FILE_CURRENT
),
686 INT_CONSTANT(FILE_END
),
688 // SetFilePointer error constant
689 UINT_CONSTANT(INVALID_SET_FILE_POINTER
),
692 INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY
),
695 INT_CONSTANT(MOVEFILE_COPY_ALLOWED
),
696 INT_CONSTANT(MOVEFILE_REPLACE_EXISTING
),
698 // GetFileAttributes error constant
699 INT_CONSTANT(INVALID_FILE_ATTRIBUTES
),
701 // GetNamedSecurityInfo and SetNamedSecurityInfo constants
702 INT_CONSTANT(UNPROTECTED_DACL_SECURITY_INFORMATION
),
703 INT_CONSTANT(SE_FILE_OBJECT
),
704 INT_CONSTANT(DACL_SECURITY_INFORMATION
),
707 INT_CONSTANT(ERROR_INVALID_HANDLE
),
708 INT_CONSTANT(ERROR_ACCESS_DENIED
),
709 INT_CONSTANT(ERROR_DIR_NOT_EMPTY
),
710 INT_CONSTANT(ERROR_FILE_EXISTS
),
711 INT_CONSTANT(ERROR_ALREADY_EXISTS
),
712 INT_CONSTANT(ERROR_FILE_NOT_FOUND
),
713 INT_CONSTANT(ERROR_NO_MORE_FILES
),
714 INT_CONSTANT(ERROR_PATH_NOT_FOUND
),
715 INT_CONSTANT(ERROR_BAD_ARGUMENTS
),
716 INT_CONSTANT(ERROR_SHARING_VIOLATION
),
717 INT_CONSTANT(ERROR_NOT_SUPPORTED
),
720 #endif // defined(XP_WIN)
723 * Get a field of an object as an object.
725 * If the field does not exist, create it. If it exists but is not an
726 * object, throw a JS error.
728 JSObject
* GetOrCreateObjectProperty(JSContext
* cx
,
729 JS::Handle
<JSObject
*> aObject
,
730 const char* aProperty
) {
731 JS::Rooted
<JS::Value
> val(cx
);
732 if (!JS_GetProperty(cx
, aObject
, aProperty
, &val
)) {
735 if (!val
.isUndefined()) {
736 if (val
.isObject()) {
737 return &val
.toObject();
740 JS_ReportErrorNumberASCII(cx
, js::GetErrorMessage
, nullptr,
741 JSMSG_UNEXPECTED_TYPE
, aProperty
,
745 return JS_DefineObject(cx
, aObject
, aProperty
, nullptr, JSPROP_ENUMERATE
);
749 * Set a property of an object from a nsString.
751 * If the nsString is void (i.e. IsVoid is true), do nothing.
753 bool SetStringProperty(JSContext
* cx
, JS::Handle
<JSObject
*> aObject
,
754 const char* aProperty
, const nsString aValue
) {
755 if (aValue
.IsVoid()) {
758 JSString
* strValue
= JS_NewUCStringCopyZ(cx
, aValue
.get());
759 NS_ENSURE_TRUE(strValue
, false);
760 JS::Rooted
<JS::Value
> valValue(cx
, JS::StringValue(strValue
));
761 return JS_SetProperty(cx
, aObject
, aProperty
, valValue
);
765 * Define OS-specific constants.
767 * This function creates or uses JS object |OS.Constants| to store
770 bool OSFileConstantsService::DefineOSFileConstants(
771 JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
) {
773 JS_ReportErrorNumberASCII(aCx
, js::GetErrorMessage
, nullptr,
774 JSMSG_CANT_OPEN
, "OSFileConstants",
775 "initialization has failed");
779 JS::Rooted
<JSObject
*> objOS(aCx
);
780 if (!(objOS
= GetOrCreateObjectProperty(aCx
, aGlobal
, "OS"))) {
783 JS::Rooted
<JSObject
*> objConstants(aCx
);
784 if (!(objConstants
= GetOrCreateObjectProperty(aCx
, objOS
, "Constants"))) {
788 // Build OS.Constants.libc
790 JS::Rooted
<JSObject
*> objLibc(aCx
);
791 if (!(objLibc
= GetOrCreateObjectProperty(aCx
, objConstants
, "libc"))) {
794 if (!dom::DefineConstants(aCx
, objLibc
, gLibcProperties
)) {
799 // Build OS.Constants.Win
801 JS::Rooted
<JSObject
*> objWin(aCx
);
802 if (!(objWin
= GetOrCreateObjectProperty(aCx
, objConstants
, "Win"))) {
805 if (!dom::DefineConstants(aCx
, objWin
, gWinProperties
)) {
808 #endif // defined(XP_WIN)
810 // Build OS.Constants.Sys
812 JS::Rooted
<JSObject
*> objSys(aCx
);
813 if (!(objSys
= GetOrCreateObjectProperty(aCx
, objConstants
, "Sys"))) {
817 nsCOMPtr
<nsIXULRuntime
> runtime
=
818 do_GetService(XULRUNTIME_SERVICE_CONTRACTID
);
821 DebugOnly
<nsresult
> rv
= runtime
->GetOS(os
);
822 MOZ_ASSERT(NS_SUCCEEDED(rv
));
824 JSString
* strVersion
= JS_NewStringCopyZ(aCx
, os
.get());
829 JS::Rooted
<JS::Value
> valVersion(aCx
, JS::StringValue(strVersion
));
830 if (!JS_SetProperty(aCx
, objSys
, "Name", valVersion
)) {
836 JS::Rooted
<JS::Value
> valDebug(aCx
, JS::TrueValue());
837 if (!JS_SetProperty(aCx
, objSys
, "DEBUG", valDebug
)) {
842 #if defined(HAVE_64BIT_BUILD)
843 JS::Rooted
<JS::Value
> valBits(aCx
, JS::Int32Value(64));
845 JS::Rooted
<JS::Value
> valBits(aCx
, JS::Int32Value(32));
846 #endif // defined (HAVE_64BIT_BUILD)
847 if (!JS_SetProperty(aCx
, objSys
, "bits", valBits
)) {
851 if (!JS_DefineProperty(
852 aCx
, objSys
, "umask", mUserUmask
,
853 JSPROP_ENUMERATE
| JSPROP_READONLY
| JSPROP_PERMANENT
)) {
857 // Build OS.Constants.Path
859 JS::Rooted
<JSObject
*> objPath(aCx
);
860 if (!(objPath
= GetOrCreateObjectProperty(aCx
, objConstants
, "Path"))) {
865 // Note that we don't actually provide the full path, only the name of the
866 // library, which is sufficient to link to the library using js-ctypes.
868 #if defined(XP_MACOSX)
869 // Under MacOS X, for some reason, libxul is called simply "XUL",
870 // and we need to provide the full path.
872 libxul
.Append(mPaths
->libDir
);
873 libxul
.AppendLiteral("/XUL");
875 // On other platforms, libxul is a library "xul" with regular
876 // library prefix/suffix.
878 libxul
.AppendLiteral(MOZ_DLL_PREFIX
);
879 libxul
.AppendLiteral("xul");
880 libxul
.AppendLiteral(MOZ_DLL_SUFFIX
);
881 #endif // defined(XP_MACOSX)
883 if (!SetStringProperty(aCx
, objPath
, "libxul", libxul
)) {
887 if (!SetStringProperty(aCx
, objPath
, "libDir", mPaths
->libDir
)) {
891 if (!SetStringProperty(aCx
, objPath
, "tmpDir", mPaths
->tmpDir
)) {
895 // Configure profileDir only if it is available at this stage
896 if (!mPaths
->profileDir
.IsVoid() &&
897 !SetStringProperty(aCx
, objPath
, "profileDir", mPaths
->profileDir
)) {
901 // Configure localProfileDir only if it is available at this stage
902 if (!mPaths
->localProfileDir
.IsVoid() &&
903 !SetStringProperty(aCx
, objPath
, "localProfileDir",
904 mPaths
->localProfileDir
)) {
908 // sqlite3 is linked from different places depending on the platform
909 nsAutoString libsqlite3
;
911 // On Android, we use the system's libsqlite3
912 libsqlite3
.AppendLiteral(MOZ_DLL_PREFIX
);
913 libsqlite3
.AppendLiteral("sqlite3");
914 libsqlite3
.AppendLiteral(MOZ_DLL_SUFFIX
);
915 #elif defined(XP_WIN)
916 // On Windows, for some reason, this is part of nss3.dll
917 libsqlite3
.AppendLiteral(MOZ_DLL_PREFIX
);
918 libsqlite3
.AppendLiteral("nss3");
919 libsqlite3
.AppendLiteral(MOZ_DLL_SUFFIX
);
921 // On other platforms, we link sqlite3 into libxul
923 #endif // defined(ANDROID) || defined(XP_WIN)
925 if (!SetStringProperty(aCx
, objPath
, "libsqlite3", libsqlite3
)) {
932 NS_IMPL_ISUPPORTS(OSFileConstantsService
, nsIOSFileConstantsService
,
936 already_AddRefed
<OSFileConstantsService
> OSFileConstantsService::GetOrCreate() {
938 MOZ_ASSERT(NS_IsMainThread());
940 RefPtr
<OSFileConstantsService
> service
= new OSFileConstantsService();
941 nsresult rv
= service
->InitOSFileConstants();
942 if (NS_WARN_IF(NS_FAILED(rv
))) {
946 gInstance
= service
.forget();
947 ClearOnShutdown(&gInstance
);
950 RefPtr
<OSFileConstantsService
> copy
= gInstance
;
951 return copy
.forget();
954 OSFileConstantsService::OSFileConstantsService()
955 : mInitialized(false), mUserUmask(0) {
956 MOZ_ASSERT(NS_IsMainThread());
959 OSFileConstantsService::~OSFileConstantsService() {
960 MOZ_ASSERT(NS_IsMainThread());
964 OSFileConstantsService::Init(JSContext
* aCx
) {
965 MOZ_ASSERT(NS_IsMainThread());
967 nsresult rv
= InitOSFileConstants();
972 mozJSComponentLoader
* loader
= mozJSComponentLoader::Get();
973 JS::Rooted
<JSObject
*> targetObj(aCx
);
974 loader
->FindTargetObject(aCx
, &targetObj
);
976 if (!DefineOSFileConstants(aCx
, targetObj
)) {
977 return NS_ERROR_FAILURE
;
983 } // namespace mozilla