tor-browser

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

FileInfoManager.h (4603B)


      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 #ifndef DOM_INDEXEDDB_FILEINFOMANAGER_H_
      8 #define DOM_INDEXEDDB_FILEINFOMANAGER_H_
      9 
     10 #include "FileInfo.h"
     11 #include "FlippedOnce.h"
     12 #include "mozilla/Mutex.h"
     13 #include "mozilla/StaticMutex.h"
     14 #include "nsHashKeys.h"
     15 #include "nsISupportsImpl.h"
     16 #include "nsTHashMap.h"
     17 
     18 namespace mozilla::dom::indexedDB {
     19 
     20 class FileInfoManagerBase {
     21 public:
     22  bool Invalidated() const { return mInvalidated; }
     23 
     24 protected:
     25  bool AssertValid() const {
     26    if (NS_WARN_IF(Invalidated())) {
     27      MOZ_ASSERT(false);
     28      return false;
     29    }
     30 
     31    return true;
     32  }
     33 
     34  void Invalidate() { mInvalidated.Flip(); }
     35 
     36 private:
     37  FlippedOnce<false> mInvalidated;
     38 };
     39 
     40 template <typename FileManager>
     41 class FileInfoManager : public FileInfoManagerBase {
     42 public:
     43  using FileInfoType = FileInfo<FileManager>;
     44  using MutexType = StaticMutex;
     45  using AutoLockType = mozilla::detail::BaseAutoLock<MutexType&>;
     46 
     47  [[nodiscard]] SafeRefPtr<FileInfoType> GetFileInfo(int64_t aId) const {
     48    return AcquireFileInfo([this, aId]() MOZ_REQUIRES(Mutex()) {
     49      return mFileInfos.MaybeGet(aId);
     50    });
     51  }
     52 
     53  bool ContainsFileInfo(int64_t aFileId) {
     54    AutoLockType lock(Mutex());
     55    return mFileInfos.Contains(aFileId);
     56  }
     57 
     58  [[nodiscard]] SafeRefPtr<FileInfoType> CreateFileInfo(
     59      const Maybe<int64_t>& aMaybeId = Nothing(),
     60      const nsrefcnt aDBRefCnt = 0) {
     61    return AcquireFileInfo([this, &aMaybeId,
     62                            &aDBRefCnt]() MOZ_REQUIRES(Mutex()) {
     63      const int64_t id = aMaybeId.isSome() ? *aMaybeId : ++mLastFileId;
     64 
     65      auto fileInfo =
     66          MakeNotNull<FileInfoType*>(FileInfoManagerGuard{},
     67                                     SafeRefPtr{static_cast<FileManager*>(this),
     68                                                AcquireStrongRefFromRawPtr{}},
     69                                     id, aDBRefCnt);
     70 
     71      mFileInfos.InsertOrUpdate(id, fileInfo);
     72 
     73      if (aMaybeId.isSome()) {
     74        mLastFileId = std::max(id, mLastFileId);
     75      }
     76 
     77      return Some(fileInfo);
     78    });
     79  }
     80 
     81  void RemoveFileInfo(const int64_t aId, const AutoLockType& aFileMutexLock)
     82      MOZ_REQUIRES(Mutex()) {
     83 #ifdef DEBUG
     84    aFileMutexLock.AssertOwns(Mutex());
     85 #endif
     86    mFileInfos.Remove(aId);
     87  }
     88 
     89  // After calling this method, callers should not call any more methods on this
     90  // class.
     91  virtual nsresult Invalidate() {
     92    AutoLockType lock(Mutex());
     93 
     94    FileInfoManagerBase::Invalidate();
     95 
     96    mFileInfos.RemoveIf([](const auto& iter) {
     97      FileInfoType* info = iter.Data();
     98      MOZ_ASSERT(info);
     99 
    100      return !info->LockedClearDBRefs(FileInfoManagerGuard{});
    101    });
    102 
    103    return NS_OK;
    104  }
    105 
    106  struct FileInfoManagerGuard {
    107    FileInfoManagerGuard() = default;
    108  };
    109 
    110  static MutexType& Mutex() { return FileManager::MutexInstance(); }
    111 
    112 private:
    113  // Runs the given aFileInfoTableOp operation, which must return a FileInfo*,
    114  // under the FileManager lock, acquires a strong reference to the returned
    115  // object under the lock, and returns the strong reference.
    116  template <typename FileInfoTableOp>
    117  [[nodiscard]] SafeRefPtr<FileInfoType> AcquireFileInfo(
    118      const FileInfoTableOp& aFileInfoTableOp) const {
    119    if (!AssertValid()) {
    120      // In release, the assertions are disabled.
    121      return nullptr;
    122    }
    123 
    124    // We cannot simply change this to SafeRefPtr<FileInfo>, because
    125    // FileInfo::AddRef also acquires the FileManager::Mutex.
    126    auto fileInfo = [&aFileInfoTableOp]() -> RefPtr<FileInfoType> {
    127      AutoLockType lock(Mutex());
    128 
    129      const auto maybeFileInfo = aFileInfoTableOp();
    130      if (maybeFileInfo) {
    131        const auto& fileInfo = maybeFileInfo.ref();
    132        fileInfo->LockedAddRef();
    133        return dont_AddRef(fileInfo.get());
    134      }
    135 
    136      return {};
    137    }();
    138 
    139    return SafeRefPtr{std::move(fileInfo)};
    140  }
    141 
    142  // Access to the following private fields must be protected by
    143  // FileManager::Mutex() which is now enforced by MOZ_GUARDED_BY annotations.
    144  nsTHashMap<nsUint64HashKey, NotNull<FileInfoType*>> mFileInfos
    145      MOZ_GUARDED_BY(Mutex());
    146 
    147  int64_t mLastFileId MOZ_GUARDED_BY(Mutex()) = 0;
    148 
    149 protected:
    150 #ifdef DEBUG
    151  ~FileInfoManager() { MOZ_ASSERT(mFileInfos.IsEmpty()); }
    152 #else
    153  ~FileInfoManager() = default;
    154 #endif
    155 };
    156 
    157 }  // namespace mozilla::dom::indexedDB
    158 
    159 #endif  // DOM_INDEXEDDB_FILEINFOMANAGER_H_