Bug 1001842, part 2: make umask available via OS.Constants. r=khuey sr=bz
authorZack Weinberg <zackw@panix.com>
Sat, 26 Apr 2014 10:56:58 -0400
changeset 180870 ea4471fb806febd3454ccd076ca7ef4cddf55a72
parent 180869 5fe8306c6409dfe6cd8151f06ae27ab1e29dd552
child 180871 e248f673c2f222e9a3aeafc5673e8bd7000e6db1
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewerskhuey, bz
bugs1001842
milestone31.0a1
Bug 1001842, part 2: make umask available via OS.Constants. r=khuey sr=bz
dom/system/OSFileConstants.cpp
dom/system/tests/test_constants.xul
dom/system/tests/worker_constants.js
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -41,16 +41,17 @@
 
 // Used to provide information on the OS
 
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIXULRuntime.h"
+#include "nsIPropertyBag2.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsXULAppAPI.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "mozJSComponentLoader.h"
@@ -158,16 +159,22 @@ struct Paths {
   }
 };
 
 /**
  * System directories.
  */
 Paths* gPaths = nullptr;
 
+/**
+ * (Unix) the umask, which goes in OS.Constants.Sys but
+ * can only be looked up (via the system-info service)
+ * on the main thread.
+ */
+uint32_t gUserUmask = 0;
 }
 
 /**
  * Return the path to one of the special directories.
  *
  * @param aKey The key to the special directory (e.g. "TmpD", "ProfD", ...)
  * @param aOutPath The path to the special directory. In case of error,
  * the string is set to void.
@@ -292,16 +299,29 @@ nsresult InitOSFileConstants()
 #endif // defined(XP_WIN)
 
 #if defined(XP_MACOSX)
   GetPathToSpecialDir(NS_MAC_USER_LIB_DIR, paths->macUserLibDir);
   GetPathToSpecialDir(NS_OSX_LOCAL_APPLICATIONS_DIR, paths->macLocalApplicationsDir);
 #endif // defined(XP_MACOSX)
 
   gPaths = paths.forget();
+
+  // Get the umask from the system-info service.
+  // The property will always be present, but it will be zero on
+  // non-Unix systems.
+  nsCOMPtr<nsIPropertyBag2> infoService =
+    do_GetService("@mozilla.org/system-info;1");
+  MOZ_ASSERT(infoService, "Could not access the system information service");
+  rv = infoService->GetPropertyAsUint32(NS_LITERAL_STRING("umask"),
+                                        &gUserUmask);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
   return NS_OK;
 }
 
 /**
  * Perform the cleaning up that can only be executed on the main thread.
  */
 void CleanupOSFileConstants()
 {
@@ -848,16 +868,24 @@ bool DefineOSFileConstants(JSContext *cx
 
 #if defined(DEBUG)
   JS::Rooted<JS::Value> valDebug(cx, JSVAL_TRUE);
   if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug)) {
     return false;
   }
 #endif
 
+  dom::ConstantSpec umask_cs[] = {
+    { "umask", UINT_TO_JSVAL(gUserUmask) },
+    PROP_END
+  };
+  if (!dom::DefineConstants(cx, objSys, umask_cs)) {
+      return false;
+  }
+
   // Build OS.Constants.Path
 
   JS::Rooted<JSObject*> objPath(cx);
   if (!(objPath = GetOrCreateObjectProperty(cx, objConstants, "Path"))) {
     return false;
   }
 
   // Locate libxul
--- a/dom/system/tests/test_constants.xul
+++ b/dom/system/tests/test_constants.xul
@@ -59,32 +59,45 @@ function test_Win() {
   }
 }
 
 // Test that OS.Constants.Sys.DEBUG is set properly on main thread
 function test_debugBuildMainThread(isDebugBuild) {
   is(isDebugBuild, !!OS.Constants.Sys.DEBUG, "OS.Constants.Sys.DEBUG is set properly on main thread");
 }
 
