Skip to content

Commit aaa72f6

Browse files
committed
Bug 1630947 - Update Reporting API - part 1 - ReportingObserver in workers, r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D71317
1 parent 238a066 commit aaa72f6

26 files changed

+363
-315
lines changed

dom/base/nsGlobalWindowInner.cpp

Lines changed: 4 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@
223223
#include "mozilla/dom/ImageBitmap.h"
224224
#include "mozilla/dom/ImageBitmapBinding.h"
225225
#include "mozilla/dom/InstallTriggerBinding.h"
226-
#include "mozilla/dom/Report.h"
227-
#include "mozilla/dom/ReportingObserver.h"
228226
#include "mozilla/dom/SharedWorker.h"
229227
#include "mozilla/dom/ServiceWorker.h"
230228
#include "mozilla/dom/ServiceWorkerRegistration.h"
@@ -328,9 +326,6 @@ static nsGlobalWindowOuter* GetOuterWindowForForwarding(
328326
// dialogs for this window.
329327
#define MAX_SUCCESSIVE_DIALOG_COUNT 5
330328

331-
// Max number of Report objects
332-
#define MAX_REPORT_RECORDS 100
333-
334329
static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
335330
extern mozilla::LazyLogModule gTimeoutLog;
336331

@@ -1134,7 +1129,7 @@ void nsGlobalWindowInner::FreeInnerObjects() {
11341129
mIndexedDB = nullptr;
11351130
}
11361131

1137-
UnlinkHostObjectURIs();
1132+
nsIGlobalObject::UnlinkObjectsInGlobal();
11381133

11391134
NotifyWindowIDDestroyed("inner-window-destroyed");
11401135

@@ -1364,10 +1359,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
13641359
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
13651360
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)
13661361
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
1367-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportRecords)
1368-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportingObservers)
13691362

1370-
tmp->TraverseHostObjectURIs(cb);
1363+
tmp->TraverseObjectsInGlobal(cb);
13711364

13721365
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
13731366
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
@@ -1465,10 +1458,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
14651458
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
14661459
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)
14671460
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
1468-
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReportRecords)
1469-
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReportingObservers)
14701461

1471-
tmp->UnlinkHostObjectURIs();
1462+
tmp->UnlinkObjectsInGlobal();
14721463

14731464
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
14741465

@@ -4938,8 +4929,8 @@ nsresult nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
49384929
if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
49394930
if (mPerformance) {
49404931
mPerformance->MemoryPressure();
4941-
mReportRecords.Clear();
49424932
}
4933+
RemoveReportRecords();
49434934
return NS_OK;
49444935
}
49454936

@@ -7337,62 +7328,6 @@ nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
73377328
}
73387329
}
73397330

7340-
void nsPIDOMWindowInner::RegisterReportingObserver(ReportingObserver* aObserver,
7341-
bool aBuffered) {
7342-
MOZ_ASSERT(aObserver);
7343-
7344-
if (mReportingObservers.Contains(aObserver)) {
7345-
return;
7346-
}
7347-
7348-
if (NS_WARN_IF(!mReportingObservers.AppendElement(aObserver, fallible))) {
7349-
return;
7350-
}
7351-
7352-
if (!aBuffered) {
7353-
return;
7354-
}
7355-
7356-
for (Report* report : mReportRecords) {
7357-
aObserver->MaybeReport(report);
7358-
}
7359-
}
7360-
7361-
void nsPIDOMWindowInner::UnregisterReportingObserver(
7362-
ReportingObserver* aObserver) {
7363-
MOZ_ASSERT(aObserver);
7364-
mReportingObservers.RemoveElement(aObserver);
7365-
}
7366-
7367-
void nsPIDOMWindowInner::BroadcastReport(Report* aReport) {
7368-
MOZ_ASSERT(aReport);
7369-
7370-
for (ReportingObserver* observer : mReportingObservers) {
7371-
observer->MaybeReport(aReport);
7372-
}
7373-
7374-
if (NS_WARN_IF(!mReportRecords.AppendElement(aReport, fallible))) {
7375-
return;
7376-
}
7377-
7378-
while (mReportRecords.Length() > MAX_REPORT_RECORDS) {
7379-
mReportRecords.RemoveElementAt(0);
7380-
}
7381-
}
7382-
7383-
void nsPIDOMWindowInner::NotifyReportingObservers() {
7384-
const nsTArray<RefPtr<ReportingObserver>> reportingObservers(
7385-
mReportingObservers);
7386-
for (auto& observer : reportingObservers) {
7387-
// MOZ_KnownLive because 'reportingObservers' is guaranteed to
7388-
// keep it alive.
7389-
//
7390-
// This can go away once
7391-
// https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
7392-
MOZ_KnownLive(observer)->MaybeNotify();
7393-
}
7394-
}
7395-
73967331
nsPIDOMWindowInner::~nsPIDOMWindowInner() = default;
73977332

