xpcom/base/nsStatusReporterManager.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsStatusReporterManager.h"
     8 #include "nsCOMPtr.h"
     9 #include "nsDirectoryServiceDefs.h"
    10 #include "nsArrayEnumerator.h"
    11 #include "nsISimpleEnumerator.h"
    12 #include "nsIFile.h"
    13 #include "nsDumpUtils.h"
    14 #include "nsIFileStreams.h"
    15 #include "nsPrintfCString.h"
    17 #ifdef XP_WIN
    18 #include <process.h>
    19 #define getpid _getpid
    20 #else
    21 #include <unistd.h>
    22 #endif
    24 #ifdef XP_UNIX
    25 #define DO_STATUS_REPORT 1
    26 #endif
    28 #ifdef DO_STATUS_REPORT // {
    29 namespace {
    31 class DumpStatusInfoToTempDirRunnable : public nsRunnable
    32 {
    33 public:
    34   DumpStatusInfoToTempDirRunnable()
    35   {}
    37   NS_IMETHOD Run()
    38   {
    39     nsCOMPtr<nsIStatusReporterManager> mgr =
    40       do_GetService("@mozilla.org/status-reporter-manager;1");
    41     mgr->DumpReports();
    42     return NS_OK;
    43   }
    44 };
    46 void doStatusReport(const nsCString& inputStr)
    47 {
    48   LOG("FifoWatcher(%s) dispatching status report runnable.", inputStr.get());
    49   nsRefPtr<DumpStatusInfoToTempDirRunnable> runnable =
    50     new DumpStatusInfoToTempDirRunnable();
    51   NS_DispatchToMainThread(runnable);
    52 }
    54 } //anonymous namespace
    55 #endif // DO_STATUS_REPORT }
    57 static bool gStatusReportProgress = 0;
    58 static int gNumReporters = 0;
    60 nsresult getStatus(nsACString& desc)
    61 {
    62   if(!gStatusReportProgress)
    63     desc.AssignLiteral("Init");
    64   else {
    65     desc.AssignLiteral("Running:\nThere are ");
    66     desc.AppendInt(gNumReporters);
    67     desc.AppendLiteral(" reporters");
    68   }
    69   return NS_OK;
    70 }
    72 NS_STATUS_REPORTER_IMPLEMENT(StatusReporter, "StatusReporter State", getStatus)
    74 #define DUMP(o, s) \
    75     do { \
    76         const char* s2 = (s); \
    77         uint32_t dummy; \
    78         nsresult rv = (o)->Write((s2), strlen(s2), &dummy); \
    79         if (NS_WARN_IF(NS_FAILED(rv))) \
    80           return rv; \
    81     } while (0)
    83 static nsresult
    84 DumpReport(nsIFileOutputStream* aOStream, const nsCString& aProcess,
    85            const nsCString& aName, const nsCString& aDescription)
    86 {
    87   int pid;
    88   if (aProcess.IsEmpty()) {
    89     pid = getpid();
    90     nsPrintfCString pidStr("PID %u", pid);
    91     DUMP(aOStream, "\n    {\"Process\": \"");
    92     DUMP(aOStream, pidStr.get());
    93   } else {
    94     pid = 0;
    95     DUMP(aOStream, "\n    {\"Unknown Process\": \"");
    96   }
    98   DUMP(aOStream, "\", \"Reporter name\": \"");
    99   DUMP(aOStream, aName.get());
   101   DUMP(aOStream, "\", \"Status Description\": \"");
   102   DUMP(aOStream, aDescription.get());
   103   DUMP(aOStream, "\"}");
   105   return NS_OK;
   106 }
   108 /**
   109  ** nsStatusReporterManager implementation
   110  **/
   112 NS_IMPL_ISUPPORTS(nsStatusReporterManager, nsIStatusReporterManager)
   114 nsStatusReporterManager::nsStatusReporterManager()
   115 {
   116 }
   118 nsStatusReporterManager::~nsStatusReporterManager()
   119 {
   120 }
   122 NS_IMETHODIMP
   123 nsStatusReporterManager::Init()
   124 {
   125   RegisterReporter(new NS_STATUS_REPORTER_NAME(StatusReporter));
   126   gStatusReportProgress = 1;
   128 #ifdef DO_STATUS_REPORT
   129   if (FifoWatcher::MaybeCreate()) {
   130     FifoWatcher* fw = FifoWatcher::GetSingleton();
   131     fw->RegisterCallback(NS_LITERAL_CSTRING("status report"),doStatusReport);
   132   }
   133 #endif
   135   return NS_OK;
   136 }
   138 NS_IMETHODIMP
   139 nsStatusReporterManager::DumpReports()
   140 {
   141   static unsigned number = 1;
   142   nsresult rv;
   144   nsCString filename("status-reports-");
   145   filename.AppendInt(getpid());
   146   filename.AppendLiteral("-");
   147   filename.AppendInt(number++);
   148   filename.AppendLiteral(".json");
   150   // Open a file in NS_OS_TEMP_DIR for writing.
   151   // The file is initialized as "incomplete-status-reports-pid-number.json" in the
   152   // begining, it will be rename as "status-reports-pid-number.json" in the end.
   153   nsCOMPtr<nsIFile> tmpFile;
   154   rv = nsDumpUtils::OpenTempFile(NS_LITERAL_CSTRING("incomplete-") +
   155                     filename,
   156                     getter_AddRefs(tmpFile),
   157                     NS_LITERAL_CSTRING("status-reports"));
   158   if (NS_WARN_IF(NS_FAILED(rv)))
   159     return rv;
   161   nsCOMPtr<nsIFileOutputStream> ostream =
   162     do_CreateInstance("@mozilla.org/network/file-output-stream;1");
   163   rv = ostream->Init(tmpFile, -1, -1, 0);
   164   if (NS_WARN_IF(NS_FAILED(rv)))
   165     return rv;
   167   //Write the reports to the file
   169   DUMP(ostream, "  [Sysdump Report Start]: ");
   171   nsCOMPtr<nsISimpleEnumerator> e;
   172   bool more;
   173   EnumerateReporters(getter_AddRefs(e));
   174   while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
   175     nsCOMPtr<nsISupports> supports;
   176     e->GetNext(getter_AddRefs(supports));
   177     nsCOMPtr<nsIStatusReporter> r = do_QueryInterface(supports);
   179     nsCString process;
   180     rv = r->GetProcess(process);
   181     if (NS_WARN_IF(NS_FAILED(rv)))
   182       return rv;
   184     nsCString name;
   185     rv = r->GetName(name);
   186     if (NS_WARN_IF(NS_FAILED(rv)))
   187       return rv;
   189     nsCString description;
   190     rv = r->GetDescription(description);
   191     if (NS_WARN_IF(NS_FAILED(rv)))
   192       return rv;
   194     rv = DumpReport(ostream, process, name, description);
   195     if (NS_WARN_IF(NS_FAILED(rv)))
   196       return rv;
   197   }
   199   DUMP(ostream, "\n  [Sysdump Report End] ");
   201   rv = ostream->Close();
   202   if (NS_WARN_IF(NS_FAILED(rv)))
   203     return rv;
   205   // Rename the status reports file
   206   nsCOMPtr<nsIFile> srFinalFile;
   207   rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(srFinalFile));
   208   if (NS_WARN_IF(NS_FAILED(rv)))
   209     return rv;
   211 #ifdef ANDROID
   212   rv = srFinalFile->AppendNative(NS_LITERAL_CSTRING("status-reports"));
   213   if (NS_WARN_IF(NS_FAILED(rv)))
   214     return rv;
   215 #endif
   217   rv = srFinalFile->AppendNative(filename);
   218   if (NS_WARN_IF(NS_FAILED(rv)))
   219     return rv;
   221   rv = srFinalFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
   222   if (NS_WARN_IF(NS_FAILED(rv)))
   223     return rv;
   225   nsAutoString srActualFinalFilename;
   226   rv = srFinalFile->GetLeafName(srActualFinalFilename);
   227   if (NS_WARN_IF(NS_FAILED(rv)))
   228     return rv;
   230   rv = tmpFile->MoveTo(/* directory */ nullptr, srActualFinalFilename);
   232   if (NS_WARN_IF(NS_FAILED(rv)))
   233     return rv;
   235   return NS_OK;
   236 }
   238 NS_IMETHODIMP
   239 nsStatusReporterManager::EnumerateReporters(nsISimpleEnumerator** result)
   240 {
   241   return NS_NewArrayEnumerator(result, mReporters);
   242 }
   244 NS_IMETHODIMP
   245 nsStatusReporterManager::RegisterReporter(nsIStatusReporter* reporter)
   246 {
   247   if (mReporters.IndexOf(reporter) != -1)
   248     return NS_ERROR_FAILURE;
   250   mReporters.AppendObject(reporter);
   251   gNumReporters++;
   252   return NS_OK;
   253 }
   255 NS_IMETHODIMP
   256 nsStatusReporterManager::UnregisterReporter(nsIStatusReporter* reporter)
   257 {
   258   if (!mReporters.RemoveObject(reporter))
   259     return NS_ERROR_FAILURE;
   260   gNumReporters--;
   261   return NS_OK;
   262 }
   264 nsresult
   265 NS_RegisterStatusReporter (nsIStatusReporter* reporter)
   266 {
   267   nsCOMPtr<nsIStatusReporterManager> mgr =
   268     do_GetService("@mozilla.org/status-reporter-manager;1");
   269   if (mgr == nullptr)
   270     return NS_ERROR_FAILURE;
   271   return mgr->RegisterReporter(reporter);
   272 }
   274 nsresult
   275 NS_UnregisterStatusReporter (nsIStatusReporter* reporter)
   276 {
   277   nsCOMPtr<nsIStatusReporterManager> mgr =
   278     do_GetService("@mozilla.org/status-reporter-manager;1");
   279   if (mgr == nullptr)
   280     return NS_ERROR_FAILURE;
   281   return mgr->UnregisterReporter(reporter);
   282 }
   284 nsresult
   285 NS_DumpStatusReporter ()
   286 {
   287   nsCOMPtr<nsIStatusReporterManager> mgr =
   288     do_GetService("@mozilla.org/status-reporter-manager;1");
   289   if (mgr == nullptr)
   290     return NS_ERROR_FAILURE;
   291   return mgr->DumpReports();
   292 }

mercurial