Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/ipc/MemoryReportRequest.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#include "MemoryReportRequest.h"
8
#include "mozilla/Unused.h"
9
#include "mozilla/dom/ContentChild.h"
10
#include "mozilla/gfx/GPUParent.h"
11
12
namespace mozilla {
13
namespace dom {
14
15
MemoryReportRequestHost::MemoryReportRequestHost(uint32_t aGeneration)
16
  : mGeneration(aGeneration),
17
    mSuccess(false)
18
0
{
19
0
  MOZ_COUNT_CTOR(MemoryReportRequestHost);
20
0
  mReporterManager = nsMemoryReporterManager::GetOrCreate();
21
0
  NS_WARNING_ASSERTION(mReporterManager, "GetOrCreate failed");
22
0
}
23
24
void
25
MemoryReportRequestHost::RecvReport(const MemoryReport& aReport)
26
0
{
27
0
  // Skip reports from older generations. We need to do this here since we
28
0
  // could receive older reports from a subprocesses before it acknowledges
29
0
  // a new request, and we only track one active request per process.
30
0
  if (aReport.generation() != mGeneration) {
31
0
    return;
32
0
  }
33
0
34
0
  if (mReporterManager) {
35
0
    mReporterManager->HandleChildReport(mGeneration, aReport);
36
0
  }
37
0
}
38
39
void
40
MemoryReportRequestHost::Finish(uint32_t aGeneration)
41
0
{
42
0
  // Skip reports from older generations. See the comment in RecvReport.
43
0
  if (mGeneration != aGeneration) {
44
0
    return;
45
0
  }
46
0
  mSuccess = true;
47
0
}
48
49
MemoryReportRequestHost::~MemoryReportRequestHost()
50
0
{
51
0
  MOZ_COUNT_DTOR(MemoryReportRequestHost);
52
0
53
0
  if (mReporterManager) {
54
0
    mReporterManager->EndProcessReport(mGeneration, mSuccess);
55
0
    mReporterManager = nullptr;
56
0
  }
57
0
}
58
59
NS_IMPL_ISUPPORTS(MemoryReportRequestClient, nsIRunnable)
60
61
/* static */ void
62
MemoryReportRequestClient::Start(uint32_t aGeneration,
63
                                 bool aAnonymize,
64
                                 bool aMinimizeMemoryUsage,
65
                                 const MaybeFileDesc& aDMDFile,
66
                                 const nsACString& aProcessString)
67
0
{
68
0
  RefPtr<MemoryReportRequestClient> request = new MemoryReportRequestClient(
69
0
    aGeneration,
70
0
    aAnonymize,
71
0
    aDMDFile,
72
0
    aProcessString);
73
0
74
0
  DebugOnly<nsresult> rv;
75
0
  if (aMinimizeMemoryUsage) {
76
0
    nsCOMPtr<nsIMemoryReporterManager> mgr =
77
0
      do_GetService("@mozilla.org/memory-reporter-manager;1");
78
0
    rv = mgr->MinimizeMemoryUsage(request);
79
0
    // mgr will eventually call actor->Run()
80
0
  } else {
81
0
    rv = request->Run();
82
0
  }
83
0
84
0
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "actor operation failed");
85
0
}
86
87
MemoryReportRequestClient::MemoryReportRequestClient(uint32_t aGeneration,
88
                                                     bool aAnonymize,
89
                                                     const MaybeFileDesc& aDMDFile,
90
                                                     const nsACString& aProcessString)
91
 : mGeneration(aGeneration),
92
   mAnonymize(aAnonymize),
93
   mProcessString(aProcessString)
94
0
{
95
0
  if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
96
0
    mDMDFile = aDMDFile.get_FileDescriptor();
97
0
  }
98
0
}
99
100
MemoryReportRequestClient::~MemoryReportRequestClient()
101
0
{
102
0
}
103
104
class HandleReportCallback final : public nsIHandleReportCallback
105
{
106
public:
107
  NS_DECL_ISUPPORTS
108
109
  explicit HandleReportCallback(uint32_t aGeneration,
110
                                const nsACString& aProcess)
111
  : mGeneration(aGeneration)
112
  , mProcess(aProcess)
113
0
  { }
114
115
  NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
116
                      int32_t aKind, int32_t aUnits, int64_t aAmount,
117
                      const nsACString& aDescription,
118
                      nsISupports* aUnused) override
119
0
  {
120
0
    MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
121
0
                           aAmount, mGeneration, nsCString(aDescription));
122
0
    switch (XRE_GetProcessType()) {
123
0
      case GeckoProcessType_Content:
124
0
        ContentChild::GetSingleton()->SendAddMemoryReport(memreport);
125
0
        break;
126
0
      case GeckoProcessType_GPU:
127
0
        Unused << gfx::GPUParent::GetSingleton()->SendAddMemoryReport(memreport);
128
0
        break;
129
0
      default:
130
0
        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
131
0
    }
132
0
    return NS_OK;
133
0
  }
134
private:
135
0
  ~HandleReportCallback() = default;
136
137
  uint32_t mGeneration;
138
  const nsCString mProcess;
139
};
140
141
NS_IMPL_ISUPPORTS(
142
  HandleReportCallback
143
, nsIHandleReportCallback
144
)
145
146
class FinishReportingCallback final : public nsIFinishReportingCallback
147
{
148
public:
149
  NS_DECL_ISUPPORTS
150
151
  explicit FinishReportingCallback(uint32_t aGeneration)
152
  : mGeneration(aGeneration)
153
0
  {
154
0
  }
155
156
  NS_IMETHOD Callback(nsISupports* aUnused) override
157
0
  {
158
0
    bool sent = false;
159
0
    switch (XRE_GetProcessType()) {
160
0
      case GeckoProcessType_Content:
161
0
        sent = ContentChild::GetSingleton()->SendFinishMemoryReport(mGeneration);
162
0
        break;
163
0
      case GeckoProcessType_GPU:
164
0
        sent = gfx::GPUParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
165
0
        break;
166
0
      default:
167
0
        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
168
0
    }
169
0
    return sent ? NS_OK : NS_ERROR_FAILURE;
170
0
  }
171
172
private:
173
  ~FinishReportingCallback() = default;
174
175
  uint32_t mGeneration;
176
};
177
178
NS_IMPL_ISUPPORTS(
179
  FinishReportingCallback
180
, nsIFinishReportingCallback
181
)
182
183
NS_IMETHODIMP MemoryReportRequestClient::Run()
184
0
{
185
0
  nsCOMPtr<nsIMemoryReporterManager> mgr =
186
0
    do_GetService("@mozilla.org/memory-reporter-manager;1");
187
0
188
0
  // Run the reporters.  The callback will turn each measurement into a
189
0
  // MemoryReport.
190
0
  RefPtr<HandleReportCallback> handleReport =
191
0
    new HandleReportCallback(mGeneration, mProcessString);
192
0
  RefPtr<FinishReportingCallback> finishReporting =
193
0
    new FinishReportingCallback(mGeneration);
194
0
195
0
  nsresult rv =
196
0
    mgr->GetReportsForThisProcessExtended(handleReport, nullptr, mAnonymize,
197
0
                                          FileDescriptorToFILE(mDMDFile, "wb"),
198
0
                                          finishReporting, nullptr);
199
0
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
200
0
                       "GetReportsForThisProcessExtended failed");
201
0
  return rv;
202
0
}
203
204
} // namespace dom
205
} // namespace mozilla