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 "mozilla/dom/ReportingObserver.h"
8 #include "mozilla/dom/Report.h"
9 #include "mozilla/dom/ReportingBinding.h"
10 #include "nsContentUtils.h"
11 #include "nsIGlobalObject.h"
12 #include "nsThreadUtils.h"
14 namespace mozilla::dom
{
16 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ReportingObserver
)
17 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ReportingObserver
)
19 NS_IMPL_CYCLE_COLLECTION_UNLINK(mReports
)
20 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal
)
21 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback
)
22 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
23 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ReportingObserver
)
26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReports
)
27 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal
)
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback
)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
32 already_AddRefed
<ReportingObserver
> ReportingObserver::Constructor(
33 const GlobalObject
& aGlobal
, ReportingObserverCallback
& aCallback
,
34 const ReportingObserverOptions
& aOptions
, ErrorResult
& aRv
) {
35 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
38 nsTArray
<nsString
> types
;
39 if (aOptions
.mTypes
.WasPassed()) {
40 types
= aOptions
.mTypes
.Value();
43 RefPtr
<ReportingObserver
> ro
=
44 new ReportingObserver(global
, aCallback
, types
, aOptions
.mBuffered
);
49 ReportingObserver::ReportingObserver(nsIGlobalObject
* aGlobal
,
50 ReportingObserverCallback
& aCallback
,
51 const nsTArray
<nsString
>& aTypes
,
54 mCallback(&aCallback
),
55 mTypes(aTypes
.Clone()),
56 mBuffered(aBuffered
) {
60 ReportingObserver::~ReportingObserver() { Disconnect(); }
62 JSObject
* ReportingObserver::WrapObject(JSContext
* aCx
,
63 JS::Handle
<JSObject
*> aGivenProto
) {
64 return ReportingObserver_Binding::Wrap(aCx
, this, aGivenProto
);
67 void ReportingObserver::Observe() {
68 mGlobal
->RegisterReportingObserver(this, mBuffered
);
71 void ReportingObserver::Disconnect() {
73 mGlobal
->UnregisterReportingObserver(this);
77 void ReportingObserver::TakeRecords(nsTArray
<RefPtr
<Report
>>& aRecords
) {
78 mReports
.SwapElements(aRecords
);
83 class ReportRunnable final
: public DiscardableRunnable
{
85 explicit ReportRunnable(nsIGlobalObject
* aGlobal
)
86 : DiscardableRunnable("ReportRunnable"), mGlobal(aGlobal
) {}
88 // MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT. See
90 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
Run() override
{
91 MOZ_KnownLive(mGlobal
)->NotifyReportingObservers();
96 const nsCOMPtr
<nsIGlobalObject
> mGlobal
;
101 void ReportingObserver::MaybeReport(Report
* aReport
) {
104 if (!mTypes
.IsEmpty()) {
106 aReport
->GetType(type
);
108 if (!mTypes
.Contains(type
)) {
113 bool wasEmpty
= mReports
.IsEmpty();
115 RefPtr
<Report
> report
= aReport
->Clone();
118 if (NS_WARN_IF(!mReports
.AppendElement(report
, fallible
))) {
126 RefPtr
<ReportRunnable
> r
= new ReportRunnable(mGlobal
);
127 NS_DispatchToCurrentThread(r
);
130 void ReportingObserver::MaybeNotify() {
131 if (mReports
.IsEmpty()) {
135 // Let's take the ownership of the reports.
136 nsTArray
<RefPtr
<Report
>> list
= std::move(mReports
);
138 Sequence
<OwningNonNull
<Report
>> reports
;
139 for (Report
* report
: list
) {
140 if (NS_WARN_IF(!reports
.AppendElement(*report
, fallible
))) {
145 // We should report if this throws exception. But where?
146 RefPtr
<ReportingObserverCallback
> callback(mCallback
);
147 callback
->Call(reports
, *this);
150 void ReportingObserver::ForgetReports() { mReports
.Clear(); }
152 } // namespace mozilla::dom