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"
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
;
42 class IndexHelper
: public AsyncConnectionHelper
45 IndexHelper(IDBTransaction
* aTransaction
,
48 : AsyncConnectionHelper(aTransaction
, aRequest
), mIndex(aIndex
),
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
;
61 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) = 0;
64 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
) = 0;
67 nsRefPtr
<IDBIndex
> mIndex
;
70 IndexedDBIndexRequestChild
* mActor
;
73 class GetKeyHelper
: public IndexHelper
76 GetKeyHelper(IDBTransaction
* aTransaction
,
79 IDBKeyRange
* aKeyRange
)
80 : IndexHelper(aTransaction
, aRequest
, aIndex
), mKeyRange(aKeyRange
)
83 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
86 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
87 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
89 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
92 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
94 virtual ChildProcessSendResult
95 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
98 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
103 nsRefPtr
<IDBKeyRange
> mKeyRange
;
109 class GetHelper
: public GetKeyHelper
112 GetHelper(IDBTransaction
* aTransaction
,
113 IDBRequest
* aRequest
,
115 IDBKeyRange
* aKeyRange
)
116 : GetKeyHelper(aTransaction
, aRequest
, aIndex
, aKeyRange
)
121 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo
);
124 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
127 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
128 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
130 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
133 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
135 virtual ChildProcessSendResult
136 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
139 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
143 StructuredCloneReadInfo mCloneReadInfo
;
146 class GetAllKeysHelper
: public GetKeyHelper
149 GetAllKeysHelper(IDBTransaction
* aTransaction
,
150 IDBRequest
* aRequest
,
152 IDBKeyRange
* aKeyRange
,
153 const uint32_t aLimit
)
154 : GetKeyHelper(aTransaction
, aRequest
, aIndex
, aKeyRange
), mLimit(aLimit
)
157 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
160 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
161 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
164 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
166 virtual ChildProcessSendResult
167 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
170 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
174 const uint32_t mLimit
;
178 class GetAllHelper
: public GetKeyHelper
181 GetAllHelper(IDBTransaction
* aTransaction
,
182 IDBRequest
* aRequest
,
184 IDBKeyRange
* aKeyRange
,
185 const uint32_t aLimit
)
186 : GetKeyHelper(aTransaction
, aRequest
, aIndex
, aKeyRange
), mLimit(aLimit
)
191 for (uint32_t index
= 0; index
< mCloneReadInfos
.Length(); index
++) {
192 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos
[index
]);
196 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
199 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
200 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
202 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
205 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
207 virtual ChildProcessSendResult
208 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
211 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
215 const uint32_t mLimit
;
216 nsTArray
<StructuredCloneReadInfo
> mCloneReadInfos
;
219 class OpenKeyCursorHelper
: public IndexHelper
222 OpenKeyCursorHelper(IDBTransaction
* aTransaction
,
223 IDBRequest
* aRequest
,
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
)
239 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
240 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
242 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
245 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
247 virtual ChildProcessSendResult
248 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
251 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
255 virtual nsresult
EnsureCursor();
258 nsRefPtr
<IDBKeyRange
> mKeyRange
;
259 const IDBCursor::Direction mDirection
;
264 nsCString mContinueQuery
;
265 nsCString mContinueToQuery
;
268 // Only used in the parent process.
269 nsRefPtr
<IDBCursor
> mCursor
;
272 class OpenCursorHelper
: public OpenKeyCursorHelper
275 OpenCursorHelper(IDBTransaction
* aTransaction
,
276 IDBRequest
* aRequest
,
278 IDBKeyRange
* aKeyRange
,
279 IDBCursor::Direction aDirection
)
280 : OpenKeyCursorHelper(aTransaction
, aRequest
, aIndex
, aKeyRange
, aDirection
)
285 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo
);
288 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
291 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
294 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
296 virtual ChildProcessSendResult
297 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
300 virtual nsresult
EnsureCursor();
302 StructuredCloneReadInfo mCloneReadInfo
;
304 // Only used in the parent process.
305 SerializedStructuredCloneReadInfo mSerializedCloneReadInfo
;
308 class CountHelper
: public IndexHelper
311 CountHelper(IDBTransaction
* aTransaction
,
312 IDBRequest
* aRequest
,
314 IDBKeyRange
* aKeyRange
)
315 : IndexHelper(aTransaction
, aRequest
, aIndex
), mKeyRange(aKeyRange
), mCount(0)
318 virtual nsresult
DoDatabaseWork(mozIStorageConnection
* aConnection
)
321 virtual nsresult
GetSuccessResult(JSContext
* aCx
,
322 JS::MutableHandle
<JS::Value
> aVal
) MOZ_OVERRIDE
;
324 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE
;
327 PackArgumentsForParentProcess(IndexRequestParams
& aParams
) MOZ_OVERRIDE
;
329 virtual ChildProcessSendResult
330 SendResponseToChildProcess(nsresult aResultCode
) MOZ_OVERRIDE
;
333 UnpackResponseFromParentProcess(const ResponseValue
& aResponseValue
)
337 nsRefPtr
<IDBKeyRange
> mKeyRange
;
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
354 already_AddRefed
<IDBIndex
>
355 IDBIndex::Create(IDBObjectStore
* aObjectStore
,
356 const IndexInfo
* aIndexInfo
,
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
;
381 CreateIndexParams createParams
;
382 createParams
.info() = *aIndexInfo
;
383 params
= createParams
;
386 GetIndexParams getParams
;
387 getParams
.name() = aIndexInfo
->name
;
391 objectStoreActor
->SendPIndexedDBIndexConstructor(actor
.forget(), params
);
394 return index
.forget();
400 mCachedKeyPath(JSVAL_VOID
),
401 mActorChild(nullptr),
402 mActorParent(nullptr),
407 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
412 IDBIndex::~IDBIndex()
414 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
415 NS_ASSERTION(!mActorParent
, "Actor parent owns us, how can we be dying?!");
418 mCachedKeyPath
= JSVAL_VOID
;
419 mozilla::DropJSObjects(this);
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
);
440 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
442 IDB_WARNING("Failed to generate request!");
443 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
447 nsRefPtr
<GetHelper
> helper
=
448 new GetHelper(transaction
, request
, this, aKeyRange
);
450 nsresult rv
= helper
->DispatchToTransactionPool();
452 IDB_WARNING("Failed to dispatch!");
453 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
457 IDB_PROFILER_MARK("IndexedDB Request %llu: "
458 "database(%s).transaction(%s).objectStore(%s).index(%s)."
460 "IDBRequest[%llu] MT IDBIndex.get()",
461 request
->GetSerialNumber(),
462 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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
);
482 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
484 IDB_WARNING("Failed to generate request!");
485 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
489 nsRefPtr
<GetKeyHelper
> helper
=
490 new GetKeyHelper(transaction
, request
, this, aKeyRange
);
492 nsresult rv
= helper
->DispatchToTransactionPool();
494 IDB_WARNING("Failed to dispatch!");
495 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
499 IDB_PROFILER_MARK("IndexedDB Request %llu: "
500 "database(%s).transaction(%s).objectStore(%s).index(%s)."
502 "IDBRequest[%llu] MT IDBIndex.getKey()",
503 request
->GetSerialNumber(),
504 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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
,
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
);
525 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
527 IDB_WARNING("Failed to generate request!");
528 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
532 nsRefPtr
<GetAllHelper
> helper
=
533 new GetAllHelper(transaction
, request
, this, aKeyRange
, aLimit
);
535 nsresult rv
= helper
->DispatchToTransactionPool();
537 IDB_WARNING("Failed to dispatch!");
538 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
542 IDB_PROFILER_MARK("IndexedDB Request %llu: "
543 "database(%s).transaction(%s).objectStore(%s).index(%s)."
545 "IDBRequest[%llu] MT IDBIndex.getAll()",
546 request
->GetSerialNumber(),
547 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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
,
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
);
569 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
571 IDB_WARNING("Failed to generate request!");
572 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
576 nsRefPtr
<GetAllKeysHelper
> helper
=
577 new GetAllKeysHelper(transaction
, request
, this, aKeyRange
, aLimit
);
579 nsresult rv
= helper
->DispatchToTransactionPool();
581 IDB_WARNING("Failed to dispatch!");
582 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
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()->
593 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
594 IDB_PROFILER_STRING(ObjectStore()),
595 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange
),
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
);
612 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
614 IDB_WARNING("Failed to generate request!");
615 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
619 nsRefPtr
<CountHelper
> helper
=
620 new CountHelper(transaction
, request
, this, aKeyRange
);
622 nsresult rv
= helper
->DispatchToTransactionPool();
624 IDB_WARNING("Failed to dispatch!");
625 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
629 IDB_PROFILER_MARK("IndexedDB Request %llu: "
630 "database(%s).transaction(%s).objectStore(%s).index(%s)."
632 "IDBRequest[%llu] MT IDBIndex.count()",
633 request
->GetSerialNumber(),
634 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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
,
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
);
655 IDBCursor::Direction direction
=
656 static_cast<IDBCursor::Direction
>(aDirection
);
658 nsRefPtr
<IDBRequest
> request
= GenerateRequest(this);
660 IDB_WARNING("Failed to generate request!");
661 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
665 nsRefPtr
<OpenKeyCursorHelper
> helper
=
666 new OpenKeyCursorHelper(transaction
, request
, this, aKeyRange
, direction
);
668 nsresult rv
= helper
->DispatchToTransactionPool();
670 IDB_WARNING("Failed to dispatch!");
671 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
675 IDB_PROFILER_MARK("IndexedDB Request %llu: "
676 "database(%s).transaction(%s).objectStore(%s).index(%s)."
678 "IDBRequest[%llu] MT IDBIndex.openKeyCursor()",
679 request
->GetSerialNumber(),
680 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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();
691 IDBIndex::OpenCursorInternal(IDBKeyRange
* aKeyRange
,
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)."
717 "IDBRequest[%llu] MT IDBIndex.openCursor()",
718 request
->GetSerialNumber(),
719 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
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
);
731 IDBIndex::OpenCursorFromChildProcess(IDBRequest
* aRequest
,
734 const Key
& aObjectKey
,
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
);
752 IDBIndex::OpenCursorFromChildProcess(
753 IDBRequest
* aRequest
,
756 const Key
& aObjectKey
,
757 const SerializedStructuredCloneReadInfo
& aCloneInfo
,
758 nsTArray
<StructuredCloneFile
>& aBlobs
,
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
,
782 IDB_ENSURE_TRUE(cursor
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
784 NS_ASSERTION(!cloneInfo
.mCloneBuffer
.data(), "Should have swapped!");
786 cursor
.forget(_retval
);
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
;
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
)
820 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex
)
821 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex
)
824 IDBIndex::WrapObject(JSContext
* aCx
)
826 return IDBIndexBinding::Wrap(aCx
, this);
830 IDBIndex::GetKeyPath(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
833 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
835 if (!mCachedKeyPath
.isUndefined()) {
836 JS::ExposeValueToActiveJS(mCachedKeyPath
);
837 aResult
.set(mCachedKeyPath
);
841 aRv
= GetKeyPath().ToJSVal(aCx
, mCachedKeyPath
);
842 if (NS_WARN_IF(aRv
.Failed())) {
846 if (mCachedKeyPath
.isGCThing()) {
847 mozilla::HoldJSObjects(this);
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
);
866 nsRefPtr
<IDBKeyRange
> keyRange
;
867 aRv
= IDBKeyRange::FromJSVal(aCx
, aKey
, getter_AddRefs(keyRange
));
868 ENSURE_SUCCESS(aRv
, nullptr);
871 // Must specify a key or keyRange for getKey().
872 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR
);
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
);
890 nsRefPtr
<IDBKeyRange
> keyRange
;
891 aRv
= IDBKeyRange::FromJSVal(aCx
, aKey
, getter_AddRefs(keyRange
));
892 ENSURE_SUCCESS(aRv
, nullptr);
895 // Must specify a key or keyRange for get().
896 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR
);
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
);
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
);
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
);
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);
973 IDB_WARNING("Failed to generate request!");
974 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
978 nsRefPtr
<OpenCursorHelper
> helper
=
979 new OpenCursorHelper(transaction
, request
, this, keyRange
, direction
);
981 nsresult rv
= helper
->DispatchToTransactionPool();
983 IDB_WARNING("Failed to dispatch!");
984 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
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
);
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
,
1017 IDBTransaction
* transaction
= mObjectStore
->Transaction();
1018 if (!transaction
->IsOpen()) {
1019 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR
);
1023 nsRefPtr
<IDBKeyRange
> keyRange
;
1024 aRv
= IDBKeyRange::FromJSVal(aCx
, aKey
, getter_AddRefs(keyRange
));
1025 ENSURE_SUCCESS(aRv
, nullptr);
1027 return CountInternal(keyRange
, aRv
);
1031 IndexHelper::ReleaseMainThreadObjects()
1034 AsyncConnectionHelper::ReleaseMainThreadObjects();
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
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
);
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");
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 ") +
1098 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
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"),
1109 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1111 rv
= mKeyRange
->BindToStatement(stmt
);
1112 NS_ENSURE_SUCCESS(rv
, rv
);
1115 rv
= stmt
->ExecuteStep(&hasResult
);
1116 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1119 rv
= mKey
.SetFromStatement(stmt
, 0);
1120 NS_ENSURE_SUCCESS(rv
, rv
);
1127 GetKeyHelper::GetSuccessResult(JSContext
* aCx
,
1128 JS::MutableHandle
<JS::Value
> aVal
)
1130 return mKey
.ToJSVal(aCx
, aVal
);
1134 GetKeyHelper::ReleaseMainThreadObjects()
1136 mKeyRange
= nullptr;
1137 IndexHelper::ReleaseMainThreadObjects();
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());
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
;
1175 GetKeyResponse getKeyResponse
;
1176 getKeyResponse
.key() = mKey
;
1177 response
= getKeyResponse
;
1180 if (!actor
->SendResponse(response
)) {
1184 return Success_Sent
;
1188 GetKeyHelper::UnpackResponseFromParentProcess(
1189 const ResponseValue
& aResponseValue
)
1191 NS_ASSERTION(aResponseValue
.type() == ResponseValue::TGetKeyResponse
,
1192 "Bad response type!");
1194 mKey
= aResponseValue
.get_GetKeyResponse().key();
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");
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") +
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"),
1236 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1238 rv
= mKeyRange
->BindToStatement(stmt
);
1239 NS_ENSURE_SUCCESS(rv
, rv
);
1242 rv
= stmt
->ExecuteStep(&hasResult
);
1243 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1246 rv
= IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt
, 0, 1,
1247 mDatabase
, mCloneReadInfo
);
1248 NS_ENSURE_SUCCESS(rv
, rv
);
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
);
1267 GetHelper::ReleaseMainThreadObjects()
1269 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo
);
1270 GetKeyHelper::ReleaseMainThreadObjects();
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
);
1285 mKeyRange
->ToSerializedKeyRange(params
.keyRange());
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
;
1318 IDBObjectStore::ConvertBlobsToActors(contentParent
, fileManager
, files
,
1320 if (NS_FAILED(aResultCode
)) {
1321 NS_WARNING("ConvertBlobActors failed!");
1325 ResponseValue response
;
1326 if (NS_FAILED(aResultCode
)) {
1327 response
= aResultCode
;
1330 GetResponse getResponse
;
1331 getResponse
.cloneInfo() = mCloneReadInfo
;
1332 getResponse
.blobsParent().SwapElements(blobsParent
);
1333 response
= getResponse
;
1336 if (!actor
->SendResponse(response
)) {
1340 return Success_Sent
;
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
);
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");
1380 tableName
.AssignLiteral("index_data");
1383 nsCString keyRangeClause
;
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 ") +
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"),
1406 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1409 rv
= mKeyRange
->BindToStatement(stmt
);
1410 NS_ENSURE_SUCCESS(rv
, rv
);
1413 mKeys
.SetCapacity(std::min
<uint32_t>(50, mLimit
));
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
);
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
);
1443 mKeys
.SwapElements(keys
);
1445 JS::Rooted
<JSObject
*> array(aCx
, JS_NewArrayObject(aCx
, 0));
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!");
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
);
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
;
1492 mKeyRange
->ToSerializedKeyRange(keyRange
);
1493 params
.optionalKeyRange() = keyRange
;
1496 params
.optionalKeyRange() = mozilla::void_t();
1499 params
.limit() = mLimit
;
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
;
1522 GetAllKeysResponse getAllKeysResponse
;
1523 getAllKeysResponse
.keys().AppendElements(mKeys
);
1524 response
= getAllKeysResponse
;
1527 if (!actor
->SendResponse(response
)) {
1531 return Success_Sent
;
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());
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");
1560 indexTable
.AssignLiteral("index_data");
1563 nsCString keyRangeClause
;
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"),
1588 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1591 rv
= mKeyRange
->BindToStatement(stmt
);
1592 NS_ENSURE_SUCCESS(rv
, rv
);
1595 mCloneReadInfos
.SetCapacity(50);
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
);
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
);
1631 GetAllHelper::ReleaseMainThreadObjects()
1633 for (uint32_t index
= 0; index
< mCloneReadInfos
.Length(); index
++) {
1634 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos
[index
]);
1636 GetKeyHelper::ReleaseMainThreadObjects();
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
;
1652 mKeyRange
->ToSerializedKeyRange(keyRange
);
1653 params
.optionalKeyRange() = keyRange
;
1656 params
.optionalKeyRange() = mozilla::void_t();
1659 params
.limit() = mLimit
;
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
;
1701 const StructuredCloneReadInfo
& clone
= mCloneReadInfos
[index
];
1703 // Append the structured clone data.
1704 SerializedStructuredCloneReadInfo
* info
= infos
.AppendElement();
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();
1715 IDBObjectStore::ConvertBlobsToActors(contentParent
, fileManager
, files
,
1717 if (NS_FAILED(aResultCode
)) {
1718 NS_WARNING("ConvertBlobsToActors failed!");
1724 ResponseValue response
;
1725 if (NS_FAILED(aResultCode
)) {
1726 response
= aResultCode
;
1729 response
= getAllResponse
;
1732 if (!actor
->SendResponse(response
)) {
1736 return Success_Sent
;
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
);
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
);
1780 if (mIndex
->IsUnique()) {
1781 table
.AssignLiteral("unique_index_data");
1784 table
.AssignLiteral("index_data");
1787 NS_NAMED_LITERAL_CSTRING(value
, "value");
1789 nsCString keyRangeClause
;
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");
1801 case IDBCursor::PREV
:
1802 directionClause
+= NS_LITERAL_CSTRING("DESC, object_data_key DESC");
1805 case IDBCursor::PREV_UNIQUE
:
1806 directionClause
+= NS_LITERAL_CSTRING("DESC, object_data_key ASC");
1810 NS_NOTREACHED("Unknown direction!");
1812 nsCString firstQuery
= NS_LITERAL_CSTRING("SELECT value, object_data_key "
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"),
1826 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1829 rv
= mKeyRange
->BindToStatement(stmt
);
1830 NS_ENSURE_SUCCESS(rv
, rv
);
1834 rv
= stmt
->ExecuteStep(&hasResult
);
1835 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
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"
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(),
1860 mRangeKey
= mKeyRange
->Upper();
1864 NS_LITERAL_CSTRING(" AND value >= :current_key AND "
1865 "( value > :current_key OR "
1866 " object_data_key > :object_key )") +
1868 NS_LITERAL_CSTRING(" LIMIT ");
1871 NS_LITERAL_CSTRING(" AND value >= :current_key ") +
1873 NS_LITERAL_CSTRING(" LIMIT ");
1876 case IDBCursor::NEXT_UNIQUE
:
1877 if (mKeyRange
&& !mKeyRange
->Upper().IsUnset()) {
1878 AppendConditionClause(value
, rangeKey
, true, !mKeyRange
->IsUpperOpen(),
1880 mRangeKey
= mKeyRange
->Upper();
1883 queryStart
+ NS_LITERAL_CSTRING(" AND value > :current_key") +
1885 NS_LITERAL_CSTRING(" LIMIT ");
1887 queryStart
+ NS_LITERAL_CSTRING(" AND value >= :current_key") +
1889 NS_LITERAL_CSTRING(" LIMIT ");
1892 case IDBCursor::PREV
:
1893 if (mKeyRange
&& !mKeyRange
->Lower().IsUnset()) {
1894 AppendConditionClause(value
, rangeKey
, false, !mKeyRange
->IsLowerOpen(),
1896 mRangeKey
= mKeyRange
->Lower();
1901 NS_LITERAL_CSTRING(" AND value <= :current_key AND "
1902 "( value < :current_key OR "
1903 " object_data_key < :object_key )") +
1905 NS_LITERAL_CSTRING(" LIMIT ");
1908 NS_LITERAL_CSTRING(" AND value <= :current_key ") +
1910 NS_LITERAL_CSTRING(" LIMIT ");
1913 case IDBCursor::PREV_UNIQUE
:
1914 if (mKeyRange
&& !mKeyRange
->Lower().IsUnset()) {
1915 AppendConditionClause(value
, rangeKey
, false, !mKeyRange
->IsLowerOpen(),
1917 mRangeKey
= mKeyRange
->Lower();
1921 NS_LITERAL_CSTRING(" AND value < :current_key") +
1923 NS_LITERAL_CSTRING(" LIMIT ");
1926 NS_LITERAL_CSTRING(" AND value <= :current_key") +
1928 NS_LITERAL_CSTRING(" LIMIT ");
1932 NS_NOTREACHED("Unknown direction type!");
1939 OpenKeyCursorHelper::EnsureCursor()
1941 if (mCursor
|| mKey
.IsUnset()) {
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
);
1955 OpenKeyCursorHelper::GetSuccessResult(JSContext
* aCx
,
1956 JS::MutableHandle
<JS::Value
> aVal
)
1958 nsresult rv
= EnsureCursor();
1959 NS_ENSURE_SUCCESS(rv
, rv
);
1962 rv
= WrapNative(aCx
, mCursor
, aVal
);
1963 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
1966 aVal
.setUndefined();
1973 OpenKeyCursorHelper::ReleaseMainThreadObjects()
1975 mKeyRange
= nullptr;
1977 IndexHelper::ReleaseMainThreadObjects();
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
;
1993 mKeyRange
->ToSerializedKeyRange(keyRange
);
1994 params
.optionalKeyRange() = keyRange
;
1997 params
.optionalKeyRange() = mozilla::void_t();
2000 params
.direction() = mDirection
;
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!");
2027 ResponseValue response
;
2028 if (NS_FAILED(aResultCode
)) {
2029 response
= aResultCode
;
2032 OpenCursorResponse openCursorResponse
;
2035 openCursorResponse
= mozilla::void_t();
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
)) {
2056 response
= openCursorResponse
;
2059 if (!actor
->SendResponse(response
)) {
2063 return Success_Sent
;
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
:
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!");
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");
2118 indexTable
.AssignLiteral("index_data");
2121 NS_NAMED_LITERAL_CSTRING(value
, "index_table.value");
2123 nsCString keyRangeClause
;
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
:
2133 NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
2136 case IDBCursor::PREV
:
2138 NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
2141 case IDBCursor::PREV_UNIQUE
:
2143 NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
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 ") +
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
);
2171 rv
= mKeyRange
->BindToStatement(stmt
);
2172 NS_ENSURE_SUCCESS(rv
, rv
);
2176 rv
= stmt
->ExecuteStep(&hasResult
);
2177 IDB_ENSURE_SUCCESS(rv
, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR
);
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 ") +
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(),
2213 mRangeKey
= mKeyRange
->Upper();
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
;
2223 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
2224 directionClause
+ limit
;
2227 case IDBCursor::NEXT_UNIQUE
:
2228 if (mKeyRange
&& !mKeyRange
->Upper().IsUnset()) {
2229 AppendConditionClause(value
, rangeKey
, true, !mKeyRange
->IsUpperOpen(),
2231 mRangeKey
= mKeyRange
->Upper();
2235 NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
2236 directionClause
+ limit
;
2239 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
2240 directionClause
+ limit
;
2243 case IDBCursor::PREV
:
2244 if (mKeyRange
&& !mKeyRange
->Lower().IsUnset()) {
2245 AppendConditionClause(value
, rangeKey
, false, !mKeyRange
->IsLowerOpen(),
2247 mRangeKey
= mKeyRange
->Lower();
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
;
2257 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
2258 directionClause
+ limit
;
2261 case IDBCursor::PREV_UNIQUE
:
2262 if (mKeyRange
&& !mKeyRange
->Lower().IsUnset()) {
2263 AppendConditionClause(value
, rangeKey
, false, !mKeyRange
->IsLowerOpen(),
2265 mRangeKey
= mKeyRange
->Lower();
2269 NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
2270 directionClause
+ limit
;
2273 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
2274 directionClause
+ limit
;
2278 NS_NOTREACHED("Unknown direction type!");
2285 OpenCursorHelper::EnsureCursor()
2287 if (mCursor
|| mKey
.IsUnset()) {
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
);
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();
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
;
2335 mKeyRange
->ToSerializedKeyRange(keyRange
);
2336 params
.optionalKeyRange() = keyRange
;
2339 params
.optionalKeyRange() = mozilla::void_t();
2342 params
.direction() = mDirection
;
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
;
2376 IDBObjectStore::ConvertBlobsToActors(contentParent
, fileManager
, files
,
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!");
2391 ResponseValue response
;
2392 if (NS_FAILED(aResultCode
)) {
2393 response
= aResultCode
;
2396 OpenCursorResponse openCursorResponse
;
2399 openCursorResponse
= mozilla::void_t();
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
)) {
2425 response
= openCursorResponse
;
2428 if (!actor
->SendResponse(response
)) {
2432 return Success_Sent
;
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
);
2445 if (mIndex
->IsUnique()) {
2446 table
.AssignLiteral("unique_index_data");
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
;
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") +
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
);
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
);
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);
2501 CountHelper::GetSuccessResult(JSContext
* aCx
,
2502 JS::MutableHandle
<JS::Value
> aVal
)
2504 aVal
.setNumber(static_cast<double>(mCount
));
2509 CountHelper::ReleaseMainThreadObjects()
2511 mKeyRange
= nullptr;
2512 IndexHelper::ReleaseMainThreadObjects();
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
);
2528 mKeyRange
->ToSerializedKeyRange(keyRange
);
2529 params
.optionalKeyRange() = keyRange
;
2532 params
.optionalKeyRange() = mozilla::void_t();
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
;
2556 CountResponse countResponse
= mCount
;
2557 response
= countResponse
;
2560 if (!actor
->SendResponse(response
)) {
2564 return Success_Sent
;
2568 CountHelper::UnpackResponseFromParentProcess(
2569 const ResponseValue
& aResponseValue
)
2571 NS_ASSERTION(aResponseValue
.type() == ResponseValue::TCountResponse
,
2572 "Bad response type!");
2574 mCount
= aResponseValue
.get_CountResponse().count();