Bug 1361500 - Don't call _tzset on startup r?ehsan,arthuredelstein draft
authorDoug Thayer <dothayer@mozilla.com>
Fri, 23 Jun 2017 12:56:03 -0400
changeset 605037 b6586918650b4cec02277445710e5c97c7892ad6
parent 604236 97a8f71407cc40b39d86d71a6907a5505d3eb867
child 605038 5b8c0d593b1e04538fce16a62a647d103158b42e
push id67278
push userbmo:dothayer@mozilla.com
push dateThu, 06 Jul 2017 22:48:19 +0000
reviewersehsan, arthuredelstein
bugs1361500
milestone56.0a1
Bug 1361500 - Don't call _tzset on startup r?ehsan,arthuredelstein The reason we call _tzset inside DateTime.cpp is to allow the privacy.resistFingerprinting pref to mask our timezone by setting the TZ environment variable. Without _tzset, the changes to the environment variable won't actually change anything. However, if a process is started with the TZ environment variable set to something (like "UTC"), then those changes will be active in that process. Since we're only masking timezone to JS running in the content process, and since those content processes will be started by the parent process which has already set its TZ to UTC, and will copy that variable to its children, we only need to call _tzset() when the pref changes, and only in the content process, provided we are on e10s. MozReview-Commit-ID: CPU99BGDUPj
js/src/vm/DateTime.cpp
toolkit/components/resistfingerprinting/nsRFPService.cpp
--- a/js/src/vm/DateTime.cpp
+++ b/js/src/vm/DateTime.cpp
@@ -67,23 +67,16 @@ ComputeUTCTime(time_t t, struct tm* ptm)
  */
 static int32_t
 UTCToLocalStandardOffsetSeconds()
 {
     using js::SecondsPerDay;
     using js::SecondsPerHour;
     using js::SecondsPerMinute;
 
-#if defined(XP_WIN)
-    // Windows doesn't follow POSIX: updates to the TZ environment variable are
-    // not reflected immediately on that platform as they are on other systems
-    // without this call.
-    _tzset();
-#endif
-
     // Get the current time.
     time_t currentMaybeWithDST = time(nullptr);
     if (currentMaybeWithDST == time_t(-1))
         return 0;
 
     // Break down the current time into its (locally-valued, maybe with DST)
     // components.
     struct tm local;
@@ -175,23 +168,16 @@ js::DateTimeInfo::DateTimeInfo()
 }
 
 int64_t
 js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds)
 {
     MOZ_ASSERT(utcSeconds >= 0);
     MOZ_ASSERT(utcSeconds <= MaxUnixTimeT);
 
-#if defined(XP_WIN)
-    // Windows does not follow POSIX. Updates to the TZ environment variable
-    // are not reflected immediately on that platform as they are on UNIX
-    // systems without this call.
-    _tzset();
-#endif
-
     struct tm tm;
     if (!ComputeLocalTime(static_cast<time_t>(utcSeconds), &tm))
         return 0;
 
     int32_t dayoff = int32_t((utcSeconds + utcToLocalStandardOffsetSeconds) % SecondsPerDay);
     int32_t tmoff = tm.tm_sec + (tm.tm_min * SecondsPerMinute) + (tm.tm_hour * SecondsPerHour);
 
     int32_t diff = tmoff - dayoff;
--- a/toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -1,23 +1,26 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsRFPService.h"
 
+#include <time.h>
+
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
+#include "nsXULAppAPI.h"
 
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsJSUtils.h"
 
 #include "prenv.h"
 
@@ -115,16 +118,29 @@ nsRFPService::Init()
   const char* tzValue = PR_GetEnv("TZ");
   if (tzValue) {
     mInitialTZValue = nsCString(tzValue);
   }
 
   // Call UpdatePref() here to cache the value of 'privacy.resistFingerprinting'
   // and set the timezone.
   UpdatePref();
+
+#if defined(XP_WIN)
+  // If we're e10s, then we don't need to run this, since the child process will
+  // simply inherit the environment variable from the parent process, in which
+  // case it's unnecessary to call _tzset().
+  if (XRE_IsParentProcess() && !XRE_IsE10sParentProcess()) {
+    // Windows does not follow POSIX. Updates to the TZ environment variable
+    // are not reflected immediately on that platform as they are on UNIX
+    // systems without this call.
+    _tzset();
+  }
+#endif
+
   return rv;
 }
 
 void
 nsRFPService::UpdatePref()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sPrivacyResistFingerprinting = Preferences::GetBool(RESIST_FINGERPRINTING_PREF);
@@ -147,18 +163,16 @@ nsRFPService::UpdatePref()
 #else
       // For Windows, we reset the TZ to an empty string. This will make Windows to use
       // its system timezone.
       PR_SetEnv("TZ=");
 #endif
     }
   }
 
-  // We don't have to call _tzset() here for Windows since the following
-  // function nsJSUtils::ResetTimeZone() will call it for us.
   nsJSUtils::ResetTimeZone();
 }
 
 void
 nsRFPService::StartShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -179,16 +193,25 @@ NS_IMETHODIMP
 nsRFPService::Observe(nsISupports* aObject, const char* aTopic,
                       const char16_t* aMessage)
 {
   if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
     NS_ConvertUTF16toUTF8 pref(aMessage);
 
     if (pref.EqualsLiteral(RESIST_FINGERPRINTING_PREF)) {
       UpdatePref();
+
+#if defined(XP_WIN)
+      if (!XRE_IsE10sParentProcess()) {
+        // Windows does not follow POSIX. Updates to the TZ environment variable
+        // are not reflected immediately on that platform as they are on UNIX
+        // systems without this call.
+        _tzset();
+      }
+#endif
     }
   }
 
   if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
     StartShutdown();
   }
 
   return NS_OK;