DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (cdf352f02ac4)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

#ifndef mozilla_dom_indexeddb_actorschild_h__
#define mozilla_dom_indexeddb_actorschild_h__

#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/IDBCursorType.h"
#include "mozilla/dom/IDBTransaction.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseRequestChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
#include "mozilla/dom/PBackgroundFileHandleChild.h"
#include "mozilla/dom/PBackgroundFileRequestChild.h"
#include "mozilla/dom/PBackgroundMutableFileChild.h"
#include "mozilla/InitializedOnce.h"
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"

class nsIEventTarget;
struct nsID;

namespace mozilla {
namespace ipc {

class BackgroundChildImpl;

}  // namespace ipc

namespace dom {

class IDBCursor;
class IDBDatabase;
class IDBFactory;
class IDBFileHandle;
class IDBFileRequest;
class IDBMutableFile;
class IDBOpenDBRequest;
class IDBRequest;
class IndexedDatabaseManager;

namespace indexedDB {

class Key;
class PermissionRequestChild;
class PermissionRequestParent;
class SerializedStructuredCloneReadInfo;
struct CloneInfo;

}  // namespace indexedDB
}  // namespace dom
}  // namespace mozilla

MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::dom::indexedDB::CloneInfo)
MOZ_DECLARE_NON_COPY_CONSTRUCTIBLE(mozilla::dom::indexedDB::CloneInfo)

namespace mozilla {
namespace dom {
namespace indexedDB {

class ThreadLocal {
  friend class DefaultDelete<ThreadLocal>;
  friend IDBFactory;

  LoggingInfo mLoggingInfo;
  IDBTransaction* mCurrentTransaction;
  nsCString mLoggingIdString;

  NS_DECL_OWNINGTHREAD

 public:
  ThreadLocal() = delete;
  ThreadLocal(const ThreadLocal& aOther) = delete;

  void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(ThreadLocal); }

  const LoggingInfo& GetLoggingInfo() const {
    AssertIsOnOwningThread();

    return mLoggingInfo;
  }

  const nsID& Id() const {
    AssertIsOnOwningThread();

    return mLoggingInfo.backgroundChildLoggingId();
  }

  const nsCString& IdString() const {
    AssertIsOnOwningThread();

    return mLoggingIdString;
  }

  int64_t NextTransactionSN(IDBTransaction::Mode aMode) {
    AssertIsOnOwningThread();
    MOZ_ASSERT(mLoggingInfo.nextTransactionSerialNumber() < INT64_MAX);
    MOZ_ASSERT(mLoggingInfo.nextVersionChangeTransactionSerialNumber() >
               INT64_MIN);

    if (aMode == IDBTransaction::Mode::VersionChange) {
      return mLoggingInfo.nextVersionChangeTransactionSerialNumber()--;
    }

    return mLoggingInfo.nextTransactionSerialNumber()++;
  }

  uint64_t NextRequestSN() {
    AssertIsOnOwningThread();
    MOZ_ASSERT(mLoggingInfo.nextRequestSerialNumber() < UINT64_MAX);

    return mLoggingInfo.nextRequestSerialNumber()++;
  }

  void SetCurrentTransaction(IDBTransaction* aCurrentTransaction) {
    AssertIsOnOwningThread();

    mCurrentTransaction = aCurrentTransaction;
  }

  IDBTransaction* GetCurrentTransaction() const {
    AssertIsOnOwningThread();

    return mCurrentTransaction;
  }

 private:
  explicit ThreadLocal(const nsID& aBackgroundChildLoggingId);
  ~ThreadLocal();
};

class BackgroundFactoryChild final : public PBackgroundIDBFactoryChild {
  friend class mozilla::ipc::BackgroundChildImpl;
  friend IDBFactory;

  // TODO: This long-lived raw pointer is very suspicious, in particular as it
  // is used in BackgroundDatabaseChild::EnsureDOMObject to reacquire a strong
  // reference. What ensures it is kept alive, and why can't we store a strong
  // reference here?
  IDBFactory* mFactory;

  NS_DECL_OWNINGTHREAD

 public:
  void AssertIsOnOwningThread() const {
    NS_ASSERT_OWNINGTHREAD(BackgroundFactoryChild);
  }

  IDBFactory& GetDOMObject() const {
    AssertIsOnOwningThread();
    MOZ_ASSERT(mFactory);
    return *mFactory;
  }

