Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/indexedDB/IDBIndex.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "IDBIndex.h"
8
9
#include "FileInfo.h"
10
#include "IDBCursor.h"
11
#include "IDBEvents.h"
12
#include "IDBKeyRange.h"
13
#include "IDBObjectStore.h"
14
#include "IDBRequest.h"
15
#include "IDBTransaction.h"
16
#include "IndexedDatabase.h"
17
#include "IndexedDatabaseInlines.h"
18
#include "mozilla/ErrorResult.h"
19
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
20
#include "ProfilerHelpers.h"
21
#include "ReportInternalError.h"
22
23
// Include this last to avoid path problems on Windows.
24
#include "ActorsChild.h"
25
26
namespace mozilla {
27
namespace dom {
28
29
using namespace mozilla::dom::indexedDB;
30
31
namespace {
32
33
already_AddRefed<IDBRequest>
34
GenerateRequest(JSContext* aCx, IDBIndex* aIndex)
35
0
{
36
0
  MOZ_ASSERT(aIndex);
37
0
  aIndex->AssertIsOnOwningThread();
38
0
39
0
  IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
40
0
41
0
  RefPtr<IDBRequest> request =
42
0
    IDBRequest::Create(aCx, aIndex, transaction->Database(), transaction);
43
0
  MOZ_ASSERT(request);
44
0
45
0
  return request.forget();
46
0
}
47
48
} // namespace
49
50
IDBIndex::IDBIndex(IDBObjectStore* aObjectStore, const IndexMetadata* aMetadata)
51
  : mObjectStore(aObjectStore)
52
  , mCachedKeyPath(JS::UndefinedValue())
53
  , mMetadata(aMetadata)
54
  , mId(aMetadata->id())
55
  , mRooted(false)
56
0
{
57
0
  MOZ_ASSERT(aObjectStore);
58
0
  aObjectStore->AssertIsOnOwningThread();
59
0
  MOZ_ASSERT(aMetadata);
60
0
}
61
62
IDBIndex::~IDBIndex()
63
0
{
64
0
  AssertIsOnOwningThread();
65
0
66
0
  if (mRooted) {
67
0
    mCachedKeyPath.setUndefined();
68
0
    mozilla::DropJSObjects(this);
69
0
  }
70
0
}
71
72
already_AddRefed<IDBIndex>
73
IDBIndex::Create(IDBObjectStore* aObjectStore,
74
                 const IndexMetadata& aMetadata)
75
0
{
76
0
  MOZ_ASSERT(aObjectStore);
77
0
  aObjectStore->AssertIsOnOwningThread();
78
0
79
0
  RefPtr<IDBIndex> index = new IDBIndex(aObjectStore, &aMetadata);
80
0
81
0
  return index.forget();
82
0
}
83
84
#ifdef DEBUG
85
86
void
87
IDBIndex::AssertIsOnOwningThread() const
88
{
89
  MOZ_ASSERT(mObjectStore);
90
  mObjectStore->AssertIsOnOwningThread();
91
}
92
93
#endif // DEBUG
94
95
void
96
IDBIndex::RefreshMetadata(bool aMayDelete)
97
0
{
98
0
  AssertIsOnOwningThread();
99
0
  MOZ_ASSERT_IF(mDeletedMetadata, mMetadata == mDeletedMetadata);
100
0
101
0
  const nsTArray<IndexMetadata>& indexes = mObjectStore->Spec().indexes();
102
0
103
0
  bool found = false;
104
0
105
0
  for (uint32_t count = indexes.Length(), index = 0;
106
0
       index < count;
107
0
       index++) {
108
0
    const IndexMetadata& metadata = indexes[index];
109
0
110
0
    if (metadata.id() == Id()) {
111
0
      mMetadata = &metadata;
112
0
113
0
      found = true;
114
0
      break;
115
0
    }
116
0
  }
117
0
118
0
  MOZ_ASSERT_IF(!aMayDelete && !mDeletedMetadata, found);
119
0
120
0
  if (found) {
121
0
    MOZ_ASSERT(mMetadata != mDeletedMetadata);
122
0
    mDeletedMetadata = nullptr;
123
0
  } else {
124
0
    NoteDeletion();
125
0
  }
126
0
}
127
128
void
129
IDBIndex::NoteDeletion()
130
0
{
131
0
  AssertIsOnOwningThread();
132
0
  MOZ_ASSERT(mMetadata);
133
0
  MOZ_ASSERT(Id() == mMetadata->id());
134
0
135
0
  if (mDeletedMetadata) {
136
0
    MOZ_ASSERT(mMetadata == mDeletedMetadata);
137
0
    return;
138
0
  }
139
0
140
0
  mDeletedMetadata = new IndexMetadata(*mMetadata);
141
0
142
0
  mMetadata = mDeletedMetadata;
143
0
}
144
145
const nsString&
146
IDBIndex::Name() const
147
0
{
148
0
  AssertIsOnOwningThread();
149
0
  MOZ_ASSERT(mMetadata);
150
0
151
0
  return mMetadata->name();
152
0
}
153
154
void
155
IDBIndex::SetName(const nsAString& aName, ErrorResult& aRv)
156
0
{
157
0
  AssertIsOnOwningThread();
158
0
159
0
  IDBTransaction* transaction = mObjectStore->Transaction();
160
0
161
0
  if (transaction->GetMode() != IDBTransaction::VERSION_CHANGE ||
162
0
      mDeletedMetadata) {
163
0
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
164
0
    return;
165
0
  }
166
0
167
0
  if (!transaction->IsOpen()) {
168
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
169
0
    return;
170
0
  }
171
0
172
0
  if (aName == mMetadata->name()) {
173
0
    return;
174
0
  }
175
0
176
0
  // Cache logging string of this index before renaming.
177
0
  const LoggingString loggingOldIndex(this);
178
0
179
0
  const int64_t indexId = Id();
180
0
181
0
  nsresult rv =
182
0
    transaction->Database()->RenameIndex(mObjectStore->Id(),
183
0
                                         indexId,
184
0
                                         aName);
185
0
186
0
  if (NS_FAILED(rv)) {
187
0
    aRv.Throw(rv);
188
0
    return;
189
0
  }
190
0
191
0
  // Don't do this in the macro because we always need to increment the serial
192
0
  // number to keep in sync with the parent.
193
0
  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
194
0
195
0
  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
196
0
                 "database(%s).transaction(%s).objectStore(%s).index(%s)."
197
0
                 "rename(%s)",
198
0
               "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.rename()",
199
0
               IDB_LOG_ID_STRING(),
200
0
               transaction->LoggingSerialNumber(),
201
0
               requestSerialNumber,
202
0
               IDB_LOG_STRINGIFY(transaction->Database()),
203
0
               IDB_LOG_STRINGIFY(transaction),
204
0
               IDB_LOG_STRINGIFY(mObjectStore),
205
0
               loggingOldIndex.get(),
206
0
               IDB_LOG_STRINGIFY(this));
207
0
208
0
  transaction->RenameIndex(mObjectStore, indexId, aName);
209
0
}
210
211
bool
212
IDBIndex::Unique() const
213
0
{
214
0
  AssertIsOnOwningThread();
215
0
  MOZ_ASSERT(mMetadata);
216
0
217
0
  return mMetadata->unique();
218
0
}
219
220
bool
221
IDBIndex::MultiEntry() const
222
0
{
223
0
  AssertIsOnOwningThread();
224
0
  MOZ_ASSERT(mMetadata);
225
0
226
0
  return mMetadata->multiEntry();
227
0
}
228
229
bool
230
IDBIndex::LocaleAware() const
231
0
{
232
0
  AssertIsOnOwningThread();
233
0
  MOZ_ASSERT(mMetadata);
234
0
235
0
  return mMetadata->locale().IsEmpty();
236
0
}
237
238
const indexedDB::KeyPath&
239
IDBIndex::GetKeyPath() const
240
0
{
241
0
  AssertIsOnOwningThread();
242
0
  MOZ_ASSERT(mMetadata);
243
0
244
0
  return mMetadata->keyPath();
245
0
}
246
247
void
248
IDBIndex::GetLocale(nsString& aLocale) const
249
0
{
250
0
  AssertIsOnOwningThread();
251
0
  MOZ_ASSERT(mMetadata);
252
0
253
0
  if (mMetadata->locale().IsEmpty()) {
254
0
    SetDOMStringToNull(aLocale);
255
0
  } else {
256
0
    CopyASCIItoUTF16(mMetadata->locale(), aLocale);
257
0
  }
258
0
}
259
260
const nsCString&
261
IDBIndex::Locale() const
262
0
{
263
0
  AssertIsOnOwningThread();
264
0
  MOZ_ASSERT(mMetadata);
265
0
266
0
  return mMetadata->locale();
267
0
}
268
269
bool
270
IDBIndex::IsAutoLocale() const
271
0
{
272
0
  AssertIsOnOwningThread();
273
0
  MOZ_ASSERT(mMetadata);
274
0
275
0
  return mMetadata->autoLocale();
276
0
}
277
278
nsPIDOMWindowInner*
279
IDBIndex::GetParentObject() const
280
0
{
281
0
  AssertIsOnOwningThread();
282
0
283
0
  return mObjectStore->GetParentObject();
284
0
}
285
286
void
287
IDBIndex::GetKeyPath(JSContext* aCx,
288
                     JS::MutableHandle<JS::Value> aResult,
289
                     ErrorResult& aRv)
290
0
{
291
0
  AssertIsOnOwningThread();
292
0
293
0
  if (!mCachedKeyPath.isUndefined()) {
294
0
    MOZ_ASSERT(mRooted);
295
0
    aResult.set(mCachedKeyPath);
296
0
    return;
297
0
  }
298
0
299
0
  MOZ_ASSERT(!mRooted);
300
0
301
0
  aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
302
0
  if (NS_WARN_IF(aRv.Failed())) {
303
0
    return;
304
0
  }
305
0
306
0
  if (mCachedKeyPath.isGCThing()) {
307
0
    mozilla::HoldJSObjects(this);
308
0
    mRooted = true;
309
0
  }
310
0
311
0
  aResult.set(mCachedKeyPath);
312
0
}
313
314
already_AddRefed<IDBRequest>
315
IDBIndex::GetInternal(bool aKeyOnly,
316
                      JSContext* aCx,
317
                      JS::Handle<JS::Value> aKey,
318
                      ErrorResult& aRv)
319
0
{
320
0
  AssertIsOnOwningThread();
321
0
322
0
  if (mDeletedMetadata) {
323
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
324
0
    return nullptr;
325
0
  }
326
0
327
0
  IDBTransaction* transaction = mObjectStore->Transaction();
328
0
  if (!transaction->IsOpen()) {
329
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
330
0
    return nullptr;
331
0
  }
332
0
333
0
  RefPtr<IDBKeyRange> keyRange;
334
0
  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
335
0
  if (NS_WARN_IF(aRv.Failed())) {
336
0
    return nullptr;
337
0
  }
338
0
339
0
  if (!keyRange) {
340
0
    // Must specify a key or keyRange for get() and getKey().
341
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_KEY_ERR);
342
0
    return nullptr;
343
0
  }
344
0
345
0
  const int64_t objectStoreId = mObjectStore->Id();
346
0
  const int64_t indexId = Id();
347
0
348
0
  SerializedKeyRange serializedKeyRange;
349
0
  keyRange->ToSerialized(serializedKeyRange);
350
0
351
0
  RequestParams params;
352
0
353
0
  if (aKeyOnly) {
354
0
    params = IndexGetKeyParams(objectStoreId, indexId, serializedKeyRange);
355
0
  } else {
356
0
    params = IndexGetParams(objectStoreId, indexId, serializedKeyRange);
357
0
  }
358
0
359
0
  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
360
0
  MOZ_ASSERT(request);
361
0
362
0
  if (aKeyOnly) {
363
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
364
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
365
0
                   "getKey(%s)",
366
0
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()",
367
0
                 IDB_LOG_ID_STRING(),
368
0
                 transaction->LoggingSerialNumber(),
369
0
                 request->LoggingSerialNumber(),
370
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
371
0
                 IDB_LOG_STRINGIFY(transaction),
372
0
                 IDB_LOG_STRINGIFY(mObjectStore),
373
0
                 IDB_LOG_STRINGIFY(this),
374
0
                 IDB_LOG_STRINGIFY(keyRange));
375
0
  } else {
376
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
377
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
378
0
                   "get(%s)",
379
0
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.get()",
380
0
                 IDB_LOG_ID_STRING(),
381
0
                 transaction->LoggingSerialNumber(),
382
0
                 request->LoggingSerialNumber(),
383
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
384
0
                 IDB_LOG_STRINGIFY(transaction),
385
0
                 IDB_LOG_STRINGIFY(mObjectStore),
386
0
                 IDB_LOG_STRINGIFY(this),
387
0
                 IDB_LOG_STRINGIFY(keyRange));
