tor-browser

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

IDBTransaction.h (11091B)


      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_idbtransaction_h__
      8 #define mozilla_dom_idbtransaction_h__
      9 
     10 #include "FlippedOnce.h"
     11 #include "SafeRefPtr.h"
     12 #include "mozilla/DOMEventTargetHelper.h"
     13 #include "mozilla/SourceLocation.h"
     14 #include "mozilla/dom/IDBTransactionBinding.h"
     15 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
     16 #include "nsCycleCollectionParticipant.h"
     17 #include "nsIRunnable.h"
     18 #include "nsString.h"
     19 #include "nsTArray.h"
     20 
     21 namespace mozilla {
     22 
     23 class ErrorResult;
     24 class EventChainPreVisitor;
     25 
     26 namespace dom {
     27 
     28 class DOMException;
     29 class DOMStringList;
     30 class IDBCursor;
     31 class IDBDatabase;
     32 class IDBObjectStore;
     33 class IDBOpenDBRequest;
     34 class IDBRequest;
     35 class StrongWorkerRef;
     36 
     37 namespace indexedDB {
     38 class PBackgroundIDBCursorChild;
     39 class BackgroundRequestChild;
     40 class BackgroundTransactionChild;
     41 class BackgroundVersionChangeTransactionChild;
     42 class IndexMetadata;
     43 class ObjectStoreSpec;
     44 class OpenCursorParams;
     45 class RequestParams;
     46 }  // namespace indexedDB
     47 
     48 class IDBTransaction final
     49    : public DOMEventTargetHelper,
     50      public nsIRunnable,
     51      public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
     52  friend class indexedDB::BackgroundRequestChild;
     53 
     54 public:
     55  enum struct Mode {
     56    ReadOnly = 0,
     57    ReadWrite,
     58    ReadWriteFlush,
     59    Cleanup,
     60    VersionChange,
     61 
     62    // Only needed for IPC serialization helper, should never be used in code.
     63    Invalid
     64  };
     65 
     66  enum struct Durability {
     67    Default = 0,
     68    Strict,
     69    Relaxed,
     70 
     71    // Only needed for IPC serialization helper, should never be used in code.
     72    Invalid
     73  };
     74 
     75  enum struct ReadyState { Active, Inactive, Committing, Finished };
     76 
     77 private:
     78  // TODO: Only non-const because of Bug 1575173.
     79  RefPtr<IDBDatabase> mDatabase;
     80  RefPtr<DOMException> mError;
     81  const nsTArray<nsString> mObjectStoreNames;
     82  nsTArray<RefPtr<IDBObjectStore>> mObjectStores;
     83  nsTArray<RefPtr<IDBObjectStore>> mDeletedObjectStores;
     84  RefPtr<StrongWorkerRef> mWorkerRef;
     85  nsTArray<NotNull<IDBCursor*>> mCursors;
     86 
     87  // Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor
     88  // will be a BackgroundVersionChangeTransactionChild. Otherwise it will be a
     89  // BackgroundTransactionChild.
     90  union {
     91    indexedDB::BackgroundTransactionChild* mNormalBackgroundActor;
     92    indexedDB::BackgroundVersionChangeTransactionChild*
     93        mVersionChangeBackgroundActor;
     94  } mBackgroundActor;
     95 
     96  const int64_t mLoggingSerialNumber;
     97 
     98  // Only used for Mode::VersionChange transactions.
     99  int64_t mNextObjectStoreId;
    100  int64_t mNextIndexId;
    101 
    102  // Request ids are issued starting from 0 and incremented by one as we send
    103  // actor creation messages to the parent process. Used to support the
    104  // explicit commit() request.
    105  int64_t mNextRequestId;
    106 
    107  nsresult mAbortCode;  ///< The result that caused the transaction to be
    108                        ///< aborted, or NS_OK if not aborted.
    109                        ///< NS_ERROR_DOM_INDEXEDDB_ABORT_ERR indicates that the
    110                        ///< user explicitly requested aborting. Should be
    111                        ///< renamed to mResult or so, because it is actually
    112                        ///< used to check if the transaction has been aborted.
    113  uint32_t mPendingRequestCount;  ///< Counted via OnNewRequest and
    114                                  ///< OnRequestFinished, so that the
    115                                  ///< transaction can auto-commit when the last
    116                                  ///< pending request finished.
    117 
    118  const JSCallingLocation mCallerLocation;
    119 
    120  ReadyState mReadyState = ReadyState::Active;
    121  FlippedOnce<false> mStarted;
    122  const Mode mMode;
    123  const Durability mDurability;
    124 
    125  bool mRegistered;  ///< Whether mDatabase->RegisterTransaction() has been
    126                     ///< called (which may not be the case if construction was
    127                     ///< incomplete).
    128  FlippedOnce<false> mAbortedByScript;
    129  bool mNotedActiveTransaction;
    130  FlippedOnce<false> mSentCommitOrAbort;
    131 
    132 #ifdef DEBUG
    133  FlippedOnce<false> mFiredCompleteOrAbort;
    134  FlippedOnce<false> mWasExplicitlyCommitted;
    135 #endif
    136 
    137 public:
    138  [[nodiscard]] static SafeRefPtr<IDBTransaction> CreateVersionChange(
    139      IDBDatabase* aDatabase,
    140      indexedDB::BackgroundVersionChangeTransactionChild* aActor,
    141      NotNull<IDBOpenDBRequest*> aOpenRequest, int64_t aNextObjectStoreId,
    142      int64_t aNextIndexId);
    143 
    144  [[nodiscard]] static SafeRefPtr<IDBTransaction> Create(
    145      JSContext* aCx, IDBDatabase* aDatabase,
    146      const nsTArray<nsString>& aObjectStoreNames, Mode aMode,
    147      Durability aDurability);
    148 
    149  static Maybe<IDBTransaction&> MaybeCurrent();
    150 
    151  void AssertIsOnOwningThread() const
    152 #ifdef DEBUG
    153      ;
    154 #else
    155  {
    156  }
    157 #endif
    158 
    159  void SetBackgroundActor(
    160      indexedDB::BackgroundTransactionChild* aBackgroundActor);
    161 
    162  void ClearBackgroundActor() {
    163    AssertIsOnOwningThread();
    164 
    165    if (mMode == Mode::VersionChange) {
    166      mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
    167    } else {
    168      mBackgroundActor.mNormalBackgroundActor = nullptr;
    169    }
    170 
    171    // Note inactive transaction here if we didn't receive the Complete message
    172    // from the parent.
    173    MaybeNoteInactiveTransaction();
    174  }
    175 
    176  indexedDB::BackgroundRequestChild* StartRequest(
    177      MovingNotNull<RefPtr<mozilla::dom::IDBRequest>> aRequest,
    178      const indexedDB::RequestParams& aParams);
    179 
    180  void OpenCursor(indexedDB::PBackgroundIDBCursorChild& aBackgroundActor,
    181                  const indexedDB::OpenCursorParams& aParams);
    182 
    183  void RefreshSpec(bool aMayDelete);
    184 
    185  bool IsCommittingOrFinished() const {
    186    AssertIsOnOwningThread();
    187 
    188    return mReadyState == ReadyState::Committing ||
    189           mReadyState == ReadyState::Finished;
    190  }
    191 
    192  bool IsActive() const {
    193    AssertIsOnOwningThread();
    194 
    195    return mReadyState == ReadyState::Active;
    196  }
    197 
    198  bool IsInactive() const {
    199    AssertIsOnOwningThread();
    200 
    201    return mReadyState == ReadyState::Inactive;
    202  }
    203 
    204  bool IsFinished() const {
    205    AssertIsOnOwningThread();
    206 
    207    return mReadyState == ReadyState::Finished;
    208  }
    209 
    210  bool IsWriteAllowed() const {
    211    AssertIsOnOwningThread();
    212    return mMode == Mode::ReadWrite || mMode == Mode::ReadWriteFlush ||
    213           mMode == Mode::Cleanup || mMode == Mode::VersionChange;
    214  }
    215 
    216  bool IsAborted() const {
    217    AssertIsOnOwningThread();
    218    return NS_FAILED(mAbortCode);
    219  }
    220 
    221 #ifdef DEBUG
    222  bool WasExplicitlyCommitted() const { return mWasExplicitlyCommitted; }
    223 #endif
    224 
    225  void TransitionToActive() {
    226    MOZ_ASSERT(mReadyState == ReadyState::Inactive);
    227    mReadyState = ReadyState::Active;
    228  }
    229 
    230  void TransitionToInactive() {
    231    MOZ_ASSERT(mReadyState == ReadyState::Active);
    232    mReadyState = ReadyState::Inactive;
    233  }
    234 
    235  nsresult AbortCode() const {
    236    AssertIsOnOwningThread();
    237    return mAbortCode;
    238  }
    239 
    240  const JSCallingLocation& GetCallerLocation() const {
    241    AssertIsOnOwningThread();
    242    return mCallerLocation;
    243  }
    244 
    245  // 'Get' prefix is to avoid name collisions with the enum
    246  Mode GetMode() const {
    247    AssertIsOnOwningThread();
    248    return mMode;
    249  }
    250 
    251  Durability GetDurability() const {
    252    AssertIsOnOwningThread();
    253    return mDurability;
    254  }
    255 
    256  uint32_t GetPendingRequestCount() const { return mPendingRequestCount; }
    257 
    258  IDBDatabase* Database() const {
    259    AssertIsOnOwningThread();
    260    return mDatabase;
    261  }
    262 
    263  // Only for use by ProfilerHelpers.h
    264  const nsTArray<nsString>& ObjectStoreNamesInternal() const {
    265    AssertIsOnOwningThread();
    266    return mObjectStoreNames;
    267  }
    268 
    269  [[nodiscard]] RefPtr<IDBObjectStore> CreateObjectStore(
    270      indexedDB::ObjectStoreSpec& aSpec);
    271 
    272  void DeleteObjectStore(int64_t aObjectStoreId);
    273 
    274  void RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName) const;
    275 
    276  void CreateIndex(IDBObjectStore* aObjectStore,
    277                   const indexedDB::IndexMetadata& aMetadata) const;
    278 
    279  void DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId) const;
    280 
    281  void RenameIndex(IDBObjectStore* aObjectStore, int64_t aIndexId,
    282                   const nsAString& aName) const;
    283 
    284  void Abort(IDBRequest* aRequest);
    285 
    286  void Abort(nsresult aErrorCode);
    287 
    288  int64_t LoggingSerialNumber() const {
    289    AssertIsOnOwningThread();
    290 
    291    return mLoggingSerialNumber;
    292  }
    293 
    294  nsIGlobalObject* GetParentObject() const;
    295 
    296  void FireCompleteOrAbortEvents(nsresult aResult);
    297 
    298  // Only for Mode::VersionChange transactions.
    299  int64_t NextObjectStoreId();
    300 
    301  // Only for Mode::VersionChange transactions.
    302  int64_t NextIndexId();
    303 
    304  // See the comment for mNextRequestId.
    305  int64_t NextRequestId();
    306 
    307  void InvalidateCursorCaches();
    308  void RegisterCursor(IDBCursor& aCursor);
    309  void UnregisterCursor(IDBCursor& aCursor);
    310 
    311  NS_DECL_ISUPPORTS_INHERITED
    312  NS_DECL_NSIRUNNABLE
    313  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, DOMEventTargetHelper)
    314 
    315  void CommitIfNotStarted();
    316 
    317  // nsWrapperCache
    318  JSObject* WrapObject(JSContext* aCx,
    319                       JS::Handle<JSObject*> aGivenProto) override;
    320 
    321  // Methods bound via WebIDL.
    322  IDBDatabase* Db() const { return Database(); }
    323 
    324  IDBTransactionMode GetMode(ErrorResult& aRv) const;
    325 
    326  IDBTransactionDurability GetDurability(ErrorResult& aRv) const;
    327 
    328  DOMException* GetError() const;
    329 
    330  [[nodiscard]] RefPtr<IDBObjectStore> ObjectStore(const nsAString& aName,
    331                                                   ErrorResult& aRv);
    332 
    333  void Commit(ErrorResult& aRv);
    334 
    335  void Abort(ErrorResult& aRv);
    336 
    337  IMPL_EVENT_HANDLER(abort)
    338  IMPL_EVENT_HANDLER(complete)
    339  IMPL_EVENT_HANDLER(error)
    340 
    341  [[nodiscard]] RefPtr<DOMStringList> ObjectStoreNames() const;
    342 
    343  // EventTarget
    344  void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
    345 
    346 private:
    347  struct CreatedFromFactoryFunction {};
    348 
    349 public:
    350  IDBTransaction(IDBDatabase* aDatabase,
    351                 const nsTArray<nsString>& aObjectStoreNames, Mode aMode,
    352                 Durability aDurability, JSCallingLocation&& aCallerLocation,
    353                 CreatedFromFactoryFunction aDummy);
    354 
    355 private:
    356  ~IDBTransaction();
    357 
    358  void AbortInternal(nsresult aAbortCode, RefPtr<DOMException> aError);
    359 
    360  void SendCommit(bool aAutoCommit);
    361 
    362  void SendAbort(nsresult aResultCode);
    363 
    364  void NoteActiveTransaction();
    365 
    366  void MaybeNoteInactiveTransaction();
    367 
    368  // TODO consider making private again, or move to the right place
    369 public:
    370  void OnNewRequest();
    371 
    372  void OnRequestFinished(bool aRequestCompletedSuccessfully);
    373 
    374 private:
    375  template <typename Func>
    376  auto DoWithTransactionChild(const Func& aFunc) const;
    377 
    378  bool HasTransactionChild() const;
    379 };
    380 
    381 inline bool ReferenceEquals(const Maybe<IDBTransaction&>& aLHS,
    382                            const Maybe<IDBTransaction&>& aRHS) {
    383  if (aLHS.isNothing() != aRHS.isNothing()) {
    384    return false;
    385  }
    386  return aLHS.isNothing() || &aLHS.ref() == &aRHS.ref();
    387 }
    388 
    389 }  // namespace dom
    390 }  // namespace mozilla
    391 
    392 #endif  // mozilla_dom_idbtransaction_h__