tor-browser

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

IDBCursor.h (9764B)


      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 mozilla_dom_idbcursor_h__
      8 #define mozilla_dom_idbcursor_h__
      9 
     10 #include "IDBCursorType.h"
     11 #include "IndexedDatabase.h"
     12 #include "js/RootingAPI.h"
     13 #include "mozilla/InitializedOnce.h"
     14 #include "mozilla/dom/IDBCursorBinding.h"
     15 #include "mozilla/dom/IDBTransaction.h"
     16 #include "mozilla/dom/indexedDB/Key.h"
     17 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
     18 #include "nsCycleCollectionParticipant.h"
     19 #include "nsWrapperCache.h"
     20 
     21 class nsIGlobalObject;
     22 
     23 namespace mozilla {
     24 
     25 class ErrorResult;
     26 
     27 namespace dom {
     28 
     29 class IDBIndex;
     30 class IDBObjectStore;
     31 class IDBRequest;
     32 class OwningIDBObjectStoreOrIDBIndex;
     33 
     34 class IDBObjectStoreCursor;
     35 class IDBObjectStoreKeyCursor;
     36 class IDBIndexCursor;
     37 class IDBIndexKeyCursor;
     38 
     39 namespace indexedDB {
     40 class BackgroundCursorChildBase;
     41 template <IDBCursorType CursorType>
     42 class BackgroundCursorChild;
     43 }  // namespace indexedDB
     44 
     45 class IDBCursor : public nsISupports, public nsWrapperCache {
     46 public:
     47  using Key = indexedDB::Key;
     48  using StructuredCloneReadInfoChild = indexedDB::StructuredCloneReadInfoChild;
     49 
     50  using Direction = IDBCursorDirection;
     51  using Type = IDBCursorType;
     52 
     53 protected:
     54  InitializedOnce<const NotNull<indexedDB::BackgroundCursorChildBase*>>
     55      mBackgroundActor;
     56 
     57  // TODO: mRequest could be made const if Bug 1575173 is resolved. It is
     58  // initialized in the constructor and never modified/cleared.
     59  RefPtr<IDBRequest> mRequest;
     60 
     61  // Sub-classes' mSource will hold this alive.
     62  CheckedUnsafePtr<IDBTransaction> mTransaction;
     63 
     64 protected:
     65  // These are cycle-collected!
     66  JS::Heap<JS::Value> mCachedKey;
     67  JS::Heap<JS::Value> mCachedPrimaryKey;
     68  JS::Heap<JS::Value> mCachedValue;
     69 
     70  const Direction mDirection;
     71 
     72  bool mHaveCachedKey : 1;
     73  bool mHaveCachedPrimaryKey : 1;
     74  bool mHaveCachedValue : 1;
     75  bool mRooted : 1;
     76  bool mContinueCalled : 1;
     77  bool mHaveValue : 1;
     78 
     79 public:
     80  [[nodiscard]] static RefPtr<IDBObjectStoreCursor> Create(
     81      indexedDB::BackgroundCursorChild<Type::ObjectStore>* aBackgroundActor,
     82      Key aKey, StructuredCloneReadInfoChild&& aCloneInfo);
     83 
     84  [[nodiscard]] static RefPtr<IDBObjectStoreKeyCursor> Create(
     85      indexedDB::BackgroundCursorChild<Type::ObjectStoreKey>* aBackgroundActor,
     86      Key aKey);
     87 
     88  [[nodiscard]] static RefPtr<IDBIndexCursor> Create(
     89      indexedDB::BackgroundCursorChild<Type::Index>* aBackgroundActor, Key aKey,
     90      Key aSortKey, Key aPrimaryKey, StructuredCloneReadInfoChild&& aCloneInfo);
     91 
     92  [[nodiscard]] static RefPtr<IDBIndexKeyCursor> Create(
     93      indexedDB::BackgroundCursorChild<Type::IndexKey>* aBackgroundActor,
     94      Key aKey, Key aSortKey, Key aPrimaryKey);
     95 
     96  void AssertIsOnOwningThread() const
     97 #ifdef DEBUG
     98      ;
     99 #else
    100  {
    101  }
    102 #endif
    103 
    104  nsIGlobalObject* GetParentObject() const;
    105 
    106  // XXX: The virtual methods that are used by the DOM binding could be removed
    107  // on the base class, if we provided a non-polymorphic wrapper instead, which
    108  // uses a custom dispatch to the actual implementation type. Don't know if
    109  // this is worth it.
    110 
    111  virtual void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const = 0;
    112 
    113  IDBCursorDirection GetDirection() const;
    114 
    115  RefPtr<IDBRequest> Request() const;
    116 
    117  virtual void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
    118                      ErrorResult& aRv) = 0;
    119 
    120  virtual void GetPrimaryKey(JSContext* aCx,
    121                             JS::MutableHandle<JS::Value> aResult,
    122                             ErrorResult& aRv) = 0;
    123 
    124  // XXX: We could move this to a sub-class, since this is only present on
    125  // IDBCursorWithValue.
    126  virtual void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
    127                        ErrorResult& aRv) = 0;
    128 
    129  virtual void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
    130                        ErrorResult& aRv) = 0;
    131 
    132  virtual void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
    133                                  JS::Handle<JS::Value> aPrimaryKey,
    134                                  ErrorResult& aRv) = 0;
    135 
    136  virtual void Advance(uint32_t aCount, ErrorResult& aRv) = 0;
    137 
    138  [[nodiscard]] virtual RefPtr<IDBRequest> Update(JSContext* aCx,
    139                                                  JS::Handle<JS::Value> aValue,
    140                                                  ErrorResult& aRv) = 0;
    141 
    142  [[nodiscard]] virtual RefPtr<IDBRequest> Delete(JSContext* aCx,
    143                                                  ErrorResult& aRv) = 0;
    144 
    145  void ClearBackgroundActor() {
    146    AssertIsOnOwningThread();
    147 
    148    mBackgroundActor.destroy();
    149  }
    150 
    151  virtual void InvalidateCachedResponses() = 0;
    152 
    153  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    154  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
    155 
    156 protected:
    157  IDBCursor(indexedDB::BackgroundCursorChildBase* aBackgroundActor);
    158 
    159  // TODO: Check if we can remove virtual by changing cycle collection.
    160  virtual ~IDBCursor() = default;
    161 
    162  void ResetBase();
    163 };
    164 
    165 template <IDBCursor::Type CursorType>
    166 class IDBTypedCursor : public IDBCursor {
    167 public:
    168  template <typename... DataArgs>
    169  explicit IDBTypedCursor(
    170      indexedDB::BackgroundCursorChild<CursorType>* aBackgroundActor,
    171      DataArgs&&... aDataArgs);
    172 
    173  static constexpr Type GetType() { return CursorType; }
    174 
    175  // Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
    176  bool IsLocaleAware() const;
    177 
    178  void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const final;
    179 
    180  void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
    181              ErrorResult& aRv) final;
    182 
    183  void GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
    184                     ErrorResult& aRv) final;
    185 
    186  void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
    187                ErrorResult& aRv) final;
    188 
    189  void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
    190                ErrorResult& aRv) final;
    191 
    192  void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
    193                          JS::Handle<JS::Value> aPrimaryKey,
    194                          ErrorResult& aRv) final;
    195 
    196  void Advance(uint32_t aCount, ErrorResult& aRv) final;
    197 
    198  [[nodiscard]] RefPtr<IDBRequest> Update(JSContext* aCx,
    199                                          JS::Handle<JS::Value> aValue,
    200                                          ErrorResult& aRv) final;
    201 
    202  [[nodiscard]] RefPtr<IDBRequest> Delete(JSContext* aCx,
    203                                          ErrorResult& aRv) final;
    204 
    205  // nsWrapperCache
    206  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
    207 
    208  void InvalidateCachedResponses() final;
    209 
    210  void Reset();
    211 
    212  void Reset(CursorData<CursorType>&& aCursorData);
    213 
    214 private:
    215  static constexpr bool IsObjectStoreCursor =
    216      CursorTypeTraits<CursorType>::IsObjectStoreCursor;
    217  static constexpr bool IsKeyOnlyCursor =
    218      CursorTypeTraits<CursorType>::IsKeyOnlyCursor;
    219 
    220  CursorSourceType<CursorType>& GetSourceRef() const {
    221    MOZ_ASSERT(mSource);
    222    return *mSource;
    223  }
    224 
    225  IDBObjectStore& GetSourceObjectStoreRef() const {
    226    if constexpr (IsObjectStoreCursor) {
    227      return GetSourceRef();
    228    } else {
    229      MOZ_ASSERT(!GetSourceRef().IsDeleted());
    230 
    231      auto res = GetSourceRef().ObjectStore();
    232      MOZ_ASSERT(res);
    233      return *res;
    234    }
    235  }
    236 
    237  indexedDB::BackgroundCursorChild<CursorType>& GetTypedBackgroundActorRef()
    238      const {
    239    // We can safely downcast to BackgroundCursorChild<CursorType>*, since we
    240    // initialized that in the constructor from that type. We just want to avoid
    241    // having a second typed field.
    242    return *static_cast<indexedDB::BackgroundCursorChild<CursorType>*>(
    243        mBackgroundActor->get());
    244  }
    245 
    246  bool IsSourceDeleted() const;
    247 
    248 protected:
    249  virtual ~IDBTypedCursor() override;
    250 
    251  void DropJSObjects();
    252 
    253  CursorData<CursorType> mData;
    254 
    255  // TODO: mSource could be made const if Bug 1575173 is resolved. It is
    256  // initialized in the constructor and never modified/cleared.
    257  RefPtr<CursorSourceType<CursorType>> mSource;
    258 };
    259 
    260 // The subclasses defined by this macro are only needed to be able to use the
    261 // cycle collector macros, which do not support templates. If spelled out, the
    262 // cycle collection could be implemented directly on IDBTypedCursor, and these
    263 // classes were not needed.
    264 #define CONCRETE_IDBCURSOR_SUBCLASS(_subclassName, _cursorType)        \
    265  class _subclassName final : public IDBTypedCursor<_cursorType> {     \
    266   public:                                                             \
    267    NS_DECL_ISUPPORTS_INHERITED                                        \
    268    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_subclassName, IDBCursor) \
    269                                                                       \
    270    using IDBTypedCursor<_cursorType>::IDBTypedCursor;                 \
    271                                                                       \
    272   private:                                                            \
    273    ~_subclassName() final = default;                                  \
    274  };
    275 
    276 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreCursor, IDBCursor::Type::ObjectStore)
    277 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreKeyCursor,
    278                            IDBCursor::Type::ObjectStoreKey)
    279 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexCursor, IDBCursor::Type::Index)
    280 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexKeyCursor, IDBCursor::Type::IndexKey)
    281 
    282 template <IDBCursor::Type CursorType>
    283 using IDBCursorImpl = typename CursorTypeTraits<CursorType>::Type;
    284 
    285 }  // namespace dom
    286 }  // namespace mozilla
    287 
    288 #endif  // mozilla_dom_idbcursor_h__