dom/indexedDB/IDBIndex.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "base/basictypes.h"
michael@0 8
michael@0 9 #include "IDBIndex.h"
michael@0 10
michael@0 11 #include <algorithm>
michael@0 12 #include "mozilla/dom/ContentChild.h"
michael@0 13 #include "mozilla/dom/ContentParent.h"
michael@0 14 #include "mozilla/dom/ipc/Blob.h"
michael@0 15 #include "mozilla/storage.h"
michael@0 16 #include "nsThreadUtils.h"
michael@0 17 #include "xpcpublic.h"
michael@0 18
michael@0 19 #include "AsyncConnectionHelper.h"
michael@0 20 #include "DatabaseInfo.h"
michael@0 21 #include "IDBCursor.h"
michael@0 22 #include "IDBEvents.h"
michael@0 23 #include "IDBKeyRange.h"
michael@0 24 #include "IDBObjectStore.h"
michael@0 25 #include "IDBTransaction.h"
michael@0 26 #include "ProfilerHelpers.h"
michael@0 27 #include "ReportInternalError.h"
michael@0 28
michael@0 29 #include "ipc/IndexedDBChild.h"
michael@0 30 #include "ipc/IndexedDBParent.h"
michael@0 31
michael@0 32 #include "IndexedDatabaseInlines.h"
michael@0 33
michael@0 34 USING_INDEXEDDB_NAMESPACE
michael@0 35 using namespace mozilla::dom;
michael@0 36 using namespace mozilla::dom::indexedDB::ipc;
michael@0 37 using mozilla::ErrorResult;
michael@0 38 using mozilla::Move;
michael@0 39
michael@0 40 namespace {
michael@0 41
michael@0 42 class IndexHelper : public AsyncConnectionHelper
michael@0 43 {
michael@0 44 public:
michael@0 45 IndexHelper(IDBTransaction* aTransaction,
michael@0 46 IDBRequest* aRequest,
michael@0 47 IDBIndex* aIndex)
michael@0 48 : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex),
michael@0 49 mActor(nullptr)
michael@0 50 {
michael@0 51 NS_ASSERTION(aTransaction, "Null transaction!");
michael@0 52 NS_ASSERTION(aRequest, "Null request!");
michael@0 53 NS_ASSERTION(aIndex, "Null index!");
michael@0 54 }
michael@0 55
michael@0 56 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 57
michael@0 58 virtual nsresult Dispatch(nsIEventTarget* aDatabaseThread) MOZ_OVERRIDE;
michael@0 59
michael@0 60 virtual nsresult
michael@0 61 PackArgumentsForParentProcess(IndexRequestParams& aParams) = 0;
michael@0 62
michael@0 63 virtual nsresult
michael@0 64 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue) = 0;
michael@0 65
michael@0 66 protected:
michael@0 67 nsRefPtr<IDBIndex> mIndex;
michael@0 68
michael@0 69 private:
michael@0 70 IndexedDBIndexRequestChild* mActor;
michael@0 71 };
michael@0 72
michael@0 73 class GetKeyHelper : public IndexHelper
michael@0 74 {
michael@0 75 public:
michael@0 76 GetKeyHelper(IDBTransaction* aTransaction,
michael@0 77 IDBRequest* aRequest,
michael@0 78 IDBIndex* aIndex,
michael@0 79 IDBKeyRange* aKeyRange)
michael@0 80 : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange)
michael@0 81 { }
michael@0 82
michael@0 83 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 84 MOZ_OVERRIDE;
michael@0 85
michael@0 86 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 87 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 88
michael@0 89 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 90
michael@0 91 virtual nsresult
michael@0 92 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 93
michael@0 94 virtual ChildProcessSendResult
michael@0 95 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 96
michael@0 97 virtual nsresult
michael@0 98 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 99 MOZ_OVERRIDE;
michael@0 100
michael@0 101 protected:
michael@0 102 // In-params.
michael@0 103 nsRefPtr<IDBKeyRange> mKeyRange;
michael@0 104
michael@0 105 // Out-params.
michael@0 106 Key mKey;
michael@0 107 };
michael@0 108
michael@0 109 class GetHelper : public GetKeyHelper
michael@0 110 {
michael@0 111 public:
michael@0 112 GetHelper(IDBTransaction* aTransaction,
michael@0 113 IDBRequest* aRequest,
michael@0 114 IDBIndex* aIndex,
michael@0 115 IDBKeyRange* aKeyRange)
michael@0 116 : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange)
michael@0 117 { }
michael@0 118
michael@0 119 ~GetHelper()
michael@0 120 {
michael@0 121 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
michael@0 122 }
michael@0 123
michael@0 124 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 125 MOZ_OVERRIDE;
michael@0 126
michael@0 127 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 128 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 129
michael@0 130 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 131
michael@0 132 virtual nsresult
michael@0 133 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 134
michael@0 135 virtual ChildProcessSendResult
michael@0 136 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 137
michael@0 138 virtual nsresult
michael@0 139 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 140 MOZ_OVERRIDE;
michael@0 141
michael@0 142 protected:
michael@0 143 StructuredCloneReadInfo mCloneReadInfo;
michael@0 144 };
michael@0 145
michael@0 146 class GetAllKeysHelper : public GetKeyHelper
michael@0 147 {
michael@0 148 public:
michael@0 149 GetAllKeysHelper(IDBTransaction* aTransaction,
michael@0 150 IDBRequest* aRequest,
michael@0 151 IDBIndex* aIndex,
michael@0 152 IDBKeyRange* aKeyRange,
michael@0 153 const uint32_t aLimit)
michael@0 154 : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
michael@0 155 { }
michael@0 156
michael@0 157 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 158 MOZ_OVERRIDE;
michael@0 159
michael@0 160 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 161 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 162
michael@0 163 virtual nsresult
michael@0 164 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 165
michael@0 166 virtual ChildProcessSendResult
michael@0 167 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 168
michael@0 169 virtual nsresult
michael@0 170 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 171 MOZ_OVERRIDE;
michael@0 172
michael@0 173 protected:
michael@0 174 const uint32_t mLimit;
michael@0 175 nsTArray<Key> mKeys;
michael@0 176 };
michael@0 177
michael@0 178 class GetAllHelper : public GetKeyHelper
michael@0 179 {
michael@0 180 public:
michael@0 181 GetAllHelper(IDBTransaction* aTransaction,
michael@0 182 IDBRequest* aRequest,
michael@0 183 IDBIndex* aIndex,
michael@0 184 IDBKeyRange* aKeyRange,
michael@0 185 const uint32_t aLimit)
michael@0 186 : GetKeyHelper(aTransaction, aRequest, aIndex, aKeyRange), mLimit(aLimit)
michael@0 187 { }
michael@0 188
michael@0 189 ~GetAllHelper()
michael@0 190 {
michael@0 191 for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
michael@0 192 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
michael@0 193 }
michael@0 194 }
michael@0 195
michael@0 196 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 197 MOZ_OVERRIDE;
michael@0 198
michael@0 199 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 200 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 201
michael@0 202 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 203
michael@0 204 virtual nsresult
michael@0 205 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 206
michael@0 207 virtual ChildProcessSendResult
michael@0 208 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 209
michael@0 210 virtual nsresult
michael@0 211 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 212 MOZ_OVERRIDE;
michael@0 213
michael@0 214 protected:
michael@0 215 const uint32_t mLimit;
michael@0 216 nsTArray<StructuredCloneReadInfo> mCloneReadInfos;
michael@0 217 };
michael@0 218
michael@0 219 class OpenKeyCursorHelper : public IndexHelper
michael@0 220 {
michael@0 221 public:
michael@0 222 OpenKeyCursorHelper(IDBTransaction* aTransaction,
michael@0 223 IDBRequest* aRequest,
michael@0 224 IDBIndex* aIndex,
michael@0 225 IDBKeyRange* aKeyRange,
michael@0 226 IDBCursor::Direction aDirection)
michael@0 227 : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange),
michael@0 228 mDirection(aDirection)
michael@0 229 { }
michael@0 230
michael@0 231 ~OpenKeyCursorHelper()
michael@0 232 {
michael@0 233 NS_ASSERTION(true, "bas");
michael@0 234 }
michael@0 235
michael@0 236 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 237 MOZ_OVERRIDE;
michael@0 238
michael@0 239 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 240 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 241
michael@0 242 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 243
michael@0 244 virtual nsresult
michael@0 245 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 246
michael@0 247 virtual ChildProcessSendResult
michael@0 248 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 249
michael@0 250 virtual nsresult
michael@0 251 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 252 MOZ_OVERRIDE;
michael@0 253
michael@0 254 protected:
michael@0 255 virtual nsresult EnsureCursor();
michael@0 256
michael@0 257 // In-params.
michael@0 258 nsRefPtr<IDBKeyRange> mKeyRange;
michael@0 259 const IDBCursor::Direction mDirection;
michael@0 260
michael@0 261 // Out-params.
michael@0 262 Key mKey;
michael@0 263 Key mObjectKey;
michael@0 264 nsCString mContinueQuery;
michael@0 265 nsCString mContinueToQuery;
michael@0 266 Key mRangeKey;
michael@0 267
michael@0 268 // Only used in the parent process.
michael@0 269 nsRefPtr<IDBCursor> mCursor;
michael@0 270 };
michael@0 271
michael@0 272 class OpenCursorHelper : public OpenKeyCursorHelper
michael@0 273 {
michael@0 274 public:
michael@0 275 OpenCursorHelper(IDBTransaction* aTransaction,
michael@0 276 IDBRequest* aRequest,
michael@0 277 IDBIndex* aIndex,
michael@0 278 IDBKeyRange* aKeyRange,
michael@0 279 IDBCursor::Direction aDirection)
michael@0 280 : OpenKeyCursorHelper(aTransaction, aRequest, aIndex, aKeyRange, aDirection)
michael@0 281 { }
michael@0 282
michael@0 283 ~OpenCursorHelper()
michael@0 284 {
michael@0 285 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
michael@0 286 }
michael@0 287
michael@0 288 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 289 MOZ_OVERRIDE;
michael@0 290
michael@0 291 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 292
michael@0 293 virtual nsresult
michael@0 294 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 295
michael@0 296 virtual ChildProcessSendResult
michael@0 297 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 298
michael@0 299 private:
michael@0 300 virtual nsresult EnsureCursor();
michael@0 301
michael@0 302 StructuredCloneReadInfo mCloneReadInfo;
michael@0 303
michael@0 304 // Only used in the parent process.
michael@0 305 SerializedStructuredCloneReadInfo mSerializedCloneReadInfo;
michael@0 306 };
michael@0 307
michael@0 308 class CountHelper : public IndexHelper
michael@0 309 {
michael@0 310 public:
michael@0 311 CountHelper(IDBTransaction* aTransaction,
michael@0 312 IDBRequest* aRequest,
michael@0 313 IDBIndex* aIndex,
michael@0 314 IDBKeyRange* aKeyRange)
michael@0 315 : IndexHelper(aTransaction, aRequest, aIndex), mKeyRange(aKeyRange), mCount(0)
michael@0 316 { }
michael@0 317
michael@0 318 virtual nsresult DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 319 MOZ_OVERRIDE;
michael@0 320
michael@0 321 virtual nsresult GetSuccessResult(JSContext* aCx,
michael@0 322 JS::MutableHandle<JS::Value> aVal) MOZ_OVERRIDE;
michael@0 323
michael@0 324 virtual void ReleaseMainThreadObjects() MOZ_OVERRIDE;
michael@0 325
michael@0 326 virtual nsresult
michael@0 327 PackArgumentsForParentProcess(IndexRequestParams& aParams) MOZ_OVERRIDE;
michael@0 328
michael@0 329 virtual ChildProcessSendResult
michael@0 330 SendResponseToChildProcess(nsresult aResultCode) MOZ_OVERRIDE;
michael@0 331
michael@0 332 virtual nsresult
michael@0 333 UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 334 MOZ_OVERRIDE;
michael@0 335
michael@0 336 private:
michael@0 337 nsRefPtr<IDBKeyRange> mKeyRange;
michael@0 338 uint64_t mCount;
michael@0 339 };
michael@0 340
michael@0 341 inline
michael@0 342 already_AddRefed<IDBRequest>
michael@0 343 GenerateRequest(IDBIndex* aIndex)
michael@0 344 {
michael@0 345 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 346 IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
michael@0 347 IDBDatabase* database = transaction->Database();
michael@0 348 return IDBRequest::Create(aIndex, database, transaction);
michael@0 349 }
michael@0 350
michael@0 351 } // anonymous namespace
michael@0 352
michael@0 353 // static
michael@0 354 already_AddRefed<IDBIndex>
michael@0 355 IDBIndex::Create(IDBObjectStore* aObjectStore,
michael@0 356 const IndexInfo* aIndexInfo,
michael@0 357 bool aCreating)
michael@0 358 {
michael@0 359 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 360 NS_ASSERTION(aObjectStore, "Null pointer!");
michael@0 361 NS_ASSERTION(aIndexInfo, "Null pointer!");
michael@0 362
michael@0 363 nsRefPtr<IDBIndex> index = new IDBIndex();
michael@0 364
michael@0 365 index->mObjectStore = aObjectStore;
michael@0 366 index->mId = aIndexInfo->id;
michael@0 367 index->mName = aIndexInfo->name;
michael@0 368 index->mKeyPath = aIndexInfo->keyPath;
michael@0 369 index->mUnique = aIndexInfo->unique;
michael@0 370 index->mMultiEntry = aIndexInfo->multiEntry;
michael@0 371
michael@0 372 if (!IndexedDatabaseManager::IsMainProcess()) {
michael@0 373 IndexedDBObjectStoreChild* objectStoreActor = aObjectStore->GetActorChild();
michael@0 374 NS_ASSERTION(objectStoreActor, "Must have an actor here!");
michael@0 375
michael@0 376 nsAutoPtr<IndexedDBIndexChild> actor(new IndexedDBIndexChild(index));
michael@0 377
michael@0 378 IndexConstructorParams params;
michael@0 379
michael@0 380 if (aCreating) {
michael@0 381 CreateIndexParams createParams;
michael@0 382 createParams.info() = *aIndexInfo;
michael@0 383 params = createParams;
michael@0 384 }
michael@0 385 else {
michael@0 386 GetIndexParams getParams;
michael@0 387 getParams.name() = aIndexInfo->name;
michael@0 388 params = getParams;
michael@0 389 }
michael@0 390
michael@0 391 objectStoreActor->SendPIndexedDBIndexConstructor(actor.forget(), params);
michael@0 392 }
michael@0 393
michael@0 394 return index.forget();
michael@0 395 }
michael@0 396
michael@0 397 IDBIndex::IDBIndex()
michael@0 398 : mId(INT64_MIN),
michael@0 399 mKeyPath(0),
michael@0 400 mCachedKeyPath(JSVAL_VOID),
michael@0 401 mActorChild(nullptr),
michael@0 402 mActorParent(nullptr),
michael@0 403 mUnique(false),
michael@0 404 mMultiEntry(false),
michael@0 405 mRooted(false)
michael@0 406 {
michael@0 407 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 408
michael@0 409 SetIsDOMBinding();
michael@0 410 }
michael@0 411
michael@0 412 IDBIndex::~IDBIndex()
michael@0 413 {
michael@0 414 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 415 NS_ASSERTION(!mActorParent, "Actor parent owns us, how can we be dying?!");
michael@0 416
michael@0 417 if (mRooted) {
michael@0 418 mCachedKeyPath = JSVAL_VOID;
michael@0 419 mozilla::DropJSObjects(this);
michael@0 420 }
michael@0 421
michael@0 422 if (mActorChild) {
michael@0 423 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 424 mActorChild->Send__delete__(mActorChild);
michael@0 425 NS_ASSERTION(!mActorChild, "Should have cleared in Send__delete__!");
michael@0 426 }
michael@0 427 }
michael@0 428
michael@0 429 already_AddRefed<IDBRequest>
michael@0 430 IDBIndex::GetInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
michael@0 431 {
michael@0 432 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 433
michael@0 434 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 435 if (!transaction->IsOpen()) {
michael@0 436 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 437 return nullptr;
michael@0 438 }
michael@0 439
michael@0 440 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 441 if (!request) {
michael@0 442 IDB_WARNING("Failed to generate request!");
michael@0 443 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 444 return nullptr;
michael@0 445 }
michael@0 446
michael@0 447 nsRefPtr<GetHelper> helper =
michael@0 448 new GetHelper(transaction, request, this, aKeyRange);
michael@0 449
michael@0 450 nsresult rv = helper->DispatchToTransactionPool();
michael@0 451 if (NS_FAILED(rv)) {
michael@0 452 IDB_WARNING("Failed to dispatch!");
michael@0 453 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 454 return nullptr;
michael@0 455 }
michael@0 456
michael@0 457 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 458 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 459 "get(%s)",
michael@0 460 "IDBRequest[%llu] MT IDBIndex.get()",
michael@0 461 request->GetSerialNumber(),
michael@0 462 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 463 Database()),
michael@0 464 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 465 IDB_PROFILER_STRING(ObjectStore()),
michael@0 466 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
michael@0 467
michael@0 468 return request.forget();
michael@0 469 }
michael@0 470
michael@0 471 already_AddRefed<IDBRequest>
michael@0 472 IDBIndex::GetKeyInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
michael@0 473 {
michael@0 474 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 475
michael@0 476 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 477 if (!transaction->IsOpen()) {
michael@0 478 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 479 return nullptr;
michael@0 480 }
michael@0 481
michael@0 482 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 483 if (!request) {
michael@0 484 IDB_WARNING("Failed to generate request!");
michael@0 485 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 486 return nullptr;
michael@0 487 }
michael@0 488
michael@0 489 nsRefPtr<GetKeyHelper> helper =
michael@0 490 new GetKeyHelper(transaction, request, this, aKeyRange);
michael@0 491
michael@0 492 nsresult rv = helper->DispatchToTransactionPool();
michael@0 493 if (NS_FAILED(rv)) {
michael@0 494 IDB_WARNING("Failed to dispatch!");
michael@0 495 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 496 return nullptr;
michael@0 497 }
michael@0 498
michael@0 499 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 500 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 501 "getKey(%s)",
michael@0 502 "IDBRequest[%llu] MT IDBIndex.getKey()",
michael@0 503 request->GetSerialNumber(),
michael@0 504 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 505 Database()),
michael@0 506 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 507 IDB_PROFILER_STRING(ObjectStore()),
michael@0 508 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
michael@0 509
michael@0 510 return request.forget();
michael@0 511 }
michael@0 512
michael@0 513 already_AddRefed<IDBRequest>
michael@0 514 IDBIndex::GetAllInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
michael@0 515 ErrorResult& aRv)
michael@0 516 {
michael@0 517 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 518
michael@0 519 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 520 if (!transaction->IsOpen()) {
michael@0 521 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 522 return nullptr;
michael@0 523 }
michael@0 524
michael@0 525 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 526 if (!request) {
michael@0 527 IDB_WARNING("Failed to generate request!");
michael@0 528 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 529 return nullptr;
michael@0 530 }
michael@0 531
michael@0 532 nsRefPtr<GetAllHelper> helper =
michael@0 533 new GetAllHelper(transaction, request, this, aKeyRange, aLimit);
michael@0 534
michael@0 535 nsresult rv = helper->DispatchToTransactionPool();
michael@0 536 if (NS_FAILED(rv)) {
michael@0 537 IDB_WARNING("Failed to dispatch!");
michael@0 538 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 539 return nullptr;
michael@0 540 }
michael@0 541
michael@0 542 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 543 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 544 "getAll(%s, %lu)",
michael@0 545 "IDBRequest[%llu] MT IDBIndex.getAll()",
michael@0 546 request->GetSerialNumber(),
michael@0 547 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 548 Database()),
michael@0 549 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 550 IDB_PROFILER_STRING(ObjectStore()),
michael@0 551 IDB_PROFILER_STRING(this),
michael@0 552 IDB_PROFILER_STRING(aKeyRange), aLimit);
michael@0 553
michael@0 554 return request.forget();
michael@0 555 }
michael@0 556
michael@0 557 already_AddRefed<IDBRequest>
michael@0 558 IDBIndex::GetAllKeysInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
michael@0 559 ErrorResult& aRv)
michael@0 560 {
michael@0 561 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 562
michael@0 563 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 564 if (!transaction->IsOpen()) {
michael@0 565 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 566 return nullptr;
michael@0 567 }
michael@0 568
michael@0 569 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 570 if (!request) {
michael@0 571 IDB_WARNING("Failed to generate request!");
michael@0 572 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 573 return nullptr;
michael@0 574 }
michael@0 575
michael@0 576 nsRefPtr<GetAllKeysHelper> helper =
michael@0 577 new GetAllKeysHelper(transaction, request, this, aKeyRange, aLimit);
michael@0 578
michael@0 579 nsresult rv = helper->DispatchToTransactionPool();
michael@0 580 if (NS_FAILED(rv)) {
michael@0 581 IDB_WARNING("Failed to dispatch!");
michael@0 582 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 583 return nullptr;
michael@0 584 }
michael@0 585
michael@0 586 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 587 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 588 "getAllKeys(%s, %lu)",
michael@0 589 "IDBRequest[%llu] MT IDBIndex.getAllKeys()",
michael@0 590 request->GetSerialNumber(),
michael@0 591 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 592 Database()),
michael@0 593 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 594 IDB_PROFILER_STRING(ObjectStore()),
michael@0 595 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
michael@0 596 aLimit);
michael@0 597
michael@0 598 return request.forget();
michael@0 599 }
michael@0 600
michael@0 601 already_AddRefed<IDBRequest>
michael@0 602 IDBIndex::CountInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
michael@0 603 {
michael@0 604 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 605
michael@0 606 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 607 if (!transaction->IsOpen()) {
michael@0 608 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 609 return nullptr;
michael@0 610 }
michael@0 611
michael@0 612 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 613 if (!request) {
michael@0 614 IDB_WARNING("Failed to generate request!");
michael@0 615 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 616 return nullptr;
michael@0 617 }
michael@0 618
michael@0 619 nsRefPtr<CountHelper> helper =
michael@0 620 new CountHelper(transaction, request, this, aKeyRange);
michael@0 621
michael@0 622 nsresult rv = helper->DispatchToTransactionPool();
michael@0 623 if (NS_FAILED(rv)) {
michael@0 624 IDB_WARNING("Failed to dispatch!");
michael@0 625 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 626 return nullptr;
michael@0 627 }
michael@0 628
michael@0 629 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 630 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 631 "count(%s)",
michael@0 632 "IDBRequest[%llu] MT IDBIndex.count()",
michael@0 633 request->GetSerialNumber(),
michael@0 634 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 635 Database()),
michael@0 636 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 637 IDB_PROFILER_STRING(ObjectStore()),
michael@0 638 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
michael@0 639
michael@0 640 return request.forget();
michael@0 641 }
michael@0 642
michael@0 643 already_AddRefed<IDBRequest>
michael@0 644 IDBIndex::OpenKeyCursorInternal(IDBKeyRange* aKeyRange, size_t aDirection,
michael@0 645 ErrorResult& aRv)
michael@0 646 {
michael@0 647 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 648
michael@0 649 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 650 if (!transaction->IsOpen()) {
michael@0 651 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 652 return nullptr;
michael@0 653 }
michael@0 654
michael@0 655 IDBCursor::Direction direction =
michael@0 656 static_cast<IDBCursor::Direction>(aDirection);
michael@0 657
michael@0 658 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 659 if (!request) {
michael@0 660 IDB_WARNING("Failed to generate request!");
michael@0 661 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 662 return nullptr;
michael@0 663 }
michael@0 664
michael@0 665 nsRefPtr<OpenKeyCursorHelper> helper =
michael@0 666 new OpenKeyCursorHelper(transaction, request, this, aKeyRange, direction);
michael@0 667
michael@0 668 nsresult rv = helper->DispatchToTransactionPool();
michael@0 669 if (NS_FAILED(rv)) {
michael@0 670 IDB_WARNING("Failed to dispatch!");
michael@0 671 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 672 return nullptr;
michael@0 673 }
michael@0 674
michael@0 675 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 676 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 677 "openKeyCursor(%s)",
michael@0 678 "IDBRequest[%llu] MT IDBIndex.openKeyCursor()",
michael@0 679 request->GetSerialNumber(),
michael@0 680 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 681 Database()),
michael@0 682 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 683 IDB_PROFILER_STRING(ObjectStore()),
michael@0 684 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
michael@0 685 IDB_PROFILER_STRING(direction));
michael@0 686
michael@0 687 return request.forget();
michael@0 688 }
michael@0 689
michael@0 690 nsresult
michael@0 691 IDBIndex::OpenCursorInternal(IDBKeyRange* aKeyRange,
michael@0 692 size_t aDirection,
michael@0 693 IDBRequest** _retval)
michael@0 694 {
michael@0 695 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 696
michael@0 697 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 698 if (!transaction->IsOpen()) {
michael@0 699 return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
michael@0 700 }
michael@0 701
michael@0 702 IDBCursor::Direction direction =
michael@0 703 static_cast<IDBCursor::Direction>(aDirection);
michael@0 704
michael@0 705 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 706 IDB_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 707
michael@0 708 nsRefPtr<OpenCursorHelper> helper =
michael@0 709 new OpenCursorHelper(transaction, request, this, aKeyRange, direction);
michael@0 710
michael@0 711 nsresult rv = helper->DispatchToTransactionPool();
michael@0 712 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 713
michael@0 714 IDB_PROFILER_MARK("IndexedDB Request %llu: "
michael@0 715 "database(%s).transaction(%s).objectStore(%s).index(%s)."
michael@0 716 "openCursor(%s)",
michael@0 717 "IDBRequest[%llu] MT IDBIndex.openCursor()",
michael@0 718 request->GetSerialNumber(),
michael@0 719 IDB_PROFILER_STRING(ObjectStore()->Transaction()->
michael@0 720 Database()),
michael@0 721 IDB_PROFILER_STRING(ObjectStore()->Transaction()),
michael@0 722 IDB_PROFILER_STRING(ObjectStore()),
michael@0 723 IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
michael@0 724 IDB_PROFILER_STRING(direction));
michael@0 725
michael@0 726 request.forget(_retval);
michael@0 727 return NS_OK;
michael@0 728 }
michael@0 729
michael@0 730 nsresult
michael@0 731 IDBIndex::OpenCursorFromChildProcess(IDBRequest* aRequest,
michael@0 732 size_t aDirection,
michael@0 733 const Key& aKey,
michael@0 734 const Key& aObjectKey,
michael@0 735 IDBCursor** _retval)
michael@0 736 {
michael@0 737 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 738
michael@0 739 IDBCursor::Direction direction =
michael@0 740 static_cast<IDBCursor::Direction>(aDirection);
michael@0 741
michael@0 742 nsRefPtr<IDBCursor> cursor =
michael@0 743 IDBCursor::Create(aRequest, mObjectStore->Transaction(), this, direction,
michael@0 744 Key(), EmptyCString(), EmptyCString(), aKey, aObjectKey);
michael@0 745 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 746
michael@0 747 cursor.forget(_retval);
michael@0 748 return NS_OK;
michael@0 749 }
michael@0 750
michael@0 751 nsresult
michael@0 752 IDBIndex::OpenCursorFromChildProcess(
michael@0 753 IDBRequest* aRequest,
michael@0 754 size_t aDirection,
michael@0 755 const Key& aKey,
michael@0 756 const Key& aObjectKey,
michael@0 757 const SerializedStructuredCloneReadInfo& aCloneInfo,
michael@0 758 nsTArray<StructuredCloneFile>& aBlobs,
michael@0 759 IDBCursor** _retval)
michael@0 760 {
michael@0 761 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 762 NS_ASSERTION((!aCloneInfo.dataLength && !aCloneInfo.data) ||
michael@0 763 (aCloneInfo.dataLength && aCloneInfo.data),
michael@0 764 "Inconsistent clone info!");
michael@0 765
michael@0 766 IDBCursor::Direction direction =
michael@0 767 static_cast<IDBCursor::Direction>(aDirection);
michael@0 768
michael@0 769 StructuredCloneReadInfo cloneInfo;
michael@0 770
michael@0 771 if (!cloneInfo.SetFromSerialized(aCloneInfo)) {
michael@0 772 IDB_WARNING("Failed to copy clone buffer!");
michael@0 773 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 774 }
michael@0 775
michael@0 776 cloneInfo.mFiles.SwapElements(aBlobs);
michael@0 777
michael@0 778 nsRefPtr<IDBCursor> cursor =
michael@0 779 IDBCursor::Create(aRequest, mObjectStore->Transaction(), this, direction,
michael@0 780 Key(), EmptyCString(), EmptyCString(), aKey, aObjectKey,
michael@0 781 Move(cloneInfo));
michael@0 782 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 783
michael@0 784 NS_ASSERTION(!cloneInfo.mCloneBuffer.data(), "Should have swapped!");
michael@0 785
michael@0 786 cursor.forget(_retval);
michael@0 787 return NS_OK;
michael@0 788 }
michael@0 789
michael@0 790 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
michael@0 791
michael@0 792 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
michael@0 793 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
michael@0 794 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKeyPath)
michael@0 795 NS_IMPL_CYCLE_COLLECTION_TRACE_END
michael@0 796
michael@0 797 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
michael@0 798 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 799 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
michael@0 800 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 801
michael@0 802 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
michael@0 803 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
michael@0 804
michael@0 805 // Don't unlink mObjectStore!
michael@0 806
michael@0 807 tmp->mCachedKeyPath = JSVAL_VOID;
michael@0 808
michael@0 809 if (tmp->mRooted) {
michael@0 810 mozilla::DropJSObjects(tmp);
michael@0 811 tmp->mRooted = false;
michael@0 812 }
michael@0 813 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 814
michael@0 815 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
michael@0 816 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 817 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 818 NS_INTERFACE_MAP_END
michael@0 819
michael@0 820 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
michael@0 821 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
michael@0 822
michael@0 823 JSObject*
michael@0 824 IDBIndex::WrapObject(JSContext* aCx)
michael@0 825 {
michael@0 826 return IDBIndexBinding::Wrap(aCx, this);
michael@0 827 }
michael@0 828
michael@0 829 void
michael@0 830 IDBIndex::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
michael@0 831 ErrorResult& aRv)
michael@0 832 {
michael@0 833 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 834
michael@0 835 if (!JSVAL_IS_VOID(mCachedKeyPath)) {
michael@0 836 JS::ExposeValueToActiveJS(mCachedKeyPath);
michael@0 837 aResult.set(mCachedKeyPath);
michael@0 838 return;
michael@0 839 }
michael@0 840
michael@0 841 aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
michael@0 842 if (NS_WARN_IF(aRv.Failed())) {
michael@0 843 return;
michael@0 844 }
michael@0 845
michael@0 846 if (JSVAL_IS_GCTHING(mCachedKeyPath)) {
michael@0 847 mozilla::HoldJSObjects(this);
michael@0 848 mRooted = true;
michael@0 849 }
michael@0 850
michael@0 851 JS::ExposeValueToActiveJS(mCachedKeyPath);
michael@0 852 aResult.set(mCachedKeyPath);
michael@0 853 }
michael@0 854
michael@0 855 already_AddRefed<IDBRequest>
michael@0 856 IDBIndex::Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
michael@0 857 {
michael@0 858 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 859
michael@0 860 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 861 if (!transaction->IsOpen()) {
michael@0 862 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 863 return nullptr;
michael@0 864 }
michael@0 865
michael@0 866 nsRefPtr<IDBKeyRange> keyRange;
michael@0 867 aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
michael@0 868 ENSURE_SUCCESS(aRv, nullptr);
michael@0 869
michael@0 870 if (!keyRange) {
michael@0 871 // Must specify a key or keyRange for getKey().
michael@0 872 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
michael@0 873 return nullptr;
michael@0 874 }
michael@0 875
michael@0 876 return GetInternal(keyRange, aRv);
michael@0 877 }
michael@0 878
michael@0 879 already_AddRefed<IDBRequest>
michael@0 880 IDBIndex::GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
michael@0 881 {
michael@0 882 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 883
michael@0 884 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 885 if (!transaction->IsOpen()) {
michael@0 886 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 887 return nullptr;
michael@0 888 }
michael@0 889
michael@0 890 nsRefPtr<IDBKeyRange> keyRange;
michael@0 891 aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
michael@0 892 ENSURE_SUCCESS(aRv, nullptr);
michael@0 893
michael@0 894 if (!keyRange) {
michael@0 895 // Must specify a key or keyRange for get().
michael@0 896 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
michael@0 897 return nullptr;
michael@0 898 }
michael@0 899
michael@0 900 return GetKeyInternal(keyRange, aRv);
michael@0 901 }
michael@0 902
michael@0 903 already_AddRefed<IDBRequest>
michael@0 904 IDBIndex::GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
michael@0 905 const Optional<uint32_t>& aLimit, ErrorResult& aRv)
michael@0 906 {
michael@0 907 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 908
michael@0 909 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 910 if (!transaction->IsOpen()) {
michael@0 911 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 912 return nullptr;
michael@0 913 }
michael@0 914
michael@0 915 nsRefPtr<IDBKeyRange> keyRange;
michael@0 916 aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
michael@0 917 ENSURE_SUCCESS(aRv, nullptr);
michael@0 918
michael@0 919 uint32_t limit = UINT32_MAX;
michael@0 920 if (aLimit.WasPassed() && aLimit.Value() > 0) {
michael@0 921 limit = aLimit.Value();
michael@0 922 }
michael@0 923
michael@0 924 return GetAllInternal(keyRange, limit, aRv);
michael@0 925 }
michael@0 926
michael@0 927 already_AddRefed<IDBRequest>
michael@0 928 IDBIndex::GetAllKeys(JSContext* aCx,
michael@0 929 JS::Handle<JS::Value> aKey,
michael@0 930 const Optional<uint32_t>& aLimit, ErrorResult& aRv)
michael@0 931 {
michael@0 932 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 933
michael@0 934 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 935 if (!transaction->IsOpen()) {
michael@0 936 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 937 return nullptr;
michael@0 938 }
michael@0 939
michael@0 940 nsRefPtr<IDBKeyRange> keyRange;
michael@0 941 aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
michael@0 942 ENSURE_SUCCESS(aRv, nullptr);
michael@0 943
michael@0 944 uint32_t limit = UINT32_MAX;
michael@0 945 if (aLimit.WasPassed() && aLimit.Value() > 0) {
michael@0 946 limit = aLimit.Value();
michael@0 947 }
michael@0 948
michael@0 949 return GetAllKeysInternal(keyRange, limit, aRv);
michael@0 950 }
michael@0 951
michael@0 952 already_AddRefed<IDBRequest>
michael@0 953 IDBIndex::OpenCursor(JSContext* aCx,
michael@0 954 JS::Handle<JS::Value> aRange,
michael@0 955 IDBCursorDirection aDirection, ErrorResult& aRv)
michael@0 956 {
michael@0 957 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 958
michael@0 959 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 960 if (!transaction->IsOpen()) {
michael@0 961 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 962 return nullptr;
michael@0 963 }
michael@0 964
michael@0 965 nsRefPtr<IDBKeyRange> keyRange;
michael@0 966 aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
michael@0 967 ENSURE_SUCCESS(aRv, nullptr);
michael@0 968
michael@0 969 IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
michael@0 970
michael@0 971 nsRefPtr<IDBRequest> request = GenerateRequest(this);
michael@0 972 if (!request) {
michael@0 973 IDB_WARNING("Failed to generate request!");
michael@0 974 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 975 return nullptr;
michael@0 976 }
michael@0 977
michael@0 978 nsRefPtr<OpenCursorHelper> helper =
michael@0 979 new OpenCursorHelper(transaction, request, this, keyRange, direction);
michael@0 980
michael@0 981 nsresult rv = helper->DispatchToTransactionPool();
michael@0 982 if (NS_FAILED(rv)) {
michael@0 983 IDB_WARNING("Failed to dispatch!");
michael@0 984 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 985 return nullptr;
michael@0 986 }
michael@0 987
michael@0 988 return request.forget();
michael@0 989 }
michael@0 990
michael@0 991 already_AddRefed<IDBRequest>
michael@0 992 IDBIndex::OpenKeyCursor(JSContext* aCx,
michael@0 993 JS::Handle<JS::Value> aRange,
michael@0 994 IDBCursorDirection aDirection, ErrorResult& aRv)
michael@0 995 {
michael@0 996 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 997
michael@0 998 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 999 if (!transaction->IsOpen()) {
michael@0 1000 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 1001 return nullptr;
michael@0 1002 }
michael@0 1003
michael@0 1004 nsRefPtr<IDBKeyRange> keyRange;
michael@0 1005 aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
michael@0 1006 ENSURE_SUCCESS(aRv, nullptr);
michael@0 1007
michael@0 1008 IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
michael@0 1009
michael@0 1010 return OpenKeyCursorInternal(keyRange, direction, aRv);
michael@0 1011 }
michael@0 1012
michael@0 1013 already_AddRefed<IDBRequest>
michael@0 1014 IDBIndex::Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
michael@0 1015 ErrorResult& aRv)
michael@0 1016 {
michael@0 1017 IDBTransaction* transaction = mObjectStore->Transaction();
michael@0 1018 if (!transaction->IsOpen()) {
michael@0 1019 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
michael@0 1020 return nullptr;
michael@0 1021 }
michael@0 1022
michael@0 1023 nsRefPtr<IDBKeyRange> keyRange;
michael@0 1024 aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
michael@0 1025 ENSURE_SUCCESS(aRv, nullptr);
michael@0 1026
michael@0 1027 return CountInternal(keyRange, aRv);
michael@0 1028 }
michael@0 1029
michael@0 1030 void
michael@0 1031 IndexHelper::ReleaseMainThreadObjects()
michael@0 1032 {
michael@0 1033 mIndex = nullptr;
michael@0 1034 AsyncConnectionHelper::ReleaseMainThreadObjects();
michael@0 1035 }
michael@0 1036
michael@0 1037 nsresult
michael@0 1038 IndexHelper::Dispatch(nsIEventTarget* aDatabaseThread)
michael@0 1039 {
michael@0 1040 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1041
michael@0 1042 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "IndexHelper::Dispatch");
michael@0 1043
michael@0 1044 if (IndexedDatabaseManager::IsMainProcess()) {
michael@0 1045 return AsyncConnectionHelper::Dispatch(aDatabaseThread);
michael@0 1046 }
michael@0 1047
michael@0 1048 // If we've been invalidated then there's no point sending anything to the
michael@0 1049 // parent process.
michael@0 1050 if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) {
michael@0 1051 IDB_REPORT_INTERNAL_ERR();
michael@0 1052 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1053 }
michael@0 1054
michael@0 1055 IndexedDBIndexChild* indexActor = mIndex->GetActorChild();
michael@0 1056 NS_ASSERTION(indexActor, "Must have an actor here!");
michael@0 1057
michael@0 1058 IndexRequestParams params;
michael@0 1059 nsresult rv = PackArgumentsForParentProcess(params);
michael@0 1060 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1061
michael@0 1062 NoDispatchEventTarget target;
michael@0 1063 rv = AsyncConnectionHelper::Dispatch(&target);
michael@0 1064 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1065
michael@0 1066 mActor = new IndexedDBIndexRequestChild(this, mIndex, params.type());
michael@0 1067 indexActor->SendPIndexedDBRequestConstructor(mActor, params);
michael@0 1068
michael@0 1069 return NS_OK;
michael@0 1070 }
michael@0 1071
michael@0 1072 nsresult
michael@0 1073 GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
michael@0 1074 {
michael@0 1075 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 1076 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1077 NS_ASSERTION(mKeyRange, "Must have a key range here!");
michael@0 1078
michael@0 1079 PROFILER_LABEL("IndexedDB", "GetKeyHelper::DoDatabaseWork");
michael@0 1080
michael@0 1081 nsCString indexTable;
michael@0 1082 if (mIndex->IsUnique()) {
michael@0 1083 indexTable.AssignLiteral("unique_index_data");
michael@0 1084 }
michael@0 1085 else {
michael@0 1086 indexTable.AssignLiteral("index_data");
michael@0 1087 }
michael@0 1088
michael@0 1089 nsCString keyRangeClause;
michael@0 1090 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
michael@0 1091
michael@0 1092 NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
michael@0 1093
michael@0 1094 nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
michael@0 1095 indexTable +
michael@0 1096 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
michael@0 1097 keyRangeClause +
michael@0 1098 NS_LITERAL_CSTRING(" LIMIT 1");
michael@0 1099
michael@0 1100 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
michael@0 1101 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1102
michael@0 1103 mozStorageStatementScoper scoper(stmt);
michael@0 1104
michael@0 1105 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
michael@0 1106 mIndex->Id());
michael@0 1107 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1108
michael@0 1109 rv = mKeyRange->BindToStatement(stmt);
michael@0 1110 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1111
michael@0 1112 bool hasResult;
michael@0 1113 rv = stmt->ExecuteStep(&hasResult);
michael@0 1114 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1115
michael@0 1116 if (hasResult) {
michael@0 1117 rv = mKey.SetFromStatement(stmt, 0);
michael@0 1118 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1119 }
michael@0 1120
michael@0 1121 return NS_OK;
michael@0 1122 }
michael@0 1123
michael@0 1124 nsresult
michael@0 1125 GetKeyHelper::GetSuccessResult(JSContext* aCx,
michael@0 1126 JS::MutableHandle<JS::Value> aVal)
michael@0 1127 {
michael@0 1128 return mKey.ToJSVal(aCx, aVal);
michael@0 1129 }
michael@0 1130
michael@0 1131 void
michael@0 1132 GetKeyHelper::ReleaseMainThreadObjects()
michael@0 1133 {
michael@0 1134 mKeyRange = nullptr;
michael@0 1135 IndexHelper::ReleaseMainThreadObjects();
michael@0 1136 }
michael@0 1137
michael@0 1138 nsresult
michael@0 1139 GetKeyHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 1140 {
michael@0 1141 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1142 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1143 NS_ASSERTION(mKeyRange, "This should never be null!");
michael@0 1144
michael@0 1145 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1146 "GetKeyHelper::PackArgumentsForParentProcess");
michael@0 1147
michael@0 1148 GetKeyParams params;
michael@0 1149
michael@0 1150 mKeyRange->ToSerializedKeyRange(params.keyRange());
michael@0 1151
michael@0 1152 aParams = params;
michael@0 1153 return NS_OK;
michael@0 1154 }
michael@0 1155
michael@0 1156 AsyncConnectionHelper::ChildProcessSendResult
michael@0 1157 GetKeyHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 1158 {
michael@0 1159 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1160 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1161
michael@0 1162 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1163 "GetKeyHelper::SendResponseToChildProcess");
michael@0 1164
michael@0 1165 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 1166 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 1167
michael@0 1168 ResponseValue response;
michael@0 1169 if (NS_FAILED(aResultCode)) {
michael@0 1170 response = aResultCode;
michael@0 1171 }
michael@0 1172 else {
michael@0 1173 GetKeyResponse getKeyResponse;
michael@0 1174 getKeyResponse.key() = mKey;
michael@0 1175 response = getKeyResponse;
michael@0 1176 }
michael@0 1177
michael@0 1178 if (!actor->SendResponse(response)) {
michael@0 1179 return Error;
michael@0 1180 }
michael@0 1181
michael@0 1182 return Success_Sent;
michael@0 1183 }
michael@0 1184
michael@0 1185 nsresult
michael@0 1186 GetKeyHelper::UnpackResponseFromParentProcess(
michael@0 1187 const ResponseValue& aResponseValue)
michael@0 1188 {
michael@0 1189 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetKeyResponse,
michael@0 1190 "Bad response type!");
michael@0 1191
michael@0 1192 mKey = aResponseValue.get_GetKeyResponse().key();
michael@0 1193 return NS_OK;
michael@0 1194 }
michael@0 1195
michael@0 1196 nsresult
michael@0 1197 GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
michael@0 1198 {
michael@0 1199 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 1200 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1201 NS_ASSERTION(mKeyRange, "Must have a key range here!");
michael@0 1202
michael@0 1203 PROFILER_LABEL("IndexedDB", "GetHelper::DoDatabaseWork [IDBIndex.cpp]");
michael@0 1204
michael@0 1205 nsCString indexTable;
michael@0 1206 if (mIndex->IsUnique()) {
michael@0 1207 indexTable.AssignLiteral("unique_index_data");
michael@0 1208 }
michael@0 1209 else {
michael@0 1210 indexTable.AssignLiteral("index_data");
michael@0 1211 }
michael@0 1212
michael@0 1213 nsCString keyRangeClause;
michael@0 1214 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
michael@0 1215
michael@0 1216 NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
michael@0 1217
michael@0 1218 nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
michael@0 1219 "INNER JOIN ") + indexTable +
michael@0 1220 NS_LITERAL_CSTRING(" AS index_table ON object_data.id = ") +
michael@0 1221 NS_LITERAL_CSTRING("index_table.object_data_id WHERE "
michael@0 1222 "index_id = :index_id") +
michael@0 1223 keyRangeClause +
michael@0 1224 NS_LITERAL_CSTRING(" LIMIT 1");
michael@0 1225
michael@0 1226 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
michael@0 1227 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1228
michael@0 1229 mozStorageStatementScoper scoper(stmt);
michael@0 1230
michael@0 1231 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
michael@0 1232 mIndex->Id());
michael@0 1233 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1234
michael@0 1235 rv = mKeyRange->BindToStatement(stmt);
michael@0 1236 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1237
michael@0 1238 bool hasResult;
michael@0 1239 rv = stmt->ExecuteStep(&hasResult);
michael@0 1240 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1241
michael@0 1242 if (hasResult) {
michael@0 1243 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
michael@0 1244 mDatabase, mCloneReadInfo);
michael@0 1245 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1246 }
michael@0 1247
michael@0 1248 return NS_OK;
michael@0 1249 }
michael@0 1250
michael@0 1251 nsresult
michael@0 1252 GetHelper::GetSuccessResult(JSContext* aCx,
michael@0 1253 JS::MutableHandle<JS::Value> aVal)
michael@0 1254 {
michael@0 1255 bool result = IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, aVal);
michael@0 1256
michael@0 1257 mCloneReadInfo.mCloneBuffer.clear();
michael@0 1258
michael@0 1259 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
michael@0 1260 return NS_OK;
michael@0 1261 }
michael@0 1262
michael@0 1263 void
michael@0 1264 GetHelper::ReleaseMainThreadObjects()
michael@0 1265 {
michael@0 1266 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
michael@0 1267 GetKeyHelper::ReleaseMainThreadObjects();
michael@0 1268 }
michael@0 1269
michael@0 1270 nsresult
michael@0 1271 GetHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 1272 {
michael@0 1273 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1274 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1275 NS_ASSERTION(mKeyRange, "This should never be null!");
michael@0 1276
michael@0 1277 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1278 "GetHelper::PackArgumentsForParentProcess "
michael@0 1279 "[IDBIndex.cpp]");
michael@0 1280
michael@0 1281 GetParams params;
michael@0 1282
michael@0 1283 mKeyRange->ToSerializedKeyRange(params.keyRange());
michael@0 1284
michael@0 1285 aParams = params;
michael@0 1286 return NS_OK;
michael@0 1287 }
michael@0 1288
michael@0 1289 AsyncConnectionHelper::ChildProcessSendResult
michael@0 1290 GetHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 1291 {
michael@0 1292 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1293 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1294
michael@0 1295 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1296 "GetHelper::SendResponseToChildProcess "
michael@0 1297 "[IDBIndex.cpp]");
michael@0 1298
michael@0 1299 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 1300 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 1301
michael@0 1302 InfallibleTArray<PBlobParent*> blobsParent;
michael@0 1303
michael@0 1304 if (NS_SUCCEEDED(aResultCode)) {
michael@0 1305 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
michael@0 1306 NS_ASSERTION(database, "This should never be null!");
michael@0 1307
michael@0 1308 ContentParent* contentParent = database->GetContentParent();
michael@0 1309 NS_ASSERTION(contentParent, "This should never be null!");
michael@0 1310
michael@0 1311 FileManager* fileManager = database->Manager();
michael@0 1312 NS_ASSERTION(fileManager, "This should never be null!");
michael@0 1313
michael@0 1314 const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
michael@0 1315
michael@0 1316 aResultCode =
michael@0 1317 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
michael@0 1318 blobsParent);
michael@0 1319 if (NS_FAILED(aResultCode)) {
michael@0 1320 NS_WARNING("ConvertBlobActors failed!");
michael@0 1321 }
michael@0 1322 }
michael@0 1323
michael@0 1324 ResponseValue response;
michael@0 1325 if (NS_FAILED(aResultCode)) {
michael@0 1326 response = aResultCode;
michael@0 1327 }
michael@0 1328 else {
michael@0 1329 GetResponse getResponse;
michael@0 1330 getResponse.cloneInfo() = mCloneReadInfo;
michael@0 1331 getResponse.blobsParent().SwapElements(blobsParent);
michael@0 1332 response = getResponse;
michael@0 1333 }
michael@0 1334
michael@0 1335 if (!actor->SendResponse(response)) {
michael@0 1336 return Error;
michael@0 1337 }
michael@0 1338
michael@0 1339 return Success_Sent;
michael@0 1340 }
michael@0 1341
michael@0 1342 nsresult
michael@0 1343 GetHelper::UnpackResponseFromParentProcess(const ResponseValue& aResponseValue)
michael@0 1344 {
michael@0 1345 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetResponse,
michael@0 1346 "Bad response type!");
michael@0 1347
michael@0 1348 const GetResponse& getResponse = aResponseValue.get_GetResponse();
michael@0 1349 const SerializedStructuredCloneReadInfo& cloneInfo = getResponse.cloneInfo();
michael@0 1350
michael@0 1351 NS_ASSERTION((!cloneInfo.dataLength && !cloneInfo.data) ||
michael@0 1352 (cloneInfo.dataLength && cloneInfo.data),
michael@0 1353 "Inconsistent clone info!");
michael@0 1354
michael@0 1355 if (!mCloneReadInfo.SetFromSerialized(cloneInfo)) {
michael@0 1356 IDB_WARNING("Failed to copy clone buffer!");
michael@0 1357 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1358 }
michael@0 1359
michael@0 1360 IDBObjectStore::ConvertActorsToBlobs(getResponse.blobsChild(),
michael@0 1361 mCloneReadInfo.mFiles);
michael@0 1362 return NS_OK;
michael@0 1363 }
michael@0 1364
michael@0 1365 nsresult
michael@0 1366 GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
michael@0 1367 {
michael@0 1368 MOZ_ASSERT(!NS_IsMainThread());
michael@0 1369 MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
michael@0 1370
michael@0 1371 PROFILER_LABEL("IndexedDB",
michael@0 1372 "GetAllKeysHelper::DoDatabaseWork [IDBIndex.cpp]");
michael@0 1373
michael@0 1374 nsCString tableName;
michael@0 1375 if (mIndex->IsUnique()) {
michael@0 1376 tableName.AssignLiteral("unique_index_data");
michael@0 1377 }
michael@0 1378 else {
michael@0 1379 tableName.AssignLiteral("index_data");
michael@0 1380 }
michael@0 1381
michael@0 1382 nsCString keyRangeClause;
michael@0 1383 if (mKeyRange) {
michael@0 1384 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
michael@0 1385 }
michael@0 1386
michael@0 1387 nsCString limitClause;
michael@0 1388 if (mLimit != UINT32_MAX) {
michael@0 1389 limitClause = NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1390 limitClause.AppendInt(mLimit);
michael@0 1391 }
michael@0 1392
michael@0 1393 nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
michael@0 1394 tableName +
michael@0 1395 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
michael@0 1396 keyRangeClause + limitClause;
michael@0 1397
michael@0 1398 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
michael@0 1399 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1400
michael@0 1401 mozStorageStatementScoper scoper(stmt);
michael@0 1402
michael@0 1403 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
michael@0 1404 mIndex->Id());
michael@0 1405 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1406
michael@0 1407 if (mKeyRange) {
michael@0 1408 rv = mKeyRange->BindToStatement(stmt);
michael@0 1409 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1410 }
michael@0 1411
michael@0 1412 mKeys.SetCapacity(std::min<uint32_t>(50, mLimit));
michael@0 1413
michael@0 1414 bool hasResult;
michael@0 1415 while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
michael@0 1416 if (mKeys.Capacity() == mKeys.Length()) {
michael@0 1417 mKeys.SetCapacity(mKeys.Capacity() * 2);
michael@0 1418 }
michael@0 1419
michael@0 1420 Key* key = mKeys.AppendElement();
michael@0 1421 NS_ASSERTION(key, "This shouldn't fail!");
michael@0 1422
michael@0 1423 rv = key->SetFromStatement(stmt, 0);
michael@0 1424 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1425 }
michael@0 1426 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1427
michael@0 1428 return NS_OK;
michael@0 1429 }
michael@0 1430
michael@0 1431 nsresult
michael@0 1432 GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
michael@0 1433 JS::MutableHandle<JS::Value> aVal)
michael@0 1434 {
michael@0 1435 MOZ_ASSERT(NS_IsMainThread());
michael@0 1436 MOZ_ASSERT(mKeys.Length() <= mLimit);
michael@0 1437
michael@0 1438 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1439 "GetAllKeysHelper::GetSuccessResult "
michael@0 1440 "[IDBIndex.cpp]");
michael@0 1441
michael@0 1442 nsTArray<Key> keys;
michael@0 1443 mKeys.SwapElements(keys);
michael@0 1444
michael@0 1445 JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
michael@0 1446 if (!array) {
michael@0 1447 IDB_WARNING("Failed to make array!");
michael@0 1448 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1449 }
michael@0 1450
michael@0 1451 if (!keys.IsEmpty()) {
michael@0 1452 if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
michael@0 1453 IDB_WARNING("Failed to set array length!");
michael@0 1454 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1455 }
michael@0 1456
michael@0 1457 for (uint32_t index = 0, count = keys.Length(); index < count; index++) {
michael@0 1458 const Key& key = keys[index];
michael@0 1459 NS_ASSERTION(!key.IsUnset(), "Bad key!");
michael@0 1460
michael@0 1461 JS::Rooted<JS::Value> value(aCx);
michael@0 1462 nsresult rv = key.ToJSVal(aCx, &value);
michael@0 1463 if (NS_FAILED(rv)) {
michael@0 1464 NS_WARNING("Failed to get jsval for key!");
michael@0 1465 return rv;
michael@0 1466 }
michael@0 1467
michael@0 1468 if (!JS_SetElement(aCx, array, index, value)) {
michael@0 1469 IDB_WARNING("Failed to set array element!");
michael@0 1470 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1471 }
michael@0 1472 }
michael@0 1473 }
michael@0 1474
michael@0 1475 aVal.setObject(*array);
michael@0 1476 return NS_OK;
michael@0 1477 }
michael@0 1478
michael@0 1479 nsresult
michael@0 1480 GetAllKeysHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 1481 {
michael@0 1482 MOZ_ASSERT(NS_IsMainThread());
michael@0 1483 MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
michael@0 1484
michael@0 1485 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1486 "GetAllKeysHelper::PackArgumentsForParentProcess "
michael@0 1487 "[IDBIndex.cpp]");
michael@0 1488
michael@0 1489 GetAllKeysParams params;
michael@0 1490
michael@0 1491 if (mKeyRange) {
michael@0 1492 KeyRange keyRange;
michael@0 1493 mKeyRange->ToSerializedKeyRange(keyRange);
michael@0 1494 params.optionalKeyRange() = keyRange;
michael@0 1495 }
michael@0 1496 else {
michael@0 1497 params.optionalKeyRange() = mozilla::void_t();
michael@0 1498 }
michael@0 1499
michael@0 1500 params.limit() = mLimit;
michael@0 1501
michael@0 1502 aParams = params;
michael@0 1503 return NS_OK;
michael@0 1504 }
michael@0 1505
michael@0 1506 AsyncConnectionHelper::ChildProcessSendResult
michael@0 1507 GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 1508 {
michael@0 1509 MOZ_ASSERT(NS_IsMainThread());
michael@0 1510 MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
michael@0 1511
michael@0 1512 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1513 "GetAllKeysHelper::SendResponseToChildProcess "
michael@0 1514 "[IDBIndex.cpp]");
michael@0 1515
michael@0 1516 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 1517 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 1518
michael@0 1519 ResponseValue response;
michael@0 1520 if (NS_FAILED(aResultCode)) {
michael@0 1521 response = aResultCode;
michael@0 1522 }
michael@0 1523 else {
michael@0 1524 GetAllKeysResponse getAllKeysResponse;
michael@0 1525 getAllKeysResponse.keys().AppendElements(mKeys);
michael@0 1526 response = getAllKeysResponse;
michael@0 1527 }
michael@0 1528
michael@0 1529 if (!actor->SendResponse(response)) {
michael@0 1530 return Error;
michael@0 1531 }
michael@0 1532
michael@0 1533 return Success_Sent;
michael@0 1534 }
michael@0 1535
michael@0 1536 nsresult
michael@0 1537 GetAllKeysHelper::UnpackResponseFromParentProcess(
michael@0 1538 const ResponseValue& aResponseValue)
michael@0 1539 {
michael@0 1540 MOZ_ASSERT(NS_IsMainThread());
michael@0 1541 MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
michael@0 1542 MOZ_ASSERT(aResponseValue.type() == ResponseValue::TGetAllKeysResponse);
michael@0 1543
michael@0 1544 mKeys.AppendElements(aResponseValue.get_GetAllKeysResponse().keys());
michael@0 1545 return NS_OK;
michael@0 1546 }
michael@0 1547
michael@0 1548 nsresult
michael@0 1549 GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
michael@0 1550 {
michael@0 1551 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 1552 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1553
michael@0 1554 PROFILER_LABEL("IndexedDB", "GetAllHelper::DoDatabaseWork [IDBIndex.cpp]");
michael@0 1555
michael@0 1556 nsCString indexTable;
michael@0 1557 if (mIndex->IsUnique()) {
michael@0 1558 indexTable.AssignLiteral("unique_index_data");
michael@0 1559 }
michael@0 1560 else {
michael@0 1561 indexTable.AssignLiteral("index_data");
michael@0 1562 }
michael@0 1563
michael@0 1564 nsCString keyRangeClause;
michael@0 1565 if (mKeyRange) {
michael@0 1566 mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
michael@0 1567 }
michael@0 1568
michael@0 1569 nsCString limitClause;
michael@0 1570 if (mLimit != UINT32_MAX) {
michael@0 1571 limitClause = NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1572 limitClause.AppendInt(mLimit);
michael@0 1573 }
michael@0 1574
michael@0 1575 nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
michael@0 1576 "INNER JOIN ") + indexTable +
michael@0 1577 NS_LITERAL_CSTRING(" AS index_table ON object_data.id = "
michael@0 1578 "index_table.object_data_id "
michael@0 1579 "WHERE index_id = :index_id") +
michael@0 1580 keyRangeClause + limitClause;
michael@0 1581
michael@0 1582 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
michael@0 1583 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1584
michael@0 1585 mozStorageStatementScoper scoper(stmt);
michael@0 1586
michael@0 1587 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
michael@0 1588 mIndex->Id());
michael@0 1589 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1590
michael@0 1591 if (mKeyRange) {
michael@0 1592 rv = mKeyRange->BindToStatement(stmt);
michael@0 1593 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1594 }
michael@0 1595
michael@0 1596 mCloneReadInfos.SetCapacity(50);
michael@0 1597
michael@0 1598 bool hasResult;
michael@0 1599 while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
michael@0 1600 if (mCloneReadInfos.Capacity() == mCloneReadInfos.Length()) {
michael@0 1601 mCloneReadInfos.SetCapacity(mCloneReadInfos.Capacity() * 2);
michael@0 1602 }
michael@0 1603
michael@0 1604 StructuredCloneReadInfo* readInfo = mCloneReadInfos.AppendElement();
michael@0 1605 NS_ASSERTION(readInfo, "This shouldn't fail!");
michael@0 1606
michael@0 1607 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 0, 1,
michael@0 1608 mDatabase, *readInfo);
michael@0 1609 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1610 }
michael@0 1611 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1612
michael@0 1613 return NS_OK;
michael@0 1614 }
michael@0 1615
michael@0 1616 nsresult
michael@0 1617 GetAllHelper::GetSuccessResult(JSContext* aCx,
michael@0 1618 JS::MutableHandle<JS::Value> aVal)
michael@0 1619 {
michael@0 1620 NS_ASSERTION(mCloneReadInfos.Length() <= mLimit, "Too many results!");
michael@0 1621
michael@0 1622 nsresult rv = ConvertToArrayAndCleanup(aCx, mCloneReadInfos, aVal);
michael@0 1623
michael@0 1624 NS_ASSERTION(mCloneReadInfos.IsEmpty(),
michael@0 1625 "Should have cleared in ConvertToArrayAndCleanup");
michael@0 1626 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1627
michael@0 1628 return NS_OK;
michael@0 1629 }
michael@0 1630
michael@0 1631 void
michael@0 1632 GetAllHelper::ReleaseMainThreadObjects()
michael@0 1633 {
michael@0 1634 for (uint32_t index = 0; index < mCloneReadInfos.Length(); index++) {
michael@0 1635 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfos[index]);
michael@0 1636 }
michael@0 1637 GetKeyHelper::ReleaseMainThreadObjects();
michael@0 1638 }
michael@0 1639
michael@0 1640 nsresult
michael@0 1641 GetAllHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 1642 {
michael@0 1643 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1644 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1645
michael@0 1646 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1647 "GetAllHelper::PackArgumentsForParentProcess "
michael@0 1648 "[IDBIndex.cpp]");
michael@0 1649
michael@0 1650 GetAllParams params;
michael@0 1651
michael@0 1652 if (mKeyRange) {
michael@0 1653 KeyRange keyRange;
michael@0 1654 mKeyRange->ToSerializedKeyRange(keyRange);
michael@0 1655 params.optionalKeyRange() = keyRange;
michael@0 1656 }
michael@0 1657 else {
michael@0 1658 params.optionalKeyRange() = mozilla::void_t();
michael@0 1659 }
michael@0 1660
michael@0 1661 params.limit() = mLimit;
michael@0 1662
michael@0 1663 aParams = params;
michael@0 1664 return NS_OK;
michael@0 1665 }
michael@0 1666
michael@0 1667 AsyncConnectionHelper::ChildProcessSendResult
michael@0 1668 GetAllHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 1669 {
michael@0 1670 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1671 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1672
michael@0 1673 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1674 "GetAllHelper::SendResponseToChildProcess "
michael@0 1675 "[IDBIndex.cpp]");
michael@0 1676
michael@0 1677 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 1678 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 1679
michael@0 1680 GetAllResponse getAllResponse;
michael@0 1681
michael@0 1682 if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
michael@0 1683 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
michael@0 1684 NS_ASSERTION(database, "This should never be null!");
michael@0 1685
michael@0 1686 ContentParent* contentParent = database->GetContentParent();
michael@0 1687 NS_ASSERTION(contentParent, "This should never be null!");
michael@0 1688
michael@0 1689 FileManager* fileManager = database->Manager();
michael@0 1690 NS_ASSERTION(fileManager, "This should never be null!");
michael@0 1691
michael@0 1692 uint32_t length = mCloneReadInfos.Length();
michael@0 1693
michael@0 1694 InfallibleTArray<SerializedStructuredCloneReadInfo>& infos =
michael@0 1695 getAllResponse.cloneInfos();
michael@0 1696 infos.SetCapacity(length);
michael@0 1697
michael@0 1698 InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
michael@0 1699 blobArrays.SetCapacity(length);
michael@0 1700
michael@0 1701 for (uint32_t index = 0;
michael@0 1702 NS_SUCCEEDED(aResultCode) && index < length;
michael@0 1703 index++) {
michael@0 1704 const StructuredCloneReadInfo& clone = mCloneReadInfos[index];
michael@0 1705
michael@0 1706 // Append the structured clone data.
michael@0 1707 SerializedStructuredCloneReadInfo* info = infos.AppendElement();
michael@0 1708 *info = clone;
michael@0 1709
michael@0 1710 const nsTArray<StructuredCloneFile>& files = clone.mFiles;
michael@0 1711
michael@0 1712 // Now take care of the files.
michael@0 1713 BlobArray* blobArray = blobArrays.AppendElement();
michael@0 1714
michael@0 1715 InfallibleTArray<PBlobParent*>& blobs = blobArray->blobsParent();
michael@0 1716
michael@0 1717 aResultCode =
michael@0 1718 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
michael@0 1719 blobs);
michael@0 1720 if (NS_FAILED(aResultCode)) {
michael@0 1721 NS_WARNING("ConvertBlobsToActors failed!");
michael@0 1722 break;
michael@0 1723 }
michael@0 1724 }
michael@0 1725 }
michael@0 1726
michael@0 1727 ResponseValue response;
michael@0 1728 if (NS_FAILED(aResultCode)) {
michael@0 1729 response = aResultCode;
michael@0 1730 }
michael@0 1731 else {
michael@0 1732 response = getAllResponse;
michael@0 1733 }
michael@0 1734
michael@0 1735 if (!actor->SendResponse(response)) {
michael@0 1736 return Error;
michael@0 1737 }
michael@0 1738
michael@0 1739 return Success_Sent;
michael@0 1740 }
michael@0 1741
michael@0 1742 nsresult
michael@0 1743 GetAllHelper::UnpackResponseFromParentProcess(
michael@0 1744 const ResponseValue& aResponseValue)
michael@0 1745 {
michael@0 1746 NS_ASSERTION(aResponseValue.type() == ResponseValue::TGetAllResponse,
michael@0 1747 "Bad response type!");
michael@0 1748
michael@0 1749 const GetAllResponse& getAllResponse = aResponseValue.get_GetAllResponse();
michael@0 1750 const InfallibleTArray<SerializedStructuredCloneReadInfo>& cloneInfos =
michael@0 1751 getAllResponse.cloneInfos();
michael@0 1752 const InfallibleTArray<BlobArray>& blobArrays = getAllResponse.blobs();
michael@0 1753
michael@0 1754 mCloneReadInfos.SetCapacity(cloneInfos.Length());
michael@0 1755
michael@0 1756 for (uint32_t index = 0; index < cloneInfos.Length(); index++) {
michael@0 1757 const SerializedStructuredCloneReadInfo srcInfo = cloneInfos[index];
michael@0 1758 const InfallibleTArray<PBlobChild*>& blobs = blobArrays[index].blobsChild();
michael@0 1759
michael@0 1760 StructuredCloneReadInfo* destInfo = mCloneReadInfos.AppendElement();
michael@0 1761 if (!destInfo->SetFromSerialized(srcInfo)) {
michael@0 1762 IDB_WARNING("Failed to copy clone buffer!");
michael@0 1763 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 1764 }
michael@0 1765
michael@0 1766 IDBObjectStore::ConvertActorsToBlobs(blobs, destInfo->mFiles);
michael@0 1767 }
michael@0 1768
michael@0 1769 return NS_OK;
michael@0 1770 }
michael@0 1771
michael@0 1772 nsresult
michael@0 1773 OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 1774 {
michael@0 1775 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 1776 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1777 NS_ASSERTION(aConnection, "Passed a null connection!");
michael@0 1778
michael@0 1779 PROFILER_LABEL("IndexedDB", "OpenKeyCursorHelper::DoDatabaseWork");
michael@0 1780
michael@0 1781 nsCString table;
michael@0 1782 if (mIndex->IsUnique()) {
michael@0 1783 table.AssignLiteral("unique_index_data");
michael@0 1784 }
michael@0 1785 else {
michael@0 1786 table.AssignLiteral("index_data");
michael@0 1787 }
michael@0 1788
michael@0 1789 NS_NAMED_LITERAL_CSTRING(value, "value");
michael@0 1790
michael@0 1791 nsCString keyRangeClause;
michael@0 1792 if (mKeyRange) {
michael@0 1793 mKeyRange->GetBindingClause(value, keyRangeClause);
michael@0 1794 }
michael@0 1795
michael@0 1796 nsAutoCString directionClause(" ORDER BY value ");
michael@0 1797 switch (mDirection) {
michael@0 1798 case IDBCursor::NEXT:
michael@0 1799 case IDBCursor::NEXT_UNIQUE:
michael@0 1800 directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
michael@0 1801 break;
michael@0 1802
michael@0 1803 case IDBCursor::PREV:
michael@0 1804 directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
michael@0 1805 break;
michael@0 1806
michael@0 1807 case IDBCursor::PREV_UNIQUE:
michael@0 1808 directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
michael@0 1809 break;
michael@0 1810
michael@0 1811 default:
michael@0 1812 NS_NOTREACHED("Unknown direction!");
michael@0 1813 }
michael@0 1814 nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
michael@0 1815 "FROM ") + table +
michael@0 1816 NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
michael@0 1817 keyRangeClause + directionClause +
michael@0 1818 NS_LITERAL_CSTRING(" LIMIT 1");
michael@0 1819
michael@0 1820 nsCOMPtr<mozIStorageStatement> stmt =
michael@0 1821 mTransaction->GetCachedStatement(firstQuery);
michael@0 1822 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1823
michael@0 1824 mozStorageStatementScoper scoper(stmt);
michael@0 1825
michael@0 1826 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
michael@0 1827 mIndex->Id());
michael@0 1828 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1829
michael@0 1830 if (mKeyRange) {
michael@0 1831 rv = mKeyRange->BindToStatement(stmt);
michael@0 1832 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1833 }
michael@0 1834
michael@0 1835 bool hasResult;
michael@0 1836 rv = stmt->ExecuteStep(&hasResult);
michael@0 1837 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1838
michael@0 1839 if (!hasResult) {
michael@0 1840 mKey.Unset();
michael@0 1841 return NS_OK;
michael@0 1842 }
michael@0 1843
michael@0 1844 rv = mKey.SetFromStatement(stmt, 0);
michael@0 1845 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1846
michael@0 1847 rv = mObjectKey.SetFromStatement(stmt, 1);
michael@0 1848 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1849
michael@0 1850 // Now we need to make the query to get the next match.
michael@0 1851 nsAutoCString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
michael@0 1852 " FROM ") + table +
michael@0 1853 NS_LITERAL_CSTRING(" WHERE index_id = :id");
michael@0 1854
michael@0 1855 NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
michael@0 1856
michael@0 1857 switch (mDirection) {
michael@0 1858 case IDBCursor::NEXT:
michael@0 1859 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
michael@0 1860 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
michael@0 1861 queryStart);
michael@0 1862 mRangeKey = mKeyRange->Upper();
michael@0 1863 }
michael@0 1864 mContinueQuery =
michael@0 1865 queryStart +
michael@0 1866 NS_LITERAL_CSTRING(" AND value >= :current_key AND "
michael@0 1867 "( value > :current_key OR "
michael@0 1868 " object_data_key > :object_key )") +
michael@0 1869 directionClause +
michael@0 1870 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1871 mContinueToQuery =
michael@0 1872 queryStart +
michael@0 1873 NS_LITERAL_CSTRING(" AND value >= :current_key ") +
michael@0 1874 directionClause +
michael@0 1875 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1876 break;
michael@0 1877
michael@0 1878 case IDBCursor::NEXT_UNIQUE:
michael@0 1879 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
michael@0 1880 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
michael@0 1881 queryStart);
michael@0 1882 mRangeKey = mKeyRange->Upper();
michael@0 1883 }
michael@0 1884 mContinueQuery =
michael@0 1885 queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
michael@0 1886 directionClause +
michael@0 1887 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1888 mContinueToQuery =
michael@0 1889 queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
michael@0 1890 directionClause +
michael@0 1891 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1892 break;
michael@0 1893
michael@0 1894 case IDBCursor::PREV:
michael@0 1895 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
michael@0 1896 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
michael@0 1897 queryStart);
michael@0 1898 mRangeKey = mKeyRange->Lower();
michael@0 1899 }
michael@0 1900
michael@0 1901 mContinueQuery =
michael@0 1902 queryStart +
michael@0 1903 NS_LITERAL_CSTRING(" AND value <= :current_key AND "
michael@0 1904 "( value < :current_key OR "
michael@0 1905 " object_data_key < :object_key )") +
michael@0 1906 directionClause +
michael@0 1907 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1908 mContinueToQuery =
michael@0 1909 queryStart +
michael@0 1910 NS_LITERAL_CSTRING(" AND value <= :current_key ") +
michael@0 1911 directionClause +
michael@0 1912 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1913 break;
michael@0 1914
michael@0 1915 case IDBCursor::PREV_UNIQUE:
michael@0 1916 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
michael@0 1917 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
michael@0 1918 queryStart);
michael@0 1919 mRangeKey = mKeyRange->Lower();
michael@0 1920 }
michael@0 1921 mContinueQuery =
michael@0 1922 queryStart +
michael@0 1923 NS_LITERAL_CSTRING(" AND value < :current_key") +
michael@0 1924 directionClause +
michael@0 1925 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1926 mContinueToQuery =
michael@0 1927 queryStart +
michael@0 1928 NS_LITERAL_CSTRING(" AND value <= :current_key") +
michael@0 1929 directionClause +
michael@0 1930 NS_LITERAL_CSTRING(" LIMIT ");
michael@0 1931 break;
michael@0 1932
michael@0 1933 default:
michael@0 1934 NS_NOTREACHED("Unknown direction type!");
michael@0 1935 }
michael@0 1936
michael@0 1937 return NS_OK;
michael@0 1938 }
michael@0 1939
michael@0 1940 nsresult
michael@0 1941 OpenKeyCursorHelper::EnsureCursor()
michael@0 1942 {
michael@0 1943 if (mCursor || mKey.IsUnset()) {
michael@0 1944 return NS_OK;
michael@0 1945 }
michael@0 1946
michael@0 1947 nsRefPtr<IDBCursor> cursor =
michael@0 1948 IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
michael@0 1949 mContinueQuery, mContinueToQuery, mKey, mObjectKey);
michael@0 1950 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1951
michael@0 1952 mCursor.swap(cursor);
michael@0 1953 return NS_OK;
michael@0 1954 }
michael@0 1955
michael@0 1956 nsresult
michael@0 1957 OpenKeyCursorHelper::GetSuccessResult(JSContext* aCx,
michael@0 1958 JS::MutableHandle<JS::Value> aVal)
michael@0 1959 {
michael@0 1960 nsresult rv = EnsureCursor();
michael@0 1961 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1962
michael@0 1963 if (mCursor) {
michael@0 1964 rv = WrapNative(aCx, mCursor, aVal);
michael@0 1965 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 1966 }
michael@0 1967 else {
michael@0 1968 aVal.setUndefined();
michael@0 1969 }
michael@0 1970
michael@0 1971 return NS_OK;
michael@0 1972 }
michael@0 1973
michael@0 1974 void
michael@0 1975 OpenKeyCursorHelper::ReleaseMainThreadObjects()
michael@0 1976 {
michael@0 1977 mKeyRange = nullptr;
michael@0 1978 mCursor = nullptr;
michael@0 1979 IndexHelper::ReleaseMainThreadObjects();
michael@0 1980 }
michael@0 1981
michael@0 1982 nsresult
michael@0 1983 OpenKeyCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 1984 {
michael@0 1985 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 1986 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 1987
michael@0 1988 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 1989 "OpenKeyCursorHelper::"
michael@0 1990 "PackArgumentsForParentProcess [IDBIndex.cpp]");
michael@0 1991
michael@0 1992 OpenKeyCursorParams params;
michael@0 1993
michael@0 1994 if (mKeyRange) {
michael@0 1995 KeyRange keyRange;
michael@0 1996 mKeyRange->ToSerializedKeyRange(keyRange);
michael@0 1997 params.optionalKeyRange() = keyRange;
michael@0 1998 }
michael@0 1999 else {
michael@0 2000 params.optionalKeyRange() = mozilla::void_t();
michael@0 2001 }
michael@0 2002
michael@0 2003 params.direction() = mDirection;
michael@0 2004
michael@0 2005 aParams = params;
michael@0 2006 return NS_OK;
michael@0 2007 }
michael@0 2008
michael@0 2009 AsyncConnectionHelper::ChildProcessSendResult
michael@0 2010 OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 2011 {
michael@0 2012 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 2013 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2014 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
michael@0 2015
michael@0 2016 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 2017 "OpenKeyCursorHelper::SendResponseToChildProcess");
michael@0 2018
michael@0 2019 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 2020 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 2021
michael@0 2022 if (NS_SUCCEEDED(aResultCode)) {
michael@0 2023 nsresult rv = EnsureCursor();
michael@0 2024 if (NS_FAILED(rv)) {
michael@0 2025 NS_WARNING("EnsureCursor failed!");
michael@0 2026 aResultCode = rv;
michael@0 2027 }
michael@0 2028 }
michael@0 2029
michael@0 2030 ResponseValue response;
michael@0 2031 if (NS_FAILED(aResultCode)) {
michael@0 2032 response = aResultCode;
michael@0 2033 }
michael@0 2034 else {
michael@0 2035 OpenCursorResponse openCursorResponse;
michael@0 2036
michael@0 2037 if (!mCursor) {
michael@0 2038 openCursorResponse = mozilla::void_t();
michael@0 2039 }
michael@0 2040 else {
michael@0 2041 IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
michael@0 2042 NS_ASSERTION(indexActor, "Must have an actor here!");
michael@0 2043
michael@0 2044 IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
michael@0 2045 NS_ASSERTION(requestActor, "Must have an actor here!");
michael@0 2046
michael@0 2047 IndexCursorConstructorParams params;
michael@0 2048 params.requestParent() = requestActor;
michael@0 2049 params.direction() = mDirection;
michael@0 2050 params.key() = mKey;
michael@0 2051 params.objectKey() = mObjectKey;
michael@0 2052 params.optionalCloneInfo() = mozilla::void_t();
michael@0 2053
michael@0 2054 if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
michael@0 2055 return Error;
michael@0 2056 }
michael@0 2057 }
michael@0 2058
michael@0 2059 response = openCursorResponse;
michael@0 2060 }
michael@0 2061
michael@0 2062 if (!actor->SendResponse(response)) {
michael@0 2063 return Error;
michael@0 2064 }
michael@0 2065
michael@0 2066 return Success_Sent;
michael@0 2067 }
michael@0 2068
michael@0 2069 nsresult
michael@0 2070 OpenKeyCursorHelper::UnpackResponseFromParentProcess(
michael@0 2071 const ResponseValue& aResponseValue)
michael@0 2072 {
michael@0 2073 NS_ASSERTION(aResponseValue.type() == ResponseValue::TOpenCursorResponse,
michael@0 2074 "Bad response type!");
michael@0 2075 NS_ASSERTION(aResponseValue.get_OpenCursorResponse().type() ==
michael@0 2076 OpenCursorResponse::Tvoid_t ||
michael@0 2077 aResponseValue.get_OpenCursorResponse().type() ==
michael@0 2078 OpenCursorResponse::TPIndexedDBCursorChild,
michael@0 2079 "Bad response union type!");
michael@0 2080 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
michael@0 2081
michael@0 2082 const OpenCursorResponse& response =
michael@0 2083 aResponseValue.get_OpenCursorResponse();
michael@0 2084
michael@0 2085 switch (response.type()) {
michael@0 2086 case OpenCursorResponse::Tvoid_t:
michael@0 2087 break;
michael@0 2088
michael@0 2089 case OpenCursorResponse::TPIndexedDBCursorChild: {
michael@0 2090 IndexedDBCursorChild* actor =
michael@0 2091 static_cast<IndexedDBCursorChild*>(
michael@0 2092 response.get_PIndexedDBCursorChild());
michael@0 2093
michael@0 2094 mCursor = actor->ForgetStrongCursor();
michael@0 2095 NS_ASSERTION(mCursor, "This should never be null!");
michael@0 2096
michael@0 2097 } break;
michael@0 2098
michael@0 2099 default:
michael@0 2100 MOZ_CRASH();
michael@0 2101 }
michael@0 2102
michael@0 2103 return NS_OK;
michael@0 2104 }
michael@0 2105
michael@0 2106 nsresult
michael@0 2107 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 2108 {
michael@0 2109 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 2110 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2111 NS_ASSERTION(aConnection, "Passed a null connection!");
michael@0 2112
michael@0 2113 PROFILER_LABEL("IndexedDB",
michael@0 2114 "OpenCursorHelper::DoDatabaseWork [IDBIndex.cpp]");
michael@0 2115
michael@0 2116 nsCString indexTable;
michael@0 2117 if (mIndex->IsUnique()) {
michael@0 2118 indexTable.AssignLiteral("unique_index_data");
michael@0 2119 }
michael@0 2120 else {
michael@0 2121 indexTable.AssignLiteral("index_data");
michael@0 2122 }
michael@0 2123
michael@0 2124 NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
michael@0 2125
michael@0 2126 nsCString keyRangeClause;
michael@0 2127 if (mKeyRange) {
michael@0 2128 mKeyRange->GetBindingClause(value, keyRangeClause);
michael@0 2129 }
michael@0 2130
michael@0 2131 nsAutoCString directionClause(" ORDER BY index_table.value ");
michael@0 2132 switch (mDirection) {
michael@0 2133 case IDBCursor::NEXT:
michael@0 2134 case IDBCursor::NEXT_UNIQUE:
michael@0 2135 directionClause +=
michael@0 2136 NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
michael@0 2137 break;
michael@0 2138
michael@0 2139 case IDBCursor::PREV:
michael@0 2140 directionClause +=
michael@0 2141 NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
michael@0 2142 break;
michael@0 2143
michael@0 2144 case IDBCursor::PREV_UNIQUE:
michael@0 2145 directionClause +=
michael@0 2146 NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
michael@0 2147 break;
michael@0 2148
michael@0 2149 default:
michael@0 2150 NS_NOTREACHED("Unknown direction!");
michael@0 2151 }
michael@0 2152
michael@0 2153 nsCString firstQuery =
michael@0 2154 NS_LITERAL_CSTRING("SELECT index_table.value, "
michael@0 2155 "index_table.object_data_key, object_data.data, "
michael@0 2156 "object_data.file_ids FROM ") +
michael@0 2157 indexTable +
michael@0 2158 NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
michael@0 2159 "index_table.object_data_id = object_data.id "
michael@0 2160 "WHERE index_table.index_id = :id") +
michael@0 2161 keyRangeClause + directionClause +
michael@0 2162 NS_LITERAL_CSTRING(" LIMIT 1");
michael@0 2163
michael@0 2164 nsCOMPtr<mozIStorageStatement> stmt =
michael@0 2165 mTransaction->GetCachedStatement(firstQuery);
michael@0 2166 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2167
michael@0 2168 mozStorageStatementScoper scoper(stmt);
michael@0 2169
michael@0 2170 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
michael@0 2171 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2172
michael@0 2173 if (mKeyRange) {
michael@0 2174 rv = mKeyRange->BindToStatement(stmt);
michael@0 2175 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2176 }
michael@0 2177
michael@0 2178 bool hasResult;
michael@0 2179 rv = stmt->ExecuteStep(&hasResult);
michael@0 2180 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2181
michael@0 2182 if (!hasResult) {
michael@0 2183 mKey.Unset();
michael@0 2184 return NS_OK;
michael@0 2185 }
michael@0 2186
michael@0 2187 rv = mKey.SetFromStatement(stmt, 0);
michael@0 2188 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2189
michael@0 2190 rv = mObjectKey.SetFromStatement(stmt, 1);
michael@0 2191 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2192
michael@0 2193 rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 2, 3,
michael@0 2194 mDatabase, mCloneReadInfo);
michael@0 2195 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2196
michael@0 2197 // Now we need to make the query to get the next match.
michael@0 2198 nsAutoCString queryStart =
michael@0 2199 NS_LITERAL_CSTRING("SELECT index_table.value, "
michael@0 2200 "index_table.object_data_key, object_data.data, "
michael@0 2201 "object_data.file_ids FROM ") +
michael@0 2202 indexTable +
michael@0 2203 NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
michael@0 2204 "index_table.object_data_id = object_data.id "
michael@0 2205 "WHERE index_table.index_id = :id");
michael@0 2206
michael@0 2207 NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
michael@0 2208
michael@0 2209 NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
michael@0 2210
michael@0 2211 switch (mDirection) {
michael@0 2212 case IDBCursor::NEXT:
michael@0 2213 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
michael@0 2214 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
michael@0 2215 queryStart);
michael@0 2216 mRangeKey = mKeyRange->Upper();
michael@0 2217 }
michael@0 2218 mContinueQuery =
michael@0 2219 queryStart +
michael@0 2220 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
michael@0 2221 "( index_table.value > :current_key OR "
michael@0 2222 " index_table.object_data_key > :object_key ) ") +
michael@0 2223 directionClause + limit;
michael@0 2224 mContinueToQuery =
michael@0 2225 queryStart +
michael@0 2226 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
michael@0 2227 directionClause + limit;
michael@0 2228 break;
michael@0 2229
michael@0 2230 case IDBCursor::NEXT_UNIQUE:
michael@0 2231 if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
michael@0 2232 AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
michael@0 2233 queryStart);
michael@0 2234 mRangeKey = mKeyRange->Upper();
michael@0 2235 }
michael@0 2236 mContinueQuery =
michael@0 2237 queryStart +
michael@0 2238 NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
michael@0 2239 directionClause + limit;
michael@0 2240 mContinueToQuery =
michael@0 2241 queryStart +
michael@0 2242 NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
michael@0 2243 directionClause + limit;
michael@0 2244 break;
michael@0 2245
michael@0 2246 case IDBCursor::PREV:
michael@0 2247 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
michael@0 2248 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
michael@0 2249 queryStart);
michael@0 2250 mRangeKey = mKeyRange->Lower();
michael@0 2251 }
michael@0 2252 mContinueQuery =
michael@0 2253 queryStart +
michael@0 2254 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
michael@0 2255 "( index_table.value < :current_key OR "
michael@0 2256 " index_table.object_data_key < :object_key ) ") +
michael@0 2257 directionClause + limit;
michael@0 2258 mContinueToQuery =
michael@0 2259 queryStart +
michael@0 2260 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
michael@0 2261 directionClause + limit;
michael@0 2262 break;
michael@0 2263
michael@0 2264 case IDBCursor::PREV_UNIQUE:
michael@0 2265 if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
michael@0 2266 AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
michael@0 2267 queryStart);
michael@0 2268 mRangeKey = mKeyRange->Lower();
michael@0 2269 }
michael@0 2270 mContinueQuery =
michael@0 2271 queryStart +
michael@0 2272 NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
michael@0 2273 directionClause + limit;
michael@0 2274 mContinueToQuery =
michael@0 2275 queryStart +
michael@0 2276 NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
michael@0 2277 directionClause + limit;
michael@0 2278 break;
michael@0 2279
michael@0 2280 default:
michael@0 2281 NS_NOTREACHED("Unknown direction type!");
michael@0 2282 }
michael@0 2283
michael@0 2284 return NS_OK;
michael@0 2285 }
michael@0 2286
michael@0 2287 nsresult
michael@0 2288 OpenCursorHelper::EnsureCursor()
michael@0 2289 {
michael@0 2290 if (mCursor || mKey.IsUnset()) {
michael@0 2291 return NS_OK;
michael@0 2292 }
michael@0 2293
michael@0 2294 mSerializedCloneReadInfo = mCloneReadInfo;
michael@0 2295
michael@0 2296 NS_ASSERTION(mSerializedCloneReadInfo.data &&
michael@0 2297 mSerializedCloneReadInfo.dataLength,
michael@0 2298 "Shouldn't be possible!");
michael@0 2299
michael@0 2300 nsRefPtr<IDBCursor> cursor =
michael@0 2301 IDBCursor::Create(mRequest, mTransaction, mIndex, mDirection, mRangeKey,
michael@0 2302 mContinueQuery, mContinueToQuery, mKey, mObjectKey,
michael@0 2303 Move(mCloneReadInfo));
michael@0 2304 IDB_ENSURE_TRUE(cursor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2305
michael@0 2306 NS_ASSERTION(!mCloneReadInfo.mCloneBuffer.data(), "Should have swapped!");
michael@0 2307
michael@0 2308 mCursor.swap(cursor);
michael@0 2309 return NS_OK;
michael@0 2310 }
michael@0 2311
michael@0 2312 void
michael@0 2313 OpenCursorHelper::ReleaseMainThreadObjects()
michael@0 2314 {
michael@0 2315 IDBObjectStore::ClearCloneReadInfo(mCloneReadInfo);
michael@0 2316
michael@0 2317 // These don't need to be released on the main thread but they're only valid
michael@0 2318 // as long as mCursor is set.
michael@0 2319 mSerializedCloneReadInfo.data = nullptr;
michael@0 2320 mSerializedCloneReadInfo.dataLength = 0;
michael@0 2321
michael@0 2322 OpenKeyCursorHelper::ReleaseMainThreadObjects();
michael@0 2323 }
michael@0 2324
michael@0 2325 nsresult
michael@0 2326 OpenCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 2327 {
michael@0 2328 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 2329 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2330
michael@0 2331 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 2332 "OpenCursorHelper::PackArgumentsForParentProcess "
michael@0 2333 "[IDBIndex.cpp]");
michael@0 2334
michael@0 2335 OpenCursorParams params;
michael@0 2336
michael@0 2337 if (mKeyRange) {
michael@0 2338 KeyRange keyRange;
michael@0 2339 mKeyRange->ToSerializedKeyRange(keyRange);
michael@0 2340 params.optionalKeyRange() = keyRange;
michael@0 2341 }
michael@0 2342 else {
michael@0 2343 params.optionalKeyRange() = mozilla::void_t();
michael@0 2344 }
michael@0 2345
michael@0 2346 params.direction() = mDirection;
michael@0 2347
michael@0 2348 aParams = params;
michael@0 2349 return NS_OK;
michael@0 2350 }
michael@0 2351
michael@0 2352 AsyncConnectionHelper::ChildProcessSendResult
michael@0 2353 OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 2354 {
michael@0 2355 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 2356 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2357 NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
michael@0 2358
michael@0 2359 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 2360 "OpenCursorHelper::SendResponseToChildProcess "
michael@0 2361 "[IDBIndex.cpp]");
michael@0 2362
michael@0 2363 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 2364 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 2365
michael@0 2366 InfallibleTArray<PBlobParent*> blobsParent;
michael@0 2367
michael@0 2368 if (NS_SUCCEEDED(aResultCode)) {
michael@0 2369 IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
michael@0 2370 NS_ASSERTION(database, "This should never be null!");
michael@0 2371
michael@0 2372 ContentParent* contentParent = database->GetContentParent();
michael@0 2373 NS_ASSERTION(contentParent, "This should never be null!");
michael@0 2374
michael@0 2375 FileManager* fileManager = database->Manager();
michael@0 2376 NS_ASSERTION(fileManager, "This should never be null!");
michael@0 2377
michael@0 2378 const nsTArray<StructuredCloneFile>& files = mCloneReadInfo.mFiles;
michael@0 2379
michael@0 2380 aResultCode =
michael@0 2381 IDBObjectStore::ConvertBlobsToActors(contentParent, fileManager, files,
michael@0 2382 blobsParent);
michael@0 2383 if (NS_FAILED(aResultCode)) {
michael@0 2384 NS_WARNING("ConvertBlobsToActors failed!");
michael@0 2385 }
michael@0 2386 }
michael@0 2387
michael@0 2388 if (NS_SUCCEEDED(aResultCode)) {
michael@0 2389 nsresult rv = EnsureCursor();
michael@0 2390 if (NS_FAILED(rv)) {
michael@0 2391 NS_WARNING("EnsureCursor failed!");
michael@0 2392 aResultCode = rv;
michael@0 2393 }
michael@0 2394 }
michael@0 2395
michael@0 2396 ResponseValue response;
michael@0 2397 if (NS_FAILED(aResultCode)) {
michael@0 2398 response = aResultCode;
michael@0 2399 }
michael@0 2400 else {
michael@0 2401 OpenCursorResponse openCursorResponse;
michael@0 2402
michael@0 2403 if (!mCursor) {
michael@0 2404 openCursorResponse = mozilla::void_t();
michael@0 2405 }
michael@0 2406 else {
michael@0 2407 IndexedDBIndexParent* indexActor = mIndex->GetActorParent();
michael@0 2408 NS_ASSERTION(indexActor, "Must have an actor here!");
michael@0 2409
michael@0 2410 IndexedDBRequestParentBase* requestActor = mRequest->GetActorParent();
michael@0 2411 NS_ASSERTION(requestActor, "Must have an actor here!");
michael@0 2412
michael@0 2413 NS_ASSERTION(mSerializedCloneReadInfo.data &&
michael@0 2414 mSerializedCloneReadInfo.dataLength,
michael@0 2415 "Shouldn't be possible!");
michael@0 2416
michael@0 2417 IndexCursorConstructorParams params;
michael@0 2418 params.requestParent() = requestActor;
michael@0 2419 params.direction() = mDirection;
michael@0 2420 params.key() = mKey;
michael@0 2421 params.objectKey() = mObjectKey;
michael@0 2422 params.optionalCloneInfo() = mSerializedCloneReadInfo;
michael@0 2423 params.blobsParent().SwapElements(blobsParent);
michael@0 2424
michael@0 2425 if (!indexActor->OpenCursor(mCursor, params, openCursorResponse)) {
michael@0 2426 return Error;
michael@0 2427 }
michael@0 2428 }
michael@0 2429
michael@0 2430 response = openCursorResponse;
michael@0 2431 }
michael@0 2432
michael@0 2433 if (!actor->SendResponse(response)) {
michael@0 2434 return Error;
michael@0 2435 }
michael@0 2436
michael@0 2437 return Success_Sent;
michael@0 2438 }
michael@0 2439
michael@0 2440 nsresult
michael@0 2441 CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
michael@0 2442 {
michael@0 2443 NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 2444 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2445
michael@0 2446 PROFILER_LABEL("IndexedDB", "CountHelper::DoDatabaseWork [IDBIndex.cpp]");
michael@0 2447
michael@0 2448 nsCString table;
michael@0 2449 if (mIndex->IsUnique()) {
michael@0 2450 table.AssignLiteral("unique_index_data");
michael@0 2451 }
michael@0 2452 else {
michael@0 2453 table.AssignLiteral("index_data");
michael@0 2454 }
michael@0 2455
michael@0 2456 NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
michael@0 2457 NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
michael@0 2458 NS_NAMED_LITERAL_CSTRING(value, "value");
michael@0 2459
michael@0 2460 nsAutoCString keyRangeClause;
michael@0 2461 if (mKeyRange) {
michael@0 2462 if (!mKeyRange->Lower().IsUnset()) {
michael@0 2463 AppendConditionClause(value, lowerKeyName, false,
michael@0 2464 !mKeyRange->IsLowerOpen(), keyRangeClause);
michael@0 2465 }
michael@0 2466 if (!mKeyRange->Upper().IsUnset()) {
michael@0 2467 AppendConditionClause(value, upperKeyName, true,
michael@0 2468 !mKeyRange->IsUpperOpen(), keyRangeClause);
michael@0 2469 }
michael@0 2470 }
michael@0 2471
michael@0 2472 nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
michael@0 2473 NS_LITERAL_CSTRING(" WHERE index_id = :id") +
michael@0 2474 keyRangeClause;
michael@0 2475
michael@0 2476 nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
michael@0 2477 IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2478
michael@0 2479 mozStorageStatementScoper scoper(stmt);
michael@0 2480
michael@0 2481 nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
michael@0 2482 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2483
michael@0 2484 if (mKeyRange) {
michael@0 2485 if (!mKeyRange->Lower().IsUnset()) {
michael@0 2486 rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
michael@0 2487 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2488 }
michael@0 2489 if (!mKeyRange->Upper().IsUnset()) {
michael@0 2490 rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
michael@0 2491 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2492 }
michael@0 2493 }
michael@0 2494
michael@0 2495 bool hasResult;
michael@0 2496 rv = stmt->ExecuteStep(&hasResult);
michael@0 2497 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2498 IDB_ENSURE_TRUE(hasResult, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 2499
michael@0 2500 mCount = stmt->AsInt64(0);
michael@0 2501 return NS_OK;
michael@0 2502 }
michael@0 2503
michael@0 2504 nsresult
michael@0 2505 CountHelper::GetSuccessResult(JSContext* aCx,
michael@0 2506 JS::MutableHandle<JS::Value> aVal)
michael@0 2507 {
michael@0 2508 aVal.setNumber(static_cast<double>(mCount));
michael@0 2509 return NS_OK;
michael@0 2510 }
michael@0 2511
michael@0 2512 void
michael@0 2513 CountHelper::ReleaseMainThreadObjects()
michael@0 2514 {
michael@0 2515 mKeyRange = nullptr;
michael@0 2516 IndexHelper::ReleaseMainThreadObjects();
michael@0 2517 }
michael@0 2518
michael@0 2519 nsresult
michael@0 2520 CountHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
michael@0 2521 {
michael@0 2522 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 2523 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2524
michael@0 2525 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 2526 "CountHelper::PackArgumentsForParentProcess "
michael@0 2527 "[IDBIndex.cpp]");
michael@0 2528
michael@0 2529 CountParams params;
michael@0 2530
michael@0 2531 if (mKeyRange) {
michael@0 2532 KeyRange keyRange;
michael@0 2533 mKeyRange->ToSerializedKeyRange(keyRange);
michael@0 2534 params.optionalKeyRange() = keyRange;
michael@0 2535 }
michael@0 2536 else {
michael@0 2537 params.optionalKeyRange() = mozilla::void_t();
michael@0 2538 }
michael@0 2539
michael@0 2540 aParams = params;
michael@0 2541 return NS_OK;
michael@0 2542 }
michael@0 2543
michael@0 2544 AsyncConnectionHelper::ChildProcessSendResult
michael@0 2545 CountHelper::SendResponseToChildProcess(nsresult aResultCode)
michael@0 2546 {
michael@0 2547 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 2548 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 2549
michael@0 2550 PROFILER_MAIN_THREAD_LABEL("IndexedDB",
michael@0 2551 "CountHelper::SendResponseToChildProcess "
michael@0 2552 "[IDBIndex.cpp]");
michael@0 2553
michael@0 2554 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 2555 NS_ASSERTION(actor, "How did we get this far without an actor?");
michael@0 2556
michael@0 2557 ResponseValue response;
michael@0 2558 if (NS_FAILED(aResultCode)) {
michael@0 2559 response = aResultCode;
michael@0 2560 }
michael@0 2561 else {
michael@0 2562 CountResponse countResponse = mCount;
michael@0 2563 response = countResponse;
michael@0 2564 }
michael@0 2565
michael@0 2566 if (!actor->SendResponse(response)) {
michael@0 2567 return Error;
michael@0 2568 }
michael@0 2569
michael@0 2570 return Success_Sent;
michael@0 2571 }
michael@0 2572
michael@0 2573 nsresult
michael@0 2574 CountHelper::UnpackResponseFromParentProcess(
michael@0 2575 const ResponseValue& aResponseValue)
michael@0 2576 {
michael@0 2577 NS_ASSERTION(aResponseValue.type() == ResponseValue::TCountResponse,
michael@0 2578 "Bad response type!");
michael@0 2579
michael@0 2580 mCount = aResponseValue.get_CountResponse().count();
michael@0 2581 return NS_OK;
michael@0 2582 }

mercurial