388
0
  }
389
0
390
0
  transaction->StartRequest(request, params);
391
0
392
0
  return request.forget();
393
0
}
394
395
already_AddRefed<IDBRequest>
396
IDBIndex::GetAllInternal(bool aKeysOnly,
397
                         JSContext* aCx,
398
                         JS::Handle<JS::Value> aKey,
399
                         const Optional<uint32_t>& aLimit,
400
                         ErrorResult& aRv)
401
0
{
402
0
  AssertIsOnOwningThread();
403
0
404
0
  if (mDeletedMetadata) {
405
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
406
0
    return nullptr;
407
0
  }
408
0
409
0
  IDBTransaction* transaction = mObjectStore->Transaction();
410
0
  if (!transaction->IsOpen()) {
411
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
412
0
    return nullptr;
413
0
  }
414
0
415
0
  RefPtr<IDBKeyRange> keyRange;
416
0
  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
417
0
  if (NS_WARN_IF(aRv.Failed())) {
418
0
    return nullptr;
419
0
  }
420
0
421
0
  const int64_t objectStoreId = mObjectStore->Id();
422
0
  const int64_t indexId = Id();
423
0
424
0
  OptionalKeyRange optionalKeyRange;
425
0
  if (keyRange) {
426
0
    SerializedKeyRange serializedKeyRange;
427
0
    keyRange->ToSerialized(serializedKeyRange);
428
0
    optionalKeyRange = serializedKeyRange;
429
0
  } else {
430
0
    optionalKeyRange = void_t();
431
0
  }
432
0
433
0
  const uint32_t limit = aLimit.WasPassed() ? aLimit.Value() : 0;
434
0
435
0
  RequestParams params;
436
0
  if (aKeysOnly) {
437
0
    params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange,
438
0
                                   limit);
439
0
  } else {
440
0
    params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit);
