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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_indexeddb_actorschild_h__
8 #define mozilla_dom_indexeddb_actorschild_h__
10 #include "js/RootingAPI.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/dom/IDBCursorType.h"
13 #include "mozilla/dom/IDBTransaction.h"
14 #include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h"
15 #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseChild.h"
16 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
17 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h"
18 #include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h"
19 #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
20 #include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h"
21 #include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h"
22 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
23 #include "mozilla/InitializedOnce.h"
24 #include "mozilla/UniquePtr.h"
34 class BackgroundChildImpl
;
43 class IDBOpenDBRequest
;
45 class IndexedDatabaseManager
;
50 class PermissionRequestChild
;
51 class PermissionRequestParent
;
52 class SerializedStructuredCloneReadInfo
;
55 } // namespace indexedDB
57 } // namespace mozilla
59 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::dom::indexedDB::CloneInfo
)
61 namespace mozilla::dom::indexedDB
{
63 class BackgroundFactoryChild final
: public PBackgroundIDBFactoryChild
{
64 friend class mozilla::ipc::BackgroundChildImpl
;
67 // TODO: This long-lived raw pointer is very suspicious, in particular as it
68 // is used in BackgroundDatabaseChild::EnsureDOMObject to reacquire a strong
69 // reference. What ensures it is kept alive, and why can't we store a strong
74 NS_INLINE_DECL_REFCOUNTING(BackgroundFactoryChild
, override
)
76 void AssertIsOnOwningThread() const {
77 NS_ASSERT_OWNINGTHREAD(BackgroundFactoryChild
);
80 IDBFactory
& GetDOMObject() const {
81 AssertIsOnOwningThread();
86 bool SendDeleteMe() = delete;
89 // Only created by IDBFactory.
90 explicit BackgroundFactoryChild(IDBFactory
& aFactory
);
92 // Only destroyed by mozilla::ipc::BackgroundChildImpl.
93 ~BackgroundFactoryChild();
95 void SendDeleteMeInternal();
98 // IPDL methods are only called by IPDL.
99 void ActorDestroy(ActorDestroyReason aWhy
) override
;
101 PBackgroundIDBFactoryRequestChild
* AllocPBackgroundIDBFactoryRequestChild(
102 const FactoryRequestParams
& aParams
);
104 bool DeallocPBackgroundIDBFactoryRequestChild(
105 PBackgroundIDBFactoryRequestChild
* aActor
);
107 PBackgroundIDBDatabaseChild
* AllocPBackgroundIDBDatabaseChild(
108 const DatabaseSpec
& aSpec
,
109 PBackgroundIDBFactoryRequestChild
* aRequest
) const;
111 bool DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild
* aActor
);
113 mozilla::ipc::IPCResult
RecvPBackgroundIDBDatabaseConstructor(
114 PBackgroundIDBDatabaseChild
* aActor
, const DatabaseSpec
& aSpec
,
115 NotNull
<PBackgroundIDBFactoryRequestChild
*> aRequest
) override
;
118 class BackgroundDatabaseChild
;
120 class BackgroundRequestChildBase
{
122 const NotNull
<RefPtr
<IDBRequest
>> mRequest
;
125 void AssertIsOnOwningThread() const
134 explicit BackgroundRequestChildBase(
135 MovingNotNull
<RefPtr
<IDBRequest
>> aRequest
);
137 virtual ~BackgroundRequestChildBase();
140 class BackgroundFactoryRequestChild final
141 : public BackgroundRequestChildBase
,
142 public PBackgroundIDBFactoryRequestChild
{
143 using PersistenceType
= mozilla::dom::quota::PersistenceType
;
146 friend class BackgroundFactoryChild
;
147 friend class BackgroundDatabaseChild
;
148 friend class PermissionRequestChild
;
149 friend class PermissionRequestParent
;
151 const SafeRefPtr
<IDBFactory
> mFactory
;
153 // Normally when opening of a database is successful, we receive a database
154 // actor in request response, so we can use it to call ReleaseDOMObject()
155 // which clears temporary strong reference to IDBDatabase.
156 // However, when there's an error, we don't receive a database actor and
157 // IDBRequest::mTransaction is already cleared (must be). So the only way how
158 // to call ReleaseDOMObject() is to have a back-reference to database actor.
159 // This creates a weak ref cycle between
160 // BackgroundFactoryRequestChild (using mDatabaseActor member) and
161 // BackgroundDatabaseChild actor (using mOpenRequestActor member).
162 // mDatabaseActor is set in EnsureDOMObject() and cleared in
163 // ReleaseDOMObject().
164 BackgroundDatabaseChild
* mDatabaseActor
;
166 const uint64_t mRequestedVersion
;
167 const bool mIsDeleteOp
;
170 NotNull
<IDBOpenDBRequest
*> GetOpenDBRequest() const;
173 // Only created by IDBFactory.
174 BackgroundFactoryRequestChild(
175 SafeRefPtr
<IDBFactory
> aFactory
,
176 MovingNotNull
<RefPtr
<IDBOpenDBRequest
>> aOpenRequest
, bool aIsDeleteOp
,
177 uint64_t aRequestedVersion
);
179 // Only destroyed by BackgroundFactoryChild.
180 ~BackgroundFactoryRequestChild();
182 void SetDatabaseActor(BackgroundDatabaseChild
* aActor
);
184 void HandleResponse(nsresult aResponse
);
186 void HandleResponse(const OpenDatabaseRequestResponse
& aResponse
);
188 void HandleResponse(const DeleteDatabaseRequestResponse
& aResponse
);
191 // IPDL methods are only called by IPDL.
192 void ActorDestroy(ActorDestroyReason aWhy
) override
;
194 mozilla::ipc::IPCResult
Recv__delete__(
195 const FactoryRequestResponse
& aResponse
);
197 mozilla::ipc::IPCResult
RecvPermissionChallenge(
198 PrincipalInfo
&& aPrincipalInfo
);
200 mozilla::ipc::IPCResult
RecvBlocked(uint64_t aCurrentVersion
);
203 class BackgroundDatabaseChild final
: public PBackgroundIDBDatabaseChild
{
204 friend class BackgroundFactoryChild
;
205 friend class BackgroundFactoryRequestChild
;
208 UniquePtr
<DatabaseSpec
> mSpec
;
209 RefPtr
<IDBDatabase
> mTemporaryStrongDatabase
;
210 BackgroundFactoryRequestChild
* mOpenRequestActor
;
211 IDBDatabase
* mDatabase
;
214 void AssertIsOnOwningThread() const
222 const DatabaseSpec
* Spec() const {
223 AssertIsOnOwningThread();
227 IDBDatabase
* GetDOMObject() const {
228 AssertIsOnOwningThread();
232 bool SendDeleteMe() = delete;
235 // Only constructed by BackgroundFactoryChild.
236 BackgroundDatabaseChild(const DatabaseSpec
& aSpec
,
237 BackgroundFactoryRequestChild
* aOpenRequest
);
239 // Only destroyed by BackgroundFactoryChild.
240 ~BackgroundDatabaseChild();
242 void SendDeleteMeInternal();
244 [[nodiscard
]] bool EnsureDOMObject();
246 void ReleaseDOMObject();
249 // IPDL methods are only called by IPDL.
250 void ActorDestroy(ActorDestroyReason aWhy
) override
;
252 PBackgroundIDBDatabaseFileChild
* AllocPBackgroundIDBDatabaseFileChild(
253 const IPCBlob
& aIPCBlob
);
255 bool DeallocPBackgroundIDBDatabaseFileChild(
256 PBackgroundIDBDatabaseFileChild
* aActor
) const;
258 already_AddRefed
<PBackgroundIDBVersionChangeTransactionChild
>
259 AllocPBackgroundIDBVersionChangeTransactionChild(uint64_t aCurrentVersion
,
260 uint64_t aRequestedVersion
,
261 int64_t aNextObjectStoreId
,
262 int64_t aNextIndexId
);
264 mozilla::ipc::IPCResult
RecvPBackgroundIDBVersionChangeTransactionConstructor(
265 PBackgroundIDBVersionChangeTransactionChild
* aActor
,
266 const uint64_t& aCurrentVersion
, const uint64_t& aRequestedVersion
,
267 const int64_t& aNextObjectStoreId
, const int64_t& aNextIndexId
) override
;
269 mozilla::ipc::IPCResult
RecvVersionChange(uint64_t aOldVersion
,
270 Maybe
<uint64_t> aNewVersion
);
272 mozilla::ipc::IPCResult
RecvInvalidate();
274 mozilla::ipc::IPCResult
RecvCloseAfterInvalidationComplete();
277 class BackgroundVersionChangeTransactionChild
;
279 class BackgroundTransactionBase
{
280 friend class BackgroundVersionChangeTransactionChild
;
282 // mTemporaryStrongTransaction is strong and is only valid until the end of
283 // NoteComplete() member function or until the NoteActorDestroyed() member
284 // function is called.
285 SafeRefPtr
<IDBTransaction
> mTemporaryStrongTransaction
;
288 // mTransaction is weak and is valid until the NoteActorDestroyed() member
289 // function is called.
290 IDBTransaction
* mTransaction
= nullptr;
294 virtual void AssertIsOnOwningThread() const = 0;
296 void AssertIsOnOwningThread() const {}
299 IDBTransaction
* GetDOMObject() const {
300 AssertIsOnOwningThread();
305 MOZ_COUNTED_DEFAULT_CTOR(BackgroundTransactionBase
);
307 explicit BackgroundTransactionBase(SafeRefPtr
<IDBTransaction
> aTransaction
);
309 MOZ_COUNTED_DTOR_VIRTUAL(BackgroundTransactionBase
);
311 void NoteActorDestroyed();
316 // Only called by BackgroundVersionChangeTransactionChild.
317 void SetDOMTransaction(SafeRefPtr
<IDBTransaction
> aTransaction
);
320 class BackgroundTransactionChild final
: public BackgroundTransactionBase
,
321 public PBackgroundIDBTransactionChild
{
322 friend class BackgroundDatabaseChild
;
326 NS_INLINE_DECL_REFCOUNTING(BackgroundTransactionChild
, override
)
329 void AssertIsOnOwningThread() const override
;
332 void SendDeleteMeInternal();
334 bool SendDeleteMe() = delete;
337 // Only created by IDBDatabase.
338 explicit BackgroundTransactionChild(SafeRefPtr
<IDBTransaction
> aTransaction
);
340 // Only destroyed by BackgroundDatabaseChild.
341 ~BackgroundTransactionChild();
344 // IPDL methods are only called by IPDL.
345 void ActorDestroy(ActorDestroyReason aWhy
) override
;
347 mozilla::ipc::IPCResult
RecvComplete(nsresult aResult
);
349 PBackgroundIDBRequestChild
* AllocPBackgroundIDBRequestChild(
350 const RequestParams
& aParams
);
352 bool DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild
* aActor
);
354 PBackgroundIDBCursorChild
* AllocPBackgroundIDBCursorChild(
355 const OpenCursorParams
& aParams
);
357 bool DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild
* aActor
);
360 class BackgroundVersionChangeTransactionChild final
361 : public BackgroundTransactionBase
,
362 public PBackgroundIDBVersionChangeTransactionChild
{
363 friend class BackgroundDatabaseChild
;
365 IDBOpenDBRequest
* mOpenDBRequest
;
368 NS_INLINE_DECL_REFCOUNTING(BackgroundVersionChangeTransactionChild
, override
)
371 void AssertIsOnOwningThread() const override
;
374 void SendDeleteMeInternal(bool aFailedConstructor
);
376 bool SendDeleteMe() = delete;
379 // Only created by BackgroundDatabaseChild.
380 explicit BackgroundVersionChangeTransactionChild(
381 IDBOpenDBRequest
* aOpenDBRequest
);
383 // Only destroyed by BackgroundDatabaseChild.
384 ~BackgroundVersionChangeTransactionChild();
386 // Only called by BackgroundDatabaseChild.
387 using BackgroundTransactionBase::SetDOMTransaction
;
390 // IPDL methods are only called by IPDL.
391 void ActorDestroy(ActorDestroyReason aWhy
) override
;
393 mozilla::ipc::IPCResult
RecvComplete(nsresult aResult
);
395 PBackgroundIDBRequestChild
* AllocPBackgroundIDBRequestChild(
396 const RequestParams
& aParams
);
398 bool DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild
* aActor
);
400 PBackgroundIDBCursorChild
* AllocPBackgroundIDBCursorChild(
401 const OpenCursorParams
& aParams
);
403 bool DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild
* aActor
);
406 class BackgroundRequestChild final
: public BackgroundRequestChildBase
,
407 public PBackgroundIDBRequestChild
{
408 friend class BackgroundTransactionChild
;
409 friend class BackgroundVersionChangeTransactionChild
;
410 friend struct CloneInfo
;
411 friend IDBTransaction
;
413 class PreprocessHelper
;
415 SafeRefPtr
<IDBTransaction
> mTransaction
;
416 nsTArray
<CloneInfo
> mCloneInfos
;
417 uint32_t mRunningPreprocessHelpers
;
418 uint32_t mCurrentCloneDataIndex
;
419 nsresult mPreprocessResultCode
;
423 // Only created by IDBTransaction.
424 explicit BackgroundRequestChild(MovingNotNull
<RefPtr
<IDBRequest
>> aRequest
);
426 // Only destroyed by BackgroundTransactionChild or
427 // BackgroundVersionChangeTransactionChild.
428 ~BackgroundRequestChild();
430 void MaybeSendContinue();
432 void OnPreprocessFinished(uint32_t aCloneDataIndex
,
433 UniquePtr
<JSStructuredCloneData
> aCloneData
);
435 void OnPreprocessFailed(uint32_t aCloneDataIndex
, nsresult aErrorCode
);
437 UniquePtr
<JSStructuredCloneData
> GetNextCloneData();
439 void HandleResponse(nsresult aResponse
);
441 void HandleResponse(const Key
& aResponse
);
443 void HandleResponse(const nsTArray
<Key
>& aResponse
);
445 void HandleResponse(SerializedStructuredCloneReadInfo
&& aResponse
);
447 void HandleResponse(nsTArray
<SerializedStructuredCloneReadInfo
>&& aResponse
);
449 void HandleResponse(JS::Handle
<JS::Value
> aResponse
);
451 void HandleResponse(uint64_t aResponse
);
453 nsresult
HandlePreprocess(const PreprocessInfo
& aPreprocessInfo
);
455 nsresult
HandlePreprocess(const nsTArray
<PreprocessInfo
>& aPreprocessInfos
);
457 nsresult
HandlePreprocessInternal(
458 const nsTArray
<PreprocessInfo
>& aPreprocessInfos
);
460 SafeRefPtr
<IDBTransaction
> AcquireTransaction() const {
461 return mTransaction
.clonePtr();
465 // IPDL methods are only called by IPDL.
466 void ActorDestroy(ActorDestroyReason aWhy
) override
;
468 mozilla::ipc::IPCResult
Recv__delete__(RequestResponse
&& aResponse
);
470 mozilla::ipc::IPCResult
RecvPreprocess(const PreprocessParams
& aParams
);
474 RefPtr
<BackgroundRequestChild::PreprocessHelper
> mPreprocessHelper
;
475 UniquePtr
<JSStructuredCloneData
> mCloneData
;
478 class BackgroundCursorChildBase
479 : public PBackgroundIDBCursorChild
,
480 public SafeRefCounted
<BackgroundCursorChildBase
> {
485 MOZ_DECLARE_REFCOUNTED_TYPENAME(
486 mozilla::dom::indexedDB::BackgroundCursorChildBase
)
487 MOZ_INLINE_DECL_SAFEREFCOUNTING_INHERITED(BackgroundCursorChildBase
,
491 ~BackgroundCursorChildBase();
493 InitializedOnce
<const NotNull
<IDBRequest
*>> mRequest
;
494 Maybe
<IDBTransaction
&> mTransaction
;
496 // These are only set while a request is in progress.
497 RefPtr
<IDBRequest
> mStrongRequest
;
498 RefPtr
<IDBCursor
> mStrongCursor
;
500 const Direction mDirection
;
502 BackgroundCursorChildBase(NotNull
<IDBRequest
*> aRequest
,
503 Direction aDirection
);
505 void HandleResponse(nsresult aResponse
);
508 void AssertIsOnOwningThread() const {
509 NS_ASSERT_OWNINGTHREAD(BackgroundCursorChildBase
);
512 MovingNotNull
<RefPtr
<IDBRequest
>> AcquireRequest() const;
514 NotNull
<IDBRequest
*> GetRequest() const {
515 AssertIsOnOwningThread();
520 Direction
GetDirection() const {
521 AssertIsOnOwningThread();
526 virtual void SendDeleteMeInternal() = 0;
528 virtual mozilla::ipc::IPCResult
RecvResponse(CursorResponse
&& aResponse
) = 0;
531 template <IDBCursorType CursorType
>
532 class BackgroundCursorChild final
: public BackgroundCursorChildBase
{
534 using SourceType
= CursorSourceType
<CursorType
>;
535 using ResponseType
= typename CursorTypeTraits
<CursorType
>::ResponseType
;
538 friend class BackgroundTransactionChild
;
539 friend class BackgroundVersionChangeTransactionChild
;
541 InitializedOnce
<const NotNull
<SourceType
*>> mSource
;
542 IDBCursorImpl
<CursorType
>* mCursor
;
544 std::deque
<CursorData
<CursorType
>> mCachedResponses
, mDelayedResponses
;
545 bool mInFlightResponseInvalidationNeeded
;
548 BackgroundCursorChild(NotNull
<IDBRequest
*> aRequest
, SourceType
* aSource
,
549 Direction aDirection
);
551 void SendContinueInternal(const CursorRequestParams
& aParams
,
552 const CursorData
<CursorType
>& aCurrentData
);
554 void InvalidateCachedResponses();
556 template <typename Condition
>
557 void DiscardCachedResponses(const Condition
& aConditionFunc
);
559 SourceType
* GetSource() const {
560 AssertIsOnOwningThread();
565 void SendDeleteMeInternal() final
;
568 // Only destroyed by BackgroundTransactionChild or
569 // BackgroundVersionChangeTransactionChild.
570 ~BackgroundCursorChild();
572 void CompleteContinueRequestFromCache();
574 using BackgroundCursorChildBase::HandleResponse
;
576 void HandleResponse(const void_t
& aResponse
);
578 void HandleResponse(nsTArray
<ResponseType
>&& aResponses
);
580 template <typename Func
>
581 void HandleMultipleCursorResponses(nsTArray
<ResponseType
>&& aResponses
,
582 const Func
& aHandleRecord
);
584 template <typename
... Args
>
585 [[nodiscard
]] RefPtr
<IDBCursor
> HandleIndividualCursorResponse(
586 bool aUseAsCurrentResult
, Args
&&... aArgs
);
588 SafeRefPtr
<BackgroundCursorChild
> SafeRefPtrFromThis();
591 // IPDL methods are only called by IPDL.
592 void ActorDestroy(ActorDestroyReason aWhy
) override
;
594 mozilla::ipc::IPCResult
RecvResponse(CursorResponse
&& aResponse
) override
;
596 // Force callers to use SendContinueInternal.
597 bool SendContinue(const CursorRequestParams
& aParams
, const Key
& aCurrentKey
,
598 const Key
& aCurrentObjectStoreKey
) = delete;
600 bool SendDeleteMe() = delete;
603 class BackgroundUtilsChild final
: public PBackgroundIndexedDBUtilsChild
{
604 friend class mozilla::ipc::BackgroundChildImpl
;
605 friend IndexedDatabaseManager
;
607 IndexedDatabaseManager
* mManager
;
612 void AssertIsOnOwningThread() const {
613 NS_ASSERT_OWNINGTHREAD(BackgroundUtilsChild
);
616 bool SendDeleteMe() = delete;
619 // Only created by IndexedDatabaseManager.
620 explicit BackgroundUtilsChild(IndexedDatabaseManager
* aManager
);
622 // Only destroyed by mozilla::ipc::BackgroundChildImpl.
623 ~BackgroundUtilsChild();
625 void SendDeleteMeInternal();
628 // IPDL methods are only called by IPDL.
629 void ActorDestroy(ActorDestroyReason aWhy
) override
;
632 } // namespace mozilla::dom::indexedDB
634 #endif // mozilla_dom_indexeddb_actorschild_h__