tor-browser

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

PerformanceStorageWorker.cpp (5537B)


      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 "PerformanceStorageWorker.h"
      8 
      9 #include "Performance.h"
     10 #include "PerformanceResourceTiming.h"
     11 #include "PerformanceTiming.h"
     12 #include "mozilla/dom/WorkerRef.h"
     13 #include "mozilla/dom/WorkerRunnable.h"
     14 #include "mozilla/dom/WorkerScope.h"
     15 
     16 namespace mozilla::dom {
     17 
     18 class PerformanceProxyData {
     19 public:
     20  PerformanceProxyData(UniquePtr<PerformanceTimingData>&& aData,
     21                       const nsAString& aInitiatorType,
     22                       const nsAString& aEntryName)
     23      : mData(std::move(aData)),
     24        mInitiatorType(aInitiatorType),
     25        mEntryName(aEntryName) {
     26    MOZ_RELEASE_ASSERT(mData);
     27  }
     28 
     29  UniquePtr<PerformanceTimingData> mData;  // always non-null
     30  nsString mInitiatorType;
     31  nsString mEntryName;
     32 };
     33 
     34 namespace {
     35 
     36 // Here we use control runnable because this code must be executed also when in
     37 // a sync event loop
     38 class PerformanceEntryAdder final : public WorkerControlRunnable {
     39 public:
     40  PerformanceEntryAdder(WorkerPrivate* aWorkerPrivate,
     41                        PerformanceStorageWorker* aStorage,
     42                        UniquePtr<PerformanceProxyData>&& aData)
     43      : WorkerControlRunnable("PerformanceEntryAdder"),
     44        mStorage(aStorage),
     45        mData(std::move(aData)) {}
     46 
     47  bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
     48    mStorage->AddEntryOnWorker(std::move(mData));
     49    return true;
     50  }
     51 
     52  nsresult Cancel() override {
     53    mStorage->ShutdownOnWorker();
     54    return NS_OK;
     55  }
     56 
     57  bool PreDispatch(WorkerPrivate* aWorkerPrivate) override { return true; }
     58 
     59  void PostDispatch(WorkerPrivate* aWorkerPrivate,
     60                    bool aDispatchResult) override {}
     61 
     62 private:
     63  RefPtr<PerformanceStorageWorker> mStorage;
     64  UniquePtr<PerformanceProxyData> mData;
     65 };
     66 
     67 }  // namespace
     68 
     69 /* static */
     70 already_AddRefed<PerformanceStorageWorker> PerformanceStorageWorker::Create(
     71    WorkerPrivate* aWorkerPrivate) {
     72  MOZ_ASSERT(aWorkerPrivate);
     73  aWorkerPrivate->AssertIsOnWorkerThread();
     74 
     75  RefPtr<PerformanceStorageWorker> storage = new PerformanceStorageWorker();
     76 
     77  MutexAutoLock lock(storage->mMutex);  // for thread-safety analysis
     78  storage->mWorkerRef = WeakWorkerRef::Create(
     79      aWorkerPrivate, [storage]() { storage->ShutdownOnWorker(); });
     80 
     81  // PerformanceStorageWorker is created at the creation time of the worker.
     82  MOZ_ASSERT(storage->mWorkerRef);
     83 
     84  return storage.forget();
     85 }
     86 
     87 PerformanceStorageWorker::PerformanceStorageWorker()
     88    : mMutex("PerformanceStorageWorker::mMutex") {}
     89 
     90 PerformanceStorageWorker::~PerformanceStorageWorker() = default;
     91 
     92 void PerformanceStorageWorker::AddEntry(nsIHttpChannel* aChannel,
     93                                        nsITimedChannel* aTimedChannel) {
     94  MOZ_ASSERT(NS_IsMainThread());
     95 
     96  MutexAutoLock lock(mMutex);
     97 
     98  if (!mWorkerRef) {
     99    return;
    100  }
    101 
    102  // If we have mWorkerRef, we haven't received the WorkerRef notification and
    103  // we haven't yet call ShutdownOnWorker, which uses the mutex.
    104  WorkerPrivate* workerPrivate = mWorkerRef->GetUnsafePrivate();
    105  MOZ_ASSERT(workerPrivate);
    106 
    107  nsAutoString initiatorType;
    108  nsAutoString entryName;
    109 
    110  UniquePtr<PerformanceTimingData> performanceTimingData(
    111      PerformanceTimingData::Create(aTimedChannel, aChannel, 0, initiatorType,
    112                                    entryName));
    113  if (!performanceTimingData) {
    114    return;
    115  }
    116 
    117  UniquePtr<PerformanceProxyData> data(new PerformanceProxyData(
    118      std::move(performanceTimingData), initiatorType, entryName));
    119 
    120  RefPtr<PerformanceEntryAdder> r =
    121      new PerformanceEntryAdder(workerPrivate, this, std::move(data));
    122  (void)NS_WARN_IF(!r->Dispatch(workerPrivate));
    123 }
    124 
    125 void PerformanceStorageWorker::AddEntry(
    126    const nsString& aEntryName, const nsString& aInitiatorType,
    127    UniquePtr<PerformanceTimingData>&& aData) {
    128  MOZ_ASSERT(!NS_IsMainThread());
    129  if (!aData) {
    130    return;
    131  }
    132 
    133  UniquePtr<PerformanceProxyData> data = MakeUnique<PerformanceProxyData>(
    134      std::move(aData), aInitiatorType, aEntryName);
    135 
    136  AddEntryOnWorker(std::move(data));
    137 }
    138 
    139 void PerformanceStorageWorker::ShutdownOnWorker() {
    140  MutexAutoLock lock(mMutex);
    141 
    142  if (!mWorkerRef) {
    143    return;
    144  }
    145 
    146  MOZ_ASSERT(!NS_IsMainThread());
    147 
    148  mWorkerRef = nullptr;
    149 }
    150 
    151 void PerformanceStorageWorker::AddEntryOnWorker(
    152    UniquePtr<PerformanceProxyData>&& aData) {
    153  RefPtr<Performance> performance;
    154  UniquePtr<PerformanceProxyData> data = std::move(aData);
    155 
    156  {
    157    MutexAutoLock lock(mMutex);
    158 
    159    if (!mWorkerRef) {
    160      return;
    161    }
    162 
    163    // We must have the workerPrivate because it is available until a
    164    // notification is received by WorkerRef and we use mutex to make the code
    165    // protected.
    166    WorkerPrivate* workerPrivate = mWorkerRef->GetPrivate();
    167    MOZ_ASSERT(workerPrivate);
    168 
    169    WorkerGlobalScope* scope = workerPrivate->GlobalScope();
    170    performance = scope->GetPerformance();
    171  }
    172 
    173  if (NS_WARN_IF(!performance)) {
    174    return;
    175  }
    176 
    177  RefPtr<PerformanceResourceTiming> performanceEntry =
    178      new PerformanceResourceTiming(std::move(data->mData), performance,
    179                                    data->mEntryName);
    180  performanceEntry->SetInitiatorType(data->mInitiatorType);
    181 
    182  performance->InsertResourceEntry(performanceEntry);
    183 }
    184 
    185 }  // namespace mozilla::dom