dom/indexedDB/IDBIndex.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=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/. */
     7 #include "base/basictypes.h"
     9 #include "IDBIndex.h"
    11 #include <algorithm>
    12 #include "mozilla/dom/ContentChild.h"
    13 #include "mozilla/dom/ContentParent.h"
    14 #include "mozilla/dom/ipc/Blob.h"
    15 #include "mozilla/storage.h"
    16 #include "nsThreadUtils.h"
    17 #include "xpcpublic.h"
    19 #include "AsyncConnectionHelper.h"
    20 #include "DatabaseInfo.h"
    21 #include "IDBCursor.h"
    22 #include "IDBEvents.h"
    23 #include "IDBKeyRange.h"
    24 #include "IDBObjectStore.h"
    25 #include "IDBTransaction.h"
    26 #include "ProfilerHelpers.h"
    27 #include "ReportInternalError.h"
    29 #include "ipc/IndexedDBChild.h"
    30 #include "ipc/IndexedDBParent.h"
    32 #include "IndexedDatabaseInlines.h"
    34 USING_INDEXEDDB_NAMESPACE
    35 using namespace mozilla::dom;
    36 using namespace mozilla::dom::indexedDB::ipc;
    37 using mozilla::ErrorResult;
    38 using mozilla::Move;
    40 namespace {
    42 class IndexHelper : public AsyncConnectionHelper
    43 {
    44 public:
    45   IndexHelper(IDBTransaction* aTransaction,
    46               IDBRequest* aRequest,
    47               IDBIndex* aIndex)
    48   : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
    49     mActor(nullptr)
    50   {
    51     NS_ASSERTION(aTransaction, "Null transaction!");
    52     NS_ASSERTION(aRequest, "Null request!");
    53     NS_ASSERTION(aIndex, "Null index!");
    54   }
    56   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
    58   virtual nsresult Dispatch(nsIEventTarget* aDatabaseThread) MOZ_OVERRIDE;
    60   virtual nsresult
    61   PackArgumentsForParentProcess(IndexRequestParams& aParams) = 0;
    63   virtual nsresult
    64   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue) = 0;
    66 protected:
    67   nsRefPtr<IDBIndex> mIndex;
    69 private:
    70   IndexedDBIndexRequestChild* mActor;
    71 };
    73 class GetKeyHelper : public IndexHelper
    74 {
    75 public:
    76   GetKeyHelper(IDBTransaction* aTransaction,
    77                IDBRequest* aRequest,
    78                IDBIndex* aIndex,
    79                IDBKeyRange* aKeyRange)
    80   : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange)
    81   { }
    83   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
    84                                   MOZ_OVERRIDE;
    86   virtual nsresult GetSuccessResult(JSContext* aCx,
    87                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
    89   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
    91   virtual nsresult
    92   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
    94   virtual ChildProcessSendResult
    95   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
    97   virtual nsresult
    98   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
    99                                   MOZ_OVERRIDE;
   101 protected:
   102   // In-params.
   103   nsRefPtr<IDBKeyRange> mKeyRange;
   105   // Out-params.
   106   Key mKey;
   107 };
   109 class GetHelper : public GetKeyHelper
   110 {
   111 public:
   112   GetHelper(IDBTransaction* aTransaction,
   113             IDBRequest* aRequest,
   114             IDBIndex* aIndex,
   115             IDBKeyRange* aKeyRange)
   116   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange)
   117   { }
   119   ~GetHelper()
   120   {
   121     IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
   122   }
   124   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   125                                   MOZ_OVERRIDE;
   127   virtual nsresult GetSuccessResult(JSContext* aCx,
   128                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
   130   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
   132   virtual nsresult
   133   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   135   virtual ChildProcessSendResult
   136   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   138   virtual nsresult
   139   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
   140                                   MOZ_OVERRIDE;
   142 protected:
   143   StructuredCloneReadInfo mCloneReadInfo;
   144 };
   146 class GetAllKeysHelper : public GetKeyHelper
   147 {
   148 public:
   149   GetAllKeysHelper(IDBTransaction* aTransaction,
   150                    IDBRequest* aRequest,
   151                    IDBIndex* aIndex,
   152                    IDBKeyRange* aKeyRange,
   153                    const uint32_t aLimit)
   154   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
   155   { }
   157   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   158                                   MOZ_OVERRIDE;
   160   virtual nsresult GetSuccessResult(JSContext* aCx,
   161                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
   163   virtual nsresult
   164   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   166   virtual ChildProcessSendResult
   167   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   169   virtual nsresult
   170   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
   171                                   MOZ_OVERRIDE;
   173 protected:
   174   const uint32_t mLimit;
   175   nsTArray<Key> mKeys;
   176 };
   178 class GetAllHelper : public GetKeyHelper
   179 {
   180 public:
   181   GetAllHelper(IDBTransaction* aTransaction,
   182                IDBRequest* aRequest,
   183                IDBIndex* aIndex,
   184                IDBKeyRange* aKeyRange,
   185                const uint32_t aLimit)
   186   : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
   187   { }
   189   ~GetAllHelper()
   190   {
   191     for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
   192       IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
   193     }
   194   }
   196   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   197                                   MOZ_OVERRIDE;
   199   virtual nsresult GetSuccessResult(JSContext* aCx,
   200                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
   202   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
   204   virtual nsresult
   205   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   207   virtual ChildProcessSendResult
   208   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   210   virtual nsresult
   211   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
   212                                   MOZ_OVERRIDE;
   214 protected:
   215   const uint32_t mLimit;
   216   nsTArray<StructuredCloneReadInfo> mCloneReadInfos;
   217 };
   219 class OpenKeyCursorHelper : public IndexHelper
   220 {
   221 public:
   222   OpenKeyCursorHelper(IDBTransaction* aTransaction,
   223                       IDBRequest* aRequest,
   224                       IDBIndex* aIndex,
   225                       IDBKeyRange* aKeyRange,
   226                       IDBCursor::Direction aDirection)
   227   : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange),
   228     mDirection(aDirection)
   229   { }
   231   ~OpenKeyCursorHelper()
   232   {
   233     NS_ASSERTION(true, "bas");
   234   }
   236   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   237                                   MOZ_OVERRIDE;
   239   virtual nsresult GetSuccessResult(JSContext* aCx,
   240                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
   242   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
   244   virtual nsresult
   245   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   247   virtual ChildProcessSendResult
   248   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   250   virtual nsresult
   251   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
   252                                   MOZ_OVERRIDE;
   254 protected:
   255   virtual nsresult EnsureCursor();
   257   // In-params.
   258   nsRefPtr<IDBKeyRange> mKeyRange;
   259   const IDBCursor::Direction mDirection;
   261   // Out-params.
   262   Key mKey;
   263   Key mObjectKey;
   264   nsCString mContinueQuery;
   265   nsCString mContinueToQuery;
   266   Key mRangeKey;
   268   // Only used in the parent process.
   269   nsRefPtr<IDBCursor> mCursor;
   270 };
   272 class OpenCursorHelper : public OpenKeyCursorHelper
   273 {
   274 public:
   275   OpenCursorHelper(IDBTransaction* aTransaction,
   276                    IDBRequest* aRequest,
   277                    IDBIndex* aIndex,
   278                    IDBKeyRange* aKeyRange,
   279                    IDBCursor::Direction aDirection)
   280   : OpenKeyCursorHelper(aTransaction, aRequest, aIndex, aKeyRange, aDirection)
   281   { }
   283   ~OpenCursorHelper()
   284   {
   285     IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
   286   }
   288   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   289                                   MOZ_OVERRIDE;
   291   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
   293   virtual nsresult
   294   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   296   virtual ChildProcessSendResult
   297   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   299 private:
   300   virtual nsresult EnsureCursor();
   302   StructuredCloneReadInfo mCloneReadInfo;
   304   // Only used in the parent process.
   305   SerializedStructuredCloneReadInfo mSerializedCloneReadInfo;
   306 };
   308 class CountHelper : public IndexHelper
   309 {
   310 public:
   311   CountHelper(IDBTransaction* aTransaction,
   312               IDBRequest* aRequest,
   313               IDBIndex* aIndex,
   314               IDBKeyRange* aKeyRange)
   315   : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange), mCount(0)
   316   { }
   318   virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
   319                                   MOZ_OVERRIDE;
   321   virtual nsresult GetSuccessResult(JSContext* aCx,
   322                                     JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
   324   virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
   326   virtual nsresult
   327   PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
   329   virtual ChildProcessSendResult
   330   SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
   332   virtual nsresult
   333   UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
   334                                   MOZ_OVERRIDE;
   336 private:
   337   nsRefPtr<IDBKeyRange> mKeyRange;
   338   uint64_t mCount;
   339 };
   341 inline
   342 already_AddRefed<IDBRequest>
   343 GenerateRequest(IDBIndex* aIndex)
   344 {
   345   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   346   IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
   347   IDBDatabase* database = transaction->Database();
   348   return IDBRequest::Create(aIndex, database, transaction);
   349 }
   351 } // anonymous namespace
   353 // static
   354 already_AddRefed<IDBIndex>
   355 IDBIndex::Create(IDBObjectStore* aObjectStore,
   356                  const IndexInfo* aIndexInfo,
   357                  bool aCreating)
   358 {
   359   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   360   NS_ASSERTION(aObjectStore, "Null pointer!");
   361   NS_ASSERTION(aIndexInfo, "Null pointer!");
   363   nsRefPtr<IDBIndex> index = new IDBIndex();
   365   index->mObjectStore = aObjectStore;
   366   index->mId = aIndexInfo->id;
   367   index->mName = aIndexInfo->name;
   368   index->mKeyPath = aIndexInfo->keyPath;
   369   index->mUnique = aIndexInfo->unique;
   370   index->mMultiEntry = aIndexInfo->multiEntry;
   372   if (!IndexedDatabaseManager::IsMainProcess()) {
   373     IndexedDBObjectStoreChild* objectStoreActor = aObjectStore->GetActorChild();
   374     NS_ASSERTION(objectStoreActor, "Must have an actor here!");
   376     nsAutoPtr<IndexedDBIndexChild> actor(new IndexedDBIndexChild(index));
   378     IndexConstructorParams params;
   380     if (aCreating) {
   381       CreateIndexParams createParams;
   382       createParams.info() = *aIndexInfo;
   383       params = createParams;
   384     }
   385     else {
   386       GetIndexParams getParams;
   387       getParams.name() = aIndexInfo->name;
   388       params = getParams;
   389     }
   391     objectStoreActor->SendPIndexedDBIndexConstructor(actor.forget(), params);
   392   }
   394   return index.forget();
   395 }
   397 IDBIndex::IDBIndex()
   398 : mId(INT64_MIN),
   399   mKeyPath(0),
   400   mCachedKeyPath(JSVAL_VOID),
   401   mActorChild(nullptr),
   402   mActorParent(nullptr),
   403   mUnique(false),
   404   mMultiEntry(false),
   405   mRooted(false)
   406 {
   407   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   409   SetIsDOMBinding();
   410 }
   412 IDBIndex::~IDBIndex()
   413 {
   414   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   415   NS_ASSERTION(!mActorParent, "Actor parent owns us, how can we be dying?!");
   417   if (mRooted) {
   418     mCachedKeyPath = JSVAL_VOID;
   419     mozilla::DropJSObjects(this);
   420   }
   422   if (mActorChild) {
   423     NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   424     mActorChild->Send__delete__(mActorChild);
   425     NS_ASSERTION(!mActorChild, "Should have cleared in Send__delete__!");
   426   }
   427 }
   429 already_AddRefed<IDBRequest>
   430 IDBIndex::GetInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
   431 {
   432   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   434   IDBTransaction* transaction = mObjectStore->Transaction();
   435   if (!transaction->IsOpen()) {
   436     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   437     return nullptr;
   438   }
   440   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   441   if (!request) {
   442     IDB_WARNING("Failed to generate request!");
   443     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   444     return nullptr;
   445   }
   447   nsRefPtr<GetHelper> helper =
   448     new GetHelper(transaction, request, this, aKeyRange);
   450   nsresult rv = helper->DispatchToTransactionPool();
   451   if (NS_FAILED(rv)) {
   452     IDB_WARNING("Failed to dispatch!");
   453     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   454     return nullptr;
   455   }
   457   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   458                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   459                     "get(%s)",
   460                     "IDBRequest[%llu] MT IDBIndex.get()",
   461                     request->GetSerialNumber(),
   462                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   463                                         Database()),
   464                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   465                     IDB_PROFILER_STRING(ObjectStore()),
   466                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
   468   return request.forget();
   469 }
   471 already_AddRefed<IDBRequest>
   472 IDBIndex::GetKeyInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
   473 {
   474   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   476   IDBTransaction* transaction = mObjectStore->Transaction();
   477   if (!transaction->IsOpen()) {
   478     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   479     return nullptr;
   480   }
   482   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   483   if (!request) {
   484     IDB_WARNING("Failed to generate request!");
   485     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   486     return nullptr;
   487   }
   489   nsRefPtr<GetKeyHelper> helper =
   490     new GetKeyHelper(transaction, request, this, aKeyRange);
   492   nsresult rv = helper->DispatchToTransactionPool();
   493   if (NS_FAILED(rv)) {
   494     IDB_WARNING("Failed to dispatch!");
   495     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   496     return nullptr;
   497   }
   499   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   500                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   501                     "getKey(%s)",
   502                     "IDBRequest[%llu] MT IDBIndex.getKey()",
   503                     request->GetSerialNumber(),
   504                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   505                                         Database()),
   506                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   507                     IDB_PROFILER_STRING(ObjectStore()),
   508                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
   510   return request.forget();
   511 }
   513 already_AddRefed<IDBRequest>
   514 IDBIndex::GetAllInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
   515                          ErrorResult& aRv)
   516 {
   517   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   519   IDBTransaction* transaction = mObjectStore->Transaction();
   520   if (!transaction->IsOpen()) {
   521     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   522     return nullptr;
   523   }
   525   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   526   if (!request) {
   527     IDB_WARNING("Failed to generate request!");
   528     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   529     return nullptr;
   530   }
   532   nsRefPtr<GetAllHelper> helper =
   533     new GetAllHelper(transaction, request, this, aKeyRange, aLimit);
   535   nsresult rv = helper->DispatchToTransactionPool();
   536   if (NS_FAILED(rv)) {
   537     IDB_WARNING("Failed to dispatch!");
   538     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   539     return nullptr;
   540   }
   542   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   543                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   544                     "getAll(%s, %lu)",
   545                     "IDBRequest[%llu] MT IDBIndex.getAll()",
   546                     request->GetSerialNumber(),
   547                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   548                                         Database()),
   549                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   550                     IDB_PROFILER_STRING(ObjectStore()),
   551                     IDB_PROFILER_STRING(this),
   552                     IDB_PROFILER_STRING(aKeyRange), aLimit);
   554   return request.forget();
   555 }
   557 already_AddRefed<IDBRequest>
   558 IDBIndex::GetAllKeysInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
   559                              ErrorResult& aRv)
   560 {
   561   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   563   IDBTransaction* transaction = mObjectStore->Transaction();
   564   if (!transaction->IsOpen()) {
   565     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   566     return nullptr;
   567   }
   569   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   570   if (!request) {
   571     IDB_WARNING("Failed to generate request!");
   572     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   573     return nullptr;
   574   }
   576   nsRefPtr<GetAllKeysHelper> helper =
   577     new GetAllKeysHelper(transaction, request, this, aKeyRange, aLimit);
   579   nsresult rv = helper->DispatchToTransactionPool();
   580   if (NS_FAILED(rv)) {
   581     IDB_WARNING("Failed to dispatch!");
   582     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   583     return nullptr;
   584   }
   586   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   587                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   588                     "getAllKeys(%s, %lu)",
   589                     "IDBRequest[%llu] MT IDBIndex.getAllKeys()",
   590                     request->GetSerialNumber(),
   591                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   592                                         Database()),
   593                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   594                     IDB_PROFILER_STRING(ObjectStore()),
   595                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
   596                     aLimit);
   598   return request.forget();
   599 }
   601 already_AddRefed<IDBRequest>
   602 IDBIndex::CountInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
   603 {
   604   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   606   IDBTransaction* transaction = mObjectStore->Transaction();
   607   if (!transaction->IsOpen()) {
   608     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   609     return nullptr;
   610   }
   612   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   613   if (!request) {
   614     IDB_WARNING("Failed to generate request!");
   615     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   616     return nullptr;
   617   }
   619   nsRefPtr<CountHelper> helper =
   620     new CountHelper(transaction, request, this, aKeyRange);
   622   nsresult rv = helper->DispatchToTransactionPool();
   623   if (NS_FAILED(rv)) {
   624     IDB_WARNING("Failed to dispatch!");
   625     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   626     return nullptr;
   627   }
   629   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   630                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   631                     "count(%s)",
   632                     "IDBRequest[%llu] MT IDBIndex.count()",
   633                     request->GetSerialNumber(),
   634                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   635                                         Database()),
   636                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   637                     IDB_PROFILER_STRING(ObjectStore()),
   638                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
   640   return request.forget();
   641 }
   643 already_AddRefed<IDBRequest>
   644 IDBIndex::OpenKeyCursorInternal(IDBKeyRange* aKeyRange, size_t aDirection,
   645                                 ErrorResult& aRv)
   646 {
   647   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   649   IDBTransaction* transaction = mObjectStore->Transaction();
   650   if (!transaction->IsOpen()) {
   651     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   652     return nullptr;
   653   }
   655   IDBCursor::Direction direction =
   656     static_cast<IDBCursor::Direction>(aDirection);
   658   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   659   if (!request) {
   660     IDB_WARNING("Failed to generate request!");
   661     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   662     return nullptr;
   663   }
   665   nsRefPtr<OpenKeyCursorHelper> helper =
   666     new OpenKeyCursorHelper(transaction, request, this, aKeyRange, direction);
   668   nsresult rv = helper->DispatchToTransactionPool();
   669   if (NS_FAILED(rv)) {
   670     IDB_WARNING("Failed to dispatch!");
   671     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   672     return nullptr;
   673   }
   675   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   676                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   677                     "openKeyCursor(%s)",
   678                     "IDBRequest[%llu] MT IDBIndex.openKeyCursor()",
   679                     request->GetSerialNumber(),
   680                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   681                                         Database()),
   682                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   683                     IDB_PROFILER_STRING(ObjectStore()),
   684                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
   685                     IDB_PROFILER_STRING(direction));
   687   return request.forget();
   688 }
   690 nsresult
   691 IDBIndex::OpenCursorInternal(IDBKeyRange* aKeyRange,
   692                              size_t aDirection,
   693                              IDBRequest** _retval)
   694 {
   695   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   697   IDBTransaction* transaction = mObjectStore->Transaction();
   698   if (!transaction->IsOpen()) {
   699     return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
   700   }
   702   IDBCursor::Direction direction =
   703     static_cast<IDBCursor::Direction>(aDirection);
   705   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   706   IDB_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   708   nsRefPtr<OpenCursorHelper> helper =
   709     new OpenCursorHelper(transaction, request, this, aKeyRange, direction);
   711   nsresult rv = helper->DispatchToTransactionPool();
   712   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   714   IDB_PROFILER_MARK("IndexedDB Request %llu: "
   715                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
   716                     "openCursor(%s)",
   717                     "IDBRequest[%llu] MT IDBIndex.openCursor()",
   718                     request->GetSerialNumber(),
   719                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
   720                                         Database()),
   721                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
   722                     IDB_PROFILER_STRING(ObjectStore()),
   723                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
   724                     IDB_PROFILER_STRING(direction));
   726   request.forget(_retval);
   727   return NS_OK;
   728 }
   730 nsresult
   731 IDBIndex::OpenCursorFromChildProcess(IDBRequest* aRequest,
   732                                      size_t aDirection,
   733                                      const Key& aKey,
   734                                      const Key& aObjectKey,
   735                                      IDBCursor** _retval)
   736 {
   737   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   739   IDBCursor::Direction direction =
   740     static_cast<IDBCursor::Direction>(aDirection);
   742   nsRefPtr<IDBCursor> cursor =
   743     IDBCursor::Create(aRequest, mObjectStore->Transaction(), this, direction,
   744                       Key(), EmptyCString(), EmptyCString(), aKey, aObjectKey);
   745   IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   747   cursor.forget(_retval);
   748   return NS_OK;
   749 }
   751 nsresult
   752 IDBIndex::OpenCursorFromChildProcess(
   753                             IDBRequest* aRequest,
   754                             size_t aDirection,
   755                             const Key& aKey,
   756                             const Key& aObjectKey,
   757                             const SerializedStructuredCloneReadInfo& aCloneInfo,
   758                             nsTArray<StructuredCloneFile>& aBlobs,
   759                             IDBCursor** _retval)
   760 {
   761   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   762   NS_ASSERTION((!aCloneInfo.dataLength && !aCloneInfo.data) ||
   763                (aCloneInfo.dataLength && aCloneInfo.data),
   764                "Inconsistent clone info!");
   766   IDBCursor::Direction direction =
   767     static_cast<IDBCursor::Direction>(aDirection);
   769   StructuredCloneReadInfo cloneInfo;
   771   if (!cloneInfo.SetFromSerialized(aCloneInfo)) {
   772     IDB_WARNING("Failed to copy clone buffer!");
   773     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   774   }
   776   cloneInfo.mFiles.SwapElements(aBlobs);
   778   nsRefPtr<IDBCursor> cursor =
   779     IDBCursor::Create(aRequest, mObjectStore->Transaction(), this, direction,
   780                       Key(), EmptyCString(), EmptyCString(), aKey, aObjectKey,
   781                       Move(cloneInfo));
   782   IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   784   NS_ASSERTION(!cloneInfo.mCloneBuffer.data(), "Should have swapped!");
   786   cursor.forget(_retval);
   787   return NS_OK;
   788 }
   790 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
   792 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
   793   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   794   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKeyPath)
   795 NS_IMPL_CYCLE_COLLECTION_TRACE_END
   797 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
   798   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   799   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
   800 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   802 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
   803   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   805   // Don't unlink mObjectStore!
   807   tmp->mCachedKeyPath = JSVAL_VOID;
   809   if (tmp->mRooted) {
   810     mozilla::DropJSObjects(tmp);
   811     tmp->mRooted = false;
   812   }
   813 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   815 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
   816   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   817   NS_INTERFACE_MAP_ENTRY(nsISupports)
   818 NS_INTERFACE_MAP_END
   820 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
   821 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
   823 JSObject*
   824 IDBIndex::WrapObject(JSContext* aCx)
   825 {
   826   return IDBIndexBinding::Wrap(aCx, this);
   827 }
   829 void
   830 IDBIndex::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
   831                      ErrorResult& aRv)
   832 {
   833   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   835   if (!JSVAL_IS_VOID(mCachedKeyPath)) {
   836     JS::ExposeValueToActiveJS(mCachedKeyPath);
   837     aResult.set(mCachedKeyPath);
   838     return;
   839   }
   841   aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
   842   if (NS_WARN_IF(aRv.Failed())) {
   843     return;
   844   }
   846   if (JSVAL_IS_GCTHING(mCachedKeyPath)) {
   847     mozilla::HoldJSObjects(this);
   848     mRooted = true;
   849   }
   851   JS::ExposeValueToActiveJS(mCachedKeyPath);
   852   aResult.set(mCachedKeyPath);
   853 }
   855 already_AddRefed<IDBRequest>
   856 IDBIndex::Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   857 {
   858   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   860   IDBTransaction* transaction = mObjectStore->Transaction();
   861   if (!transaction->IsOpen()) {
   862     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   863     return nullptr;
   864   }
   866   nsRefPtr<IDBKeyRange> keyRange;
   867   aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
   868   ENSURE_SUCCESS(aRv, nullptr);
   870   if (!keyRange) {
   871     // Must specify a key or keyRange for getKey().
   872     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
   873     return nullptr;
   874   }
   876   return GetInternal(keyRange, aRv);
   877 }
   879 already_AddRefed<IDBRequest>
   880 IDBIndex::GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   881 {
   882   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   884   IDBTransaction* transaction = mObjectStore->Transaction();
   885   if (!transaction->IsOpen()) {
   886     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   887     return nullptr;
   888   }
   890   nsRefPtr<IDBKeyRange> keyRange;
   891   aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
   892   ENSURE_SUCCESS(aRv, nullptr);
   894   if (!keyRange) {
   895     // Must specify a key or keyRange for get().
   896     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
   897     return nullptr;
   898   }
   900   return GetKeyInternal(keyRange, aRv);
   901 }
   903 already_AddRefed<IDBRequest>
   904 IDBIndex::GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
   905                  const Optional<uint32_t>& aLimit, ErrorResult& aRv)
   906 {
   907   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   909   IDBTransaction* transaction = mObjectStore->Transaction();
   910   if (!transaction->IsOpen()) {
   911     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   912     return nullptr;
   913   }
   915   nsRefPtr<IDBKeyRange> keyRange;
   916   aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
   917   ENSURE_SUCCESS(aRv, nullptr);
   919   uint32_t limit = UINT32_MAX;
   920   if (aLimit.WasPassed() && aLimit.Value() > 0) {
   921     limit = aLimit.Value();
   922   }
   924   return GetAllInternal(keyRange, limit, aRv);
   925 }
   927 already_AddRefed<IDBRequest>
   928 IDBIndex::GetAllKeys(JSContext* aCx,
   929                      JS::Handle<JS::Value> aKey,
   930                      const Optional<uint32_t>& aLimit, ErrorResult& aRv)
   931 {
   932   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   934   IDBTransaction* transaction = mObjectStore->Transaction();
   935   if (!transaction->IsOpen()) {
   936     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   937     return nullptr;
   938   }
   940   nsRefPtr<IDBKeyRange> keyRange;
   941   aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
   942   ENSURE_SUCCESS(aRv, nullptr);
   944   uint32_t limit = UINT32_MAX;
   945   if (aLimit.WasPassed() && aLimit.Value() > 0) {
   946     limit = aLimit.Value();
   947   }
   949   return GetAllKeysInternal(keyRange, limit, aRv);
   950 }
   952 already_AddRefed<IDBRequest>
   953 IDBIndex::OpenCursor(JSContext* aCx,
   954                      JS::Handle<JS::Value> aRange,
   955                      IDBCursorDirection aDirection, ErrorResult& aRv)
   956 {
   957   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   959   IDBTransaction* transaction = mObjectStore->Transaction();
   960   if (!transaction->IsOpen()) {
   961     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   962     return nullptr;
   963   }
   965   nsRefPtr<IDBKeyRange> keyRange;
   966   aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
   967   ENSURE_SUCCESS(aRv, nullptr);
   969   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
   971   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   972   if (!request) {
   973     IDB_WARNING("Failed to generate request!");
   974     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   975     return nullptr;
   976   }
   978   nsRefPtr<OpenCursorHelper> helper =
   979     new OpenCursorHelper(transaction, request, this, keyRange, direction);
   981   nsresult rv = helper->DispatchToTransactionPool();
   982   if (NS_FAILED(rv)) {
   983     IDB_WARNING("Failed to dispatch!");
   984     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   985     return nullptr;
   986   }
   988   return request.forget();
   989 }
   991 already_AddRefed<IDBRequest>
   992 IDBIndex::OpenKeyCursor(JSContext* aCx,
   993                         JS::Handle<JS::Value> aRange,
   994                         IDBCursorDirection aDirection, ErrorResult& aRv)
   995 {
   996   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   998   IDBTransaction* transaction = mObjectStore->Transaction();
   999   if (!transaction->IsOpen()) {
  1000     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
  1001     return nullptr;
  1004   nsRefPtr<IDBKeyRange> keyRange;
  1005   aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
  1006   ENSURE_SUCCESS(aRv, nullptr);
  1008   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
  1010   return OpenKeyCursorInternal(keyRange, direction, aRv);
  1013 already_AddRefed<IDBRequest>
  1014 IDBIndex::Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
  1015                 ErrorResult& aRv)
  1017   IDBTransaction* transaction = mObjectStore->Transaction();
  1018   if (!transaction->IsOpen()) {
  1019     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
  1020     return nullptr;
  1023   nsRefPtr<IDBKeyRange> keyRange;
  1024   aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
  1025   ENSURE_SUCCESS(aRv, nullptr);
  1027   return CountInternal(keyRange, aRv);
  1030 void
  1031 IndexHelper::ReleaseMainThreadObjects()
  1033   mIndex = nullptr;
  1034   AsyncConnectionHelper::ReleaseMainThreadObjects();
  1037 nsresult
  1038 IndexHelper::Dispatch(nsIEventTarget* aDatabaseThread)
  1040   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1042   PROFILER_MAIN_THREAD_LABEL("IndexedDB", "IndexHelper::Dispatch");
  1044   if (IndexedDatabaseManager::IsMainProcess()) {
  1045     return AsyncConnectionHelper::Dispatch(aDatabaseThread);
  1048   // If we've been invalidated then there's no point sending anything to the
  1049   // parent process.
  1050   if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) {
  1051     IDB_REPORT_INTERNAL_ERR();
  1052     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1055   IndexedDBIndexChild* indexActor = mIndex->GetActorChild();
  1056   NS_ASSERTION(indexActor, "Must have an actor here!");
  1058   IndexRequestParams params;
  1059   nsresult rv = PackArgumentsForParentProcess(params);
  1060   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1062   NoDispatchEventTarget target;
  1063   rv = AsyncConnectionHelper::Dispatch(&target);
  1064   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1066   mActor = new IndexedDBIndexRequestChild(this, mIndex, params.type());
  1067   indexActor->SendPIndexedDBRequestConstructor(mActor, params);
  1069   return NS_OK;
  1072 nsresult
  1073 GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
  1075   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  1076   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1077   NS_ASSERTION(mKeyRange, "Must have a key range here!");
  1079   PROFILER_LABEL("IndexedDB", "GetKeyHelper::DoDatabaseWork");
  1081   nsCString indexTable;
  1082   if (mIndex->IsUnique()) {
  1083     indexTable.AssignLiteral("unique_index_data");
  1085   else {
  1086     indexTable.AssignLiteral("index_data");
  1089   nsCString keyRangeClause;
  1090   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
  1092   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
  1094   nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
  1095                     indexTable +
  1096                     NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
  1097                     keyRangeClause +
  1098                     NS_LITERAL_CSTRING(" LIMIT 1");
  1100   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  1101   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1103   mozStorageStatementScoper scoper(stmt);
  1105   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
  1106                                       mIndex->Id());
  1107   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1109   rv = mKeyRange->BindToStatement(stmt);
  1110   NS_ENSURE_SUCCESS(rv, rv);
  1112   bool hasResult;
  1113   rv = stmt->ExecuteStep(&hasResult);
  1114   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1116   if (hasResult) {
  1117     rv = mKey.SetFromStatement(stmt, 0);
  1118     NS_ENSURE_SUCCESS(rv, rv);
  1121   return NS_OK;
  1124 nsresult
  1125 GetKeyHelper::GetSuccessResult(JSContext* aCx,
  1126                                JS::MutableHandle<JS::Value> aVal)
  1128   return mKey.ToJSVal(aCx, aVal);
  1131 void
  1132 GetKeyHelper::ReleaseMainThreadObjects()
  1134   mKeyRange = nullptr;
  1135   IndexHelper::ReleaseMainThreadObjects();
  1138 nsresult
  1139 GetKeyHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  1141   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1142   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1143   NS_ASSERTION(mKeyRange, "This should never be null!");
  1145   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1146                              "GetKeyHelper::PackArgumentsForParentProcess");
  1148   GetKeyParams params;
  1150   mKeyRange->ToSerializedKeyRange(params.keyRange());
  1152   aParams = params;
  1153   return NS_OK;
  1156 AsyncConnectionHelper::ChildProcessSendResult
  1157 GetKeyHelper::SendResponseToChildProcess(nsresult aResultCode)
  1159   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1160   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1162   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1163                              "GetKeyHelper::SendResponseToChildProcess");
  1165   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  1166   NS_ASSERTION(actor, "How did we get this far without an actor?");
  1168   ResponseValue response;
  1169   if (NS_FAILED(aResultCode)) {
  1170     response = aResultCode;
  1172   else {
  1173     GetKeyResponse getKeyResponse;
  1174     getKeyResponse.key() = mKey;
  1175     response = getKeyResponse;
  1178   if (!actor->SendResponse(response)) {
  1179     return Error;
  1182   return Success_Sent;
  1185 nsresult
  1186 GetKeyHelper::UnpackResponseFromParentProcess(
  1187                                             const ResponseValue& aResponseValue)
  1189   NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetKeyResponse,
  1190                "Bad response type!");
  1192   mKey = aResponseValue.get_GetKeyResponse().key();
  1193   return NS_OK;
  1196 nsresult
  1197 GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
  1199   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  1200   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1201   NS_ASSERTION(mKeyRange, "Must have a key range here!");
  1203   PROFILER_LABEL("IndexedDB", "GetHelper::DoDatabaseWork [IDBIndex.cpp]");
  1205   nsCString indexTable;
  1206   if (mIndex->IsUnique()) {
  1207     indexTable.AssignLiteral("unique_index_data");
  1209   else {
  1210     indexTable.AssignLiteral("index_data");
  1213   nsCString keyRangeClause;
  1214   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
  1216   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
  1218   nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
  1219                                        "INNER JOIN ") + indexTable +
  1220                     NS_LITERAL_CSTRING(" AS index_table ON object_data.id = ") +
  1221                     NS_LITERAL_CSTRING("index_table.object_data_id WHERE "
  1222                                        "index_id = :index_id") +
  1223                     keyRangeClause +
  1224                     NS_LITERAL_CSTRING(" LIMIT 1");
  1226   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  1227   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1229   mozStorageStatementScoper scoper(stmt);
  1231   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
  1232                                       mIndex->Id());
  1233   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1235   rv = mKeyRange->BindToStatement(stmt);
  1236   NS_ENSURE_SUCCESS(rv, rv);
  1238   bool hasResult;
  1239   rv = stmt->ExecuteStep(&hasResult);
  1240   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1242   if (hasResult) {
  1243     rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
  1244       mDatabase, mCloneReadInfo);
  1245     NS_ENSURE_SUCCESS(rv, rv);
  1248   return NS_OK;
  1251 nsresult
  1252 GetHelper::GetSuccessResult(JSContext* aCx,
  1253                             JS::MutableHandle<JS::Value> aVal)
  1255   bool result = IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, aVal);
  1257   mCloneReadInfo.mCloneBuffer.clear();
  1259   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
  1260   return NS_OK;
  1263 void
  1264 GetHelper::ReleaseMainThreadObjects()
  1266   IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
  1267   GetKeyHelper::ReleaseMainThreadObjects();
  1270 nsresult
  1271 GetHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  1273   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1274   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1275   NS_ASSERTION(mKeyRange, "This should never be null!");
  1277   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1278                              "GetHelper::PackArgumentsForParentProcess "
  1279                              "[IDBIndex.cpp]");
  1281   GetParams params;
  1283   mKeyRange->ToSerializedKeyRange(params.keyRange());
  1285   aParams = params;
  1286   return NS_OK;
  1289 AsyncConnectionHelper::ChildProcessSendResult
  1290 GetHelper::SendResponseToChildProcess(nsresult aResultCode)
  1292   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1293   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1295   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1296                              "GetHelper::SendResponseToChildProcess "
  1297                              "[IDBIndex.cpp]");
  1299   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  1300   NS_ASSERTION(actor, "How did we get this far without an actor?");
  1302   InfallibleTArray<PBlobParent*> blobsParent;
  1304   if (NS_SUCCEEDED(aResultCode)) {
  1305     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
  1306     NS_ASSERTION(database, "This should never be null!");
  1308     ContentParent* contentParent = database->GetContentParent();
  1309     NS_ASSERTION(contentParent, "This should never be null!");
  1311     FileManager* fileManager = database->Manager();
  1312     NS_ASSERTION(fileManager, "This should never be null!");
  1314     const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
  1316     aResultCode =
  1317       IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
  1318                                            blobsParent);
  1319     if (NS_FAILED(aResultCode)) {
  1320       NS_WARNING("ConvertBlobActors failed!");
  1324   ResponseValue response;
  1325   if (NS_FAILED(aResultCode)) {
  1326     response = aResultCode;
  1328   else {
  1329     GetResponse getResponse;
  1330     getResponse.cloneInfo() = mCloneReadInfo;
  1331     getResponse.blobsParent().SwapElements(blobsParent);
  1332     response = getResponse;
  1335   if (!actor->SendResponse(response)) {
  1336     return Error;
  1339   return Success_Sent;
  1342 nsresult
  1343 GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
  1345   NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetResponse,
  1346                "Bad response type!");
  1348   const GetResponse& getResponse = aResponseValue.get_GetResponse();
  1349   const SerializedStructuredCloneReadInfo& cloneInfo = getResponse.cloneInfo();
  1351   NS_ASSERTION((!cloneInfo.dataLength && !cloneInfo.data) ||
  1352                (cloneInfo.dataLength && cloneInfo.data),
  1353                "Inconsistent clone info!");
  1355   if (!mCloneReadInfo.SetFromSerialized(cloneInfo)) {
  1356     IDB_WARNING("Failed to copy clone buffer!");
  1357     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1360   IDBObjectStore::ConvertActorsToBlobs(getResponse.blobsChild(),
  1361                                        mCloneReadInfo.mFiles);
  1362   return NS_OK;
  1365 nsresult
  1366 GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
  1368   MOZ_ASSERT(!NS_IsMainThread());
  1369   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
  1371   PROFILER_LABEL("IndexedDB",
  1372                  "GetAllKeysHelper::DoDatabaseWork [IDBIndex.cpp]");
  1374   nsCString tableName;
  1375   if (mIndex->IsUnique()) {
  1376     tableName.AssignLiteral("unique_index_data");
  1378   else {
  1379     tableName.AssignLiteral("index_data");
  1382   nsCString keyRangeClause;
  1383   if (mKeyRange) {
  1384     mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
  1387   nsCString limitClause;
  1388   if (mLimit != UINT32_MAX) {
  1389     limitClause = NS_LITERAL_CSTRING(" LIMIT ");
  1390     limitClause.AppendInt(mLimit);
  1393   nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
  1394                     tableName +
  1395                     NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
  1396                     keyRangeClause + limitClause;
  1398   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  1399   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1401   mozStorageStatementScoper scoper(stmt);
  1403   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
  1404                                       mIndex->Id());
  1405   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1407   if (mKeyRange) {
  1408     rv = mKeyRange->BindToStatement(stmt);
  1409     NS_ENSURE_SUCCESS(rv, rv);
  1412   mKeys.SetCapacity(std::min<uint32_t>(50, mLimit));
  1414   bool hasResult;
  1415   while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
  1416     if (mKeys.Capacity() == mKeys.Length()) {
  1417       mKeys.SetCapacity(mKeys.Capacity() * 2);
  1420     Key* key = mKeys.AppendElement();
  1421     NS_ASSERTION(key, "This shouldn't fail!");
  1423     rv = key->SetFromStatement(stmt, 0);
  1424     NS_ENSURE_SUCCESS(rv, rv);
  1426   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1428   return NS_OK;
  1431 nsresult
  1432 GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
  1433                                    JS::MutableHandle<JS::Value> aVal)
  1435   MOZ_ASSERT(NS_IsMainThread());
  1436   MOZ_ASSERT(mKeys.Length() <= mLimit);
  1438   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1439                              "GetAllKeysHelper::GetSuccessResult "
  1440                              "[IDBIndex.cpp]");
  1442   nsTArray<Key> keys;
  1443   mKeys.SwapElements(keys);
  1445   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
  1446   if (!array) {
  1447     IDB_WARNING("Failed to make array!");
  1448     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1451   if (!keys.IsEmpty()) {
  1452     if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
  1453       IDB_WARNING("Failed to set array length!");
  1454       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1457     for (uint32_t index = 0, count = keys.Length(); index < count; index++) {
  1458       const Key& key = keys[index];
  1459       NS_ASSERTION(!key.IsUnset(), "Bad key!");
  1461       JS::Rooted<JS::Value> value(aCx);
  1462       nsresult rv = key.ToJSVal(aCx, &value);
  1463       if (NS_FAILED(rv)) {
  1464         NS_WARNING("Failed to get jsval for key!");
  1465         return rv;
  1468       if (!JS_SetElement(aCx, array, index, value)) {
  1469         IDB_WARNING("Failed to set array element!");
  1470         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1475   aVal.setObject(*array);
  1476   return NS_OK;
  1479 nsresult
  1480 GetAllKeysHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  1482   MOZ_ASSERT(NS_IsMainThread());
  1483   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
  1485   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1486                              "GetAllKeysHelper::PackArgumentsForParentProcess "
  1487                              "[IDBIndex.cpp]");
  1489   GetAllKeysParams params;
  1491   if (mKeyRange) {
  1492     KeyRange keyRange;
  1493     mKeyRange->ToSerializedKeyRange(keyRange);
  1494     params.optionalKeyRange() = keyRange;
  1496   else {
  1497     params.optionalKeyRange() = mozilla::void_t();
  1500   params.limit() = mLimit;
  1502   aParams = params;
  1503   return NS_OK;
  1506 AsyncConnectionHelper::ChildProcessSendResult
  1507 GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode)
  1509   MOZ_ASSERT(NS_IsMainThread());
  1510   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
  1512   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1513                              "GetAllKeysHelper::SendResponseToChildProcess "
  1514                              "[IDBIndex.cpp]");
  1516   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  1517   NS_ASSERTION(actor, "How did we get this far without an actor?");
  1519   ResponseValue response;
  1520   if (NS_FAILED(aResultCode)) {
  1521     response = aResultCode;
  1523   else {
  1524     GetAllKeysResponse getAllKeysResponse;
  1525     getAllKeysResponse.keys().AppendElements(mKeys);
  1526     response = getAllKeysResponse;
  1529   if (!actor->SendResponse(response)) {
  1530     return Error;
  1533   return Success_Sent;
  1536 nsresult
  1537 GetAllKeysHelper::UnpackResponseFromParentProcess(
  1538                                             const ResponseValue& aResponseValue)
  1540   MOZ_ASSERT(NS_IsMainThread());
  1541   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
  1542   MOZ_ASSERT(aResponseValue.type() == ResponseValue::TGetAllKeysResponse);
  1544   mKeys.AppendElements(aResponseValue.get_GetAllKeysResponse().keys());
  1545   return NS_OK;
  1548 nsresult
  1549 GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
  1551   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  1552   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1554   PROFILER_LABEL("IndexedDB", "GetAllHelper::DoDatabaseWork [IDBIndex.cpp]");
  1556   nsCString indexTable;
  1557   if (mIndex->IsUnique()) {
  1558     indexTable.AssignLiteral("unique_index_data");
  1560   else {
  1561     indexTable.AssignLiteral("index_data");
  1564   nsCString keyRangeClause;
  1565   if (mKeyRange) {
  1566     mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
  1569   nsCString limitClause;
  1570   if (mLimit != UINT32_MAX) {
  1571     limitClause = NS_LITERAL_CSTRING(" LIMIT ");
  1572     limitClause.AppendInt(mLimit);
  1575   nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
  1576                                        "INNER JOIN ") + indexTable +
  1577                     NS_LITERAL_CSTRING(" AS index_table ON object_data.id = "
  1578                                        "index_table.object_data_id "
  1579                                        "WHERE index_id = :index_id") +
  1580                     keyRangeClause + limitClause;
  1582   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  1583   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1585   mozStorageStatementScoper scoper(stmt);
  1587   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
  1588                                       mIndex->Id());
  1589   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1591   if (mKeyRange) {
  1592     rv = mKeyRange->BindToStatement(stmt);
  1593     NS_ENSURE_SUCCESS(rv, rv);
  1596   mCloneReadInfos.SetCapacity(50);
  1598   bool hasResult;
  1599   while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
  1600     if (mCloneReadInfos.Capacity() == mCloneReadInfos.Length()) {
  1601       mCloneReadInfos.SetCapacity(mCloneReadInfos.Capacity() * 2);
  1604     StructuredCloneReadInfo* readInfo = mCloneReadInfos.AppendElement();
  1605     NS_ASSERTION(readInfo, "This shouldn't fail!");
  1607     rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
  1608       mDatabase, *readInfo);
  1609     NS_ENSURE_SUCCESS(rv, rv);
  1611   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1613   return NS_OK;
  1616 nsresult
  1617 GetAllHelper::GetSuccessResult(JSContext* aCx,
  1618                                JS::MutableHandle<JS::Value> aVal)
  1620   NS_ASSERTION(mCloneReadInfos.Length() <= mLimit, "Too many results!");
  1622   nsresult rv = ConvertToArrayAndCleanup(aCx, mCloneReadInfos, aVal);
  1624   NS_ASSERTION(mCloneReadInfos.IsEmpty(),
  1625                "Should have cleared in ConvertToArrayAndCleanup");
  1626   NS_ENSURE_SUCCESS(rv, rv);
  1628   return NS_OK;
  1631 void
  1632 GetAllHelper::ReleaseMainThreadObjects()
  1634   for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
  1635     IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
  1637   GetKeyHelper::ReleaseMainThreadObjects();
  1640 nsresult
  1641 GetAllHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  1643   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1644   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1646   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1647                              "GetAllHelper::PackArgumentsForParentProcess "
  1648                              "[IDBIndex.cpp]");
  1650   GetAllParams params;
  1652   if (mKeyRange) {
  1653     KeyRange keyRange;
  1654     mKeyRange->ToSerializedKeyRange(keyRange);
  1655     params.optionalKeyRange() = keyRange;
  1657   else {
  1658     params.optionalKeyRange() = mozilla::void_t();
  1661   params.limit() = mLimit;
  1663   aParams = params;
  1664   return NS_OK;
  1667 AsyncConnectionHelper::ChildProcessSendResult
  1668 GetAllHelper::SendResponseToChildProcess(nsresult aResultCode)
  1670   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1671   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1673   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1674                              "GetAllHelper::SendResponseToChildProcess "
  1675                              "[IDBIndex.cpp]");
  1677   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  1678   NS_ASSERTION(actor, "How did we get this far without an actor?");
  1680   GetAllResponse getAllResponse;
  1682   if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
  1683     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
  1684     NS_ASSERTION(database, "This should never be null!");
  1686     ContentParent* contentParent = database->GetContentParent();
  1687     NS_ASSERTION(contentParent, "This should never be null!");
  1689     FileManager* fileManager = database->Manager();
  1690     NS_ASSERTION(fileManager, "This should never be null!");
  1692     uint32_t length = mCloneReadInfos.Length();
  1694     InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
  1695       getAllResponse.cloneInfos();
  1696     infos.SetCapacity(length);
  1698     InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
  1699     blobArrays.SetCapacity(length);
  1701     for (uint32_t index = 0;
  1702          NS_SUCCEEDED(aResultCode) && index < length;
  1703          index++) {
  1704       const StructuredCloneReadInfo& clone = mCloneReadInfos[index];
  1706       // Append the structured clone data.
  1707       SerializedStructuredCloneReadInfo* info = infos.AppendElement();
  1708       *info = clone;
  1710       const nsTArray<StructuredCloneFile>& files = clone.mFiles;
  1712       // Now take care of the files.
  1713       BlobArray* blobArray = blobArrays.AppendElement();
  1715       InfallibleTArray<PBlobParent*>& blobs = blobArray->blobsParent();
  1717       aResultCode =
  1718         IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
  1719                                              blobs);
  1720       if (NS_FAILED(aResultCode)) {
  1721         NS_WARNING("ConvertBlobsToActors failed!");
  1722         break;
  1727   ResponseValue response;
  1728   if (NS_FAILED(aResultCode)) {
  1729     response = aResultCode;
  1731   else {
  1732     response = getAllResponse;
  1735   if (!actor->SendResponse(response)) {
  1736     return Error;
  1739   return Success_Sent;
  1742 nsresult
  1743 GetAllHelper::UnpackResponseFromParentProcess(
  1744                                             const ResponseValue& aResponseValue)
  1746   NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetAllResponse,
  1747                "Bad response type!");
  1749   const GetAllResponse& getAllResponse = aResponseValue.get_GetAllResponse();
  1750   const InfallibleTArray<SerializedStructuredCloneReadInfo>& cloneInfos =
  1751     getAllResponse.cloneInfos();
  1752   const InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
  1754   mCloneReadInfos.SetCapacity(cloneInfos.Length());
  1756   for (uint32_t index = 0; index < cloneInfos.Length(); index++) {
  1757     const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index];
  1758     const InfallibleTArray<PBlobChild*>& blobs = blobArrays[index].blobsChild();
  1760     StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement();
  1761     if (!destInfo->SetFromSerialized(srcInfo)) {
  1762       IDB_WARNING("Failed to copy clone buffer!");
  1763       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
  1766     IDBObjectStore::ConvertActorsToBlobs(blobs, destInfo->mFiles);
  1769   return NS_OK;
  1772 nsresult
  1773 OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
  1775   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  1776   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1777   NS_ASSERTION(aConnection, "Passed a null connection!");
  1779   PROFILER_LABEL("IndexedDB", "OpenKeyCursorHelper::DoDatabaseWork");
  1781   nsCString table;
  1782   if (mIndex->IsUnique()) {
  1783     table.AssignLiteral("unique_index_data");
  1785   else {
  1786     table.AssignLiteral("index_data");
  1789   NS_NAMED_LITERAL_CSTRING(value, "value");
  1791   nsCString keyRangeClause;
  1792   if (mKeyRange) {
  1793     mKeyRange->GetBindingClause(value, keyRangeClause);
  1796   nsAutoCString directionClause(" ORDER BY value ");
  1797   switch (mDirection) {
  1798     case IDBCursor::NEXT:
  1799     case IDBCursor::NEXT_UNIQUE:
  1800       directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
  1801       break;
  1803     case IDBCursor::PREV:
  1804       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
  1805       break;
  1807     case IDBCursor::PREV_UNIQUE:
  1808       directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
  1809       break;
  1811     default:
  1812       NS_NOTREACHED("Unknown direction!");
  1814   nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
  1815                                             "FROM ") + table +
  1816                          NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
  1817                          keyRangeClause + directionClause +
  1818                          NS_LITERAL_CSTRING(" LIMIT 1");
  1820   nsCOMPtr<mozIStorageStatement> stmt =
  1821     mTransaction->GetCachedStatement(firstQuery);
  1822   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1824   mozStorageStatementScoper scoper(stmt);
  1826   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
  1827                                       mIndex->Id());
  1828   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1830   if (mKeyRange) {
  1831     rv = mKeyRange->BindToStatement(stmt);
  1832     NS_ENSURE_SUCCESS(rv, rv);
  1835   bool hasResult;
  1836   rv = stmt->ExecuteStep(&hasResult);
  1837   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1839   if (!hasResult) {
  1840     mKey.Unset();
  1841     return NS_OK;
  1844   rv = mKey.SetFromStatement(stmt, 0);
  1845   NS_ENSURE_SUCCESS(rv, rv);
  1847   rv = mObjectKey.SetFromStatement(stmt, 1);
  1848   NS_ENSURE_SUCCESS(rv, rv);
  1850   // Now we need to make the query to get the next match.
  1851   nsAutoCString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
  1852                                                 " FROM ") + table +
  1853                              NS_LITERAL_CSTRING(" WHERE index_id = :id");
  1855   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
  1857   switch (mDirection) {
  1858     case IDBCursor::NEXT:
  1859       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
  1860         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
  1861                               queryStart);
  1862         mRangeKey = mKeyRange->Upper();
  1864       mContinueQuery =
  1865         queryStart +
  1866         NS_LITERAL_CSTRING(" AND value >= :current_key AND "
  1867                            "( value > :current_key OR "
  1868                            "  object_data_key > :object_key )") +
  1869         directionClause +
  1870         NS_LITERAL_CSTRING(" LIMIT ");
  1871       mContinueToQuery =
  1872         queryStart +
  1873         NS_LITERAL_CSTRING(" AND value >= :current_key ") +
  1874         directionClause +
  1875         NS_LITERAL_CSTRING(" LIMIT ");
  1876       break;
  1878     case IDBCursor::NEXT_UNIQUE:
  1879       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
  1880         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
  1881                               queryStart);
  1882         mRangeKey = mKeyRange->Upper();
  1884       mContinueQuery =
  1885         queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
  1886         directionClause +
  1887         NS_LITERAL_CSTRING(" LIMIT ");
  1888       mContinueToQuery =
  1889         queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
  1890         directionClause +
  1891         NS_LITERAL_CSTRING(" LIMIT ");
  1892       break;
  1894     case IDBCursor::PREV:
  1895       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
  1896         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
  1897                               queryStart);
  1898         mRangeKey = mKeyRange->Lower();
  1901       mContinueQuery =
  1902         queryStart +
  1903         NS_LITERAL_CSTRING(" AND value <= :current_key AND "
  1904                            "( value < :current_key OR "
  1905                            "  object_data_key < :object_key )") +
  1906         directionClause +
  1907         NS_LITERAL_CSTRING(" LIMIT ");
  1908       mContinueToQuery =
  1909         queryStart +
  1910         NS_LITERAL_CSTRING(" AND value <= :current_key ") +
  1911         directionClause +
  1912         NS_LITERAL_CSTRING(" LIMIT ");
  1913       break;
  1915     case IDBCursor::PREV_UNIQUE:
  1916       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
  1917         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
  1918                               queryStart);
  1919         mRangeKey = mKeyRange->Lower();
  1921       mContinueQuery =
  1922         queryStart +
  1923         NS_LITERAL_CSTRING(" AND value < :current_key") +
  1924         directionClause +
  1925         NS_LITERAL_CSTRING(" LIMIT ");
  1926       mContinueToQuery =
  1927         queryStart +
  1928         NS_LITERAL_CSTRING(" AND value <= :current_key") +
  1929         directionClause +
  1930         NS_LITERAL_CSTRING(" LIMIT ");
  1931       break;
  1933     default:
  1934       NS_NOTREACHED("Unknown direction type!");
  1937   return NS_OK;
  1940 nsresult
  1941 OpenKeyCursorHelper::EnsureCursor()
  1943   if (mCursor || mKey.IsUnset()) {
  1944     return NS_OK;
  1947   nsRefPtr<IDBCursor> cursor =
  1948     IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
  1949                       mContinueQuery, mContinueToQuery, mKey, mObjectKey);
  1950   IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1952   mCursor.swap(cursor);
  1953   return NS_OK;
  1956 nsresult
  1957 OpenKeyCursorHelper::GetSuccessResult(JSContext* aCx,
  1958                                       JS::MutableHandle<JS::Value> aVal)
  1960   nsresult rv = EnsureCursor();
  1961   NS_ENSURE_SUCCESS(rv, rv);
  1963   if (mCursor) {
  1964     rv = WrapNative(aCx, mCursor, aVal);
  1965     IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  1967   else {
  1968     aVal.setUndefined();
  1971   return NS_OK;
  1974 void
  1975 OpenKeyCursorHelper::ReleaseMainThreadObjects()
  1977   mKeyRange = nullptr;
  1978   mCursor = nullptr;
  1979   IndexHelper::ReleaseMainThreadObjects();
  1982 nsresult
  1983 OpenKeyCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  1985   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1986   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  1988   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  1989                              "OpenKeyCursorHelper::"
  1990                              "PackArgumentsForParentProcess [IDBIndex.cpp]");
  1992   OpenKeyCursorParams params;
  1994   if (mKeyRange) {
  1995     KeyRange keyRange;
  1996     mKeyRange->ToSerializedKeyRange(keyRange);
  1997     params.optionalKeyRange() = keyRange;
  1999   else {
  2000     params.optionalKeyRange() = mozilla::void_t();
  2003   params.direction() = mDirection;
  2005   aParams = params;
  2006   return NS_OK;
  2009 AsyncConnectionHelper::ChildProcessSendResult
  2010 OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
  2012   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  2013   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2014   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
  2016   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  2017                              "OpenKeyCursorHelper::SendResponseToChildProcess");
  2019   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  2020   NS_ASSERTION(actor, "How did we get this far without an actor?");
  2022   if (NS_SUCCEEDED(aResultCode)) {
  2023     nsresult rv = EnsureCursor();
  2024     if (NS_FAILED(rv)) {
  2025       NS_WARNING("EnsureCursor failed!");
  2026       aResultCode = rv;
  2030   ResponseValue response;
  2031   if (NS_FAILED(aResultCode)) {
  2032     response = aResultCode;
  2034   else {
  2035     OpenCursorResponse openCursorResponse;
  2037     if (!mCursor) {
  2038       openCursorResponse = mozilla::void_t();
  2040     else {
  2041       IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
  2042       NS_ASSERTION(indexActor, "Must have an actor here!");
  2044       IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
  2045       NS_ASSERTION(requestActor, "Must have an actor here!");
  2047       IndexCursorConstructorParams params;
  2048       params.requestParent() = requestActor;
  2049       params.direction() = mDirection;
  2050       params.key() = mKey;
  2051       params.objectKey() = mObjectKey;
  2052       params.optionalCloneInfo() = mozilla::void_t();
  2054       if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
  2055         return Error;
  2059     response = openCursorResponse;
  2062   if (!actor->SendResponse(response)) {
  2063     return Error;
  2066   return Success_Sent;
  2069 nsresult
  2070 OpenKeyCursorHelper::UnpackResponseFromParentProcess(
  2071                                             const ResponseValue& aResponseValue)
  2073   NS_ASSERTION(aResponseValue.type() == ResponseValue::TOpenCursorResponse,
  2074                "Bad response type!");
  2075   NS_ASSERTION(aResponseValue.get_OpenCursorResponse().type() ==
  2076                OpenCursorResponse::Tvoid_t ||
  2077                aResponseValue.get_OpenCursorResponse().type() ==
  2078                OpenCursorResponse::TPIndexedDBCursorChild,
  2079                "Bad response union type!");
  2080   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
  2082   const OpenCursorResponse& response =
  2083     aResponseValue.get_OpenCursorResponse();
  2085   switch (response.type()) {
  2086     case OpenCursorResponse::Tvoid_t:
  2087       break;
  2089     case OpenCursorResponse::TPIndexedDBCursorChild: {
  2090       IndexedDBCursorChild* actor =
  2091         static_cast<IndexedDBCursorChild*>(
  2092           response.get_PIndexedDBCursorChild());
  2094       mCursor = actor->ForgetStrongCursor();
  2095       NS_ASSERTION(mCursor, "This should never be null!");
  2097     } break;
  2099     default:
  2100       MOZ_CRASH();
  2103   return NS_OK;
  2106 nsresult
  2107 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
  2109   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  2110   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2111   NS_ASSERTION(aConnection, "Passed a null connection!");
  2113   PROFILER_LABEL("IndexedDB",
  2114                  "OpenCursorHelper::DoDatabaseWork [IDBIndex.cpp]");
  2116   nsCString indexTable;
  2117   if (mIndex->IsUnique()) {
  2118     indexTable.AssignLiteral("unique_index_data");
  2120   else {
  2121     indexTable.AssignLiteral("index_data");
  2124   NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
  2126   nsCString keyRangeClause;
  2127   if (mKeyRange) {
  2128     mKeyRange->GetBindingClause(value, keyRangeClause);
  2131   nsAutoCString directionClause(" ORDER BY index_table.value ");
  2132   switch (mDirection) {
  2133     case IDBCursor::NEXT:
  2134     case IDBCursor::NEXT_UNIQUE:
  2135       directionClause +=
  2136         NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
  2137       break;
  2139     case IDBCursor::PREV:
  2140       directionClause +=
  2141         NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
  2142       break;
  2144     case IDBCursor::PREV_UNIQUE:
  2145       directionClause +=
  2146         NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
  2147       break;
  2149     default:
  2150       NS_NOTREACHED("Unknown direction!");
  2153   nsCString firstQuery =
  2154     NS_LITERAL_CSTRING("SELECT index_table.value, "
  2155                        "index_table.object_data_key, object_data.data, "
  2156                        "object_data.file_ids FROM ") +
  2157     indexTable +
  2158     NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
  2159                        "index_table.object_data_id = object_data.id "
  2160                        "WHERE index_table.index_id = :id") +
  2161     keyRangeClause + directionClause +
  2162     NS_LITERAL_CSTRING(" LIMIT 1");
  2164   nsCOMPtr<mozIStorageStatement> stmt =
  2165     mTransaction->GetCachedStatement(firstQuery);
  2166   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2168   mozStorageStatementScoper scoper(stmt);
  2170   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
  2171   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2173   if (mKeyRange) {
  2174     rv = mKeyRange->BindToStatement(stmt);
  2175     NS_ENSURE_SUCCESS(rv, rv);
  2178   bool hasResult;
  2179   rv = stmt->ExecuteStep(&hasResult);
  2180   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2182   if (!hasResult) {
  2183     mKey.Unset();
  2184     return NS_OK;
  2187   rv = mKey.SetFromStatement(stmt, 0);
  2188   NS_ENSURE_SUCCESS(rv, rv);
  2190   rv = mObjectKey.SetFromStatement(stmt, 1);
  2191   NS_ENSURE_SUCCESS(rv, rv);
  2193   rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 2, 3,
  2194     mDatabase, mCloneReadInfo);
  2195   NS_ENSURE_SUCCESS(rv, rv);
  2197   // Now we need to make the query to get the next match.
  2198   nsAutoCString queryStart =
  2199     NS_LITERAL_CSTRING("SELECT index_table.value, "
  2200                        "index_table.object_data_key, object_data.data, "
  2201                        "object_data.file_ids FROM ") +
  2202     indexTable +
  2203     NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
  2204                        "index_table.object_data_id = object_data.id "
  2205                        "WHERE index_table.index_id = :id");
  2207   NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
  2209   NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
  2211   switch (mDirection) {
  2212     case IDBCursor::NEXT:
  2213       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
  2214         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
  2215                               queryStart);
  2216         mRangeKey = mKeyRange->Upper();
  2218       mContinueQuery =
  2219         queryStart +
  2220         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
  2221                            "( index_table.value > :current_key OR "
  2222                            "  index_table.object_data_key > :object_key ) ") +
  2223         directionClause + limit;
  2224       mContinueToQuery =
  2225         queryStart +
  2226         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
  2227         directionClause + limit;
  2228       break;
  2230     case IDBCursor::NEXT_UNIQUE:
  2231       if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
  2232         AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
  2233                               queryStart);
  2234         mRangeKey = mKeyRange->Upper();
  2236       mContinueQuery =
  2237         queryStart +
  2238         NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
  2239         directionClause + limit;
  2240       mContinueToQuery =
  2241         queryStart +
  2242         NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
  2243         directionClause + limit;
  2244       break;
  2246     case IDBCursor::PREV:
  2247       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
  2248         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
  2249                               queryStart);
  2250         mRangeKey = mKeyRange->Lower();
  2252       mContinueQuery =
  2253         queryStart +
  2254         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
  2255                            "( index_table.value < :current_key OR "
  2256                            "  index_table.object_data_key < :object_key ) ") +
  2257         directionClause + limit;
  2258       mContinueToQuery =
  2259         queryStart +
  2260         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
  2261         directionClause + limit;
  2262       break;
  2264     case IDBCursor::PREV_UNIQUE:
  2265       if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
  2266         AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
  2267                               queryStart);
  2268         mRangeKey = mKeyRange->Lower();
  2270       mContinueQuery =
  2271         queryStart +
  2272         NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
  2273         directionClause + limit;
  2274       mContinueToQuery =
  2275         queryStart +
  2276         NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
  2277         directionClause + limit;
  2278       break;
  2280     default:
  2281       NS_NOTREACHED("Unknown direction type!");
  2284   return NS_OK;
  2287 nsresult
  2288 OpenCursorHelper::EnsureCursor()
  2290   if (mCursor || mKey.IsUnset()) {
  2291     return NS_OK;
  2294   mSerializedCloneReadInfo = mCloneReadInfo;
  2296   NS_ASSERTION(mSerializedCloneReadInfo.data &&
  2297                mSerializedCloneReadInfo.dataLength,
  2298                "Shouldn't be possible!");
  2300   nsRefPtr<IDBCursor> cursor =
  2301     IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
  2302                       mContinueQuery, mContinueToQuery, mKey, mObjectKey,
  2303                       Move(mCloneReadInfo));
  2304   IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2306   NS_ASSERTION(!mCloneReadInfo.mCloneBuffer.data(), "Should have swapped!");
  2308   mCursor.swap(cursor);
  2309   return NS_OK;
  2312 void
  2313 OpenCursorHelper::ReleaseMainThreadObjects()
  2315   IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
  2317   // These don't need to be released on the main thread but they're only valid
  2318   // as long as mCursor is set.
  2319   mSerializedCloneReadInfo.data = nullptr;
  2320   mSerializedCloneReadInfo.dataLength = 0;
  2322   OpenKeyCursorHelper::ReleaseMainThreadObjects();
  2325 nsresult
  2326 OpenCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  2328   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  2329   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2331   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  2332                              "OpenCursorHelper::PackArgumentsForParentProcess "
  2333                              "[IDBIndex.cpp]");
  2335   OpenCursorParams params;
  2337   if (mKeyRange) {
  2338     KeyRange keyRange;
  2339     mKeyRange->ToSerializedKeyRange(keyRange);
  2340     params.optionalKeyRange() = keyRange;
  2342   else {
  2343     params.optionalKeyRange() = mozilla::void_t();
  2346   params.direction() = mDirection;
  2348   aParams = params;
  2349   return NS_OK;
  2352 AsyncConnectionHelper::ChildProcessSendResult
  2353 OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
  2355   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  2356   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2357   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
  2359   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  2360                              "OpenCursorHelper::SendResponseToChildProcess "
  2361                              "[IDBIndex.cpp]");
  2363   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  2364   NS_ASSERTION(actor, "How did we get this far without an actor?");
  2366   InfallibleTArray<PBlobParent*> blobsParent;
  2368   if (NS_SUCCEEDED(aResultCode)) {
  2369     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
  2370     NS_ASSERTION(database, "This should never be null!");
  2372     ContentParent* contentParent = database->GetContentParent();
  2373     NS_ASSERTION(contentParent, "This should never be null!");
  2375     FileManager* fileManager = database->Manager();
  2376     NS_ASSERTION(fileManager, "This should never be null!");
  2378     const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
  2380     aResultCode =
  2381       IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
  2382                                            blobsParent);
  2383     if (NS_FAILED(aResultCode)) {
  2384       NS_WARNING("ConvertBlobsToActors failed!");
  2388   if (NS_SUCCEEDED(aResultCode)) {
  2389     nsresult rv = EnsureCursor();
  2390     if (NS_FAILED(rv)) {
  2391       NS_WARNING("EnsureCursor failed!");
  2392       aResultCode = rv;
  2396   ResponseValue response;
  2397   if (NS_FAILED(aResultCode)) {
  2398     response = aResultCode;
  2400   else {
  2401     OpenCursorResponse openCursorResponse;
  2403     if (!mCursor) {
  2404       openCursorResponse = mozilla::void_t();
  2406     else {
  2407       IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
  2408       NS_ASSERTION(indexActor, "Must have an actor here!");
  2410       IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
  2411       NS_ASSERTION(requestActor, "Must have an actor here!");
  2413       NS_ASSERTION(mSerializedCloneReadInfo.data &&
  2414                    mSerializedCloneReadInfo.dataLength,
  2415                    "Shouldn't be possible!");
  2417       IndexCursorConstructorParams params;
  2418       params.requestParent() = requestActor;
  2419       params.direction() = mDirection;
  2420       params.key() = mKey;
  2421       params.objectKey() = mObjectKey;
  2422       params.optionalCloneInfo() = mSerializedCloneReadInfo;
  2423       params.blobsParent().SwapElements(blobsParent);
  2425       if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
  2426         return Error;
  2430     response = openCursorResponse;
  2433   if (!actor->SendResponse(response)) {
  2434     return Error;
  2437   return Success_Sent;
  2440 nsresult
  2441 CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
  2443   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
  2444   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2446   PROFILER_LABEL("IndexedDB", "CountHelper::DoDatabaseWork [IDBIndex.cpp]");
  2448   nsCString table;
  2449   if (mIndex->IsUnique()) {
  2450     table.AssignLiteral("unique_index_data");
  2452   else {
  2453     table.AssignLiteral("index_data");
  2456   NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
  2457   NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
  2458   NS_NAMED_LITERAL_CSTRING(value, "value");
  2460   nsAutoCString keyRangeClause;
  2461   if (mKeyRange) {
  2462     if (!mKeyRange->Lower().IsUnset()) {
  2463       AppendConditionClause(value, lowerKeyName, false,
  2464                             !mKeyRange->IsLowerOpen(), keyRangeClause);
  2466     if (!mKeyRange->Upper().IsUnset()) {
  2467       AppendConditionClause(value, upperKeyName, true,
  2468                             !mKeyRange->IsUpperOpen(), keyRangeClause);
  2472   nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
  2473                     NS_LITERAL_CSTRING(" WHERE index_id = :id") +
  2474                     keyRangeClause;
  2476   nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  2477   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2479   mozStorageStatementScoper scoper(stmt);
  2481   nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
  2482   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2484   if (mKeyRange) {
  2485     if (!mKeyRange->Lower().IsUnset()) {
  2486       rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
  2487       NS_ENSURE_SUCCESS(rv, rv);
  2489     if (!mKeyRange->Upper().IsUnset()) {
  2490       rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
  2491       NS_ENSURE_SUCCESS(rv, rv);
  2495   bool hasResult;
  2496   rv = stmt->ExecuteStep(&hasResult);
  2497   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2498   IDB_ENSURE_TRUE(hasResult, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  2500   mCount = stmt->AsInt64(0);
  2501   return NS_OK;
  2504 nsresult
  2505 CountHelper::GetSuccessResult(JSContext* aCx,
  2506                               JS::MutableHandle<JS::Value> aVal)
  2508   aVal.setNumber(static_cast<double>(mCount));
  2509   return NS_OK;
  2512 void
  2513 CountHelper::ReleaseMainThreadObjects()
  2515   mKeyRange = nullptr;
  2516   IndexHelper::ReleaseMainThreadObjects();
  2519 nsresult
  2520 CountHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
  2522   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  2523   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2525   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  2526                              "CountHelper::PackArgumentsForParentProcess "
  2527                              "[IDBIndex.cpp]");
  2529   CountParams params;
  2531   if (mKeyRange) {
  2532     KeyRange keyRange;
  2533     mKeyRange->ToSerializedKeyRange(keyRange);
  2534     params.optionalKeyRange() = keyRange;
  2536   else {
  2537     params.optionalKeyRange() = mozilla::void_t();
  2540   aParams = params;
  2541   return NS_OK;
  2544 AsyncConnectionHelper::ChildProcessSendResult
  2545 CountHelper::SendResponseToChildProcess(nsresult aResultCode)
  2547   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  2548   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
  2550   PROFILER_MAIN_THREAD_LABEL("IndexedDB",
  2551                              "CountHelper::SendResponseToChildProcess "
  2552                              "[IDBIndex.cpp]");
  2554   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
  2555   NS_ASSERTION(actor, "How did we get this far without an actor?");
  2557   ResponseValue response;
  2558   if (NS_FAILED(aResultCode)) {
  2559     response = aResultCode;
  2561   else {
  2562     CountResponse countResponse = mCount;
  2563     response = countResponse;
  2566   if (!actor->SendResponse(response)) {
  2567     return Error;
  2570   return Success_Sent;
  2573 nsresult
  2574 CountHelper::UnpackResponseFromParentProcess(
  2575                                             const ResponseValue& aResponseValue)
  2577   NS_ASSERTION(aResponseValue.type() == ResponseValue::TCountResponse,
  2578                "Bad response type!");
  2580   mCount = aResponseValue.get_CountResponse().count();
  2581   return NS_OK;

mercurial