  bool SendDeleteMe() = delete;

 private:
  // Only created by IDBFactory.
  explicit BackgroundFactoryChild(IDBFactory& aFactory);

  // Only destroyed by mozilla::ipc::BackgroundChildImpl.
  ~BackgroundFactoryChild();

  void SendDeleteMeInternal();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  PBackgroundIDBFactoryRequestChild* AllocPBackgroundIDBFactoryRequestChild(
      const FactoryRequestParams& aParams);

  bool DeallocPBackgroundIDBFactoryRequestChild(
      PBackgroundIDBFactoryRequestChild* aActor);

  PBackgroundIDBDatabaseChild* AllocPBackgroundIDBDatabaseChild(
      const DatabaseSpec& aSpec, PBackgroundIDBFactoryRequestChild* aRequest);

  bool DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild* aActor);

  mozilla::ipc::IPCResult RecvPBackgroundIDBDatabaseConstructor(
      PBackgroundIDBDatabaseChild* aActor, const DatabaseSpec& aSpec,
      PBackgroundIDBFactoryRequestChild* aRequest) override;
};

class BackgroundDatabaseChild;

class BackgroundRequestChildBase {
 protected:
  RefPtr<IDBRequest> mRequest;

 public:
  void AssertIsOnOwningThread() const
#ifdef DEBUG
      ;
#else
  {
  }
#endif

 protected:
  explicit BackgroundRequestChildBase(IDBRequest* aRequest);

  virtual ~BackgroundRequestChildBase();
};

class BackgroundFactoryRequestChild final
    : public BackgroundRequestChildBase,
      public PBackgroundIDBFactoryRequestChild {
  typedef mozilla::dom::quota::PersistenceType PersistenceType;

  friend IDBFactory;
  friend class BackgroundFactoryChild;
  friend class BackgroundDatabaseChild;
  friend class PermissionRequestChild;
  friend class PermissionRequestParent;

  const SafeRefPtr<IDBFactory> mFactory;

  // Normally when opening of a database is successful, we receive a database
  // actor in request response, so we can use it to call ReleaseDOMObject()
  // which clears temporary strong reference to IDBDatabase.
  // However, when there's an error, we don't receive a database actor and
  // IDBRequest::mTransaction is already cleared (must be). So the only way how
  // to call ReleaseDOMObject() is to have a back-reference to database actor.
  // This creates a weak ref cycle between
  // BackgroundFactoryRequestChild (using mDatabaseActor member) and
  // BackgroundDatabaseChild actor (using mOpenRequestActor member).
  // mDatabaseActor is set in EnsureDOMObject() and cleared in
  // ReleaseDOMObject().
  BackgroundDatabaseChild* mDatabaseActor;

  const uint64_t mRequestedVersion;
  const bool mIsDeleteOp;

 public:
  IDBOpenDBRequest* GetOpenDBRequest() const;

 private:
  // Only created by IDBFactory.
  BackgroundFactoryRequestChild(SafeRefPtr<IDBFactory> aFactory,
                                IDBOpenDBRequest* aOpenRequest,
                                bool aIsDeleteOp, uint64_t aRequestedVersion);

  // Only destroyed by BackgroundFactoryChild.
  ~BackgroundFactoryRequestChild();

  void SetDatabaseActor(BackgroundDatabaseChild* aActor);

  bool HandleResponse(nsresult aResponse);

  bool HandleResponse(const OpenDatabaseRequestResponse& aResponse);

  bool HandleResponse(const DeleteDatabaseRequestResponse& aResponse);

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult Recv__delete__(
      const FactoryRequestResponse& aResponse);

  mozilla::ipc::IPCResult RecvPermissionChallenge(
      PrincipalInfo&& aPrincipalInfo);

  mozilla::ipc::IPCResult RecvBlocked(uint64_t aCurrentVersion);
};

class BackgroundDatabaseChild final : public PBackgroundIDBDatabaseChild {
  friend class BackgroundFactoryChild;
  friend class BackgroundFactoryRequestChild;
  friend IDBDatabase;

  UniquePtr<DatabaseSpec> mSpec;
  RefPtr<IDBDatabase> mTemporaryStrongDatabase;
  BackgroundFactoryRequestChild* mOpenRequestActor;
  IDBDatabase* mDatabase;

 public:
  void AssertIsOnOwningThread() const
#ifdef DEBUG
      ;
#else
  {
  }
#endif