441
0
  }
442
0
443
0
  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
444
0
  MOZ_ASSERT(request);
445
0
446
0
  if (aKeysOnly) {
447
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
448
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
449
0
                   "getAllKeys(%s, %s)",
450
0
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()",
451
0
                 IDB_LOG_ID_STRING(),
452
0
                 transaction->LoggingSerialNumber(),
453
0
                 request->LoggingSerialNumber(),
454
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
455
0
                 IDB_LOG_STRINGIFY(transaction),
456
0
                 IDB_LOG_STRINGIFY(mObjectStore),
457
0
                 IDB_LOG_STRINGIFY(this),
458
0
                 IDB_LOG_STRINGIFY(keyRange),
459
0
                 IDB_LOG_STRINGIFY(aLimit));
460
0
  } else {
461
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
462
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
463
0
                   "getAll(%s, %s)",
464
0
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()",
465
0
                 IDB_LOG_ID_STRING(),
466
0
                 transaction->LoggingSerialNumber(),
467
0
                 request->LoggingSerialNumber(),
468
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
469
0
                 IDB_LOG_STRINGIFY(transaction),
470
0
                 IDB_LOG_STRINGIFY(mObjectStore),
471
0
                 IDB_LOG_STRINGIFY(this),
472
0
                 IDB_LOG_STRINGIFY(keyRange),
473
0
                 IDB_LOG_STRINGIFY(aLimit));
