no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / dom / reporting / ReportingObserver.cpp
blob808824ce9504896a73803d158bb6ba3dd719abc9
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)
18 tmp->Disconnect();
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
31 /* static */
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());
36 MOZ_ASSERT(global);
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);
46 return ro.forget();
49 ReportingObserver::ReportingObserver(nsIGlobalObject* aGlobal,
50 ReportingObserverCallback& aCallback,
51 const nsTArray<nsString>& aTypes,
52 bool aBuffered)
53 : mGlobal(aGlobal),
54 mCallback(&aCallback),
55 mTypes(aTypes.Clone()),
56 mBuffered(aBuffered) {
57 MOZ_ASSERT(aGlobal);
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() {
72 if (mGlobal) {
73 mGlobal->UnregisterReportingObserver(this);
77 void ReportingObserver::TakeRecords(nsTArray<RefPtr<Report>>& aRecords) {
78 mReports.SwapElements(aRecords);
81 namespace {
83 class ReportRunnable final : public DiscardableRunnable {
84 public:
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
89 // bug 1535398.
90 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override {
91 MOZ_KnownLive(mGlobal)->NotifyReportingObservers();
92 return NS_OK;
95 private:
96 const nsCOMPtr<nsIGlobalObject> mGlobal;
99 } // namespace
101 void ReportingObserver::MaybeReport(Report* aReport) {
102 MOZ_ASSERT(aReport);
104 if (!mTypes.IsEmpty()) {
105 nsAutoString type;
106 aReport->GetType(type);
108 if (!mTypes.Contains(type)) {
109 return;
113 bool wasEmpty = mReports.IsEmpty();
115 RefPtr<Report> report = aReport->Clone();
116 MOZ_ASSERT(report);
118 if (NS_WARN_IF(!mReports.AppendElement(report, fallible))) {
119 return;
122 if (!wasEmpty) {
123 return;
126 RefPtr<ReportRunnable> r = new ReportRunnable(mGlobal);
127 NS_DispatchToCurrentThread(r);
130 void ReportingObserver::MaybeNotify() {
131 if (mReports.IsEmpty()) {
132 return;
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))) {
141 return;
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