Bug 1428258 - Stop using GetNativePath in Telemetry.cpp. r?gfritzsche draft
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Sat, 16 Dec 2017 22:40:32 +0900
changeset 754868 c1d9531629853b9e4b2fc29878d7bbfa2f6e5134
parent 754867 0d9e40201dab89aa5deabc36fc4fc654fffa9af9
child 754869 8de036244133e071643a6f0b7a392b4ace2b6bc0
push id99020
push userVYV03354@nifty.ne.jp
push dateWed, 14 Feb 2018 12:33:05 +0000
reviewersgfritzsche
bugs1428258
milestone60.0a1
Bug 1428258 - Stop using GetNativePath in Telemetry.cpp. r?gfritzsche MozReview-Commit-ID: A8CCpfWAf73
toolkit/components/telemetry/Telemetry.cpp
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 <algorithm>
 
-#include <fstream>
-
 #include <prio.h>
 #include <prproces.h>
 #ifdef XP_LINUX
 #include <time.h>
 #else
 #include <chrono>
 #endif
 
@@ -39,20 +37,22 @@
 #include "mozilla/ModuleUtils.h"
 #include "nsIXPConnect.h"
 #include "mozilla/Services.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/GCAPI.h"
 #include "nsString.h"
 #include "nsITelemetry.h"
-#include "nsIFile.h"
+#include "nsIDirectoryEnumerator.h"
 #include "nsIFileStreams.h"
+#include "nsLocalFile.h"
 #include "nsIMemoryReporter.h"
 #include "nsISeekableStream.h"
+#include "nsISimpleEnumerator.h"
 #include "Telemetry.h"
 #include "TelemetryCommon.h"
 #include "TelemetryHistogram.h"
 #include "TelemetryIOInterposeObserver.h"
 #include "ipc/TelemetryIPCAccumulator.h"
 #include "TelemetryScalar.h"
 #include "TelemetryEvent.h"
 #include "WebrtcTelemetry.h"
@@ -68,19 +68,19 @@
 #endif
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsJSUtils.h"
 #include "nsReadableUtils.h"
 #include "plstr.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "mozilla/BackgroundHangMonitor.h"
+#include "mozilla/FStream.h"
 #include "mozilla/ProcessedStack.h"
 #include "mozilla/Mutex.h"
-#include "mozilla/FileUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/IOInterposer.h"
 #include "mozilla/PoisonIOInterposer.h"
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/HangMonitor.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsProxyRelease.h"
@@ -230,20 +230,25 @@ TelemetryImpl::CollectReports(nsIHandleR
 }
 
 void
 InitHistogramRecordingEnabled()
 {
   TelemetryHistogram::InitHistogramRecordingEnabled();
 }
 
+using PathChar = filesystem::Path::value_type;
+using PathCharPtr = const PathChar*;
+
 static uint32_t