  const DatabaseSpec* Spec() const {
    AssertIsOnOwningThread();
    return mSpec.get();
  }

  IDBDatabase* GetDOMObject() const {
    AssertIsOnOwningThread();
    return mDatabase;
  }

  bool SendDeleteMe() = delete;

 private:
  // Only constructed by BackgroundFactoryChild.
  BackgroundDatabaseChild(const DatabaseSpec& aSpec,
                          BackgroundFactoryRequestChild* aOpenRequest);

  // Only destroyed by BackgroundFactoryChild.
  ~BackgroundDatabaseChild();

  void SendDeleteMeInternal();

  void EnsureDOMObject();

  void ReleaseDOMObject();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  PBackgroundIDBDatabaseFileChild* AllocPBackgroundIDBDatabaseFileChild(
      const IPCBlob& aIPCBlob);

  bool DeallocPBackgroundIDBDatabaseFileChild(
      PBackgroundIDBDatabaseFileChild* aActor);

  PBackgroundIDBDatabaseRequestChild* AllocPBackgroundIDBDatabaseRequestChild(
      const DatabaseRequestParams& aParams);

  bool DeallocPBackgroundIDBDatabaseRequestChild(
      PBackgroundIDBDatabaseRequestChild* aActor);

  PBackgroundIDBTransactionChild* AllocPBackgroundIDBTransactionChild(
      const nsTArray<nsString>& aObjectStoreNames, const Mode& aMode);

  bool DeallocPBackgroundIDBTransactionChild(
      PBackgroundIDBTransactionChild* aActor);

  PBackgroundIDBVersionChangeTransactionChild*
  AllocPBackgroundIDBVersionChangeTransactionChild(uint64_t aCurrentVersion,
                                                   uint64_t aRequestedVersion,
                                                   int64_t aNextObjectStoreId,
                                                   int64_t aNextIndexId);

  mozilla::ipc::IPCResult RecvPBackgroundIDBVersionChangeTransactionConstructor(
      PBackgroundIDBVersionChangeTransactionChild* aActor,
      const uint64_t& aCurrentVersion, const uint64_t& aRequestedVersion,
      const int64_t& aNextObjectStoreId, const int64_t& aNextIndexId) override;

  bool DeallocPBackgroundIDBVersionChangeTransactionChild(
      PBackgroundIDBVersionChangeTransactionChild* aActor);

  PBackgroundMutableFileChild* AllocPBackgroundMutableFileChild(
      const nsString& aName, const nsString& aType);

  bool DeallocPBackgroundMutableFileChild(PBackgroundMutableFileChild* aActor);

  mozilla::ipc::IPCResult RecvVersionChange(uint64_t aOldVersion,
                                            Maybe<uint64_t> aNewVersion);

  mozilla::ipc::IPCResult RecvInvalidate();

  mozilla::ipc::IPCResult RecvCloseAfterInvalidationComplete();
};

class BackgroundDatabaseRequestChild final
    : public BackgroundRequestChildBase,
      public PBackgroundIDBDatabaseRequestChild {
  friend class BackgroundDatabaseChild;
  friend IDBDatabase;

  RefPtr<IDBDatabase> mDatabase;

 private:
  // Only created by IDBDatabase.
  BackgroundDatabaseRequestChild(IDBDatabase* aDatabase, IDBRequest* aRequest);

  // Only destroyed by BackgroundDatabaseChild.
  ~BackgroundDatabaseRequestChild();

  bool HandleResponse(nsresult aResponse);

  bool HandleResponse(const CreateFileRequestResponse& aResponse);

 public:
  // IPDL methods are only called by IPDL.
  mozilla::ipc::IPCResult Recv__delete__(
      const DatabaseRequestResponse& aResponse);
};

class BackgroundVersionChangeTransactionChild;

class BackgroundTransactionBase {
  friend class BackgroundVersionChangeTransactionChild;

  // mTemporaryStrongTransaction is strong and is only valid until the end of
  // NoteComplete() member function or until the NoteActorDestroyed() member
  // function is called.
  RefPtr<IDBTransaction> mTemporaryStrongTransaction;

 protected:
  // mTransaction is weak and is valid until the NoteActorDestroyed() member
  // function is called.
  IDBTransaction* mTransaction;

