tor-browser

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

RefMessageBodyService.cpp (4553B)


      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 "RefMessageBodyService.h"
      8 
      9 #include <cstdint>
     10 
     11 #include "mozilla/ErrorResult.h"
     12 #include "mozilla/RefPtr.h"
     13 #include "mozilla/dom/ipc/StructuredCloneData.h"
     14 #include "nsBaseHashtable.h"
     15 #include "nsDebug.h"
     16 
     17 namespace mozilla::dom {
     18 
     19 // Guards sService and its members.
     20 StaticMutex sRefMessageBodyServiceMutex;
     21 
     22 // Raw pointer because the service is kept alive by other objects.
     23 // See the CTOR and the DTOR of this object.
     24 RefMessageBodyService* sService;
     25 
     26 // static
     27 already_AddRefed<RefMessageBodyService> RefMessageBodyService::GetOrCreate() {
     28  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
     29 
     30  RefPtr<RefMessageBodyService> service = GetOrCreateInternal(lock);
     31  return service.forget();
     32 }
     33 
     34 // static
     35 RefMessageBodyService* RefMessageBodyService::GetOrCreateInternal(
     36    const StaticMutexAutoLock& aProofOfLock) {
     37  if (!sService) {
     38    sService = new RefMessageBodyService(aProofOfLock);
     39  }
     40  return sService;
     41 }
     42 
     43 RefMessageBodyService::RefMessageBodyService(
     44    const StaticMutexAutoLock& aProofOfLock) {
     45  MOZ_DIAGNOSTIC_ASSERT(sService == nullptr);
     46 }
     47 
     48 RefMessageBodyService::~RefMessageBodyService() {
     49  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
     50  MOZ_DIAGNOSTIC_ASSERT(sService == this);
     51  sService = nullptr;
     52 }
     53 
     54 const nsID RefMessageBodyService::Register(
     55    already_AddRefed<RefMessageBody> aBody, ErrorResult& aRv) {
     56  RefPtr<RefMessageBody> body = aBody;
     57  MOZ_ASSERT(body);
     58 
     59  nsID uuid = {};
     60  aRv = nsID::GenerateUUIDInPlace(uuid);
     61  if (NS_WARN_IF(aRv.Failed())) {
     62    return nsID();
     63  }
     64 
     65  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
     66  GetOrCreateInternal(lock)->mMessages.InsertOrUpdate(uuid, std::move(body));
     67  return uuid;
     68 }
     69 
     70 already_AddRefed<RefMessageBody> RefMessageBodyService::Steal(const nsID& aID) {
     71  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
     72  if (!sService) {
     73    return nullptr;
     74  }
     75 
     76  RefPtr<RefMessageBody> body;
     77  sService->mMessages.Remove(aID, getter_AddRefs(body));
     78 
     79  return body.forget();
     80 }
     81 
     82 already_AddRefed<RefMessageBody> RefMessageBodyService::GetAndCount(
     83    const nsID& aID) {
     84  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
     85  if (!sService) {
     86    return nullptr;
     87  }
     88 
     89  RefPtr<RefMessageBody> body = sService->mMessages.Get(aID);
     90  if (!body) {
     91    return nullptr;
     92  }
     93 
     94  ++body->mCount;
     95 
     96  MOZ_ASSERT_IF(body->mMaxCount.isSome(),
     97                body->mCount <= body->mMaxCount.value());
     98  if (body->mMaxCount.isSome() && body->mCount >= body->mMaxCount.value()) {
     99    sService->mMessages.Remove(aID);
    100  }
    101 
    102  return body.forget();
    103 }
    104 
    105 void RefMessageBodyService::SetMaxCount(const nsID& aID, uint32_t aMaxCount) {
    106  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
    107  if (!sService) {
    108    return;
    109  }
    110 
    111  RefPtr<RefMessageBody> body = sService->mMessages.Get(aID);
    112  if (!body) {
    113    return;
    114  }
    115 
    116  MOZ_ASSERT(body->mMaxCount.isNothing());
    117  body->mMaxCount.emplace(aMaxCount);
    118 
    119  MOZ_ASSERT(body->mCount <= body->mMaxCount.value());
    120  if (body->mCount >= body->mMaxCount.value()) {
    121    sService->mMessages.Remove(aID);
    122  }
    123 }
    124 
    125 void RefMessageBodyService::ForgetPort(const nsID& aPortID) {
    126  StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
    127  if (!sService) {
    128    return;
    129  }
    130 
    131  for (auto iter = sService->mMessages.Iter(); !iter.Done(); iter.Next()) {
    132    if (iter.UserData()->PortID() == aPortID) {
    133      iter.Remove();
    134    }
    135  }
    136 }
    137 
    138 RefMessageBody::RefMessageBody(const nsID& aPortID,
    139                               UniquePtr<ipc::StructuredCloneData>&& aCloneData)
    140    : mPortID(aPortID),
    141      mMutex("RefMessageBody::mMutex"),
    142      mCloneData(std::move(aCloneData)),
    143      mMaxCount(Nothing()),
    144      mCount(0) {}
    145 
    146 RefMessageBody::~RefMessageBody() = default;
    147 
    148 void RefMessageBody::Read(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
    149                          const JS::CloneDataPolicy& aCloneDataPolicy,
    150                          ErrorResult& aRv) {
    151  MutexAutoLock lock(mMutex);
    152  mCloneData->Read(aCx, aValue, aCloneDataPolicy, aRv);
    153 }
    154 
    155 bool RefMessageBody::TakeTransferredPortsAsSequence(
    156    Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts) {
    157  MOZ_ASSERT(mMaxCount.isNothing());
    158  return mCloneData->TakeTransferredPortsAsSequence(aPorts);
    159 }
    160 
    161 }  // namespace mozilla::dom