tor-browser

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

CacheWorkerRef.cpp (4073B)


      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/cache/CacheWorkerRef.h"
      8 
      9 #include "mozilla/dom/WorkerPrivate.h"
     10 #include "mozilla/dom/WorkerRef.h"
     11 #include "mozilla/dom/cache/ActorChild.h"
     12 
     13 namespace mozilla::dom::cache {
     14 
     15 // static
     16 SafeRefPtr<CacheWorkerRef> CacheWorkerRef::Create(WorkerPrivate* aWorkerPrivate,
     17                                                  Behavior aBehavior) {
     18  MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
     19 
     20  // XXX This looks as if this could be simplified now by moving into the ctor
     21  // of CacheWorkerRef, since we can now use SafeRefPtrFromThis in the ctor
     22  auto workerRef =
     23      MakeSafeRefPtr<CacheWorkerRef>(aBehavior, ConstructorGuard{});
     24  auto notify = [workerRef = workerRef.clonePtr()] { workerRef->Notify(); };
     25  if (aBehavior == eStrongWorkerRef) {
     26    workerRef->mStrongWorkerRef = StrongWorkerRef::Create(
     27        aWorkerPrivate, "CacheWorkerRef-Strong", std::move(notify));
     28  } else {
     29    MOZ_ASSERT(aBehavior == eIPCWorkerRef);
     30    workerRef->mIPCWorkerRef = IPCWorkerRef::Create(
     31        aWorkerPrivate, "CacheWorkerRef-IPC", std::move(notify));
     32  }
     33 
     34  if (NS_WARN_IF(!workerRef->mIPCWorkerRef && !workerRef->mStrongWorkerRef)) {
     35    return nullptr;
     36  }
     37 
     38  return workerRef;
     39 }
     40 
     41 // static
     42 SafeRefPtr<CacheWorkerRef> CacheWorkerRef::PreferBehavior(
     43    SafeRefPtr<CacheWorkerRef> aCurrentRef, Behavior aBehavior) {
     44  if (!aCurrentRef) {
     45    return nullptr;
     46  }
     47 
     48  SafeRefPtr<CacheWorkerRef> orig = std::move(aCurrentRef);
     49  if (orig->mBehavior == aBehavior) {
     50    return orig;
     51  }
     52 
     53  WorkerPrivate* workerPrivate = nullptr;
     54  if (orig->mBehavior == eStrongWorkerRef) {
     55    workerPrivate = orig->mStrongWorkerRef->Private();
     56  } else {
     57    MOZ_ASSERT(orig->mBehavior == eIPCWorkerRef);
     58    workerPrivate = orig->mIPCWorkerRef->Private();
     59  }
     60 
     61  MOZ_ASSERT(workerPrivate);
     62 
     63  SafeRefPtr<CacheWorkerRef> replace = Create(workerPrivate, aBehavior);
     64  return static_cast<bool>(replace) ? std::move(replace) : std::move(orig);
     65 }
     66 
     67 void CacheWorkerRef::AddActor(ActorChild& aActor) {
     68  NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
     69  MOZ_ASSERT(!mActorList.Contains(&aActor));
     70 
     71  mActorList.AppendElement(WrapNotNullUnchecked(&aActor));
     72  if (mBehavior == eIPCWorkerRef) {
     73    MOZ_ASSERT(mIPCWorkerRef);
     74    mIPCWorkerRef->SetActorCount(mActorList.Length());
     75  }
     76 
     77  // Allow an actor to be added after we've entered the Notifying case.  We
     78  // can't stop the actor creation from racing with out destruction of the
     79  // other actors and we need to wait for this extra one to close as well.
     80  // Signal it should destroy itself right away.
     81  if (mNotified) {
     82    aActor.StartDestroy();
     83  }
     84 }
     85 
     86 void CacheWorkerRef::RemoveActor(ActorChild& aActor) {
     87  NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
     88 
     89 #if defined(RELEASE_OR_BETA)
     90  mActorList.RemoveElement(&aActor);
     91 #else
     92  MOZ_DIAGNOSTIC_ASSERT(mActorList.RemoveElement(&aActor));
     93 #endif
     94 
     95  MOZ_ASSERT(!mActorList.Contains(&aActor));
     96 
     97  if (mBehavior == eIPCWorkerRef) {
     98    MOZ_ASSERT(mIPCWorkerRef);
     99    mIPCWorkerRef->SetActorCount(mActorList.Length());
    100  }
    101 
    102  if (mActorList.IsEmpty()) {
    103    mStrongWorkerRef = nullptr;
    104    mIPCWorkerRef = nullptr;
    105  }
    106 }
    107 
    108 bool CacheWorkerRef::Notified() const { return mNotified; }
    109 
    110 void CacheWorkerRef::Notify() {
    111  NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
    112 
    113  mNotified = true;
    114 
    115  // Start the asynchronous destruction of our actors.  These will call back
    116  // into RemoveActor() once the actor is destroyed.
    117  for (const auto& actor : mActorList) {
    118    actor->StartDestroy();
    119  }
    120 }
    121 
    122 CacheWorkerRef::CacheWorkerRef(Behavior aBehavior, ConstructorGuard)
    123    : mBehavior(aBehavior), mNotified(false) {}
    124 
    125 CacheWorkerRef::~CacheWorkerRef() {
    126  NS_ASSERT_OWNINGTHREAD(CacheWorkerRef);
    127  MOZ_DIAGNOSTIC_ASSERT(mActorList.IsEmpty());
    128 }
    129 
    130 }  // namespace mozilla::dom::cache