 public:
#ifdef DEBUG
  virtual void AssertIsOnOwningThread() const = 0;
#else
  void AssertIsOnOwningThread() const {}
#endif

  IDBTransaction* GetDOMObject() const {
    AssertIsOnOwningThread();
    return mTransaction;
  }

 protected:
  BackgroundTransactionBase();
  explicit BackgroundTransactionBase(IDBTransaction* aTransaction);

  virtual ~BackgroundTransactionBase();

  void NoteActorDestroyed();

  void NoteComplete();

 private:
  // Only called by BackgroundVersionChangeTransactionChild.
  void SetDOMTransaction(IDBTransaction* aTransaction);
};

class BackgroundTransactionChild final : public BackgroundTransactionBase,
                                         public PBackgroundIDBTransactionChild {
  friend class BackgroundDatabaseChild;
  friend IDBDatabase;

 public:
#ifdef DEBUG
  void AssertIsOnOwningThread() const override;
#endif

  void SendDeleteMeInternal();

  bool SendDeleteMe() = delete;

 private:
  // Only created by IDBDatabase.
  explicit BackgroundTransactionChild(IDBTransaction* aTransaction);

  // Only destroyed by BackgroundDatabaseChild.
  ~BackgroundTransactionChild();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult RecvComplete(nsresult aResult);

  PBackgroundIDBRequestChild* AllocPBackgroundIDBRequestChild(
      const RequestParams& aParams);

  bool DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor);

  PBackgroundIDBCursorChild* AllocPBackgroundIDBCursorChild(
      const OpenCursorParams& aParams);

  bool DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor);
};

class BackgroundVersionChangeTransactionChild final
    : public BackgroundTransactionBase,
      public PBackgroundIDBVersionChangeTransactionChild {
  friend class BackgroundDatabaseChild;

  IDBOpenDBRequest* mOpenDBRequest;

 public:
#ifdef DEBUG
  void AssertIsOnOwningThread() const override;
#endif

  void SendDeleteMeInternal(bool aFailedConstructor);

  bool SendDeleteMe() = delete;

 private:
  // Only created by BackgroundDatabaseChild.
  explicit BackgroundVersionChangeTransactionChild(
      IDBOpenDBRequest* aOpenDBRequest);

  // Only destroyed by BackgroundDatabaseChild.
  ~BackgroundVersionChangeTransactionChild();

  // Only called by BackgroundDatabaseChild.
  void SetDOMTransaction(IDBTransaction* aDOMObject) {
    BackgroundTransactionBase::SetDOMTransaction(aDOMObject);
  }

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult RecvComplete(nsresult aResult);

  PBackgroundIDBRequestChild* AllocPBackgroundIDBRequestChild(
      const RequestParams& aParams);

  bool DeallocPBackgroundIDBRequestChild(PBackgroundIDBRequestChild* aActor);

  PBackgroundIDBCursorChild* AllocPBackgroundIDBCursorChild(
      const OpenCursorParams& aParams);

  bool DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor);
};

class BackgroundMutableFileChild final : public PBackgroundMutableFileChild {
  friend class BackgroundDatabaseChild;
  friend IDBMutableFile;

  RefPtr<IDBMutableFile> mTemporaryStrongMutableFile;
  IDBMutableFile* mMutableFile;
  nsString mName;
  nsString mType;

 public:
  void AssertIsOnOwningThread() const
#ifdef DEBUG
      ;
#else
  {
  }
#endif

  void EnsureDOMObject();

  IDBMutableFile* GetDOMObject() const {
    AssertIsOnOwningThread();
    return mMutableFile;
  }

  void ReleaseDOMObject();

  bool SendDeleteMe() = delete;

 private:
  // Only constructed by BackgroundDatabaseChild.
  BackgroundMutableFileChild(const nsAString& aName, const nsAString& aType);

  // Only destroyed by BackgroundDatabaseChild.
  ~BackgroundMutableFileChild();

  void SendDeleteMeInternal();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  PBackgroundFileHandleChild* AllocPBackgroundFileHandleChild(
      const FileMode& aMode);

  bool DeallocPBackgroundFileHandleChild(PBackgroundFileHandleChild* aActor);
};

