Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / indexedDB / IDBIndex.cpp
bloba2a3e154a59d71333190ad25350449d244df452d
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
44 public:
45 IndexHelper(IDBTransaction* aTransaction,
46 IDBRequest* aRequest,
47 IDBIndex* aIndex)
48 : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
49 mActor(nullptr)
51 NS_ASSERTION(aTransaction, "Null transaction!");
52 NS_ASSERTION(aRequest, "Null request!");
53 NS_ASSERTION(aIndex, "Null index!");
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;
73 class GetKeyHelper : public IndexHelper
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;
109 class GetHelper : public GetKeyHelper
111 public:
112 GetHelper(IDBTransaction* aTransaction,
113 IDBRequest* aRequest,
114 IDBIndex* aIndex,
115 IDBKeyRange* aKeyRange)
116 : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange)
119 ~GetHelper()
121 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
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;
146 class GetAllKeysHelper : public GetKeyHelper
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)
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;
178 class GetAllHelper : public GetKeyHelper
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)
189 ~GetAllHelper()
191 for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
192 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
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;
219 class OpenKeyCursorHelper : public IndexHelper
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)
231 ~OpenKeyCursorHelper()
233 NS_ASSERTION(true, "bas");
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;
272 class OpenCursorHelper : public OpenKeyCursorHelper
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)
283 ~OpenCursorHelper()
285 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
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;
308 class CountHelper : public IndexHelper
310 public:
311 CountHelper(IDBTransaction* aTransaction,
312 IDBRequest* aRequest,
313 IDBIndex* aIndex,
314 IDBKeyRange* aKeyRange)
315 : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange), mCount(0)
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;
341 inline
342 already_AddRefed<IDBRequest>
343 GenerateRequest(IDBIndex* aIndex)
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);
351 } // anonymous namespace
353 // static
354 already_AddRefed<IDBIndex>
355 IDBIndex::Create(IDBObjectStore* aObjectStore,
356 const IndexInfo* aIndexInfo,
357 bool aCreating)
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;
385 else {
386 GetIndexParams getParams;
387 getParams.name() = aIndexInfo->name;
388 params = getParams;
391 objectStoreActor->SendPIndexedDBIndexConstructor(actor.forget(), params);
394 return index.forget();
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)
407 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
409 SetIsDOMBinding();
412 IDBIndex::~IDBIndex()
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);
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__!");
429 already_AddRefed<IDBRequest>
430 IDBIndex::GetInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
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;
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;
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;
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();
471 already_AddRefed<IDBRequest>
472 IDBIndex::GetKeyInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
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;
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;
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;
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();
513 already_AddRefed<IDBRequest>
514 IDBIndex::GetAllInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
515 ErrorResult& aRv)
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;
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;
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;
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();
557 already_AddRefed<IDBRequest>
558 IDBIndex::GetAllKeysInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
559 ErrorResult& aRv)
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;
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;
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;
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();
601 already_AddRefed<IDBRequest>
602 IDBIndex::CountInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
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;
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;
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;
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();
643 already_AddRefed<IDBRequest>
644 IDBIndex::OpenKeyCursorInternal(IDBKeyRange* aKeyRange, size_t aDirection,
645 ErrorResult& aRv)
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;
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;
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;
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();
690 nsresult
691 IDBIndex::OpenCursorInternal(IDBKeyRange* aKeyRange,
692 size_t aDirection,
693 IDBRequest** _retval)
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;
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;
730 nsresult
731 IDBIndex::OpenCursorFromChildProcess(IDBRequest* aRequest,
732 size_t aDirection,
733 const Key& aKey,
734 const Key& aObjectKey,
735 IDBCursor** _retval)
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;
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)
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;
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;
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;
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)
826 return IDBIndexBinding::Wrap(aCx, this);
829 void
830 IDBIndex::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
831 ErrorResult& aRv)
833 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
835 if (!mCachedKeyPath.isUndefined()) {
836 JS::ExposeValueToActiveJS(mCachedKeyPath);
837 aResult.set(mCachedKeyPath);
838 return;
841 aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
842 if (NS_WARN_IF(aRv.Failed())) {
843 return;
846 if (mCachedKeyPath.isGCThing()) {
847 mozilla::HoldJSObjects(this);
848 mRooted = true;
851 JS::ExposeValueToActiveJS(mCachedKeyPath);
852 aResult.set(mCachedKeyPath);
855 already_AddRefed<IDBRequest>
856 IDBIndex::Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
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;
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;
876 return GetInternal(keyRange, aRv);
879 already_AddRefed<IDBRequest>
880 IDBIndex::GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
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;
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;
900 return GetKeyInternal(keyRange, aRv);
903 already_AddRefed<IDBRequest>
904 IDBIndex::GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
905 const Optional<uint32_t>& aLimit, ErrorResult& aRv)
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;
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();
924 return GetAllInternal(keyRange, limit, aRv);
927 already_AddRefed<IDBRequest>
928 IDBIndex::GetAllKeys(JSContext* aCx,
929 JS::Handle<JS::Value> aKey,
930 const Optional<uint32_t>& aLimit, ErrorResult& aRv)
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;
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();
949 return GetAllKeysInternal(keyRange, limit, aRv);
952 already_AddRefed<IDBRequest>
953 IDBIndex::OpenCursor(JSContext* aCx,
954 JS::Handle<JS::Value> aRange,
955 IDBCursorDirection aDirection, ErrorResult& aRv)
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;
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;
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;
988 return request.forget();
991 already_AddRefed<IDBRequest>
992 IDBIndex::OpenKeyCursor(JSContext* aCx,
993 JS::Handle<JS::Value> aRange,
994 IDBCursorDirection aDirection, ErrorResult& aRv)
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("IndexHelper", "Dispatch",
1043 js::ProfileEntry::Category::STORAGE);
1045 if (IndexedDatabaseManager::IsMainProcess()) {
1046 return AsyncConnectionHelper::Dispatch(aDatabaseThread);
1049 // If we've been invalidated then there's no point sending anything to the
1050 // parent process.
1051 if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) {
1052 IDB_REPORT_INTERNAL_ERR();
1053 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
1056 IndexedDBIndexChild* indexActor = mIndex->GetActorChild();
1057 NS_ASSERTION(indexActor, "Must have an actor here!");
1059 IndexRequestParams params;
1060 nsresult rv = PackArgumentsForParentProcess(params);
1061 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1063 NoDispatchEventTarget target;
1064 rv = AsyncConnectionHelper::Dispatch(&target);
1065 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1067 mActor = new IndexedDBIndexRequestChild(this, mIndex, params.type());
1068 indexActor->SendPIndexedDBRequestConstructor(mActor, params);
1070 return NS_OK;
1073 nsresult
1074 GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
1076 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
1077 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1078 NS_ASSERTION(mKeyRange, "Must have a key range here!");
1080 PROFILER_LABEL("GetKeyHelper", "DoDatabaseWork",
1081 js::ProfileEntry::Category::STORAGE);
1083 nsCString indexTable;
1084 if (mIndex->IsUnique()) {
1085 indexTable.AssignLiteral("unique_index_data");
1087 else {
1088 indexTable.AssignLiteral("index_data");
1091 nsCString keyRangeClause;
1092 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
1094 NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
1096 nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
1097 indexTable +
1098 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
1099 keyRangeClause +
1100 NS_LITERAL_CSTRING(" LIMIT 1");
1102 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
1103 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1105 mozStorageStatementScoper scoper(stmt);
1107 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
1108 mIndex->Id());
1109 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1111 rv = mKeyRange->BindToStatement(stmt);
1112 NS_ENSURE_SUCCESS(rv, rv);
1114 bool hasResult;
1115 rv = stmt->ExecuteStep(&hasResult);
1116 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1118 if (hasResult) {
1119 rv = mKey.SetFromStatement(stmt, 0);
1120 NS_ENSURE_SUCCESS(rv, rv);
1123 return NS_OK;
1126 nsresult
1127 GetKeyHelper::GetSuccessResult(JSContext* aCx,
1128 JS::MutableHandle<JS::Value> aVal)
1130 return mKey.ToJSVal(aCx, aVal);
1133 void
1134 GetKeyHelper::ReleaseMainThreadObjects()
1136 mKeyRange = nullptr;
1137 IndexHelper::ReleaseMainThreadObjects();
1140 nsresult
1141 GetKeyHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
1143 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1144 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1145 NS_ASSERTION(mKeyRange, "This should never be null!");
1147 PROFILER_MAIN_THREAD_LABEL("GetKeyHelper", "PackArgumentsForParentProcess",
1148 js::ProfileEntry::Category::STORAGE);
1150 GetKeyParams params;
1152 mKeyRange->ToSerializedKeyRange(params.keyRange());
1154 aParams = params;
1155 return NS_OK;
1158 AsyncConnectionHelper::ChildProcessSendResult
1159 GetKeyHelper::SendResponseToChildProcess(nsresult aResultCode)
1161 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1162 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1164 PROFILER_MAIN_THREAD_LABEL("GetKeyHelper", "SendResponseToChildProcess",
1165 js::ProfileEntry::Category::STORAGE);
1167 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
1168 NS_ASSERTION(actor, "How did we get this far without an actor?");
1170 ResponseValue response;
1171 if (NS_FAILED(aResultCode)) {
1172 response = aResultCode;
1174 else {
1175 GetKeyResponse getKeyResponse;
1176 getKeyResponse.key() = mKey;
1177 response = getKeyResponse;
1180 if (!actor->SendResponse(response)) {
1181 return Error;
1184 return Success_Sent;
1187 nsresult
1188 GetKeyHelper::UnpackResponseFromParentProcess(
1189 const ResponseValue& aResponseValue)
1191 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetKeyResponse,
1192 "Bad response type!");
1194 mKey = aResponseValue.get_GetKeyResponse().key();
1195 return NS_OK;
1198 nsresult
1199 GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
1201 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
1202 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1203 NS_ASSERTION(mKeyRange, "Must have a key range here!");
1205 PROFILER_LABEL("GetHelper", "DoDatabaseWork [IDBIndex.cpp]",
1206 js::ProfileEntry::Category::STORAGE);
1208 nsCString indexTable;
1209 if (mIndex->IsUnique()) {
1210 indexTable.AssignLiteral("unique_index_data");
1212 else {
1213 indexTable.AssignLiteral("index_data");
1216 nsCString keyRangeClause;
1217 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
1219 NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
1221 nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
1222 "INNER JOIN ") + indexTable +
1223 NS_LITERAL_CSTRING(" AS index_table ON object_data.id = ") +
1224 NS_LITERAL_CSTRING("index_table.object_data_id WHERE "
1225 "index_id = :index_id") +
1226 keyRangeClause +
1227 NS_LITERAL_CSTRING(" LIMIT 1");
1229 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
1230 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1232 mozStorageStatementScoper scoper(stmt);
1234 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
1235 mIndex->Id());
1236 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1238 rv = mKeyRange->BindToStatement(stmt);
1239 NS_ENSURE_SUCCESS(rv, rv);
1241 bool hasResult;
1242 rv = stmt->ExecuteStep(&hasResult);
1243 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1245 if (hasResult) {
1246 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
1247 mDatabase, mCloneReadInfo);
1248 NS_ENSURE_SUCCESS(rv, rv);
1251 return NS_OK;
1254 nsresult
1255 GetHelper::GetSuccessResult(JSContext* aCx,
1256 JS::MutableHandle<JS::Value> aVal)
1258 bool result = IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, aVal);
1260 mCloneReadInfo.mCloneBuffer.clear();
1262 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1263 return NS_OK;
1266 void
1267 GetHelper::ReleaseMainThreadObjects()
1269 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
1270 GetKeyHelper::ReleaseMainThreadObjects();
1273 nsresult
1274 GetHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
1276 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1277 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1278 NS_ASSERTION(mKeyRange, "This should never be null!");
1280 PROFILER_MAIN_THREAD_LABEL("GetHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
1281 js::ProfileEntry::Category::STORAGE);
1283 GetParams params;
1285 mKeyRange->ToSerializedKeyRange(params.keyRange());
1287 aParams = params;
1288 return NS_OK;
1291 AsyncConnectionHelper::ChildProcessSendResult
1292 GetHelper::SendResponseToChildProcess(nsresult aResultCode)
1294 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1295 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1297 PROFILER_MAIN_THREAD_LABEL("GetHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
1298 js::ProfileEntry::Category::STORAGE);
1300 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
1301 NS_ASSERTION(actor, "How did we get this far without an actor?");
1303 InfallibleTArray<PBlobParent*> blobsParent;
1305 if (NS_SUCCEEDED(aResultCode)) {
1306 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
1307 NS_ASSERTION(database, "This should never be null!");
1309 nsIContentParent* contentParent = database->GetContentParent();
1310 NS_ASSERTION(contentParent, "This should never be null!");
1312 FileManager* fileManager = database->Manager();
1313 NS_ASSERTION(fileManager, "This should never be null!");
1315 const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
1317 aResultCode =
1318 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
1319 blobsParent);
1320 if (NS_FAILED(aResultCode)) {
1321 NS_WARNING("ConvertBlobActors failed!");
1325 ResponseValue response;
1326 if (NS_FAILED(aResultCode)) {
1327 response = aResultCode;
1329 else {
1330 GetResponse getResponse;
1331 getResponse.cloneInfo() = mCloneReadInfo;
1332 getResponse.blobsParent().SwapElements(blobsParent);
1333 response = getResponse;
1336 if (!actor->SendResponse(response)) {
1337 return Error;
1340 return Success_Sent;
1343 nsresult
1344 GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
1346 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetResponse,
1347 "Bad response type!");
1349 const GetResponse& getResponse = aResponseValue.get_GetResponse();
1350 const SerializedStructuredCloneReadInfo& cloneInfo = getResponse.cloneInfo();
1352 NS_ASSERTION((!cloneInfo.dataLength && !cloneInfo.data) ||
1353 (cloneInfo.dataLength && cloneInfo.data),
1354 "Inconsistent clone info!");
1356 if (!mCloneReadInfo.SetFromSerialized(cloneInfo)) {
1357 IDB_WARNING("Failed to copy clone buffer!");
1358 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
1361 IDBObjectStore::ConvertActorsToBlobs(getResponse.blobsChild(),
1362 mCloneReadInfo.mFiles);
1363 return NS_OK;
1366 nsresult
1367 GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
1369 MOZ_ASSERT(!NS_IsMainThread());
1370 MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
1372 PROFILER_LABEL("GetAllKeysHelper", "DoDatabaseWork [IDBIndex.cpp]",
1373 js::ProfileEntry::Category::STORAGE);
1375 nsCString tableName;
1376 if (mIndex->IsUnique()) {
1377 tableName.AssignLiteral("unique_index_data");
1379 else {
1380 tableName.AssignLiteral("index_data");
1383 nsCString keyRangeClause;
1384 if (mKeyRange) {
1385 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
1388 nsCString limitClause;
1389 if (mLimit != UINT32_MAX) {
1390 limitClause = NS_LITERAL_CSTRING(" LIMIT ");
1391 limitClause.AppendInt(mLimit);
1394 nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
1395 tableName +
1396 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
1397 keyRangeClause + limitClause;
1399 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
1400 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1402 mozStorageStatementScoper scoper(stmt);
1404 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
1405 mIndex->Id());
1406 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1408 if (mKeyRange) {
1409 rv = mKeyRange->BindToStatement(stmt);
1410 NS_ENSURE_SUCCESS(rv, rv);
1413 mKeys.SetCapacity(std::min<uint32_t>(50, mLimit));
1415 bool hasResult;
1416 while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
1417 if (mKeys.Capacity() == mKeys.Length()) {
1418 mKeys.SetCapacity(mKeys.Capacity() * 2);
1421 Key* key = mKeys.AppendElement();
1422 NS_ASSERTION(key, "This shouldn't fail!");
1424 rv = key->SetFromStatement(stmt, 0);
1425 NS_ENSURE_SUCCESS(rv, rv);
1427 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1429 return NS_OK;
1432 nsresult
1433 GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
1434 JS::MutableHandle<JS::Value> aVal)
1436 MOZ_ASSERT(NS_IsMainThread());
1437 MOZ_ASSERT(mKeys.Length() <= mLimit);
1439 PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "GetSuccessResult [IDBIndex.cpp]",
1440 js::ProfileEntry::Category::STORAGE);
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("GetAllKeysHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
1486 js::ProfileEntry::Category::STORAGE);
1488 GetAllKeysParams params;
1490 if (mKeyRange) {
1491 KeyRange keyRange;
1492 mKeyRange->ToSerializedKeyRange(keyRange);
1493 params.optionalKeyRange() = keyRange;
1495 else {
1496 params.optionalKeyRange() = mozilla::void_t();
1499 params.limit() = mLimit;
1501 aParams = params;
1502 return NS_OK;
1505 AsyncConnectionHelper::ChildProcessSendResult
1506 GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode)
1508 MOZ_ASSERT(NS_IsMainThread());
1509 MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
1511 PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
1512 js::ProfileEntry::Category::STORAGE);
1514 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
1515 NS_ASSERTION(actor, "How did we get this far without an actor?");
1517 ResponseValue response;
1518 if (NS_FAILED(aResultCode)) {
1519 response = aResultCode;
1521 else {
1522 GetAllKeysResponse getAllKeysResponse;
1523 getAllKeysResponse.keys().AppendElements(mKeys);
1524 response = getAllKeysResponse;
1527 if (!actor->SendResponse(response)) {
1528 return Error;
1531 return Success_Sent;
1534 nsresult
1535 GetAllKeysHelper::UnpackResponseFromParentProcess(
1536 const ResponseValue& aResponseValue)
1538 MOZ_ASSERT(NS_IsMainThread());
1539 MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
1540 MOZ_ASSERT(aResponseValue.type() == ResponseValue::TGetAllKeysResponse);
1542 mKeys.AppendElements(aResponseValue.get_GetAllKeysResponse().keys());
1543 return NS_OK;
1546 nsresult
1547 GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
1549 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
1550 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1552 PROFILER_LABEL("GetAllHelper", "DoDatabaseWork [IDBIndex.cpp]",
1553 js::ProfileEntry::Category::STORAGE);
1555 nsCString indexTable;
1556 if (mIndex->IsUnique()) {
1557 indexTable.AssignLiteral("unique_index_data");
1559 else {
1560 indexTable.AssignLiteral("index_data");
1563 nsCString keyRangeClause;
1564 if (mKeyRange) {
1565 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
1568 nsCString limitClause;
1569 if (mLimit != UINT32_MAX) {
1570 limitClause = NS_LITERAL_CSTRING(" LIMIT ");
1571 limitClause.AppendInt(mLimit);
1574 nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
1575 "INNER JOIN ") + indexTable +
1576 NS_LITERAL_CSTRING(" AS index_table ON object_data.id = "
1577 "index_table.object_data_id "
1578 "WHERE index_id = :index_id") +
1579 keyRangeClause + limitClause;
1581 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
1582 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1584 mozStorageStatementScoper scoper(stmt);
1586 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
1587 mIndex->Id());
1588 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1590 if (mKeyRange) {
1591 rv = mKeyRange->BindToStatement(stmt);
1592 NS_ENSURE_SUCCESS(rv, rv);
1595 mCloneReadInfos.SetCapacity(50);
1597 bool hasResult;
1598 while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
1599 if (mCloneReadInfos.Capacity() == mCloneReadInfos.Length()) {
1600 mCloneReadInfos.SetCapacity(mCloneReadInfos.Capacity() * 2);
1603 StructuredCloneReadInfo* readInfo = mCloneReadInfos.AppendElement();
1604 NS_ASSERTION(readInfo, "This shouldn't fail!");
1606 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
1607 mDatabase, *readInfo);
1608 NS_ENSURE_SUCCESS(rv, rv);
1610 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1612 return NS_OK;
1615 nsresult
1616 GetAllHelper::GetSuccessResult(JSContext* aCx,
1617 JS::MutableHandle<JS::Value> aVal)
1619 NS_ASSERTION(mCloneReadInfos.Length() <= mLimit, "Too many results!");
1621 nsresult rv = ConvertToArrayAndCleanup(aCx, mCloneReadInfos, aVal);
1623 NS_ASSERTION(mCloneReadInfos.IsEmpty(),
1624 "Should have cleared in ConvertToArrayAndCleanup");
1625 NS_ENSURE_SUCCESS(rv, rv);
1627 return NS_OK;
1630 void
1631 GetAllHelper::ReleaseMainThreadObjects()
1633 for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
1634 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
1636 GetKeyHelper::ReleaseMainThreadObjects();
1639 nsresult
1640 GetAllHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
1642 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1643 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1645 PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
1646 js::ProfileEntry::Category::STORAGE);
1648 GetAllParams params;
1650 if (mKeyRange) {
1651 KeyRange keyRange;
1652 mKeyRange->ToSerializedKeyRange(keyRange);
1653 params.optionalKeyRange() = keyRange;
1655 else {
1656 params.optionalKeyRange() = mozilla::void_t();
1659 params.limit() = mLimit;
1661 aParams = params;
1662 return NS_OK;
1665 AsyncConnectionHelper::ChildProcessSendResult
1666 GetAllHelper::SendResponseToChildProcess(nsresult aResultCode)
1668 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1669 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1671 PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
1672 js::ProfileEntry::Category::STORAGE);
1674 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
1675 NS_ASSERTION(actor, "How did we get this far without an actor?");
1677 GetAllResponse getAllResponse;
1679 if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
1680 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
1681 NS_ASSERTION(database, "This should never be null!");
1683 nsIContentParent* contentParent = database->GetContentParent();
1684 NS_ASSERTION(contentParent, "This should never be null!");
1686 FileManager* fileManager = database->Manager();
1687 NS_ASSERTION(fileManager, "This should never be null!");
1689 uint32_t length = mCloneReadInfos.Length();
1691 InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
1692 getAllResponse.cloneInfos();
1693 infos.SetCapacity(length);
1695 InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
1696 blobArrays.SetCapacity(length);
1698 for (uint32_t index = 0;
1699 NS_SUCCEEDED(aResultCode) && index < length;
1700 index++) {
1701 const StructuredCloneReadInfo& clone = mCloneReadInfos[index];
1703 // Append the structured clone data.
1704 SerializedStructuredCloneReadInfo* info = infos.AppendElement();
1705 *info = clone;
1707 const nsTArray<StructuredCloneFile>& files = clone.mFiles;
1709 // Now take care of the files.
1710 BlobArray* blobArray = blobArrays.AppendElement();
1712 InfallibleTArray<PBlobParent*>& blobs = blobArray->blobsParent();
1714 aResultCode =
1715 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
1716 blobs);
1717 if (NS_FAILED(aResultCode)) {
1718 NS_WARNING("ConvertBlobsToActors failed!");
1719 break;
1724 ResponseValue response;
1725 if (NS_FAILED(aResultCode)) {
1726 response = aResultCode;
1728 else {
1729 response = getAllResponse;
1732 if (!actor->SendResponse(response)) {
1733 return Error;
1736 return Success_Sent;
1739 nsresult
1740 GetAllHelper::UnpackResponseFromParentProcess(
1741 const ResponseValue& aResponseValue)
1743 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetAllResponse,
1744 "Bad response type!");
1746 const GetAllResponse& getAllResponse = aResponseValue.get_GetAllResponse();
1747 const InfallibleTArray<SerializedStructuredCloneReadInfo>& cloneInfos =
1748 getAllResponse.cloneInfos();
1749 const InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
1751 mCloneReadInfos.SetCapacity(cloneInfos.Length());
1753 for (uint32_t index = 0; index < cloneInfos.Length(); index++) {
1754 const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index];
1755 const InfallibleTArray<PBlobChild*>& blobs = blobArrays[index].blobsChild();
1757 StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement();
1758 if (!destInfo->SetFromSerialized(srcInfo)) {
1759 IDB_WARNING("Failed to copy clone buffer!");
1760 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
1763 IDBObjectStore::ConvertActorsToBlobs(blobs, destInfo->mFiles);
1766 return NS_OK;
1769 nsresult
1770 OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
1772 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
1773 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1774 NS_ASSERTION(aConnection, "Passed a null connection!");
1776 PROFILER_LABEL("OpenKeyCursorHelper", "DoDatabaseWork",
1777 js::ProfileEntry::Category::STORAGE);
1779 nsCString table;
1780 if (mIndex->IsUnique()) {
1781 table.AssignLiteral("unique_index_data");
1783 else {
1784 table.AssignLiteral("index_data");
1787 NS_NAMED_LITERAL_CSTRING(value, "value");
1789 nsCString keyRangeClause;
1790 if (mKeyRange) {
1791 mKeyRange->GetBindingClause(value, keyRangeClause);
1794 nsAutoCString directionClause(" ORDER BY value ");
1795 switch (mDirection) {
1796 case IDBCursor::NEXT:
1797 case IDBCursor::NEXT_UNIQUE:
1798 directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
1799 break;
1801 case IDBCursor::PREV:
1802 directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
1803 break;
1805 case IDBCursor::PREV_UNIQUE:
1806 directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
1807 break;
1809 default:
1810 NS_NOTREACHED("Unknown direction!");
1812 nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
1813 "FROM ") + table +
1814 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
1815 keyRangeClause + directionClause +
1816 NS_LITERAL_CSTRING(" LIMIT 1");
1818 nsCOMPtr<mozIStorageStatement> stmt =
1819 mTransaction->GetCachedStatement(firstQuery);
1820 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1822 mozStorageStatementScoper scoper(stmt);
1824 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
1825 mIndex->Id());
1826 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1828 if (mKeyRange) {
1829 rv = mKeyRange->BindToStatement(stmt);
1830 NS_ENSURE_SUCCESS(rv, rv);
1833 bool hasResult;
1834 rv = stmt->ExecuteStep(&hasResult);
1835 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1837 if (!hasResult) {
1838 mKey.Unset();
1839 return NS_OK;
1842 rv = mKey.SetFromStatement(stmt, 0);
1843 NS_ENSURE_SUCCESS(rv, rv);
1845 rv = mObjectKey.SetFromStatement(stmt, 1);
1846 NS_ENSURE_SUCCESS(rv, rv);
1848 // Now we need to make the query to get the next match.
1849 nsAutoCString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
1850 " FROM ") + table +
1851 NS_LITERAL_CSTRING(" WHERE index_id = :id");
1853 NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
1855 switch (mDirection) {
1856 case IDBCursor::NEXT:
1857 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
1858 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
1859 queryStart);
1860 mRangeKey = mKeyRange->Upper();
1862 mContinueQuery =
1863 queryStart +
1864 NS_LITERAL_CSTRING(" AND value >= :current_key AND "
1865 "( value > :current_key OR "
1866 " object_data_key > :object_key )") +
1867 directionClause +
1868 NS_LITERAL_CSTRING(" LIMIT ");
1869 mContinueToQuery =
1870 queryStart +
1871 NS_LITERAL_CSTRING(" AND value >= :current_key ") +
1872 directionClause +
1873 NS_LITERAL_CSTRING(" LIMIT ");
1874 break;
1876 case IDBCursor::NEXT_UNIQUE:
1877 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
1878 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
1879 queryStart);
1880 mRangeKey = mKeyRange->Upper();
1882 mContinueQuery =
1883 queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
1884 directionClause +
1885 NS_LITERAL_CSTRING(" LIMIT ");
1886 mContinueToQuery =
1887 queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
1888 directionClause +
1889 NS_LITERAL_CSTRING(" LIMIT ");
1890 break;
1892 case IDBCursor::PREV:
1893 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
1894 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
1895 queryStart);
1896 mRangeKey = mKeyRange->Lower();
1899 mContinueQuery =
1900 queryStart +
1901 NS_LITERAL_CSTRING(" AND value <= :current_key AND "
1902 "( value < :current_key OR "
1903 " object_data_key < :object_key )") +
1904 directionClause +
1905 NS_LITERAL_CSTRING(" LIMIT ");
1906 mContinueToQuery =
1907 queryStart +
1908 NS_LITERAL_CSTRING(" AND value <= :current_key ") +
1909 directionClause +
1910 NS_LITERAL_CSTRING(" LIMIT ");
1911 break;
1913 case IDBCursor::PREV_UNIQUE:
1914 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
1915 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
1916 queryStart);
1917 mRangeKey = mKeyRange->Lower();
1919 mContinueQuery =
1920 queryStart +
1921 NS_LITERAL_CSTRING(" AND value < :current_key") +
1922 directionClause +
1923 NS_LITERAL_CSTRING(" LIMIT ");
1924 mContinueToQuery =
1925 queryStart +
1926 NS_LITERAL_CSTRING(" AND value <= :current_key") +
1927 directionClause +
1928 NS_LITERAL_CSTRING(" LIMIT ");
1929 break;
1931 default:
1932 NS_NOTREACHED("Unknown direction type!");
1935 return NS_OK;
1938 nsresult
1939 OpenKeyCursorHelper::EnsureCursor()
1941 if (mCursor || mKey.IsUnset()) {
1942 return NS_OK;
1945 nsRefPtr<IDBCursor> cursor =
1946 IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
1947 mContinueQuery, mContinueToQuery, mKey, mObjectKey);
1948 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1950 mCursor.swap(cursor);
1951 return NS_OK;
1954 nsresult
1955 OpenKeyCursorHelper::GetSuccessResult(JSContext* aCx,
1956 JS::MutableHandle<JS::Value> aVal)
1958 nsresult rv = EnsureCursor();
1959 NS_ENSURE_SUCCESS(rv, rv);
1961 if (mCursor) {
1962 rv = WrapNative(aCx, mCursor, aVal);
1963 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
1965 else {
1966 aVal.setUndefined();
1969 return NS_OK;
1972 void
1973 OpenKeyCursorHelper::ReleaseMainThreadObjects()
1975 mKeyRange = nullptr;
1976 mCursor = nullptr;
1977 IndexHelper::ReleaseMainThreadObjects();
1980 nsresult
1981 OpenKeyCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
1983 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
1984 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
1986 PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
1987 js::ProfileEntry::Category::STORAGE);
1989 OpenKeyCursorParams params;
1991 if (mKeyRange) {
1992 KeyRange keyRange;
1993 mKeyRange->ToSerializedKeyRange(keyRange);
1994 params.optionalKeyRange() = keyRange;
1996 else {
1997 params.optionalKeyRange() = mozilla::void_t();
2000 params.direction() = mDirection;
2002 aParams = params;
2003 return NS_OK;
2006 AsyncConnectionHelper::ChildProcessSendResult
2007 OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
2009 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2010 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2011 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
2013 PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "SendResponseToChildProcess",
2014 js::ProfileEntry::Category::STORAGE);
2016 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
2017 NS_ASSERTION(actor, "How did we get this far without an actor?");
2019 if (NS_SUCCEEDED(aResultCode)) {
2020 nsresult rv = EnsureCursor();
2021 if (NS_FAILED(rv)) {
2022 NS_WARNING("EnsureCursor failed!");
2023 aResultCode = rv;
2027 ResponseValue response;
2028 if (NS_FAILED(aResultCode)) {
2029 response = aResultCode;
2031 else {
2032 OpenCursorResponse openCursorResponse;
2034 if (!mCursor) {
2035 openCursorResponse = mozilla::void_t();
2037 else {
2038 IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
2039 NS_ASSERTION(indexActor, "Must have an actor here!");
2041 IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
2042 NS_ASSERTION(requestActor, "Must have an actor here!");
2044 IndexCursorConstructorParams params;
2045 params.requestParent() = requestActor;
2046 params.direction() = mDirection;
2047 params.key() = mKey;
2048 params.objectKey() = mObjectKey;
2049 params.optionalCloneInfo() = mozilla::void_t();
2051 if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
2052 return Error;
2056 response = openCursorResponse;
2059 if (!actor->SendResponse(response)) {
2060 return Error;
2063 return Success_Sent;
2066 nsresult
2067 OpenKeyCursorHelper::UnpackResponseFromParentProcess(
2068 const ResponseValue& aResponseValue)
2070 NS_ASSERTION(aResponseValue.type() == ResponseValue::TOpenCursorResponse,
2071 "Bad response type!");
2072 NS_ASSERTION(aResponseValue.get_OpenCursorResponse().type() ==
2073 OpenCursorResponse::Tvoid_t ||
2074 aResponseValue.get_OpenCursorResponse().type() ==
2075 OpenCursorResponse::TPIndexedDBCursorChild,
2076 "Bad response union type!");
2077 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
2079 const OpenCursorResponse& response =
2080 aResponseValue.get_OpenCursorResponse();
2082 switch (response.type()) {
2083 case OpenCursorResponse::Tvoid_t:
2084 break;
2086 case OpenCursorResponse::TPIndexedDBCursorChild: {
2087 IndexedDBCursorChild* actor =
2088 static_cast<IndexedDBCursorChild*>(
2089 response.get_PIndexedDBCursorChild());
2091 mCursor = actor->ForgetStrongCursor();
2092 NS_ASSERTION(mCursor, "This should never be null!");
2094 } break;
2096 default:
2097 MOZ_CRASH();
2100 return NS_OK;
2103 nsresult
2104 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
2106 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
2107 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2108 NS_ASSERTION(aConnection, "Passed a null connection!");
2110 PROFILER_LABEL("OpenCursorHelper", "DoDatabaseWork [IDBIndex.cpp]",
2111 js::ProfileEntry::Category::STORAGE);
2113 nsCString indexTable;
2114 if (mIndex->IsUnique()) {
2115 indexTable.AssignLiteral("unique_index_data");
2117 else {
2118 indexTable.AssignLiteral("index_data");
2121 NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
2123 nsCString keyRangeClause;
2124 if (mKeyRange) {
2125 mKeyRange->GetBindingClause(value, keyRangeClause);
2128 nsAutoCString directionClause(" ORDER BY index_table.value ");
2129 switch (mDirection) {
2130 case IDBCursor::NEXT:
2131 case IDBCursor::NEXT_UNIQUE:
2132 directionClause +=
2133 NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
2134 break;
2136 case IDBCursor::PREV:
2137 directionClause +=
2138 NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
2139 break;
2141 case IDBCursor::PREV_UNIQUE:
2142 directionClause +=
2143 NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
2144 break;
2146 default:
2147 NS_NOTREACHED("Unknown direction!");
2150 nsCString firstQuery =
2151 NS_LITERAL_CSTRING("SELECT index_table.value, "
2152 "index_table.object_data_key, object_data.data, "
2153 "object_data.file_ids FROM ") +
2154 indexTable +
2155 NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
2156 "index_table.object_data_id = object_data.id "
2157 "WHERE index_table.index_id = :id") +
2158 keyRangeClause + directionClause +
2159 NS_LITERAL_CSTRING(" LIMIT 1");
2161 nsCOMPtr<mozIStorageStatement> stmt =
2162 mTransaction->GetCachedStatement(firstQuery);
2163 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2165 mozStorageStatementScoper scoper(stmt);
2167 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
2168 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2170 if (mKeyRange) {
2171 rv = mKeyRange->BindToStatement(stmt);
2172 NS_ENSURE_SUCCESS(rv, rv);
2175 bool hasResult;
2176 rv = stmt->ExecuteStep(&hasResult);
2177 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2179 if (!hasResult) {
2180 mKey.Unset();
2181 return NS_OK;
2184 rv = mKey.SetFromStatement(stmt, 0);
2185 NS_ENSURE_SUCCESS(rv, rv);
2187 rv = mObjectKey.SetFromStatement(stmt, 1);
2188 NS_ENSURE_SUCCESS(rv, rv);
2190 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 2, 3,
2191 mDatabase, mCloneReadInfo);
2192 NS_ENSURE_SUCCESS(rv, rv);
2194 // Now we need to make the query to get the next match.
2195 nsAutoCString queryStart =
2196 NS_LITERAL_CSTRING("SELECT index_table.value, "
2197 "index_table.object_data_key, object_data.data, "
2198 "object_data.file_ids FROM ") +
2199 indexTable +
2200 NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
2201 "index_table.object_data_id = object_data.id "
2202 "WHERE index_table.index_id = :id");
2204 NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
2206 NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
2208 switch (mDirection) {
2209 case IDBCursor::NEXT:
2210 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
2211 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
2212 queryStart);
2213 mRangeKey = mKeyRange->Upper();
2215 mContinueQuery =
2216 queryStart +
2217 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
2218 "( index_table.value > :current_key OR "
2219 " index_table.object_data_key > :object_key ) ") +
2220 directionClause + limit;
2221 mContinueToQuery =
2222 queryStart +
2223 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
2224 directionClause + limit;
2225 break;
2227 case IDBCursor::NEXT_UNIQUE:
2228 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
2229 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
2230 queryStart);
2231 mRangeKey = mKeyRange->Upper();
2233 mContinueQuery =
2234 queryStart +
2235 NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
2236 directionClause + limit;
2237 mContinueToQuery =
2238 queryStart +
2239 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
2240 directionClause + limit;
2241 break;
2243 case IDBCursor::PREV:
2244 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
2245 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
2246 queryStart);
2247 mRangeKey = mKeyRange->Lower();
2249 mContinueQuery =
2250 queryStart +
2251 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
2252 "( index_table.value < :current_key OR "
2253 " index_table.object_data_key < :object_key ) ") +
2254 directionClause + limit;
2255 mContinueToQuery =
2256 queryStart +
2257 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
2258 directionClause + limit;
2259 break;
2261 case IDBCursor::PREV_UNIQUE:
2262 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
2263 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
2264 queryStart);
2265 mRangeKey = mKeyRange->Lower();
2267 mContinueQuery =
2268 queryStart +
2269 NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
2270 directionClause + limit;
2271 mContinueToQuery =
2272 queryStart +
2273 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
2274 directionClause + limit;
2275 break;
2277 default:
2278 NS_NOTREACHED("Unknown direction type!");
2281 return NS_OK;
2284 nsresult
2285 OpenCursorHelper::EnsureCursor()
2287 if (mCursor || mKey.IsUnset()) {
2288 return NS_OK;
2291 mSerializedCloneReadInfo = mCloneReadInfo;
2293 NS_ASSERTION(mSerializedCloneReadInfo.data &&
2294 mSerializedCloneReadInfo.dataLength,
2295 "Shouldn't be possible!");
2297 nsRefPtr<IDBCursor> cursor =
2298 IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
2299 mContinueQuery, mContinueToQuery, mKey, mObjectKey,
2300 Move(mCloneReadInfo));
2301 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2303 NS_ASSERTION(!mCloneReadInfo.mCloneBuffer.data(), "Should have swapped!");
2305 mCursor.swap(cursor);
2306 return NS_OK;
2309 void
2310 OpenCursorHelper::ReleaseMainThreadObjects()
2312 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
2314 // These don't need to be released on the main thread but they're only valid
2315 // as long as mCursor is set.
2316 mSerializedCloneReadInfo.data = nullptr;
2317 mSerializedCloneReadInfo.dataLength = 0;
2319 OpenKeyCursorHelper::ReleaseMainThreadObjects();
2322 nsresult
2323 OpenCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
2325 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2326 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2328 PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
2329 js::ProfileEntry::Category::STORAGE);
2331 OpenCursorParams params;
2333 if (mKeyRange) {
2334 KeyRange keyRange;
2335 mKeyRange->ToSerializedKeyRange(keyRange);
2336 params.optionalKeyRange() = keyRange;
2338 else {
2339 params.optionalKeyRange() = mozilla::void_t();
2342 params.direction() = mDirection;
2344 aParams = params;
2345 return NS_OK;
2348 AsyncConnectionHelper::ChildProcessSendResult
2349 OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
2351 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2352 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2353 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
2355 PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
2356 js::ProfileEntry::Category::STORAGE);
2358 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
2359 NS_ASSERTION(actor, "How did we get this far without an actor?");
2361 InfallibleTArray<PBlobParent*> blobsParent;
2363 if (NS_SUCCEEDED(aResultCode)) {
2364 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
2365 NS_ASSERTION(database, "This should never be null!");
2367 nsIContentParent* contentParent = database->GetContentParent();
2368 NS_ASSERTION(contentParent, "This should never be null!");
2370 FileManager* fileManager = database->Manager();
2371 NS_ASSERTION(fileManager, "This should never be null!");
2373 const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
2375 aResultCode =
2376 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
2377 blobsParent);
2378 if (NS_FAILED(aResultCode)) {
2379 NS_WARNING("ConvertBlobsToActors failed!");
2383 if (NS_SUCCEEDED(aResultCode)) {
2384 nsresult rv = EnsureCursor();
2385 if (NS_FAILED(rv)) {
2386 NS_WARNING("EnsureCursor failed!");
2387 aResultCode = rv;
2391 ResponseValue response;
2392 if (NS_FAILED(aResultCode)) {
2393 response = aResultCode;
2395 else {
2396 OpenCursorResponse openCursorResponse;
2398 if (!mCursor) {
2399 openCursorResponse = mozilla::void_t();
2401 else {
2402 IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
2403 NS_ASSERTION(indexActor, "Must have an actor here!");
2405 IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
2406 NS_ASSERTION(requestActor, "Must have an actor here!");
2408 NS_ASSERTION(mSerializedCloneReadInfo.data &&
2409 mSerializedCloneReadInfo.dataLength,
2410 "Shouldn't be possible!");
2412 IndexCursorConstructorParams params;
2413 params.requestParent() = requestActor;
2414 params.direction() = mDirection;
2415 params.key() = mKey;
2416 params.objectKey() = mObjectKey;
2417 params.optionalCloneInfo() = mSerializedCloneReadInfo;
2418 params.blobsParent().SwapElements(blobsParent);
2420 if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
2421 return Error;
2425 response = openCursorResponse;
2428 if (!actor->SendResponse(response)) {
2429 return Error;
2432 return Success_Sent;
2435 nsresult
2436 CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
2438 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
2439 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2441 PROFILER_LABEL("CountHelper", "DoDatabaseWork [IDBIndex.cpp]",
2442 js::ProfileEntry::Category::STORAGE);
2444 nsCString table;
2445 if (mIndex->IsUnique()) {
2446 table.AssignLiteral("unique_index_data");
2448 else {
2449 table.AssignLiteral("index_data");
2452 NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
2453 NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
2454 NS_NAMED_LITERAL_CSTRING(value, "value");
2456 nsAutoCString keyRangeClause;
2457 if (mKeyRange) {
2458 if (!mKeyRange->Lower().IsUnset()) {
2459 AppendConditionClause(value, lowerKeyName, false,
2460 !mKeyRange->IsLowerOpen(), keyRangeClause);
2462 if (!mKeyRange->Upper().IsUnset()) {
2463 AppendConditionClause(value, upperKeyName, true,
2464 !mKeyRange->IsUpperOpen(), keyRangeClause);
2468 nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
2469 NS_LITERAL_CSTRING(" WHERE index_id = :id") +
2470 keyRangeClause;
2472 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
2473 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2475 mozStorageStatementScoper scoper(stmt);
2477 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
2478 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2480 if (mKeyRange) {
2481 if (!mKeyRange->Lower().IsUnset()) {
2482 rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
2483 NS_ENSURE_SUCCESS(rv, rv);
2485 if (!mKeyRange->Upper().IsUnset()) {
2486 rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
2487 NS_ENSURE_SUCCESS(rv, rv);
2491 bool hasResult;
2492 rv = stmt->ExecuteStep(&hasResult);
2493 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2494 IDB_ENSURE_TRUE(hasResult, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
2496 mCount = stmt->AsInt64(0);
2497 return NS_OK;
2500 nsresult
2501 CountHelper::GetSuccessResult(JSContext* aCx,
2502 JS::MutableHandle<JS::Value> aVal)
2504 aVal.setNumber(static_cast<double>(mCount));
2505 return NS_OK;
2508 void
2509 CountHelper::ReleaseMainThreadObjects()
2511 mKeyRange = nullptr;
2512 IndexHelper::ReleaseMainThreadObjects();
2515 nsresult
2516 CountHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
2518 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2519 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2521 PROFILER_MAIN_THREAD_LABEL("CountHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
2522 js::ProfileEntry::Category::STORAGE);
2524 CountParams params;
2526 if (mKeyRange) {
2527 KeyRange keyRange;
2528 mKeyRange->ToSerializedKeyRange(keyRange);
2529 params.optionalKeyRange() = keyRange;
2531 else {
2532 params.optionalKeyRange() = mozilla::void_t();
2535 aParams = params;
2536 return NS_OK;
2539 AsyncConnectionHelper::ChildProcessSendResult
2540 CountHelper::SendResponseToChildProcess(nsresult aResultCode)
2542 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
2543 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
2545 PROFILER_MAIN_THREAD_LABEL("CountHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
2546 js::ProfileEntry::Category::STORAGE);
2548 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
2549 NS_ASSERTION(actor, "How did we get this far without an actor?");
2551 ResponseValue response;
2552 if (NS_FAILED(aResultCode)) {
2553 response = aResultCode;
2555 else {
2556 CountResponse countResponse = mCount;
2557 response = countResponse;
2560 if (!actor->SendResponse(response)) {
2561 return Error;
2564 return Success_Sent;
2567 nsresult
2568 CountHelper::UnpackResponseFromParentProcess(
2569 const ResponseValue& aResponseValue)
2571 NS_ASSERTION(aResponseValue.type() == ResponseValue::TCountResponse,
2572 "Bad response type!");
2574 mCount = aResponseValue.get_CountResponse().count();
2575 return NS_OK;