73987333
#undef FORWARD_TO_OUTER

dom/base/nsGlobalWindowOuter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowOuter)
16061606
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
16071607
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
16081608

1609-
tmp->TraverseHostObjectURIs(cb);
1609+
tmp->TraverseObjectsInGlobal(cb);
16101610

16111611
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)
16121612
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -1649,7 +1649,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)
16491649
tmp->mBrowsingContext = nullptr;
16501650
}
16511651

1652-
tmp->UnlinkHostObjectURIs();
1652+
tmp->UnlinkObjectsInGlobal();
16531653

16541654
if (tmp->IsChromeWindow()) {
16551655
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)

dom/base/nsIGlobalObject.cpp

Lines changed: 102 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88
#include "mozilla/CycleCollectedJSContext.h"
99
#include "mozilla/dom/BlobURLProtocolHandler.h"
1010
#include "mozilla/dom/FunctionBinding.h"
11+
#include "mozilla/dom/Report.h"
12+
#include "mozilla/dom/ReportingObserver.h"
1113
#include "mozilla/dom/ServiceWorker.h"
1214
#include "mozilla/dom/ServiceWorkerRegistration.h"
1315
#include "nsContentUtils.h"
1416
#include "nsThreadUtils.h"
1517
#include "nsGlobalWindowInner.h"
1618

19+
// Max number of Report objects
20+
constexpr auto MAX_REPORT_RECORDS = 100;
21+
1722
using mozilla::AutoSlowOperation;
1823
using mozilla::CycleCollectedJSContext;
1924
using mozilla::DOMEventTargetHelper;
@@ -30,6 +35,9 @@ using mozilla::dom::ServiceWorkerRegistration;
3035
using mozilla::dom::ServiceWorkerRegistrationDescriptor;
3136
using mozilla::dom::VoidFunction;
3237

38+
nsIGlobalObject::nsIGlobalObject()
39+
: mIsDying(false), mIsScriptForbidden(false), mIsInnerWindow(false) {}
40+
3341
bool nsIGlobalObject::IsScriptForbidden(JSObject* aCallback,
3442
bool aIsJSImplementedWebIDL) const {
3543
if (mIsScriptForbidden) {
@@ -49,7 +57,7 @@ bool nsIGlobalObject::IsScriptForbidden(JSObject* aCallback,
4957
}
5058

5159
nsIGlobalObject::~nsIGlobalObject() {
52-
UnlinkHostObjectURIs();
60+
UnlinkObjectsInGlobal();
5361
DisconnectEventTargetObjects();
5462
MOZ_DIAGNOSTIC_ASSERT(mEventTargetObjects.isEmpty());
5563
}
@@ -101,47 +109,44 @@ class UnlinkHostObjectURIsRunnable final : public mozilla::Runnable {
101109

102110
} // namespace
103111

104-
void nsIGlobalObject::UnlinkHostObjectURIs() {
105-
if (mHostObjectURIs.IsEmpty()) {
106-
return;
107-
}
108-
109-
if (NS_IsMainThread()) {
110-
for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) {
111-
BlobURLProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]);
112+
void nsIGlobalObject::UnlinkObjectsInGlobal() {
113+
if (!mHostObjectURIs.IsEmpty()) {
114+
// BlobURLProtocolHandler is main-thread only.
115+
if (NS_IsMainThread()) {
116+
for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) {
117+
BlobURLProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]);
118+
}
119+
120+
mHostObjectURIs.Clear();
121+
} else {
122+
RefPtr<UnlinkHostObjectURIsRunnable> runnable =
123+
new UnlinkHostObjectURIsRunnable(mHostObjectURIs);
124+
MOZ_ASSERT(mHostObjectURIs.IsEmpty());
125+
126+
nsresult rv = NS_DispatchToMainThread(runnable);
127+
if (NS_FAILED(rv)) {
128+
NS_WARNING("Failed to dispatch a runnable to the main-thread.");
129+
}
112130
}
113-
114-
mHostObjectURIs.Clear();
115-
return;
116131
}
117132