+// Test that OS.Constants.Sys.umask is set properly on main thread
+function test_umaskMainThread(umask) {
+  is(umask, OS.Constants.Sys.umask,
+     "OS.Constants.Sys.umask is set properly on main thread: " +
+     ("0000"+umask.toString(8)).slice(-4));
+}
+
+
 function test() {
   ok(true, "test_constants.xul: Starting test");
 
   // Test 1: Load libxul from main thread
   Components.classes["@mozilla.org/net/osfileconstantsservice;1"].
     getService(Components.interfaces.nsIOSFileConstantsService).
     init();
   Components.utils.import("resource://gre/modules/ctypes.jsm");
   test_xul();
   test_libc();
   test_Win();
 
   let isDebugBuild = Components.classes["@mozilla.org/xpcom/debug;1"]
                             .getService(Components.interfaces.nsIDebug2).isDebugBuild;
   test_debugBuildMainThread(isDebugBuild);
 
+  let umask = Components.classes["@mozilla.org/system-info;1"].
+    getService(Components.interfaces.nsIPropertyBag2).
+    getProperty("umask");
+  test_umaskMainThread(umask);
+
   // Test 2: Load libxul from chrome thread
   worker = new ChromeWorker("worker_constants.js");
   SimpleTest.waitForExplicitFinish();
   ok(true, "test_constants.xul: Chrome worker created");
   worker.onerror = function onerror(error) {
     error.preventDefault();
     ok(false, "error " + error);
   }
@@ -103,18 +116,22 @@ function test() {
       SimpleTest.finish();
       return;
     default:
       SimpleTest.ok(false, "test_constants.xul: wrong message " + JSON.stringify(msg.data));
       return;
     }
   };
 
-  // nsIDebug2 is inaccessible from ChromeWorker. We need to pass isDebugBuild to the worker
-  worker.postMessage(isDebugBuild);
+  // pass expected values that are unavailable off-main-thread
+  // to the worker
+  worker.postMessage({
+    isDebugBuild: isDebugBuild,
+    umask: umask
+  });
   ok(true, "test_constants.xul: Test in progress");
 };
 ]]>
   </script>
 
   <body xmlns="http://www.w3.org/1999/xhtml">
     <p id="display"></p>
     <div id="content" style="display:none;"></div>
--- a/dom/system/tests/worker_constants.js
+++ b/dom/system/tests/worker_constants.js
@@ -8,21 +8,22 @@ function log(text) {
 function send(message) {
   self.postMessage(message);
 }
 
 self.onmessage = function(msg) {
   self.onmessage = function(msg) {
     log("ignored message "+JSON.stringify(msg.data));
   };
-  let isDebugBuild = msg.data;
+  let { isDebugBuild, umask } = msg.data;
   try {
     test_name();
     test_xul();
     test_debugBuildWorkerThread(isDebugBuild);
+    test_umaskWorkerThread(umask);
   } catch (x) {
     log("Catching error: " + x);
     log("Stack: " + x.stack);
     log("Source: " + x.toSource());
     ok(false, x.toString() + "\n" + x.stack);
   }
   finish();
 };
@@ -46,16 +47,23 @@ function test_name() {
   isnot(null, OS.Constants.Sys.Name, "OS.Constants.Sys.Name is defined");
 }
 
 // Test that OS.Constants.Sys.DEBUG is set properly in ChromeWorker thread
 function test_debugBuildWorkerThread(isDebugBuild) {
   is(isDebugBuild, !!OS.Constants.Sys.DEBUG, "OS.Constants.Sys.DEBUG is set properly on worker thread");
 }
 
+// Test that OS.Constants.Sys.umask is set properly in ChromeWorker thread
+function test_umaskWorkerThread(umask) {
+  is(umask, OS.Constants.Sys.umask,
+     "OS.Constants.Sys.umask is set properly on worker thread: " +
+     ("0000"+umask.toString(8)).slice(-4));
+}
+
 // Test that OS.Constants.Path.libxul lets us open libxul
 function test_xul() {
   let lib;
   isnot(null, OS.Constants.Path.libxul, "libxul is defined");
   try {
     lib = ctypes.open(OS.Constants.Path.libxul);
     lib.declare("DumpJSStack", ctypes.default_abi, ctypes.void_t);
   } catch (x) {