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 "nsMemoryReporterManager.h"
8 #include "MemoryReportRequest.h"
9 #include "mozilla/ipc/FileDescriptor.h"
10 #include "mozilla/ipc/FileDescriptorUtils.h"
12 using namespace mozilla::ipc
;
14 namespace mozilla::dom
{
16 MemoryReportRequestHost::MemoryReportRequestHost(uint32_t aGeneration
)
17 : mGeneration(aGeneration
), mSuccess(false) {
18 MOZ_COUNT_CTOR(MemoryReportRequestHost
);
19 mReporterManager
= nsMemoryReporterManager::GetOrCreate();
20 NS_WARNING_ASSERTION(mReporterManager
, "GetOrCreate failed");
23 void MemoryReportRequestHost::RecvReport(const MemoryReport
& aReport
) {
24 // Skip reports from older generations. We need to do this here since we
25 // could receive older reports from a subprocesses before it acknowledges
26 // a new request, and we only track one active request per process.
27 if (aReport
.generation() != mGeneration
) {
31 if (mReporterManager
) {
32 mReporterManager
->HandleChildReport(mGeneration
, aReport
);
36 void MemoryReportRequestHost::Finish(uint32_t aGeneration
) {
37 // Skip reports from older generations. See the comment in RecvReport.
38 if (mGeneration
!= aGeneration
) {
44 MemoryReportRequestHost::~MemoryReportRequestHost() {
45 MOZ_COUNT_DTOR(MemoryReportRequestHost
);
47 if (mReporterManager
) {
48 mReporterManager
->EndProcessReport(mGeneration
, mSuccess
);
49 mReporterManager
= nullptr;
53 NS_IMPL_ISUPPORTS(MemoryReportRequestClient
, nsIRunnable
)
55 /* static */ void MemoryReportRequestClient::Start(
56 uint32_t aGeneration
, bool aAnonymize
, bool aMinimizeMemoryUsage
,
57 const Maybe
<FileDescriptor
>& aDMDFile
, const nsACString
& aProcessString
,
58 const ReportCallback
& aReportCallback
,
59 const FinishCallback
& aFinishCallback
) {
60 RefPtr
<MemoryReportRequestClient
> request
= new MemoryReportRequestClient(
61 aGeneration
, aAnonymize
, aDMDFile
, aProcessString
, aReportCallback
,
64 DebugOnly
<nsresult
> rv
;
65 if (aMinimizeMemoryUsage
) {
66 nsCOMPtr
<nsIMemoryReporterManager
> mgr
=
67 do_GetService("@mozilla.org/memory-reporter-manager;1");
68 rv
= mgr
->MinimizeMemoryUsage(request
);
69 // mgr will eventually call actor->Run()
74 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "actor operation failed");
77 MemoryReportRequestClient::MemoryReportRequestClient(
78 uint32_t aGeneration
, bool aAnonymize
,
79 const Maybe
<FileDescriptor
>& aDMDFile
, const nsACString
& aProcessString
,
80 const ReportCallback
& aReportCallback
,
81 const FinishCallback
& aFinishCallback
)
82 : mGeneration(aGeneration
),
83 mAnonymize(aAnonymize
),
84 mProcessString(aProcessString
),
85 mReportCallback(aReportCallback
),
86 mFinishCallback(aFinishCallback
) {
87 if (aDMDFile
.isSome()) {
88 mDMDFile
= aDMDFile
.value();
92 MemoryReportRequestClient::~MemoryReportRequestClient() = default;
94 class HandleReportCallback final
: public nsIHandleReportCallback
{
96 using ReportCallback
= typename
MemoryReportRequestClient::ReportCallback
;
100 explicit HandleReportCallback(uint32_t aGeneration
,
101 const nsACString
& aProcess
,
102 const ReportCallback
& aReportCallback
)
103 : mGeneration(aGeneration
),
105 mReportCallback(aReportCallback
) {}
107 NS_IMETHOD
Callback(const nsACString
& aProcess
, const nsACString
& aPath
,
108 int32_t aKind
, int32_t aUnits
, int64_t aAmount
,
109 const nsACString
& aDescription
,
110 nsISupports
* aUnused
) override
{
111 MemoryReport
memreport(mProcess
, nsCString(aPath
), aKind
, aUnits
, aAmount
,
112 mGeneration
, nsCString(aDescription
));
113 mReportCallback(memreport
);
118 ~HandleReportCallback() = default;
120 uint32_t mGeneration
;
121 const nsCString mProcess
;
122 ReportCallback mReportCallback
;
125 NS_IMPL_ISUPPORTS(HandleReportCallback
, nsIHandleReportCallback
)
127 class FinishReportingCallback final
: public nsIFinishReportingCallback
{
129 using FinishCallback
= typename
MemoryReportRequestClient::FinishCallback
;
133 explicit FinishReportingCallback(uint32_t aGeneration
,
134 const FinishCallback
& aFinishCallback
)
135 : mGeneration(aGeneration
), mFinishCallback(aFinishCallback
) {}
137 NS_IMETHOD
Callback(nsISupports
* aUnused
) override
{
138 mFinishCallback(mGeneration
);
143 ~FinishReportingCallback() = default;
145 uint32_t mGeneration
;
146 FinishCallback mFinishCallback
;
149 NS_IMPL_ISUPPORTS(FinishReportingCallback
, nsIFinishReportingCallback
)
151 NS_IMETHODIMP
MemoryReportRequestClient::Run() {
152 nsCOMPtr
<nsIMemoryReporterManager
> mgr
=
153 do_GetService("@mozilla.org/memory-reporter-manager;1");
155 // Run the reporters. The callback will turn each measurement into a
157 RefPtr
<HandleReportCallback
> handleReport
=
158 new HandleReportCallback(mGeneration
, mProcessString
, mReportCallback
);
159 RefPtr
<FinishReportingCallback
> finishReporting
=
160 new FinishReportingCallback(mGeneration
, mFinishCallback
);
162 nsresult rv
= mgr
->GetReportsForThisProcessExtended(
163 handleReport
, nullptr, mAnonymize
, FileDescriptorToFILE(mDMDFile
, "wb"),
164 finishReporting
, nullptr);
165 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
),
166 "GetReportsForThisProcessExtended failed");
170 } // namespace mozilla::dom