118-
// BlobURLProtocolHandler is main-thread only.
119-
120-
RefPtr<UnlinkHostObjectURIsRunnable> runnable =
121-
new UnlinkHostObjectURIsRunnable(mHostObjectURIs);
122-
MOZ_ASSERT(mHostObjectURIs.IsEmpty());
123-
124-
nsresult rv = NS_DispatchToMainThread(runnable);
125-
if (NS_FAILED(rv)) {
126-
NS_WARNING("Failed to dispatch a runnable to the main-thread.");
127-
}
133+
mReportRecords.Clear();
134+
mReportingObservers.Clear();
128135
}
129136

130-
void nsIGlobalObject::TraverseHostObjectURIs(
131-
nsCycleCollectionTraversalCallback& aCb) {
132-
if (mHostObjectURIs.IsEmpty()) {
133-
return;
134-
}
135-
137+
void nsIGlobalObject::TraverseObjectsInGlobal(
138+
nsCycleCollectionTraversalCallback& cb) {
136139
// Currently we only store BlobImpl objects off the the main-thread and they
137140
// are not CCed.
138-
if (!NS_IsMainThread()) {
139-
return;
141+
if (!mHostObjectURIs.IsEmpty() && NS_IsMainThread()) {
142+
for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) {
143+
BlobURLProtocolHandler::Traverse(mHostObjectURIs[index], cb);
144+
}
140145
}
141146

142-
for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) {
143-
BlobURLProtocolHandler::Traverse(mHostObjectURIs[index], aCb);
144-
}
147+
nsIGlobalObject* tmp = this;
148+
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportRecords)
149+
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportingObservers)
145150
}
146151

147152
void nsIGlobalObject::AddEventTargetObject(DOMEventTargetHelper* aObject) {
@@ -274,3 +279,67 @@ void nsIGlobalObject::QueueMicrotask(VoidFunction& aCallback) {
274279
context->DispatchToMicroTask(mt.forget());
275280
}
276281
}
282+
283+
void nsIGlobalObject::RegisterReportingObserver(ReportingObserver* aObserver,
284+
bool aBuffered) {
285+
MOZ_ASSERT(aObserver);
286+
287+
if (mReportingObservers.Contains(aObserver)) {
288+
return;
289+
}
290+
291+
if (NS_WARN_IF(!mReportingObservers.AppendElement(aObserver, fallible))) {
292+
return;
293+
}
294+
295+
if (!aBuffered) {
296+
return;
297+
}
298+
299+
for (Report* report : mReportRecords) {
300+
aObserver->MaybeReport(report);
301+
}
302+
}
303+
304+
void nsIGlobalObject::UnregisterReportingObserver(
305+
ReportingObserver* aObserver) {
306+
MOZ_ASSERT(aObserver);
307+
mReportingObservers.RemoveElement(aObserver);
308+
}
309+
310+
void nsIGlobalObject::BroadcastReport(Report* aReport) {
311+
MOZ_ASSERT(aReport);
312+
313+
for (ReportingObserver* observer : mReportingObservers) {
314+
observer->MaybeReport(aReport);
315+
}
316+
317+
if (NS_WARN_IF(!mReportRecords.AppendElement(aReport, fallible))) {
318+
return;
319+
}
320+
321+
while (mReportRecords.Length() > MAX_REPORT_RECORDS) {
322+
mReportRecords.RemoveElementAt(0);
323+
}
324+
}
325+
326+
void nsIGlobalObject::NotifyReportingObservers() {
327+
const nsTArray<RefPtr<ReportingObserver>> reportingObservers(
328+
mReportingObservers);
329+
for (auto& observer : reportingObservers) {
330+
// MOZ_KnownLive because 'reportingObservers' is guaranteed to
331+
// keep it alive.
332+
//
333+
// This can go away once
334+
// https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
335+
MOZ_KnownLive(observer)->MaybeNotify();
336+
}
337+
}
338+
339+
void nsIGlobalObject::RemoveReportRecords() {
340+
mReportRecords.Clear();
341+
342+
for (auto& observer : mReportingObservers) {
343+
observer->ForgetReports();
344+
}
345+
}

