Bug 1554951 [wpt PR 17043] - wake-lock: Fix invalid types test in wakelock-type.https...
[gecko.git] / dom / system / OSFileConstants.cpp
blob4e2c96fa7755d81bf1c95adbbfeedfc0f5b9fcd8
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"
9 #include "fcntl.h"
10 #include "errno.h"
12 #include "prsystem.h"
14 #if defined(XP_UNIX)
15 # include "unistd.h"
16 # include "dirent.h"
17 # include "poll.h"
18 # include "sys/stat.h"
19 # if defined(XP_LINUX)
20 # include <sys/vfs.h>
21 # define statvfs statfs
22 # define f_frsize f_bsize
23 # else
24 # include "sys/statvfs.h"
25 # endif // defined(XP_LINUX)
26 # if !defined(ANDROID)
27 # include "sys/wait.h"
28 # include <spawn.h>
29 # endif // !defined(ANDROID)
30 #endif // defined(XP_UNIX)
32 #if defined(XP_LINUX)
33 # include <linux/fadvise.h>
34 #endif // defined(XP_LINUX)
36 #if defined(XP_MACOSX)
37 # include "copyfile.h"
38 #endif // defined(XP_MACOSX)
40 #if defined(XP_WIN)
41 # include <windows.h>
42 # include <accctrl.h>
44 # ifndef PATH_MAX
45 # define PATH_MAX MAX_PATH
46 # endif
48 #endif // defined(XP_WIN)
50 #include "jsapi.h"
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"
64 #include "nsString.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__) || \
80 defined(__OpenBSD__)
81 # define __dd_fd dd_fd
82 #endif
84 /**
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.
89 namespace mozilla {
91 namespace {
93 StaticRefPtr<OSFileConstantsService> gInstance;
95 } // anonymous namespace
97 struct OSFileConstantsService::Paths {
98 /**
99 * The name of the directory holding all the libraries (libxpcom, libnss,
100 * etc.)
102 nsString libDir;
103 nsString tmpDir;
104 nsString profileDir;
105 nsString localProfileDir;
107 Paths() {
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) {
126 return rv;
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.
142 NS_IMETHODIMP
143 OSFileConstantsService::Observe(nsISupports*, const char* aTopic,
144 const char16_t*) {
145 if (!mInitialized) {
146 // Initialization has not taken place, something is wrong,
147 // don't make things worse.
148 return NS_OK;
151 nsresult rv =
152 GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, mPaths->profileDir);
153 if (NS_FAILED(rv)) {
154 return rv;
156 rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR,
157 mPaths->localProfileDir);
158 if (NS_FAILED(rv)) {
159 return rv;
162 return NS_OK;
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());
171 if (mInitialized) {
172 return NS_OK;
175 UniquePtr<Paths> paths(new Paths);
177 // Initialize paths->libDir
178 nsCOMPtr<nsIFile> file;
179 nsresult rv =
180 NS_GetSpecialDirectory(NS_XPCOM_LIBRARY_FILE, getter_AddRefs(file));
181 if (NS_FAILED(rv)) {
182 return rv;
185 nsCOMPtr<nsIFile> libDir;
186 rv = file->GetParent(getter_AddRefs(libDir));
187 if (NS_FAILED(rv)) {
188 return rv;
191 rv = libDir->GetPath(paths->libDir);
192 if (NS_FAILED(rv)) {
193 return rv;
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
206 // become available.
207 if (NS_FAILED(rv)) {
208 nsCOMPtr<nsIObserverService> obsService =
209 do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
210 if (NS_FAILED(rv)) {
211 return rv;
213 rv = obsService->AddObserver(this, "profile-do-change", false);
214 if (NS_FAILED(rv)) {
215 return rv;
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
225 // non-Unix systems.
226 // nsSystemInfo::gUserUmask is initialized by NS_InitXPCOM so we don't need
227 // to initialize the service.
228 mUserUmask = nsSystemInfo::gUserUmask;
230 mInitialized = true;
231 return NS_OK;
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
259 #define PROP_END \
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),
314 #if defined(O_RSYNC)
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)
323 #if defined(O_SYNC)
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)
347 // access
348 #if defined(F_OK)
349 INT_CONSTANT(F_OK),
350 INT_CONSTANT(R_OK),
351 INT_CONSTANT(W_OK),
352 INT_CONSTANT(X_OK),
353 #endif // defined(F_OK)
355 // modes
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),
369 // seek
370 INT_CONSTANT(SEEK_CUR),
371 INT_CONSTANT(SEEK_END),
372 INT_CONSTANT(SEEK_SET),
374 #if defined(XP_UNIX)
375 // poll
376 INT_CONSTANT(POLLERR),
377 INT_CONSTANT(POLLHUP),
378 INT_CONSTANT(POLLIN),
379 INT_CONSTANT(POLLNVAL),
380 INT_CONSTANT(POLLOUT),
382 // wait
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),
394 // flock type values
395 INT_CONSTANT(F_RDLCK),
396 INT_CONSTANT(F_WRLCK),
397 INT_CONSTANT(F_UNLCK),
399 // splice
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)
413 // copyfile
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)
423 // error values
424 INT_CONSTANT(EACCES),
425 INT_CONSTANT(EAGAIN),
426 INT_CONSTANT(EBADF),
427 INT_CONSTANT(EEXIST),
428 INT_CONSTANT(EFAULT),
429 INT_CONSTANT(EFBIG),
430 INT_CONSTANT(EINVAL),
431 INT_CONSTANT(EINTR),
432 INT_CONSTANT(EIO),
433 INT_CONSTANT(EISDIR),
434 #if defined(ELOOP) // not defined with VC9
435 INT_CONSTANT(ELOOP),
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),
444 INT_CONSTANT(ENXIO),
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)
451 INT_CONSTANT(EPERM),
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)
459 INT_CONSTANT(EXDEV),
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)
473 #if defined(S_IFIFO)
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.
495 #if defined(XP_UNIX)
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|.
518 // Size
519 {"OSFILE_SIZEOF_DIRENT", JS::Int32Value(sizeof(dirent))},
521 // Defining |flock|.
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
553 // except mingw32.
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
560 # if defined(dirfd)
561 {"OSFILE_SIZEOF_DIR", JS::Int32Value(sizeof(DIR))},
563 {"OSFILE_OFFSETOF_DIR_DD_FD", JS::Int32Value(offsetof(DIR, __dd_fd))},
564 # endif
566 // Defining |stat|
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))},
586 # else
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)
629 PROP_END};
631 #if defined(XP_WIN)
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))},
680 // CreateFile flags
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),
691 // File attributes
692 INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
694 // MoveFile flags
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),
706 // Errors
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),
719 PROP_END};
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)) {
733 return nullptr;
735 if (!val.isUndefined()) {
736 if (val.isObject()) {
737 return &val.toObject();
740 JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr,
741 JSMSG_UNEXPECTED_TYPE, aProperty,
742 "not an object");
743 return nullptr;
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()) {
756 return true;
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
768 * all its constants.
770 bool OSFileConstantsService::DefineOSFileConstants(
771 JSContext* aCx, JS::Handle<JSObject*> aGlobal) {
772 if (!mInitialized) {
773 JS_ReportErrorNumberASCII(aCx, js::GetErrorMessage, nullptr,
774 JSMSG_CANT_OPEN, "OSFileConstants",
775 "initialization has failed");
776 return false;
779 JS::Rooted<JSObject*> objOS(aCx);
780 if (!(objOS = GetOrCreateObjectProperty(aCx, aGlobal, "OS"))) {
781 return false;
783 JS::Rooted<JSObject*> objConstants(aCx);
784 if (!(objConstants = GetOrCreateObjectProperty(aCx, objOS, "Constants"))) {
785 return false;
788 // Build OS.Constants.libc
790 JS::Rooted<JSObject*> objLibc(aCx);
791 if (!(objLibc = GetOrCreateObjectProperty(aCx, objConstants, "libc"))) {
792 return false;
794 if (!dom::DefineConstants(aCx, objLibc, gLibcProperties)) {
795 return false;
798 #if defined(XP_WIN)
799 // Build OS.Constants.Win
801 JS::Rooted<JSObject*> objWin(aCx);
802 if (!(objWin = GetOrCreateObjectProperty(aCx, objConstants, "Win"))) {
803 return false;
805 if (!dom::DefineConstants(aCx, objWin, gWinProperties)) {
806 return false;
808 #endif // defined(XP_WIN)
810 // Build OS.Constants.Sys
812 JS::Rooted<JSObject*> objSys(aCx);
813 if (!(objSys = GetOrCreateObjectProperty(aCx, objConstants, "Sys"))) {
814 return false;
817 nsCOMPtr<nsIXULRuntime> runtime =
818 do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
819 if (runtime) {
820 nsAutoCString os;
821 DebugOnly<nsresult> rv = runtime->GetOS(os);
822 MOZ_ASSERT(NS_SUCCEEDED(rv));
824 JSString* strVersion = JS_NewStringCopyZ(aCx, os.get());
825 if (!strVersion) {
826 return false;
829 JS::Rooted<JS::Value> valVersion(aCx, JS::StringValue(strVersion));
830 if (!JS_SetProperty(aCx, objSys, "Name", valVersion)) {
831 return false;
835 #if defined(DEBUG)
836 JS::Rooted<JS::Value> valDebug(aCx, JS::TrueValue());
837 if (!JS_SetProperty(aCx, objSys, "DEBUG", valDebug)) {
838 return false;
840 #endif
842 #if defined(HAVE_64BIT_BUILD)
843 JS::Rooted<JS::Value> valBits(aCx, JS::Int32Value(64));
844 #else
845 JS::Rooted<JS::Value> valBits(aCx, JS::Int32Value(32));
846 #endif // defined (HAVE_64BIT_BUILD)
847 if (!JS_SetProperty(aCx, objSys, "bits", valBits)) {
848 return false;
851 if (!JS_DefineProperty(
852 aCx, objSys, "umask", mUserUmask,
853 JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
854 return false;
857 // Build OS.Constants.Path
859 JS::Rooted<JSObject*> objPath(aCx);
860 if (!(objPath = GetOrCreateObjectProperty(aCx, objConstants, "Path"))) {
861 return false;
864 // Locate libxul
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.
871 nsAutoString libxul;
872 libxul.Append(mPaths->libDir);
873 libxul.AppendLiteral("/XUL");
874 #else
875 // On other platforms, libxul is a library "xul" with regular
876 // library prefix/suffix.
877 nsAutoString libxul;
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)) {
884 return false;
887 if (!SetStringProperty(aCx, objPath, "libDir", mPaths->libDir)) {
888 return false;
891 if (!SetStringProperty(aCx, objPath, "tmpDir", mPaths->tmpDir)) {
892 return false;
895 // Configure profileDir only if it is available at this stage
896 if (!mPaths->profileDir.IsVoid() &&
897 !SetStringProperty(aCx, objPath, "profileDir", mPaths->profileDir)) {
898 return false;
901 // Configure localProfileDir only if it is available at this stage
902 if (!mPaths->localProfileDir.IsVoid() &&
903 !SetStringProperty(aCx, objPath, "localProfileDir",
904 mPaths->localProfileDir)) {
905 return false;
908 // sqlite3 is linked from different places depending on the platform
909 nsAutoString libsqlite3;
910 #if defined(ANDROID)
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);
920 #else
921 // On other platforms, we link sqlite3 into libxul
922 libsqlite3 = libxul;
923 #endif // defined(ANDROID) || defined(XP_WIN)
925 if (!SetStringProperty(aCx, objPath, "libsqlite3", libsqlite3)) {
926 return false;
929 return true;
932 NS_IMPL_ISUPPORTS(OSFileConstantsService, nsIOSFileConstantsService,
933 nsIObserver)
935 /* static */
936 already_AddRefed<OSFileConstantsService> OSFileConstantsService::GetOrCreate() {
937 if (!gInstance) {
938 MOZ_ASSERT(NS_IsMainThread());
940 RefPtr<OSFileConstantsService> service = new OSFileConstantsService();
941 nsresult rv = service->InitOSFileConstants();
942 if (NS_WARN_IF(NS_FAILED(rv))) {
943 return nullptr;
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());
963 NS_IMETHODIMP
964 OSFileConstantsService::Init(JSContext* aCx) {
965 MOZ_ASSERT(NS_IsMainThread());
967 nsresult rv = InitOSFileConstants();
968 if (NS_FAILED(rv)) {
969 return rv;
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;
980 return NS_OK;
983 } // namespace mozilla