-ReadLastShutdownDuration(const char *filename) {
-  FILE *f = fopen(filename, "r");
-  if (!f) {
+ReadLastShutdownDuration(PathCharPtr filename) {
+  RefPtr<nsLocalFile> file =
+    new nsLocalFile(nsTDependentString<PathChar>(filename));
+  FILE *f;
+  if (NS_FAILED(file->OpenANSIFileDesc("r", &f)) || !f) {
     return 0;
   }
 
   int shutdownTime;
   int r = fscanf(f, "%d\n", &shutdownTime);
   fclose(f);
   if (r != 1) {
     return 0;
@@ -276,29 +281,29 @@ GetFailedProfileLockFile(nsIFile* *aFile
 
   (*aFile)->AppendNative(NS_LITERAL_CSTRING("Telemetry.FailedProfileLocks.txt"));
   return NS_OK;
 }
 
 class nsFetchTelemetryData : public Runnable
 {
 public:
-  nsFetchTelemetryData(const char* aShutdownTimeFilename,
+  nsFetchTelemetryData(PathCharPtr aShutdownTimeFilename,
                        nsIFile* aFailedProfileLockFile,
                        nsIFile* aProfileDir)
     : mozilla::Runnable("nsFetchTelemetryData")
     , mShutdownTimeFilename(aShutdownTimeFilename)
     , mFailedProfileLockFile(aFailedProfileLockFile)
     , mTelemetry(TelemetryImpl::sTelemetry)
     , mProfileDir(aProfileDir)
   {
   }
 
 private:
-  const char* mShutdownTimeFilename;
+  PathCharPtr mShutdownTimeFilename;
   nsCOMPtr<nsIFile> mFailedProfileLockFile;
   RefPtr<TelemetryImpl> mTelemetry;
   nsCOMPtr<nsIFile> mProfileDir;
 
 public:
   void MainThread() {
     mTelemetry->mCachedTelemetryData = true;
     for (unsigned int i = 0, n = mTelemetry->mCallbacks.Count(); i < n; ++i) {
@@ -348,38 +353,34 @@ private:
 
     mFailedProfileLockFile->Remove(false);
     return NS_OK;
   }
 };
 
 static TimeStamp gRecordedShutdownStartTime;
 static bool gAlreadyFreedShutdownTimeFileName = false;
-static char *gRecordedShutdownTimeFileName = nullptr;
+static PathCharPtr gRecordedShutdownTimeFileName = nullptr;
 
-static char *
+static PathCharPtr
 GetShutdownTimeFileName()
 {
   if (gAlreadyFreedShutdownTimeFileName) {
     return nullptr;
   }
 
   if (!gRecordedShutdownTimeFileName) {
     nsCOMPtr<nsIFile> mozFile;
     NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
     if (!mozFile)
       return nullptr;
 
     mozFile->AppendNative(NS_LITERAL_CSTRING("Telemetry.ShutdownTime.txt"));
-    nsAutoCString nativePath;
-    nsresult rv = mozFile->GetNativePath(nativePath);
-    if (!NS_SUCCEEDED(rv))
-      return nullptr;
 
-    gRecordedShutdownTimeFileName = PL_strdup(nativePath.get());
+    gRecordedShutdownTimeFileName = NS_strdup(mozFile->NativePath().get());
   }
 
   return gRecordedShutdownTimeFileName;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetLastShutdownDuration(uint32_t *aResult)
 {
@@ -440,17 +441,17 @@ TelemetryImpl::AsyncFetchTelemetryData(n
     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
   if (!targetThread) {
     mCachedTelemetryData = true;
     aCallback->Complete();
     return NS_OK;
   }
 
   // We have to get the filename from the main thread.
-  const char *shutdownTimeFilename = GetShutdownTimeFileName();
+  PathCharPtr shutdownTimeFilename = GetShutdownTimeFileName();
   if (!shutdownTimeFilename) {
     mCachedTelemetryData = true;
     aCallback->Complete();
     return NS_OK;
   }
 
   nsCOMPtr<nsIFile> profileDir;
   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
@@ -971,19 +972,19 @@ IsValidBreakpadId(const std::string &bre
     }
   }
   return true;
 }
 
 // Read a stack from the given file name. In case of any error, aStack is
 // unchanged.
 static void
-ReadStack(const char *aFileName, Telemetry::ProcessedStack &aStack)
+ReadStack(PathCharPtr aFileName, Telemetry::ProcessedStack &aStack)
 {
-  std::ifstream file(aFileName);
+  IFStream file(aFileName);
 
   size_t numModules;
   file >> numModules;
   if (file.fail()) {
     return;
   }
 
   char newline = file.get();
@@ -1045,49 +1046,42 @@ ReadStack(const char *aFileName, Telemet
   }
 
   aStack = stack;
 }
 
 void
 TelemetryImpl::ReadLateWritesStacks(nsIFile* aProfileDir)
 {
-  nsAutoCString nativePath;
-  nsresult rv = aProfileDir->GetNativePath(nativePath);
-  if (NS_FAILED(rv)) {
+  nsCOMPtr<nsISimpleEnumerator> e;
+  if (NS_FAILED(aProfileDir->GetDirectoryEntries(getter_AddRefs(e)))) {
     return;
   }
-
-  const char *name = nativePath.get();
-  PRDir *dir = PR_OpenDir(name);
-  if (!dir) {
+  nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e));
+  if (!files) {
     return;
   }
 
-  PRDirEntry *ent;
-  const char *prefix = "Telemetry.LateWriteFinal-";
-  unsigned int prefixLen = strlen(prefix);
-  while ((ent = PR_ReadDir(dir, PR_SKIP_NONE))) {
-    if (strncmp(prefix, ent->name, prefixLen) != 0) {
+  NS_NAMED_LITERAL_STRING(prefix, "Telemetry.LateWriteFinal-");
+  nsCOMPtr<nsIFile> file;
+  while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file) {
+    nsAutoString leafName;
+    if (NS_FAILED(file->GetLeafName(leafName)) ||
+        !StringBeginsWith(leafName, prefix)) {
       continue;
     }
 
-    nsAutoCString stackNativePath = nativePath;
-    stackNativePath += XPCOM_FILE_PATH_SEPARATOR;
-    stackNativePath += nsDependentCString(ent->name);
-
     Telemetry::ProcessedStack stack;
-    ReadStack(stackNativePath.get(), stack);
+    ReadStack(file->NativePath().get(), stack);
     if (stack.GetStackSize() != 0) {
       mLateWritesStacks.AddStack(stack);
     }
     // Delete the file so that we don't report it again on the next run.
-    PR_Delete(stackNativePath.get());
+    file->Remove(false);
   }
-  PR_CloseDir(dir);
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetLateWrites(JSContext *cx, JS::MutableHandle<JS::Value> ret)
 {
   // The user must call AsyncReadTelemetryData first. We return an empty list
   // instead of reporting a failure so that the rest of telemetry can uniformly
   // handle the read not being available yet.
@@ -1873,53 +1867,56 @@ RecordShutdownStartTimeStamp() {
   GetShutdownTimeFileName();
 }
 
 void
 RecordShutdownEndTimeStamp() {
   if (!gRecordedShutdownTimeFileName || gAlreadyFreedShutdownTimeFileName)
     return;
 
-  nsCString name(gRecordedShutdownTimeFileName);
-  PL_strfree(gRecordedShutdownTimeFileName);
+  PathString name(gRecordedShutdownTimeFileName);
+  free(const_cast<PathChar*>(gRecordedShutdownTimeFileName));
   gRecordedShutdownTimeFileName = nullptr;
   gAlreadyFreedShutdownTimeFileName = true;
 
   if (gRecordedShutdownStartTime.IsNull()) {
     // If |CanRecordExtended()| is true before |AsyncFetchTelemetryData| is called and
     // then disabled before shutdown, |RecordShutdownStartTimeStamp| will bail out and
     // we will end up with a null |gRecordedShutdownStartTime| here. This can happen
     // during tests.
     return;
   }
 
-  nsCString tmpName = name;
-  tmpName += ".tmp";
-  FILE *f = fopen(tmpName.get(), "w");
-  if (!f)
+  nsTAutoString<PathChar> tmpName(name);
+  tmpName.AppendLiteral(".tmp");
+  RefPtr<nsLocalFile> tmpFile = new nsLocalFile(tmpName);
+  FILE *f;
+  if (NS_FAILED(tmpFile->OpenANSIFileDesc("w", &f)) || !f)
     return;
   // On a normal release build this should be called just before
   // calling _exit, but on a debug build or when the user forces a full
   // shutdown this is called as late as possible, so we have to
   // white list this write as write poisoning will be enabled.
   MozillaRegisterDebugFILE(f);
 
   TimeStamp now = TimeStamp::Now();
   MOZ_ASSERT(now >= gRecordedShutdownStartTime);
   TimeDuration diff = now - gRecordedShutdownStartTime;
   uint32_t diff2 = diff.ToMilliseconds();
   int written = fprintf(f, "%d\n", diff2);
   MozillaUnRegisterDebugFILE(f);
   int rv = fclose(f);
   if (written < 0 || rv != 0) {
-    PR_Delete(tmpName.get());
+    tmpFile->Remove(false);
     return;
   }
-  PR_Delete(name.get());
-  PR_Rename(tmpName.get(), name.get());
+  RefPtr<nsLocalFile> file = new nsLocalFile(name);
+  nsAutoString leafName;
+  file->GetLeafName(leafName);
+  tmpFile->RenameTo(nullptr, leafName);
 }
 
 } // namespace mozilla
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //