зеркало из https://github.com/mozilla/gecko-dev.git
323 строки
7.5 KiB
C++
323 строки
7.5 KiB
C++
/* -*- 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 "nsStatusReporterManager.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "nsArrayEnumerator.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
#include "nsIFile.h"
|
|
#include "nsDumpUtils.h"
|
|
#include "nsIFileStreams.h"
|
|
#include "nsPrintfCString.h"
|
|
|
|
#ifdef XP_WIN
|
|
#include <process.h>
|
|
#define getpid _getpid
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#ifdef XP_UNIX
|
|
#define DO_STATUS_REPORT 1
|
|
#endif
|
|
|
|
#ifdef DO_STATUS_REPORT // {
|
|
namespace {
|
|
|
|
class DumpStatusInfoToTempDirRunnable : public nsRunnable
|
|
{
|
|
public:
|
|
DumpStatusInfoToTempDirRunnable()
|
|
{
|
|
}
|
|
|
|
NS_IMETHOD Run()
|
|
{
|
|
nsCOMPtr<nsIStatusReporterManager> mgr =
|
|
do_GetService("@mozilla.org/status-reporter-manager;1");
|
|
mgr->DumpReports();
|
|
return NS_OK;
|
|
}
|
|
};
|
|
|
|
void
|
|
doStatusReport(const nsCString& aInputStr)
|
|
{
|
|
LOG("FifoWatcher(%s) dispatching status report runnable.", aInputStr.get());
|
|
nsRefPtr<DumpStatusInfoToTempDirRunnable> runnable =
|
|
new DumpStatusInfoToTempDirRunnable();
|
|
NS_DispatchToMainThread(runnable);
|
|
}
|
|
|
|
} //anonymous namespace
|
|
#endif // DO_STATUS_REPORT }
|
|
|
|
static bool gStatusReportProgress = 0;
|
|
static int gNumReporters = 0;
|
|
|
|
nsresult
|
|
getStatus(nsACString& aDesc)
|
|
{
|
|
if (!gStatusReportProgress) {
|
|
aDesc.AssignLiteral("Init");
|
|
} else {
|
|
aDesc.AssignLiteral("Running: There are ");
|
|
aDesc.AppendInt(gNumReporters);
|
|
aDesc.AppendLiteral(" reporters");
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_STATUS_REPORTER_IMPLEMENT(StatusReporter, "StatusReporter State", getStatus)
|
|
|
|
#define DUMP(o, s) \
|
|
do { \
|
|
const char* s2 = (s); \
|
|
uint32_t dummy; \
|
|
nsresult rv = (o)->Write((s2), strlen(s2), &dummy); \
|
|
if (NS_WARN_IF(NS_FAILED(rv))) \
|
|
return rv; \
|
|
} while (0)
|
|
|
|
static nsresult
|
|
DumpReport(nsIFileOutputStream* aOStream, const nsCString& aProcess,
|
|
const nsCString& aName, const nsCString& aDescription)
|
|
{
|
|
int pid;
|
|
if (aProcess.IsEmpty()) {
|
|
pid = getpid();
|
|
nsPrintfCString pidStr("PID %u", pid);
|
|
DUMP(aOStream, "\n {\n \"Process\": \"");
|
|
DUMP(aOStream, pidStr.get());
|
|
} else {
|
|
pid = 0;
|
|
DUMP(aOStream, "\n { \"Unknown Process\": \"");
|
|
}
|
|
|
|
DUMP(aOStream, "\",\n \"Reporter name\": \"");
|
|
DUMP(aOStream, aName.get());
|
|
|
|
DUMP(aOStream, "\",\n \"Status Description\": [\"");
|
|
nsCString desc = aDescription;
|
|
desc.ReplaceSubstring("|", "\",\"");
|
|
DUMP(aOStream, desc.get());
|
|
|
|
DUMP(aOStream, "\"]\n }");
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
** nsStatusReporterManager implementation
|
|
**/
|
|
|
|
NS_IMPL_ISUPPORTS(nsStatusReporterManager, nsIStatusReporterManager)
|
|
|
|
nsStatusReporterManager::nsStatusReporterManager()
|
|
{
|
|
}
|
|
|
|
nsStatusReporterManager::~nsStatusReporterManager()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStatusReporterManager::Init()
|
|
{
|
|
RegisterReporter(new NS_STATUS_REPORTER_NAME(StatusReporter));
|
|
gStatusReportProgress = 1;
|
|
|
|
#ifdef DO_STATUS_REPORT
|
|
if (FifoWatcher::MaybeCreate()) {
|
|
FifoWatcher* fw = FifoWatcher::GetSingleton();
|
|
fw->RegisterCallback(NS_LITERAL_CSTRING("status report"), doStatusReport);
|
|
}
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStatusReporterManager::DumpReports()
|
|
{
|
|
static unsigned number = 1;
|
|
nsresult rv;
|
|
|
|
nsCString filename("status-reports-");
|
|
filename.AppendInt(getpid());
|
|
filename.Append('-');
|
|
filename.AppendInt(number++);
|
|
filename.AppendLiteral(".json");
|
|
|
|
// Open a file in NS_OS_TEMP_DIR for writing.
|
|
// The file is initialized as "incomplete-status-reports-pid-number.json" in the
|
|
// begining, it will be rename as "status-reports-pid-number.json" in the end.
|
|
nsCOMPtr<nsIFile> tmpFile;
|
|
rv = nsDumpUtils::OpenTempFile(NS_LITERAL_CSTRING("incomplete-") +
|
|
filename,
|
|
getter_AddRefs(tmpFile),
|
|
NS_LITERAL_CSTRING("status-reports"));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIFileOutputStream> ostream =
|
|
do_CreateInstance("@mozilla.org/network/file-output-stream;1");
|
|
rv = ostream->Init(tmpFile, -1, -1, 0);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
//Write the reports to the file
|
|
|
|
DUMP(ostream, "{\n\"subject\":\"about:service reports\",\n");
|
|
DUMP(ostream, "\"reporters\": [ ");
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> e;
|
|
bool more, first = true;
|
|
EnumerateReporters(getter_AddRefs(e));
|
|
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
|
|
nsCOMPtr<nsISupports> supports;
|
|
e->GetNext(getter_AddRefs(supports));
|
|
nsCOMPtr<nsIStatusReporter> r = do_QueryInterface(supports);
|
|
|
|
nsCString process;
|
|
rv = r->GetProcess(process);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsCString name;
|
|
rv = r->GetName(name);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsCString description;
|
|
rv = r->GetDescription(description);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
if (first) {
|
|
first = false;
|
|
} else {
|
|
DUMP(ostream, ",");
|
|
}
|
|
|
|
rv = DumpReport(ostream, process, name, description);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
}
|
|
DUMP(ostream, "\n]\n}\n");
|
|
|
|
rv = ostream->Close();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
// Rename the status reports file
|
|
nsCOMPtr<nsIFile> srFinalFile;
|
|
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(srFinalFile));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
#ifdef ANDROID
|
|
rv = srFinalFile->AppendNative(NS_LITERAL_CSTRING("status-reports"));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
#endif
|
|
|
|
rv = srFinalFile->AppendNative(filename);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
rv = srFinalFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsAutoString srActualFinalFilename;
|
|
rv = srFinalFile->GetLeafName(srActualFinalFilename);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
rv = tmpFile->MoveTo(/* directory */ nullptr, srActualFinalFilename);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStatusReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult)
|
|
{
|
|
return NS_NewArrayEnumerator(aResult, mReporters);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStatusReporterManager::RegisterReporter(nsIStatusReporter* aReporter)
|
|
{
|
|
if (mReporters.IndexOf(aReporter) != -1) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
mReporters.AppendObject(aReporter);
|
|
gNumReporters++;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsStatusReporterManager::UnregisterReporter(nsIStatusReporter* aReporter)
|
|
{
|
|
if (!mReporters.RemoveObject(aReporter)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
gNumReporters--;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
NS_RegisterStatusReporter(nsIStatusReporter* aReporter)
|
|
{
|
|
nsCOMPtr<nsIStatusReporterManager> mgr =
|
|
do_GetService("@mozilla.org/status-reporter-manager;1");
|
|
if (!mgr) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return mgr->RegisterReporter(aReporter);
|
|
}
|
|
|
|
nsresult
|
|
NS_UnregisterStatusReporter(nsIStatusReporter* aReporter)
|
|
{
|
|
nsCOMPtr<nsIStatusReporterManager> mgr =
|
|
do_GetService("@mozilla.org/status-reporter-manager;1");
|
|
if (!mgr) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return mgr->UnregisterReporter(aReporter);
|
|
}
|
|
|
|
nsresult
|
|
NS_DumpStatusReporter()
|
|
{
|
|
nsCOMPtr<nsIStatusReporterManager> mgr =
|
|
do_GetService("@mozilla.org/status-reporter-manager;1");
|
|
if (!mgr) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return mgr->DumpReports();
|
|
}
|