474
0
  }
475
0
476
0
  transaction->StartRequest(request, params);
477
0
478
0
  return request.forget();
479
0
}
480
481
already_AddRefed<IDBRequest>
482
IDBIndex::OpenCursorInternal(bool aKeysOnly,
483
                             JSContext* aCx,
484
                             JS::Handle<JS::Value> aRange,
485
                             IDBCursorDirection aDirection,
486
                             ErrorResult& aRv)
487
0
{
488
0
  AssertIsOnOwningThread();
489
0
490
0
  if (mDeletedMetadata) {
491
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
492
0
    return nullptr;
493
0
  }
494
0
495
0
  IDBTransaction* transaction = mObjectStore->Transaction();
496
0
  if (!transaction->IsOpen()) {
497
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
498
0
    return nullptr;
499
0
  }
500
0
501
0
  RefPtr<IDBKeyRange> keyRange;
502
0
  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
503
0
  if (NS_WARN_IF(aRv.Failed())) {
504
0
    return nullptr;
505
0
  }
506
0
507
0
  int64_t objectStoreId = mObjectStore->Id();
508
0
  int64_t indexId = Id();
509
0
510
0
  OptionalKeyRange optionalKeyRange;
511
0
512
0
  if (keyRange) {
513
0
    SerializedKeyRange serializedKeyRange;
514
0
    keyRange->ToSerialized(serializedKeyRange);
515
0
516
0
    optionalKeyRange = std::move(serializedKeyRange);
517
0
  } else {
518
0
    optionalKeyRange = void_t();
519
0
  }
520
0
521
0
  IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
522
0
523
0
  OpenCursorParams params;
524
0
  if (aKeysOnly) {
525
0
    IndexOpenKeyCursorParams openParams;
526
0
    openParams.objectStoreId() = objectStoreId;
527
0
    openParams.indexId() = indexId;
528
0
    openParams.optionalKeyRange() = std::move(optionalKeyRange);
529
0
    openParams.direction() = direction;
530
0
531
0
    params = std::move(openParams);
532
0
  } else {
533
0
    IndexOpenCursorParams openParams;
534
0
    openParams.objectStoreId() = objectStoreId;
535
0
    openParams.indexId() = indexId;
536
0
    openParams.optionalKeyRange() = std::move(optionalKeyRange);
537
0
    openParams.direction() = direction;
538
0
539
0
    params = std::move(openParams);
540
0
  }
541
0
542
0
  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
543
0
  MOZ_ASSERT(request);
544
0
545
0
  if (aKeysOnly) {
546
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
547
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
548
0
                   "openKeyCursor(%s, %s)",
549
0
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()",
550
0
                 IDB_LOG_ID_STRING(),
551
0
                 transaction->LoggingSerialNumber(),
552
0
                 request->LoggingSerialNumber(),
553
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
554
0
                 IDB_LOG_STRINGIFY(transaction),
555
0
                 IDB_LOG_STRINGIFY(mObjectStore),
556
0
                 IDB_LOG_STRINGIFY(this),
557
0
                 IDB_LOG_STRINGIFY(keyRange),
558
0
                 IDB_LOG_STRINGIFY(direction));
559
0
  } else {
560
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
561
0
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
562
0
                   "openCursor(%s, %s)",
563
0
                 "IndexedDB %s: C T[%lld] R[%llu]: "
564
0
                   "IDBObjectStore.openKeyCursor()",
565
0
                 IDB_LOG_ID_STRING(),
566
0
                 transaction->LoggingSerialNumber(),
567
0
                 request->LoggingSerialNumber(),
568
0
                 IDB_LOG_STRINGIFY(transaction->Database()),
569
0
                 IDB_LOG_STRINGIFY(transaction),
570
0
                 IDB_LOG_STRINGIFY(mObjectStore),
571
0
                 IDB_LOG_STRINGIFY(this),
572
0
                 IDB_LOG_STRINGIFY(keyRange),
573
0
                 IDB_LOG_STRINGIFY(direction));