class BackgroundRequestChild final : public BackgroundRequestChildBase,
                                     public PBackgroundIDBRequestChild {
  friend class BackgroundTransactionChild;
  friend class BackgroundVersionChangeTransactionChild;
  friend struct CloneInfo;
  friend IDBTransaction;

  class PreprocessHelper;

  RefPtr<IDBTransaction> mTransaction;
  nsTArray<CloneInfo> mCloneInfos;
  uint32_t mRunningPreprocessHelpers;
  uint32_t mCurrentCloneDataIndex;
  nsresult mPreprocessResultCode;
  bool mGetAll;

 private:
  // Only created by IDBTransaction.
  explicit BackgroundRequestChild(IDBRequest* aRequest);

  // Only destroyed by BackgroundTransactionChild or
  // BackgroundVersionChangeTransactionChild.
  ~BackgroundRequestChild();

  void MaybeSendContinue();

  void OnPreprocessFinished(uint32_t aCloneDataIndex,
                            UniquePtr<JSStructuredCloneData> aCloneData);

  void OnPreprocessFailed(uint32_t aCloneDataIndex, nsresult aErrorCode);

  UniquePtr<JSStructuredCloneData> GetNextCloneData();

  void HandleResponse(nsresult aResponse);

  void HandleResponse(const Key& aResponse);

  void HandleResponse(const nsTArray<Key>& aResponse);

  void HandleResponse(SerializedStructuredCloneReadInfo&& aResponse);

  void HandleResponse(nsTArray<SerializedStructuredCloneReadInfo>&& aResponse);

  void HandleResponse(JS::Handle<JS::Value> aResponse);

  void HandleResponse(uint64_t aResponse);

  nsresult HandlePreprocess(const PreprocessInfo& aPreprocessInfo);

  nsresult HandlePreprocess(const nsTArray<PreprocessInfo>& aPreprocessInfos);

  nsresult HandlePreprocessInternal(
      const nsTArray<PreprocessInfo>& aPreprocessInfos);

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult Recv__delete__(RequestResponse&& aResponse);

  mozilla::ipc::IPCResult RecvPreprocess(const PreprocessParams& aParams);
};

struct CloneInfo {
  RefPtr<BackgroundRequestChild::PreprocessHelper> mPreprocessHelper;
  UniquePtr<JSStructuredCloneData> mCloneData;
};

class BackgroundCursorChildBase : public PBackgroundIDBCursorChild {
 private:
  NS_DECL_OWNINGTHREAD
 protected:
  InitializedOnceNotNull<IDBRequest* const> mRequest;
  IDBTransaction* mTransaction;

  // These are only set while a request is in progress.
  RefPtr<IDBRequest> mStrongRequest;
  RefPtr<IDBCursor> mStrongCursor;

  const Direction mDirection;

  BackgroundCursorChildBase(IDBRequest* aRequest, Direction aDirection);

  void HandleResponse(nsresult aResponse);

 public:
  void AssertIsOnOwningThread() const {
    NS_ASSERT_OWNINGTHREAD(BackgroundCursorChildBase);
  }

  IDBRequest* GetRequest() const {
    AssertIsOnOwningThread();

    return *mRequest;
  }

  Direction GetDirection() const {
    AssertIsOnOwningThread();

    return mDirection;
  }

  virtual void SendDeleteMeInternal() = 0;

  virtual mozilla::ipc::IPCResult RecvResponse(CursorResponse&& aResponse) = 0;
};

template <IDBCursorType CursorType>
class BackgroundCursorChild final : public BackgroundCursorChildBase {
 public:
  using SourceType = CursorSourceType<CursorType>;
  using ResponseType = typename CursorTypeTraits<CursorType>::ResponseType;

 private:
  friend class BackgroundTransactionChild;
  friend class BackgroundVersionChangeTransactionChild;

  InitializedOnceNotNull<SourceType* const> mSource;
  IDBCursorImpl<CursorType>* mCursor;

  std::deque<CursorData<CursorType>> mCachedResponses, mDelayedResponses;
  bool mInFlightResponseInvalidationNeeded;

 public:
  BackgroundCursorChild(IDBRequest* aRequest, SourceType* aSource,
                        Direction aDirection);

  void SendContinueInternal(const CursorRequestParams& aParams,
                            const CursorData<CursorType>& aCurrentData);

  void InvalidateCachedResponses();

  template <typename Condition>
  void DiscardCachedResponses(const Condition& aConditionFunc);

  SourceType* GetSource() const {
    AssertIsOnOwningThread();

    return *mSource;
  }

  void SendDeleteMeInternal() final;