dom/base/nsIGlobalObject.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class DOMEventTargetHelper;
3636
namespace dom {
3737
class VoidFunction;
3838
class DebuggerNotificationManager;
39+
class Report;
40+
class ReportBody;
41+
class ReportingObserver;
3942
class ServiceWorker;
4043
class ServiceWorkerRegistration;
4144
class ServiceWorkerRegistrationDescriptor;
@@ -56,8 +59,7 @@ class nsIGlobalObject : public nsISupports,
5659
protected:
5760
bool mIsInnerWindow;
5861

59-
nsIGlobalObject()
60-
: mIsDying(false), mIsScriptForbidden(false), mIsInnerWindow(false) {}
62+
nsIGlobalObject();
6163

6264
public:
6365
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
@@ -122,10 +124,10 @@ class nsIGlobalObject : public nsISupports,
122124

123125
void UnregisterHostObjectURI(const nsACString& aURI);
124126

125-
// Any CC class inheriting nsIGlobalObject should call these 2 methods if it
126-
// exposes the URL API.
127-
void UnlinkHostObjectURIs();
128-
void TraverseHostObjectURIs(nsCycleCollectionTraversalCallback& aCb);
127+
// Any CC class inheriting nsIGlobalObject should call these 2 methods to
128+
// cleanup objects stored in nsIGlobalObject such as blobURLs and Reports.
129+
void UnlinkObjectsInGlobal();
130+
void TraverseObjectsInGlobal(nsCycleCollectionTraversalCallback& aCb);
129131

130132
// DETH objects must register themselves on the global when they
131133
// bind to it in order to get the DisconnectFromOwner() method
@@ -187,6 +189,17 @@ class nsIGlobalObject : public nsISupports,
187189

188190
void QueueMicrotask(mozilla::dom::VoidFunction& aCallback);
189191

192+
void RegisterReportingObserver(mozilla::dom::ReportingObserver* aObserver,
193+
bool aBuffered);
194+
195+
void UnregisterReportingObserver(mozilla::dom::ReportingObserver* aObserver);
196+
197+
void BroadcastReport(mozilla::dom::Report* aReport);
198+
199+
MOZ_CAN_RUN_SCRIPT void NotifyReportingObservers();
200+
201+
void RemoveReportRecords();
202+
190203
protected:
191204
virtual ~nsIGlobalObject();
192205

@@ -198,6 +211,11 @@ class nsIGlobalObject : public nsISupports,
198211
void DisconnectEventTargetObjects();
199212

200213
size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aSizeOf) const;
214+
215+
private:
216+
// List of Report objects for ReportingObservers.
217+
nsTArray<RefPtr<mozilla::dom::ReportingObserver>> mReportingObservers;
218+
nsTArray<RefPtr<mozilla::dom::Report>> mReportRecords;
201219
};
202220

203221
NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject, NS_IGLOBALOBJECT_IID)

0 commit comments

Comments
 (0)