Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/quota/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 6 kB image not shown  

Quelle  CanonicalQuotaObject.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "CanonicalQuotaObject.h"

#include "GroupInfo.h"
#include "GroupInfoPair.h"
#include "OriginInfo.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/StorageActivityService.h"
#include "mozilla/dom/quota/AssertionsImpl.h"
#include "mozilla/dom/quota/NotifyUtils.h"
#include "mozilla/dom/quota/OriginDirectoryLock.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/ipc/BackgroundParent.h"

namespace mozilla::dom::quota {

CanonicalQuotaObject::CanonicalQuotaObject(
    const RefPtr<OriginInfo>& aOriginInfo, Client::Type aClientType,
    const nsAString& aPath, int64_t aSize)
    : QuotaObject(/* aIsRemote */ false),
      mOriginInfo(aOriginInfo),
      mPath(aPath),
      mSize(aSize),
      mClientType(aClientType),
      mQuotaCheckDisabled(false),
      mWritingDone(false) {
  MOZ_COUNT_CTOR(CanonicalQuotaObject);
}

NS_IMETHODIMP_(MozExternalRefCountType) CanonicalQuotaObject::AddRef() {
  QuotaManager* quotaManager = QuotaManager::Get();
  if (!quotaManager) {
    NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");

    return ++mRefCnt;
  }

  MutexAutoLock lock(quotaManager->mQuotaMutex);

  return ++mRefCnt;
}

NS_IMETHODIMP_(MozExternalRefCountType) CanonicalQuotaObject::Release() {
  QuotaManager* quotaManager = QuotaManager::Get();
  if (!quotaManager) {
    NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");

    nsrefcnt count = --mRefCnt;
    if (count == 0) {
      mRefCnt = 1;
      delete this;
      return 0;
    }

    return mRefCnt;
  }

  {
    MutexAutoLock lock(quotaManager->mQuotaMutex);

    --mRefCnt;

    if (mRefCnt > 0) {
      return mRefCnt;
    }

    if (RefPtr<OriginInfo> originInfo = RefPtr<OriginInfo>(mOriginInfo)) {
      originInfo->mCanonicalQuotaObjects.Remove(mPath);
    }
  }

  delete this;
  return 0;
}

bool CanonicalQuotaObject::MaybeUpdateSize(int64_t aSize, bool aTruncate) {
  QuotaManager* quotaManager = QuotaManager::Get();
  MOZ_ASSERT(quotaManager);

  MutexAutoLock lock(quotaManager->mQuotaMutex);

  return LockedMaybeUpdateSize(aSize, aTruncate);
}

bool CanonicalQuotaObject::IncreaseSize(int64_t aDelta) {
  MOZ_ASSERT(aDelta >= 0);

  QuotaManager* quotaManager = QuotaManager::Get();
  MOZ_ASSERT(quotaManager);

  MutexAutoLock lock(quotaManager->mQuotaMutex);

  AssertNoOverflow(mSize, aDelta);
  int64_t size = mSize + aDelta;

  return LockedMaybeUpdateSize(size, /* aTruncate */ false);
}

void CanonicalQuotaObject::DisableQuotaCheck() {
  QuotaManager* quotaManager = QuotaManager::Get();
  MOZ_ASSERT(quotaManager);

  MutexAutoLock lock(quotaManager->mQuotaMutex);

  mQuotaCheckDisabled = true;
}

void CanonicalQuotaObject::EnableQuotaCheck() {
  QuotaManager* quotaManager = QuotaManager::Get();
  MOZ_ASSERT(quotaManager);

  MutexAutoLock lock(quotaManager->mQuotaMutex);

  mQuotaCheckDisabled = false;
}

bool CanonicalQuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate)
    MOZ_NO_THREAD_SAFETY_ANALYSIS {
  QuotaManager* quotaManager = QuotaManager::Get();
  MOZ_ASSERT(quotaManager);

  quotaManager->mQuotaMutex.AssertCurrentThreadOwns();

  RefPtr<OriginInfo> originInfo = RefPtr<OriginInfo>(mOriginInfo);

  if (mWritingDone == false && originInfo) {
    mWritingDone = true;
    StorageActivityService::SendActivity(originInfo->mOrigin);
  }

  if (mQuotaCheckDisabled) {
    return true;
  }

  if (mSize == aSize) {
    return true;
  }

  if (!originInfo) {
    mSize = aSize;
    return true;
  }

  DebugOnly<GroupInfo*> groupInfo = originInfo->mGroupInfo;
  MOZ_ASSERT(groupInfo);

  if (mSize > aSize) {
    if (aTruncate) {
      const int64_t delta = mSize - aSize;
      originInfo->LockedTruncateUsages(mClientType, delta);
      mSize = aSize;
    }
    return true;
  }

  MOZ_ASSERT(mSize < aSize);

  uint64_t delta = aSize - mSize;

  // Temporary storage has no limit for origin usage (there's a group and the
  // global limit though).

  if (const auto& maybeReturnValue =
          originInfo->LockedUpdateUsages(mClientType, delta)) {
    if (maybeReturnValue.value()) {
      mSize = aSize;  // No limit was breached and we are done.
    }

    return maybeReturnValue.value();
  }

  // This will block the thread without holding the lock while waitting.

  AutoTArray<RefPtr<OriginDirectoryLock>, 10> locks;
  uint64_t sizeToBeFreed;

  if (::mozilla::ipc::IsOnBackgroundThread()) {
    MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);

    sizeToBeFreed = quotaManager->CollectOriginsForEviction(delta, locks);
  } else {
    sizeToBeFreed = quotaManager->LockedCollectOriginsForEviction(delta, locks);
  }

  if (!sizeToBeFreed) {
    uint64_t usage = quotaManager->mTemporaryStorageUsage;

    MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);

    NotifyStoragePressure(*quotaManager, usage);

    return false;
  }

  NS_ASSERTION(sizeToBeFreed >= delta, "Huh?");

  {
    MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);

    for (const auto& lock : locks) {
      quotaManager->DeleteOriginDirectory(lock->OriginMetadata());
    }
  }

  // Relocked.

  for (const auto& lock : locks) {
    MOZ_ASSERT(!(lock->GetPersistenceType() == groupInfo->mPersistenceType &&
                 lock->Origin() == originInfo->mOrigin),
               "Deleted itself!");

    quotaManager->LockedRemoveQuotaForOrigin(lock->OriginMetadata());
  }

  // We unlocked and relocked several times so we need to recompute all the
  // essential variables and recheck the group limit.

  AssertNoUnderflow(aSize, mSize);
  const uint64_t increase = aSize - mSize;

  if (!originInfo->LockedUpdateUsagesForEviction(mClientType, increase)) {
    // Unfortunately some other thread increased the group usage in the
    // meantime and we are not below the group limit anymore.

    // However, the origin eviction must be finalized in this case too.
    MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);

    quotaManager->FinalizeOriginEviction(std::move(locks));
    return false;
  }

  // Some other thread could increase the size in the meantime, but no more
  // than this one.
  MOZ_ASSERT(mSize < aSize);
  mSize = aSize;

  // Finally, release IO thread only objects and allow next synchronized
  // ops for the evicted origins.
  MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);

  quotaManager->FinalizeOriginEviction(std::move(locks));

  return true;
}

}  // namespace mozilla::dom::quota

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-08-22) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.