tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ReportingObserver.cpp (4335B)


      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 "mozilla/dom/ReportingObserver.h"
      8 
      9 #include "mozilla/dom/Report.h"
     10 #include "mozilla/dom/ReportingBinding.h"
     11 #include "nsContentUtils.h"
     12 #include "nsIGlobalObject.h"
     13 #include "nsThreadUtils.h"
     14 
     15 namespace mozilla::dom {
     16 
     17 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ReportingObserver)
     18 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ReportingObserver)
     19  tmp->Disconnect();
     20  NS_IMPL_CYCLE_COLLECTION_UNLINK(mReports)
     21  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
     22  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
     23  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     24 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     25 
     26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ReportingObserver)
     27  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReports)
     28  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
     29  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
     30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     31 
     32 /* static */
     33 already_AddRefed<ReportingObserver> ReportingObserver::Constructor(
     34    const GlobalObject& aGlobal, ReportingObserverCallback& aCallback,
     35    const ReportingObserverOptions& aOptions, ErrorResult& aRv) {
     36  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
     37  MOZ_ASSERT(global);
     38 
     39  nsTArray<nsString> types;
     40  if (aOptions.mTypes.WasPassed()) {
     41    types = aOptions.mTypes.Value();
     42  }
     43 
     44  RefPtr<ReportingObserver> ro =
     45      new ReportingObserver(global, aCallback, types, aOptions.mBuffered);
     46 
     47  return ro.forget();
     48 }
     49 
     50 ReportingObserver::ReportingObserver(nsIGlobalObject* aGlobal,
     51                                     ReportingObserverCallback& aCallback,
     52                                     const nsTArray<nsString>& aTypes,
     53                                     bool aBuffered)
     54    : mGlobal(aGlobal),
     55      mCallback(&aCallback),
     56      mTypes(aTypes.Clone()),
     57      mBuffered(aBuffered) {
     58  MOZ_ASSERT(aGlobal);
     59 }
     60 
     61 ReportingObserver::~ReportingObserver() { Disconnect(); }
     62 
     63 JSObject* ReportingObserver::WrapObject(JSContext* aCx,
     64                                        JS::Handle<JSObject*> aGivenProto) {
     65  return ReportingObserver_Binding::Wrap(aCx, this, aGivenProto);
     66 }
     67 
     68 void ReportingObserver::Observe() {
     69  mGlobal->RegisterReportingObserver(this, mBuffered);
     70 }
     71 
     72 void ReportingObserver::Disconnect() {
     73  if (mGlobal) {
     74    mGlobal->UnregisterReportingObserver(this);
     75  }
     76 }
     77 
     78 void ReportingObserver::TakeRecords(nsTArray<RefPtr<Report>>& aRecords) {
     79  mReports.SwapElements(aRecords);
     80 }
     81 
     82 namespace {
     83 
     84 class ReportRunnable final : public DiscardableRunnable {
     85 public:
     86  explicit ReportRunnable(nsIGlobalObject* aGlobal)
     87      : DiscardableRunnable("ReportRunnable"), mGlobal(aGlobal) {}
     88 
     89  // MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT.  See
     90  // bug 1535398.
     91  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override {
     92    MOZ_KnownLive(mGlobal)->NotifyReportingObservers();
     93    return NS_OK;
     94  }
     95 
     96 private:
     97  const nsCOMPtr<nsIGlobalObject> mGlobal;
     98 };
     99 
    100 }  // namespace
    101 
    102 void ReportingObserver::MaybeReport(Report* aReport) {
    103  MOZ_ASSERT(aReport);
    104 
    105  if (!mTypes.IsEmpty()) {
    106    nsAutoString type;
    107    aReport->GetType(type);
    108 
    109    if (!mTypes.Contains(type)) {
    110      return;
    111    }
    112  }
    113 
    114  bool wasEmpty = mReports.IsEmpty();
    115 
    116  RefPtr<Report> report = aReport->Clone();
    117  MOZ_ASSERT(report);
    118 
    119  if (NS_WARN_IF(!mReports.AppendElement(report, fallible))) {
    120    return;
    121  }
    122 
    123  if (!wasEmpty) {
    124    return;
    125  }
    126 
    127  RefPtr<ReportRunnable> r = new ReportRunnable(mGlobal);
    128  NS_DispatchToCurrentThread(r);
    129 }
    130 
    131 void ReportingObserver::MaybeNotify() {
    132  if (mReports.IsEmpty()) {
    133    return;
    134  }
    135 
    136  // Let's take the ownership of the reports.
    137  nsTArray<RefPtr<Report>> list = std::move(mReports);
    138 
    139  Sequence<OwningNonNull<Report>> reports;
    140  for (Report* report : list) {
    141    if (NS_WARN_IF(!reports.AppendElement(*report, fallible))) {
    142      return;
    143    }
    144  }
    145 
    146  // We should report if this throws exception. But where?
    147  RefPtr<ReportingObserverCallback> callback(mCallback);
    148  callback->Call(reports, *this);
    149 }
    150 
    151 void ReportingObserver::ForgetReports() { mReports.Clear(); }
    152 
    153 }  // namespace mozilla::dom