 private:
  // Only destroyed by BackgroundTransactionChild or
  // BackgroundVersionChangeTransactionChild.
  ~BackgroundCursorChild();

  void CompleteContinueRequestFromCache();

  using BackgroundCursorChildBase::HandleResponse;

  void HandleResponse(const void_t& aResponse);

  void HandleResponse(nsTArray<ResponseType>&& aResponses);

  template <typename Func>
  void HandleMultipleCursorResponses(nsTArray<ResponseType>&& aResponses,
                                     const Func& aHandleRecord);

  template <typename... Args>
  MOZ_MUST_USE RefPtr<IDBCursor> HandleIndividualCursorResponse(
      bool aUseAsCurrentResult, Args&&... aArgs);

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult RecvResponse(CursorResponse&& aResponse) override;

  // Force callers to use SendContinueInternal.
  bool SendContinue(const CursorRequestParams& aParams, const Key& aCurrentKey,
                    const Key& aCurrentObjectStoreKey) = delete;

  bool SendDeleteMe() = delete;
};

class BackgroundFileHandleChild : public PBackgroundFileHandleChild {
  friend class BackgroundMutableFileChild;
  friend IDBMutableFile;

  // mTemporaryStrongFileHandle is strong and is only valid until the end of
  // NoteComplete() member function or until the NoteActorDestroyed() member
  // function is called.
  RefPtr<IDBFileHandle> mTemporaryStrongFileHandle;

  // mFileHandle is weak and is valid until the NoteActorDestroyed() member
  // function is called.
  IDBFileHandle* mFileHandle;

 public:
  void AssertIsOnOwningThread() const
#ifdef DEBUG
      ;
#else
  {
  }
#endif

  void SendDeleteMeInternal();

  bool SendDeleteMe() = delete;

 private:
  // Only created by IDBMutableFile.
  explicit BackgroundFileHandleChild(IDBFileHandle* aFileHandle);

  ~BackgroundFileHandleChild();

  void NoteActorDestroyed();

  void NoteComplete();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult RecvComplete(bool aAborted);

  PBackgroundFileRequestChild* AllocPBackgroundFileRequestChild(
      const FileRequestParams& aParams);

  bool DeallocPBackgroundFileRequestChild(PBackgroundFileRequestChild* aActor);
};

class BackgroundFileRequestChild final : public PBackgroundFileRequestChild {
  friend class BackgroundFileHandleChild;
  friend IDBFileHandle;

  RefPtr<IDBFileRequest> mFileRequest;
  RefPtr<IDBFileHandle> mFileHandle;
  bool mActorDestroyed;

 public:
  void AssertIsOnOwningThread() const
#ifdef DEBUG
      ;
#else
  {
  }
#endif

 private:
  // Only created by IDBFileHandle.
  explicit BackgroundFileRequestChild(IDBFileRequest* aFileRequest);

  // Only destroyed by BackgroundFileHandleChild.
  ~BackgroundFileRequestChild();

  void HandleResponse(nsresult aResponse);

  void HandleResponse(const nsCString& aResponse);

  void HandleResponse(const FileRequestMetadata& aResponse);

  void HandleResponse(JS::Handle<JS::Value> aResponse);

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;

  mozilla::ipc::IPCResult Recv__delete__(const FileRequestResponse& aResponse);

  mozilla::ipc::IPCResult RecvProgress(uint64_t aProgress,
                                       uint64_t aProgressMax);
};

class BackgroundUtilsChild final : public PBackgroundIndexedDBUtilsChild {
  friend class mozilla::ipc::BackgroundChildImpl;
  friend IndexedDatabaseManager;

  IndexedDatabaseManager* mManager;

  NS_DECL_OWNINGTHREAD

 public:
  void AssertIsOnOwningThread() const {
    NS_ASSERT_OWNINGTHREAD(BackgroundUtilsChild);
  }

  bool SendDeleteMe() = delete;

 private:
  // Only created by IndexedDatabaseManager.
  explicit BackgroundUtilsChild(IndexedDatabaseManager* aManager);

  // Only destroyed by mozilla::ipc::BackgroundChildImpl.
  ~BackgroundUtilsChild();

  void SendDeleteMeInternal();

 public:
  // IPDL methods are only called by IPDL.
  void ActorDestroy(ActorDestroyReason aWhy) override;
};

}  // namespace indexedDB
}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_indexeddb_actorschild_h__