574
0
  }
575
0
576
0
  BackgroundCursorChild* actor =
577
0
    new BackgroundCursorChild(request, this, direction);
578
0
579
0
  mObjectStore->Transaction()->OpenCursor(actor, params);
580
0
581
0
  return request.forget();
582
0
}
583
584
already_AddRefed<IDBRequest>
585
IDBIndex::Count(JSContext* aCx,
586
                JS::Handle<JS::Value> aKey,
587
                ErrorResult& aRv)
588
0
{
589
0
  AssertIsOnOwningThread();
590
0
591
0
  if (mDeletedMetadata) {
592
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
593
0
    return nullptr;
594
0
  }
595
0
596
0
  IDBTransaction* transaction = mObjectStore->Transaction();
597
0
  if (!transaction->IsOpen()) {
598
0
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
599
0
    return nullptr;
600
0
  }
601
0
602
0
  RefPtr<IDBKeyRange> keyRange;
603
0
  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
604
0
  if (aRv.Failed()) {
605
0
    return nullptr;
606
0
  }
607
0
608
0
  IndexCountParams params;
609
0
  params.objectStoreId() = mObjectStore->Id();
610
0
  params.indexId() = Id();
611
0
612
0
  if (keyRange) {
613
0
    SerializedKeyRange serializedKeyRange;
614
0
    keyRange->ToSerialized(serializedKeyRange);
615
0
    params.optionalKeyRange() = serializedKeyRange;
616
0
  } else {
617
0
    params.optionalKeyRange() = void_t();
618
0
  }
619
0
620
0
  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
621
0
  MOZ_ASSERT(request);
622
0
623
0
  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
624
0
                 "database(%s).transaction(%s).objectStore(%s).index(%s)."
625
0
                 "count(%s)",
626
0
               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
627
0
               IDB_LOG_ID_STRING(),
628
0
               transaction->LoggingSerialNumber(),
629
0
               request->LoggingSerialNumber(),
630
0
               IDB_LOG_STRINGIFY(transaction->Database()),
631
0
               IDB_LOG_STRINGIFY(transaction),
632
0
               IDB_LOG_STRINGIFY(mObjectStore),
633
0
               IDB_LOG_STRINGIFY(this),
634
0
               IDB_LOG_STRINGIFY(keyRange));
635
0
636
0
  transaction->StartRequest(request, params);
637
0
638
0
  return request.forget();
639
0
}
640
641
NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
642
NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
643
644
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
645
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
646
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
647
0
NS_INTERFACE_MAP_END
648
649
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
650
651
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
652
0
  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
653
0
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedKeyPath)
654
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
655
656
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
657
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
658
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
659
660
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
661
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
662
0
663
0
  // Don't unlink mObjectStore!
664
0
665
0
  tmp->mCachedKeyPath.setUndefined();
666
0
667
0
  if (tmp->mRooted) {
668
0
    mozilla::DropJSObjects(tmp);
669
0
    tmp->mRooted = false;
670
0
  }
671
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
672
673
JSObject*
674
IDBIndex::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
675
0
{
676
0
  return IDBIndex_Binding::Wrap(aCx, this, aGivenProto);
677
0
}
678
679
} // namespace dom
680
} // namespace mozilla