NS_IMETHODIMP nsStatusReporterManager::DumpReports() { static unsigned number = 1; nsresult rv; int thispid = 181818; thispid = getpid(); nsCString filename("status-reports-"); filename.AppendInt(thispid); 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 nsMemoryReporterManager::GetExplicit(PRInt64 *aExplicit) { InfallibleTArray<MemoryReport> nonheap; PRInt64 heapUsed = PRInt64(-1); // Get "heap-allocated" and all the KIND_NONHEAP measurements from vanilla // reporters. nsCOMPtr<nsISimpleEnumerator> e; EnumerateReporters(getter_AddRefs(e)); PRBool more; while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr<nsIMemoryReporter> r; e->GetNext(getter_AddRefs(r)); PRInt32 kind; nsresult rv = r->GetKind(&kind); NS_ENSURE_SUCCESS(rv, rv); if (kind == nsIMemoryReporter::KIND_NONHEAP) { nsCString path; rv = r->GetPath(path); NS_ENSURE_SUCCESS(rv, rv); PRInt64 amount; rv = r->GetAmount(&amount); NS_ENSURE_SUCCESS(rv, rv); // Just skip any NONHEAP reporters that fail, because // "heap-allocated" is the most important one. if (amount != PRInt64(-1)) { MemoryReport mr(path, amount); nonheap.AppendElement(mr); } } else { nsCString path; rv = r->GetPath(path); NS_ENSURE_SUCCESS(rv, rv); if (path.Equals("heap-allocated")) { rv = r->GetAmount(&heapUsed); NS_ENSURE_SUCCESS(rv, rv); // If "heap-allocated" fails, we give up, because the result // would be horribly inaccurate. if (heapUsed == PRInt64(-1)) { *aExplicit = PRInt64(-1); return NS_OK; } } } } // Get KIND_NONHEAP measurements from multi-reporters, too. nsCOMPtr<nsISimpleEnumerator> e2; EnumerateMultiReporters(getter_AddRefs(e2)); nsRefPtr<MemoryReportsWrapper> wrappedMRs = new MemoryReportsWrapper(&nonheap); nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(); while (NS_SUCCEEDED(e2->HasMoreElements(&more)) && more) { nsCOMPtr<nsIMemoryMultiReporter> r; e2->GetNext(getter_AddRefs(r)); r->CollectReports(cb, wrappedMRs); } // Ignore (by zeroing its amount) any reporter that is a child of another // reporter. Eg. if we have "explicit/a" and "explicit/a/b", zero the // latter. This is quadratic in the number of NONHEAP reporters, but there // shouldn't be many. for (PRUint32 i = 0; i < nonheap.Length(); i++) { const nsCString &iPath = nonheap[i].path; for (PRUint32 j = i + 1; j < nonheap.Length(); j++) { const nsCString &jPath = nonheap[j].path; if (isParent(iPath, jPath)) { nonheap[j].amount = 0; } else if (isParent(jPath, iPath)) { nonheap[i].amount = 0; } } } // Sum all the nonheap reporters and heapUsed. *aExplicit = heapUsed; for (PRUint32 i = 0; i < nonheap.Length(); i++) { *aExplicit += nonheap[i].amount; } return NS_OK; }