Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/indexedDB/ActorsChild.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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "ActorsChild.h"
8
9
#include "BackgroundChildImpl.h"
10
#include "FileSnapshot.h"
11
#include "IDBDatabase.h"
12
#include "IDBEvents.h"
13
#include "IDBFactory.h"
14
#include "IDBFileHandle.h"
15
#include "IDBIndex.h"
16
#include "IDBMutableFile.h"
17
#include "IDBObjectStore.h"
18
#include "IDBRequest.h"
19
#include "IDBTransaction.h"
20
#include "IndexedDatabase.h"
21
#include "IndexedDatabaseInlines.h"
22
#include "mozilla/BasicEvents.h"
23
#include "mozilla/CycleCollectedJSRuntime.h"
24
#include "mozilla/Maybe.h"
25
#include "mozilla/TypeTraits.h"
26
#include "mozilla/dom/Element.h"
27
#include "mozilla/dom/Event.h"
28
#include "mozilla/dom/PermissionMessageUtils.h"
29
#include "mozilla/dom/TabChild.h"
30
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
31
#include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
32
#include "mozilla/dom/ipc/PendingIPCBlobChild.h"
33
#include "mozilla/dom/IPCBlobUtils.h"
34
#include "mozilla/dom/WorkerPrivate.h"
35
#include "mozilla/dom/WorkerRunnable.h"
36
#include "mozilla/Encoding.h"
37
#include "mozilla/ipc/BackgroundUtils.h"
38
#include "mozilla/TaskQueue.h"
39
#include "nsCOMPtr.h"
40
#include "nsContentUtils.h"
41
#include "nsIAsyncInputStream.h"
42
#include "nsIBFCacheEntry.h"
43
#include "nsIDocument.h"
44
#include "nsIEventTarget.h"
45
#include "nsIFileStreams.h"
46
#include "nsNetCID.h"
47
#include "nsPIDOMWindow.h"
48
#include "nsThreadUtils.h"
49
#include "nsTraceRefcnt.h"
50
#include "PermissionRequestBase.h"
51
#include "ProfilerHelpers.h"
52
#include "ReportInternalError.h"
53
54
#ifdef DEBUG
55
#include "IndexedDatabaseManager.h"
56
#endif
57
58
#define GC_ON_IPC_MESSAGES 0
59
60
#if defined(DEBUG) || GC_ON_IPC_MESSAGES
61
62
#include "js/GCAPI.h"
63
#include "nsJSEnvironment.h"
64
65
#define BUILD_GC_ON_IPC_MESSAGES
66
67
#endif // DEBUG || GC_ON_IPC_MESSAGES
68
69
namespace mozilla {
70
71
using ipc::PrincipalInfo;
72
73
namespace dom {
74
75
namespace indexedDB {
76
77
/*******************************************************************************
78
 * ThreadLocal
79
 ******************************************************************************/
80
81
ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId)
82
  : mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1)
83
  , mCurrentTransaction(0)
84
0
{
85
0
  MOZ_COUNT_CTOR(mozilla::dom::indexedDB::ThreadLocal);
86
0
87
0
  // NSID_LENGTH counts the null terminator, SetLength() does not.
88
0
  mLoggingIdString.SetLength(NSID_LENGTH - 1);
89
0
90
0
  aBackgroundChildLoggingId.ToProvidedString(
91
0
    *reinterpret_cast<char(*)[NSID_LENGTH]>(mLoggingIdString.BeginWriting()));
92
0
}
93
94
ThreadLocal::~ThreadLocal()
95
0
{
96
0
  MOZ_COUNT_DTOR(mozilla::dom::indexedDB::ThreadLocal);
97
0
}
98
99
/*******************************************************************************
100
 * Helpers
101
 ******************************************************************************/
102
103
namespace {
104
105
void
106
MaybeCollectGarbageOnIPCMessage()
107
0
{
108
#ifdef BUILD_GC_ON_IPC_MESSAGES
109
  static const bool kCollectGarbageOnIPCMessages =
110
#if GC_ON_IPC_MESSAGES
111
    true;
112
#else
113
    false;
114
#endif // GC_ON_IPC_MESSAGES
115
116
  if (!kCollectGarbageOnIPCMessages) {
117
    return;
118
  }
119
120
  static bool haveWarnedAboutGC = false;
121
  static bool haveWarnedAboutNonMainThread = false;
122
123
  if (!haveWarnedAboutGC) {
124
    haveWarnedAboutGC = true;
125
    NS_WARNING("IndexedDB child actor GC debugging enabled!");
126
  }
127
128
  if (!NS_IsMainThread()) {
129
    if (!haveWarnedAboutNonMainThread)  {
130
      haveWarnedAboutNonMainThread = true;
131
      NS_WARNING("Don't know how to GC on a non-main thread yet.");
132
    }
133
    return;
134
  }
135
136
  nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
137
  nsJSContext::CycleCollectNow();
138
#endif // BUILD_GC_ON_IPC_MESSAGES
139
}
140
141
class MOZ_STACK_CLASS AutoSetCurrentTransaction final
142
{
143
  typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
144
145
  IDBTransaction* const mTransaction;
146
  IDBTransaction* mPreviousTransaction;
147
  ThreadLocal* mThreadLocal;
148
149
public:
150
  explicit AutoSetCurrentTransaction(IDBTransaction* aTransaction)
151
    : mTransaction(aTransaction)
152
    , mPreviousTransaction(nullptr)
153
    , mThreadLocal(nullptr)
154
0
  {
155
0
    if (aTransaction) {
156
0
      BackgroundChildImpl::ThreadLocal* threadLocal =
157
0
        BackgroundChildImpl::GetThreadLocalForCurrentThread();
158
0
      MOZ_ASSERT(threadLocal);
159
0
160
0
      // Hang onto this for resetting later.
161
0
      mThreadLocal = threadLocal->mIndexedDBThreadLocal;
162
0
      MOZ_ASSERT(mThreadLocal);
163
0
164
0
      // Save the current value.
165
0
      mPreviousTransaction = mThreadLocal->GetCurrentTransaction();
166
0
167
0
      // Set the new value.
168
0
      mThreadLocal->SetCurrentTransaction(aTransaction);
169
0
    }
170
0
  }
171
172
  ~AutoSetCurrentTransaction()
173
0
  {
174
0
    MOZ_ASSERT_IF(mThreadLocal, mTransaction);
175
0
    MOZ_ASSERT_IF(mThreadLocal,
176
0
                  mThreadLocal->GetCurrentTransaction() == mTransaction);
177
0
178
0
    if (mThreadLocal) {
179
0
      // Reset old value.
180
0
      mThreadLocal->SetCurrentTransaction(mPreviousTransaction);
181
0
    }
182
0
  }
183
184
  IDBTransaction*
185
  Transaction() const
186
0
  {
187
0
    return mTransaction;
188
0
  }
189
};
190
191
class MOZ_STACK_CLASS ResultHelper final
192
  : public IDBRequest::ResultCallback
193
{
194
  IDBRequest* mRequest;
195
  AutoSetCurrentTransaction mAutoTransaction;
196
197
  union
198
  {
199
    IDBDatabase* mDatabase;
200
    IDBCursor* mCursor;
201
    IDBMutableFile* mMutableFile;
202
    StructuredCloneReadInfo* mStructuredClone;
203
    const nsTArray<StructuredCloneReadInfo>* mStructuredCloneArray;
204
    const Key* mKey;
205
    const nsTArray<Key>* mKeyArray;
206
    const JS::Value* mJSVal;
207
    const JS::Handle<JS::Value>* mJSValHandle;
208
  } mResult;
209
210
  enum
211
  {
212
    ResultTypeDatabase,
213
    ResultTypeCursor,
214
    ResultTypeMutableFile,
215
    ResultTypeStructuredClone,
216
    ResultTypeStructuredCloneArray,
217
    ResultTypeKey,
218
    ResultTypeKeyArray,
219
    ResultTypeJSVal,
220
    ResultTypeJSValHandle,
221
  } mResultType;
222
223
public:
224
  ResultHelper(IDBRequest* aRequest,
225
               IDBTransaction* aTransaction,
226
               IDBDatabase* aResult)
227
    : mRequest(aRequest)
228
    , mAutoTransaction(aTransaction)
229
    , mResultType(ResultTypeDatabase)
230
0
  {
231
0
    MOZ_ASSERT(aRequest);
232
0
    MOZ_ASSERT(aResult);
233
0
234
0
    mResult.mDatabase = aResult;
235
0
  }
236
237
  ResultHelper(IDBRequest* aRequest,
238
               IDBTransaction* aTransaction,
239
               IDBCursor* aResult)
240
    : mRequest(aRequest)
241
    , mAutoTransaction(aTransaction)
242
    , mResultType(ResultTypeCursor)
243
0
  {
244
0
    MOZ_ASSERT(aRequest);
245
0
246
0
    mResult.mCursor = aResult;
247
0
  }
248
249
  ResultHelper(IDBRequest* aRequest,
250
               IDBTransaction* aTransaction,
251
               IDBMutableFile* aResult)
252
    : mRequest(aRequest)
253
    , mAutoTransaction(aTransaction)
254
    , mResultType(ResultTypeMutableFile)
255
0
  {
256
0
    MOZ_ASSERT(aRequest);
257
0
258
0
    mResult.mMutableFile = aResult;
259
0
  }
260
261
  ResultHelper(IDBRequest* aRequest,
262
               IDBTransaction* aTransaction,
263
               StructuredCloneReadInfo* aResult)
264
    : mRequest(aRequest)
265
    , mAutoTransaction(aTransaction)
266
    , mResultType(ResultTypeStructuredClone)
267
0
  {
268
0
    MOZ_ASSERT(aRequest);
269
0
    MOZ_ASSERT(aResult);
270
0
271
0
    mResult.mStructuredClone = aResult;
272
0
  }
273
274
  ResultHelper(IDBRequest* aRequest,
275
               IDBTransaction* aTransaction,
276
               const nsTArray<StructuredCloneReadInfo>* aResult)
277
    : mRequest(aRequest)
278
    , mAutoTransaction(aTransaction)
279
    , mResultType(ResultTypeStructuredCloneArray)
280
0
  {
281
0
    MOZ_ASSERT(aRequest);
282
0
    MOZ_ASSERT(aResult);
283
0
284
0
    mResult.mStructuredCloneArray = aResult;
285
0
  }
286
287
  ResultHelper(IDBRequest* aRequest,
288
               IDBTransaction* aTransaction,
289
               const Key* aResult)
290
    : mRequest(aRequest)
291
    , mAutoTransaction(aTransaction)
292
    , mResultType(ResultTypeKey)
293
0
  {
294
0
    MOZ_ASSERT(aRequest);
295
0
    MOZ_ASSERT(aResult);
296
0
297
0
    mResult.mKey = aResult;
298
0
  }
299
300
  ResultHelper(IDBRequest* aRequest,
301
               IDBTransaction* aTransaction,
302
               const nsTArray<Key>* aResult)
303
    : mRequest(aRequest)
304
    , mAutoTransaction(aTransaction)
305
    , mResultType(ResultTypeKeyArray)
306
0
  {
307
0
    MOZ_ASSERT(aRequest);
308
0
    MOZ_ASSERT(aResult);
309
0
310
0
    mResult.mKeyArray = aResult;
311
0
  }
312
313
  ResultHelper(IDBRequest* aRequest,
314
               IDBTransaction* aTransaction,
315
               const JS::Value* aResult)
316
    : mRequest(aRequest)
317
    , mAutoTransaction(aTransaction)
318
    , mResultType(ResultTypeJSVal)
319
0
  {
320
0
    MOZ_ASSERT(aRequest);
321
0
    MOZ_ASSERT(!aResult->isGCThing());
322
0
323
0
    mResult.mJSVal = aResult;
324
0
  }
325
326
  ResultHelper(IDBRequest* aRequest,
327
               IDBTransaction* aTransaction,
328
               const JS::Handle<JS::Value>* aResult)
329
    : mRequest(aRequest)
330
    , mAutoTransaction(aTransaction)
331
    , mResultType(ResultTypeJSValHandle)
332
0
  {
333
0
    MOZ_ASSERT(aRequest);
334
0
335
0
    mResult.mJSValHandle = aResult;
336
0
  }
337
338
  IDBRequest*
339
  Request() const
340
0
  {
341
0
    return mRequest;
342
0
  }
343
344
  IDBTransaction*
345
  Transaction() const
346
0
  {
347
0
    return mAutoTransaction.Transaction();
348
0
  }
349
350
  virtual nsresult
351
  GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) override
352
0
  {
353
0
    MOZ_ASSERT(aCx);
354
0
    MOZ_ASSERT(mRequest);
355
0
356
0
    switch (mResultType) {
357
0
      case ResultTypeDatabase:
358
0
        return GetResult(aCx, mResult.mDatabase, aResult);
359
0
360
0
      case ResultTypeCursor:
361
0
        return GetResult(aCx, mResult.mCursor, aResult);
362
0
363
0
      case ResultTypeMutableFile:
364
0
        return GetResult(aCx, mResult.mMutableFile, aResult);
365
0
366
0
      case ResultTypeStructuredClone:
367
0
        return GetResult(aCx, mResult.mStructuredClone, aResult);
368
0
369
0
      case ResultTypeStructuredCloneArray:
370
0
        return GetResult(aCx, mResult.mStructuredCloneArray, aResult);
371
0
372
0
      case ResultTypeKey:
373
0
        return GetResult(aCx, mResult.mKey, aResult);
374
0
375
0
      case ResultTypeKeyArray:
376
0
        return GetResult(aCx, mResult.mKeyArray, aResult);
377
0
378
0
      case ResultTypeJSVal:
379
0
        aResult.set(*mResult.mJSVal);
380
0
        return NS_OK;
381
0
382
0
      case ResultTypeJSValHandle:
383
0
        aResult.set(*mResult.mJSValHandle);
384
0
        return NS_OK;
385
0
386
0
      default:
387
0
        MOZ_CRASH("Unknown result type!");
388
0
    }
389
0
390
0
    MOZ_CRASH("Should never get here!");
391
0
  }
392
393
private:
394
  template <class T>
395
  typename EnableIf<IsSame<T, IDBDatabase>::value ||
396
                    IsSame<T, IDBCursor>::value ||
397
                    IsSame<T, IDBMutableFile>::value,
398
                    nsresult>::Type
399
  GetResult(JSContext* aCx,
400
            T* aDOMObject,
401
            JS::MutableHandle<JS::Value> aResult)
402
0
  {
403
0
    if (!aDOMObject) {
404
0
      aResult.setNull();
405
0
      return NS_OK;
406
0
    }
407
0
408
0
    bool ok = GetOrCreateDOMReflector(aCx, aDOMObject, aResult);
409
0
    if (NS_WARN_IF(!ok)) {
410
0
      IDB_REPORT_INTERNAL_ERR();
411
0
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
412
0
    }
413
0
414
0
    return NS_OK;
415
0
  }
Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:_ZN7mozilla3dom9indexedDB12_GLOBAL__N_112ResultHelper9GetResultINS0_11IDBDatabaseEEENS_8EnableIfIXoooosr6IsSameIT_S5_EE5valuesr6IsSameIS7_NS0_9IDBCursorEEE5valuesr6IsSameIS7_NS0_14IDBMutableFileEEE5valueE8nsresultE4TypeEP9JSContextPS7_N2JS13MutableHandleINSG_5ValueEEE
Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:_ZN7mozilla3dom9indexedDB12_GLOBAL__N_112ResultHelper9GetResultINS0_9IDBCursorEEENS_8EnableIfIXoooosr6IsSameIT_NS0_11IDBDatabaseEEE5valuesr6IsSameIS7_S5_EE5valuesr6IsSameIS7_NS0_14IDBMutableFileEEE5valueE8nsresultE4TypeEP9JSContextPS7_N2JS13MutableHandleINSG_5ValueEEE
Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:_ZN7mozilla3dom9indexedDB12_GLOBAL__N_112ResultHelper9GetResultINS0_14IDBMutableFileEEENS_8EnableIfIXoooosr6IsSameIT_NS0_11IDBDatabaseEEE5valuesr6IsSameIS7_NS0_9IDBCursorEEE5valuesr6IsSameIS7_S5_EE5valueE8nsresultE4TypeEP9JSContextPS7_N2JS13MutableHandleINSG_5ValueEEE
416
417
  nsresult
418
  GetResult(JSContext* aCx,
419
            StructuredCloneReadInfo* aCloneInfo,
420
            JS::MutableHandle<JS::Value> aResult)
421
0
  {
422
0
    bool ok = IDBObjectStore::DeserializeValue(aCx, *aCloneInfo, aResult);
423
0
424
0
    if (NS_WARN_IF(!ok)) {
425
0
      return NS_ERROR_DOM_DATA_CLONE_ERR;
426
0
    }
427
0
428
0
    return NS_OK;
429
0
  }
430
431
  nsresult
432
  GetResult(JSContext* aCx,
433
            const nsTArray<StructuredCloneReadInfo>* aCloneInfos,
434
            JS::MutableHandle<JS::Value> aResult)
435
0
  {
436
0
    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
437
0
    if (NS_WARN_IF(!array)) {
438
0
      IDB_REPORT_INTERNAL_ERR();
439
0
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
440
0
    }
441
0
442
0
    if (!aCloneInfos->IsEmpty()) {
443
0
      const uint32_t count = aCloneInfos->Length();
444
0
445
0
      if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
446
0
        IDB_REPORT_INTERNAL_ERR();
447
0
        return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
448
0
      }
449
0
450
0
      for (uint32_t index = 0; index < count; index++) {
451
0
        auto& cloneInfo =
452
0
          const_cast<StructuredCloneReadInfo&>(aCloneInfos->ElementAt(index));
453
0
454
0
        JS::Rooted<JS::Value> value(aCx);
455
0
456
0
        nsresult rv = GetResult(aCx, &cloneInfo, &value);
457
0
        if (NS_WARN_IF(NS_FAILED(rv))) {
458
0
          return rv;
459
0
        }
460
0
461
0
        if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
462
0
                                         JSPROP_ENUMERATE))) {
463
0
          IDB_REPORT_INTERNAL_ERR();
464
0
          return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
465
0
        }
466
0
      }
467
0
    }
468
0
469
0
    aResult.setObject(*array);
470
0
    return NS_OK;
471
0
  }
472
473
  nsresult
474
  GetResult(JSContext* aCx,
475
            const Key* aKey,
476
            JS::MutableHandle<JS::Value> aResult)
477
0
  {
478
0
    nsresult rv = aKey->ToJSVal(aCx, aResult);
479
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
480
0
      return rv;
481
0
    }
482
0
    return NS_OK;
483
0
  }
484
485
  nsresult
486
  GetResult(JSContext* aCx,
487
            const nsTArray<Key>* aKeys,
488
            JS::MutableHandle<JS::Value> aResult)
489
0
  {
490
0
    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
491
0
    if (NS_WARN_IF(!array)) {
492
0
      IDB_REPORT_INTERNAL_ERR();
493
0
      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
494
0
    }
495
0
496
0
    if (!aKeys->IsEmpty()) {
497
0
      const uint32_t count = aKeys->Length();
498
0
499
0
      if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
500
0
        IDB_REPORT_INTERNAL_ERR();
501
0
        return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
502
0
      }
503
0
504
0
      for (uint32_t index = 0; index < count; index++) {
505
0
        const Key& key = aKeys->ElementAt(index);
506
0
        MOZ_ASSERT(!key.IsUnset());
507
0
508
0
        JS::Rooted<JS::Value> value(aCx);
509
0
510
0
        nsresult rv = GetResult(aCx, &key, &value);
511
0
        if (NS_WARN_IF(NS_FAILED(rv))) {
512
0
          return rv;
513
0
        }
514
0
515
0
        if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
516
0
                                         JSPROP_ENUMERATE))) {
517
0
          IDB_REPORT_INTERNAL_ERR();
518
0
          return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
519
0
        }
520
0
      }
521
0
    }
522
0
523
0
    aResult.setObject(*array);
524
0
    return NS_OK;
525
0
  }
526
};
527
528
class PermissionRequestMainProcessHelper final
529
  : public PermissionRequestBase
530
{
531
  BackgroundFactoryRequestChild* mActor;
532
  RefPtr<IDBFactory> mFactory;
533
534
public:
535
  PermissionRequestMainProcessHelper(BackgroundFactoryRequestChild* aActor,
536
                                     IDBFactory* aFactory,
537
                                     Element* aOwnerElement,
538
                                     nsIPrincipal* aPrincipal)
539
    : PermissionRequestBase(aOwnerElement, aPrincipal)
540
    , mActor(aActor)
541
    , mFactory(aFactory)
542
0
  {
543
0
    MOZ_ASSERT(aActor);
544
0
    MOZ_ASSERT(aFactory);
545
0
    aActor->AssertIsOnOwningThread();
546
0
  }
547
548
protected:
549
  ~PermissionRequestMainProcessHelper()
550
0
  { }
551
552
private:
553
  virtual void
554
  OnPromptComplete(PermissionValue aPermissionValue) override;
555
};
556
557
class PermissionRequestChildProcessActor final
558
  : public PIndexedDBPermissionRequestChild
559
{
560
  BackgroundFactoryRequestChild* mActor;
561
  RefPtr<IDBFactory> mFactory;
562
563
public:
564
  PermissionRequestChildProcessActor(BackgroundFactoryRequestChild* aActor,
565
                                     IDBFactory* aFactory)
566
    : mActor(aActor)
567
    , mFactory(aFactory)
568
0
  {
569
0
    MOZ_ASSERT(aActor);
570
0
    MOZ_ASSERT(aFactory);
571
0
    aActor->AssertIsOnOwningThread();
572
0
  }
573
574
protected:
575
  ~PermissionRequestChildProcessActor()
576
0
  { }
577
578
  virtual mozilla::ipc::IPCResult
579
  Recv__delete__(const uint32_t& aPermission) override;
580
};
581
582
void
583
DeserializeStructuredCloneFiles(
584
                IDBDatabase* aDatabase,
585
                const nsTArray<SerializedStructuredCloneFile>& aSerializedFiles,
586
                const nsTArray<RefPtr<JS::WasmModule>>* aModuleSet,
587
                nsTArray<StructuredCloneFile>& aFiles)
588
0
{
589
0
  MOZ_ASSERT_IF(aModuleSet, !aModuleSet->IsEmpty());
590
0
  MOZ_ASSERT(aFiles.IsEmpty());
591
0
592
0
  if (!aSerializedFiles.IsEmpty()) {
593
0
    uint32_t moduleIndex = 0;
594
0
595
0
    const uint32_t count = aSerializedFiles.Length();
596
0
    aFiles.SetCapacity(count);
597
0
598
0
    for (uint32_t index = 0; index < count; index++) {
599
0
      const SerializedStructuredCloneFile& serializedFile =
600
0
        aSerializedFiles[index];
601
0
602
0
      const BlobOrMutableFile& blobOrMutableFile = serializedFile.file();
603
0
604
0
      switch (serializedFile.type()) {
605
0
        case StructuredCloneFile::eBlob: {
606
0
          MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TIPCBlob);
607
0
608
0
          const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
609
0
610
0
          RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(ipcBlob);
611
0
          MOZ_ASSERT(blobImpl);
612
0
613
0
          RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
614
0
615
0
          StructuredCloneFile* file = aFiles.AppendElement();
616
0
          MOZ_ASSERT(file);
617
0
618
0
          file->mType = StructuredCloneFile::eBlob;
619
0
          file->mBlob.swap(blob);
620
0
621
0
          break;
622
0
        }
623
0
624
0
        case StructuredCloneFile::eMutableFile: {
625
0
          MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t ||
626
0
                     blobOrMutableFile.type() ==
627
0
                       BlobOrMutableFile::TPBackgroundMutableFileChild);
628
0
629
0
          switch (blobOrMutableFile.type()) {
630
0
            case BlobOrMutableFile::Tnull_t: {
631
0
              StructuredCloneFile* file = aFiles.AppendElement();
632
0
              MOZ_ASSERT(file);
633
0
634
0
              file->mType = StructuredCloneFile::eMutableFile;
635
0
636
0
              break;
637
0
            }
638
0
639
0
            case BlobOrMutableFile::TPBackgroundMutableFileChild: {
640
0
              auto* actor =
641
0
                static_cast<BackgroundMutableFileChild*>(
642
0
                  blobOrMutableFile.get_PBackgroundMutableFileChild());
643
0
              MOZ_ASSERT(actor);
644
0
645
0
              actor->EnsureDOMObject();
646
0
647
0
              auto* mutableFile =
648
0
                static_cast<IDBMutableFile*>(actor->GetDOMObject());
649
0
              MOZ_ASSERT(mutableFile);
650
0
651
0
              StructuredCloneFile* file = aFiles.AppendElement();
652
0
              MOZ_ASSERT(file);
653
0
654
0
              file->mType = StructuredCloneFile::eMutableFile;
655
0
              file->mMutableFile = mutableFile;
656
0
657
0
              actor->ReleaseDOMObject();
658
0
659
0
              break;
660
0
            }
661
0
662
0
            default:
663
0
              MOZ_CRASH("Should never get here!");
664
0
          }
665
0
666
0
          break;
667
0
        }
668
0
669
0
        case StructuredCloneFile::eStructuredClone: {
670
0
          StructuredCloneFile* file = aFiles.AppendElement();
671
0
          MOZ_ASSERT(file);
672
0
673
0
          file->mType = StructuredCloneFile::eStructuredClone;
674
0
675
0
          break;
676
0
        }
677
0
678
0
        case StructuredCloneFile::eWasmBytecode: {
679
0
          if (aModuleSet) {
680
0
            MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
681
0
682
0
            StructuredCloneFile* file = aFiles.AppendElement();
683
0
            MOZ_ASSERT(file);
684
0
685
0
            file->mType = StructuredCloneFile::eWasmBytecode;
686
0
687
0
            MOZ_ASSERT(moduleIndex < aModuleSet->Length());
688
0
            file->mWasmModule = aModuleSet->ElementAt(moduleIndex);
689
0
690
0
            moduleIndex++;
691
0
692
0
            break;
693
0
          }
694
0
695
0
          MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TIPCBlob);
696
0
697
0
          const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
698
0
699
0
          RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(ipcBlob);
700
0
          MOZ_ASSERT(blobImpl);
701
0
702
0
          RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
703
0
704
0
          StructuredCloneFile* file = aFiles.AppendElement();
705
0
          MOZ_ASSERT(file);
706
0
707
0
          file->mType = StructuredCloneFile::eWasmBytecode;
708
0
          file->mBlob.swap(blob);
709
0
710
0
          break;
711
0
        }
712
0
713
0
        case StructuredCloneFile::eWasmCompiled: {
714
0
          StructuredCloneFile* file = aFiles.AppendElement();
715
0
          MOZ_ASSERT(file);
716
0
717
0
          file->mType = StructuredCloneFile::eWasmCompiled;
718
0
719
0
          break;
720
0
        }
721
0
722
0
        default:
723
0
          MOZ_CRASH("Should never get here!");
724
0
      }
725
0
    }
726
0
  }
727
0
}
728
729
void
730
DispatchErrorEvent(IDBRequest* aRequest,
731
                   nsresult aErrorCode,
732
                   IDBTransaction* aTransaction = nullptr,
733
                   Event* aEvent = nullptr)
734
0
{
735
0
  MOZ_ASSERT(aRequest);
736
0
  aRequest->AssertIsOnOwningThread();
737
0
  MOZ_ASSERT(NS_FAILED(aErrorCode));
738
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
739
0
740
0
  AUTO_PROFILER_LABEL("IndexedDB:DispatchErrorEvent", DOM);
741
0
742
0
  RefPtr<IDBRequest> request = aRequest;
743
0
  RefPtr<IDBTransaction> transaction = aTransaction;
744
0
745
0
  request->SetError(aErrorCode);
746
0
747
0
  RefPtr<Event> errorEvent;
748
0
  if (!aEvent) {
749
0
    // Make an error event and fire it at the target.
750
0
    errorEvent = CreateGenericEvent(request,
751
0
                                    nsDependentString(kErrorEventType),
752
0
                                    eDoesBubble,
753
0
                                    eCancelable);
754
0
    MOZ_ASSERT(errorEvent);
755
0
756
0
    aEvent = errorEvent;
757
0
  }
758
0
759
0
  Maybe<AutoSetCurrentTransaction> asct;
760
0
  if (aTransaction) {
761
0
    asct.emplace(aTransaction);
762
0
  }
763
0
764
0
  if (transaction) {
765
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
766
0
                   "Firing %s event with error 0x%x",
767
0
                 "IndexedDB %s: C T[%lld] R[%llu]: %s (0x%x)",
768
0
                 IDB_LOG_ID_STRING(),
769
0
                 transaction->LoggingSerialNumber(),
770
0
                 request->LoggingSerialNumber(),
771
0
                 IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
772
0
                 aErrorCode);
773
0
  } else {
774
0
    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
775
0
                   "Firing %s event with error 0x%x",
776
0
                 "IndexedDB %s: C R[%llu]: %s (0x%x)",
777
0
                 IDB_LOG_ID_STRING(),
778
0
                 request->LoggingSerialNumber(),
779
0
                 IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
780
0
                 aErrorCode);
781
0
  }
782
0
783
0
  IgnoredErrorResult rv;
784
0
  bool doDefault = request->DispatchEvent(*aEvent, CallerType::System, rv);
785
0
  if (NS_WARN_IF(rv.Failed())) {
786
0
    return;
787
0
  }
788
0
789
0
  MOZ_ASSERT(!transaction || transaction->IsOpen() || transaction->IsAborted());
790
0
791
0
  // Do not abort the transaction here if this request is failed due to the
792
0
  // abortion of its transaction to ensure that the correct error cause of
793
0
  // the abort event be set in IDBTransaction::FireCompleteOrAbortEvents() later.
794
0
  if (transaction && transaction->IsOpen() &&
795
0
      aErrorCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) {
796
0
    WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
797
0
    MOZ_ASSERT(internalEvent);
798
0
799
0
    if (internalEvent->mFlags.mExceptionWasRaised) {
800
0
      transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
801
0
    } else if (doDefault) {
802
0
      transaction->Abort(request);
803
0
    }
804
0
  }
805
0
}
806
807
void
808
DispatchSuccessEvent(ResultHelper* aResultHelper,
809
                     Event* aEvent = nullptr)
810
0
{
811
0
  MOZ_ASSERT(aResultHelper);
812
0
813
0
  AUTO_PROFILER_LABEL("IndexedDB:DispatchSuccessEvent", DOM);
814
0
815
0
  RefPtr<IDBRequest> request = aResultHelper->Request();
816
0
  MOZ_ASSERT(request);
817
0
  request->AssertIsOnOwningThread();
818
0
819
0
  RefPtr<IDBTransaction> transaction = aResultHelper->Transaction();
820
0
821
0
  if (transaction && transaction->IsAborted()) {
822
0
    DispatchErrorEvent(request, transaction->AbortCode(), transaction);
823
0
    return;
824
0
  }
825
0
826
0
  RefPtr<Event> successEvent;
827
0
  if (!aEvent) {
828
0
    successEvent = CreateGenericEvent(request,
829
0
                                      nsDependentString(kSuccessEventType),
830
0
                                      eDoesNotBubble,
831
0
                                      eNotCancelable);
832
0
    MOZ_ASSERT(successEvent);
833
0
834
0
    aEvent = successEvent;
835
0
  }
836
0
837
0
  request->SetResultCallback(aResultHelper);
838
0
839
0
  MOZ_ASSERT(aEvent);
840
0
  MOZ_ASSERT_IF(transaction, transaction->IsOpen());
841
0
842
0
  if (transaction) {
843
0
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
844
0
                   "Firing %s event",
845
0
                 "IndexedDB %s: C T[%lld] R[%llu]: %s",
846
0
                 IDB_LOG_ID_STRING(),
847
0
                 transaction->LoggingSerialNumber(),
848
0
                 request->LoggingSerialNumber(),
849
0
                 IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
850
0
  } else {
851
0
    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: Firing %s event",
852
0
                 "IndexedDB %s: C R[%llu]: %s",
853
0
                 IDB_LOG_ID_STRING(),
854
0
                 request->LoggingSerialNumber(),
855
0
                 IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
856
0
  }
857
0
858
0
  MOZ_ASSERT_IF(transaction,
859
0
                transaction->IsOpen() && !transaction->IsAborted());
860
0
861
0
  IgnoredErrorResult rv;
862
0
  request->DispatchEvent(*aEvent, rv);
863
0
  if (NS_WARN_IF(rv.Failed())) {
864
0
    return;
865
0
  }
866
0
867
0
  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
868
0
  MOZ_ASSERT(internalEvent);
869
0
870
0
  if (transaction &&
871
0
      transaction->IsOpen()) {
872
0
    if (internalEvent->mFlags.mExceptionWasRaised) {
873
0
      transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
874
0
    } else {
875
0
      // To handle upgrade transaction.
876
0
      transaction->Run();
877
0
    }
878
0
  }
879
0
}
880
881
PRFileDesc*
882
GetFileDescriptorFromStream(nsIInputStream* aStream)
883
0
{
884
0
  MOZ_ASSERT(aStream);
885
0
886
0
  nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
887
0
  if (NS_WARN_IF(!fileMetadata)) {
888
0
    return nullptr;
889
0
  }
890
0
891
0
  PRFileDesc* fileDesc;
892
0
  nsresult rv = fileMetadata->GetFileDescriptor(&fileDesc);
893
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
894
0
    return nullptr;
895
0
  }
896
0
897
0
  MOZ_ASSERT(fileDesc);
898
0
899
0
  return fileDesc;
900
0
}
901
902
class WorkerPermissionChallenge;
903
904
// This class calles WorkerPermissionChallenge::OperationCompleted() in the
905
// worker thread.
906
class WorkerPermissionOperationCompleted final : public WorkerControlRunnable
907
{
908
  RefPtr<WorkerPermissionChallenge> mChallenge;
909
910
public:
911
  WorkerPermissionOperationCompleted(WorkerPrivate* aWorkerPrivate,
912
                                     WorkerPermissionChallenge* aChallenge)
913
    : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
914
    , mChallenge(aChallenge)
915
0
  {
916
0
    MOZ_ASSERT(NS_IsMainThread());
917
0
  }
918
919
  virtual bool
920
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
921
};
922
923
// This class used to do prompting in the main thread and main process.
924
class WorkerPermissionRequest final : public PermissionRequestBase
925
{
926
  RefPtr<WorkerPermissionChallenge> mChallenge;
927
928
public:
929
  WorkerPermissionRequest(Element* aElement,
930
                          nsIPrincipal* aPrincipal,
931
                          WorkerPermissionChallenge* aChallenge)
932
    : PermissionRequestBase(aElement, aPrincipal)
933
    , mChallenge(aChallenge)
934
0
  {
935
0
    MOZ_ASSERT(XRE_IsParentProcess());
936
0
    MOZ_ASSERT(NS_IsMainThread());
937
0
    MOZ_ASSERT(aChallenge);
938
0
  }
939
940
private:
941
  ~WorkerPermissionRequest()
942
0
  {
943
0
    MOZ_ASSERT(NS_IsMainThread());
944
0
  }
945
946
  virtual void
947
  OnPromptComplete(PermissionValue aPermissionValue) override;
948
};
949
950
// This class is used in the main thread of all child processes.
951
class WorkerPermissionRequestChildProcessActor final
952
  : public PIndexedDBPermissionRequestChild
953
{
954
  RefPtr<WorkerPermissionChallenge> mChallenge;
955
956
public:
957
  explicit WorkerPermissionRequestChildProcessActor(
958
                                          WorkerPermissionChallenge* aChallenge)
959
    : mChallenge(aChallenge)
960
0
  {
961
0
    MOZ_ASSERT(!XRE_IsParentProcess());
962
0
    MOZ_ASSERT(NS_IsMainThread());
963
0
    MOZ_ASSERT(aChallenge);
964
0
  }
965
966
protected:
967
  ~WorkerPermissionRequestChildProcessActor()
968
0
  {}
969
970
  virtual mozilla::ipc::IPCResult
971
  Recv__delete__(const uint32_t& aPermission) override;
972
};
973
974
class WorkerPermissionChallenge final : public Runnable
975
{
976
public:
977
  WorkerPermissionChallenge(WorkerPrivate* aWorkerPrivate,
978
                            BackgroundFactoryRequestChild* aActor,
979
                            IDBFactory* aFactory,
980
                            const PrincipalInfo& aPrincipalInfo)
981
    : Runnable("indexedDB::WorkerPermissionChallenge")
982
    , mWorkerPrivate(aWorkerPrivate)
983
    , mActor(aActor)
984
    , mFactory(aFactory)
985
    , mPrincipalInfo(aPrincipalInfo)
986
0
  {
987
0
    MOZ_ASSERT(mWorkerPrivate);
988
0
    MOZ_ASSERT(aActor);
989
0
    MOZ_ASSERT(aFactory);
990
0
    mWorkerPrivate->AssertIsOnWorkerThread();
991
0
  }
992
993
  bool
994
  Dispatch()
995
0
  {
996
0
    mWorkerPrivate->AssertIsOnWorkerThread();
997
0
    if (NS_WARN_IF(!mWorkerPrivate->ModifyBusyCountFromWorker(true))) {
998
0
      return false;
999
0
    }
1000
0
1001
0
    if (NS_WARN_IF(NS_FAILED(mWorkerPrivate->DispatchToMainThread(this)))) {
1002
0
      mWorkerPrivate->ModifyBusyCountFromWorker(false);
1003
0
      return false;
1004
0
    }
1005
0
1006
0
    return true;
1007
0
  }
1008
1009
  NS_IMETHOD
1010
  Run() override
1011
0
  {
1012
0
    bool completed = RunInternal();
1013
0
    if (completed) {
1014
0
      OperationCompleted();
1015
0
    }
1016
0
1017
0
    return NS_OK;
1018
0
  }
1019
1020
  void
1021
  OperationCompleted()
1022
0
  {
1023
0
    if (NS_IsMainThread()) {
1024
0
      RefPtr<WorkerPermissionOperationCompleted> runnable =
1025
0
        new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
1026
0
1027
0
      MOZ_ALWAYS_TRUE(runnable->Dispatch());
1028
0
      return;
1029
0
    }
1030
0
1031
0
    MOZ_ASSERT(mActor);
1032
0
    mActor->AssertIsOnOwningThread();
1033
0
1034
0
    MaybeCollectGarbageOnIPCMessage();
1035
0
1036
0
    RefPtr<IDBFactory> factory;
1037
0
    mFactory.swap(factory);
1038
0
1039
0
    mActor->SendPermissionRetry();
1040
0
    mActor = nullptr;
1041
0
1042
0
    mWorkerPrivate->AssertIsOnWorkerThread();
1043
0
    mWorkerPrivate->ModifyBusyCountFromWorker(false);
1044
0
  }
1045
1046
private:
1047
  bool
1048
  RunInternal()
1049
0
  {
1050
0
    MOZ_ASSERT(NS_IsMainThread());
1051
0
1052
0
    // Walk up to our containing page
1053
0
    WorkerPrivate* wp = mWorkerPrivate;
1054
0
    while (wp->GetParent()) {
1055
0
      wp = wp->GetParent();
1056
0
    }
1057
0
1058
0
    nsPIDOMWindowInner* window = wp->GetWindow();
1059
0
    if (!window) {
1060
0
      return true;
1061
0
    }
1062
0
1063
0
    nsresult rv;
1064
0
    nsCOMPtr<nsIPrincipal> principal =
1065
0
      mozilla::ipc::PrincipalInfoToPrincipal(mPrincipalInfo, &rv);
1066
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
1067
0
      return true;
1068
0
    }
1069
0
1070
0
    if (XRE_IsParentProcess()) {
1071
0
      nsCOMPtr<Element> ownerElement =
1072
0
        do_QueryInterface(window->GetChromeEventHandler());
1073
0
      if (NS_WARN_IF(!ownerElement)) {
1074
0
        return true;
1075
0
      }
1076
0
1077
0
      RefPtr<WorkerPermissionRequest> helper =
1078
0
        new WorkerPermissionRequest(ownerElement, principal, this);
1079
0
1080
0
      PermissionRequestBase::PermissionValue permission;
1081
0
      if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {
1082
0
        return true;
1083
0
      }
1084
0
1085
0
      MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
1086
0
                 permission == PermissionRequestBase::kPermissionDenied ||
1087
0
                 permission == PermissionRequestBase::kPermissionPrompt);
1088
0
1089
0
      return permission != PermissionRequestBase::kPermissionPrompt;
1090
0
    }
1091
0
1092
0
    TabChild* tabChild = TabChild::GetFrom(window);
1093
0
    MOZ_ASSERT(tabChild);
1094
0
1095
0
    IPC::Principal ipcPrincipal(principal);
1096
0
1097
0
    auto* actor = new WorkerPermissionRequestChildProcessActor(this);
1098
0
    tabChild->SetEventTargetForActor(actor, wp->MainThreadEventTarget());
1099
0
    MOZ_ASSERT(actor->GetActorEventTarget());
1100
0
    tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
1101
0
    return false;
1102
0
  }
1103
1104
private:
1105
  WorkerPrivate* mWorkerPrivate;
1106
  BackgroundFactoryRequestChild* mActor;
1107
  RefPtr<IDBFactory> mFactory;
1108
  PrincipalInfo mPrincipalInfo;
1109
};
1110
1111
void
1112
WorkerPermissionRequest::OnPromptComplete(PermissionValue aPermissionValue)
1113
0
{
1114
0
  MOZ_ASSERT(NS_IsMainThread());
1115
0
  mChallenge->OperationCompleted();
1116
0
}
1117
1118
bool
1119
WorkerPermissionOperationCompleted::WorkerRun(JSContext* aCx,
1120
                                              WorkerPrivate* aWorkerPrivate)
1121
0
{
1122
0
  aWorkerPrivate->AssertIsOnWorkerThread();
1123
0
  mChallenge->OperationCompleted();
1124
0
  return true;
1125
0
}
1126
1127
mozilla::ipc::IPCResult
1128
WorkerPermissionRequestChildProcessActor::Recv__delete__(
1129
                                              const uint32_t& /* aPermission */)
1130
0
{
1131
0
  MOZ_ASSERT(NS_IsMainThread());
1132
0
  mChallenge->OperationCompleted();
1133
0
  return IPC_OK();
1134
0
}
1135
1136
class MOZ_STACK_CLASS AutoSetCurrentFileHandle final
1137
{
1138
  typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
1139
1140
  IDBFileHandle* const mFileHandle;
1141
  IDBFileHandle* mPreviousFileHandle;
1142
  IDBFileHandle** mThreadLocalSlot;
1143
1144
public:
1145
  explicit AutoSetCurrentFileHandle(IDBFileHandle* aFileHandle)
1146
    : mFileHandle(aFileHandle)
1147
    , mPreviousFileHandle(nullptr)
1148
    , mThreadLocalSlot(nullptr)
1149
0
  {
1150
0
    if (aFileHandle) {
1151
0
      BackgroundChildImpl::ThreadLocal* threadLocal =
1152
0
        BackgroundChildImpl::GetThreadLocalForCurrentThread();
1153
0
      MOZ_ASSERT(threadLocal);
1154
0
1155
0
      // Hang onto this location for resetting later.
1156
0
      mThreadLocalSlot = &threadLocal->mCurrentFileHandle;
1157
0
1158
0
      // Save the current value.
1159
0
      mPreviousFileHandle = *mThreadLocalSlot;
1160
0
1161
0
      // Set the new value.
1162
0
      *mThreadLocalSlot = aFileHandle;
1163
0
    }
1164
0
  }
1165
1166
  ~AutoSetCurrentFileHandle()
1167
0
  {
1168
0
    MOZ_ASSERT_IF(mThreadLocalSlot, mFileHandle);
1169
0
    MOZ_ASSERT_IF(mThreadLocalSlot, *mThreadLocalSlot == mFileHandle);
1170
0
1171
0
    if (mThreadLocalSlot) {
1172
0
      // Reset old value.
1173
0
      *mThreadLocalSlot = mPreviousFileHandle;
1174
0
    }
1175
0
  }
1176
1177
  IDBFileHandle*
1178
  FileHandle() const
1179
0
  {
1180
0
    return mFileHandle;
1181
0
  }
1182
};
1183
1184
class MOZ_STACK_CLASS FileHandleResultHelper final
1185
  : public IDBFileRequest::ResultCallback
1186
{
1187
  IDBFileRequest* mFileRequest;
1188
  AutoSetCurrentFileHandle mAutoFileHandle;
1189
1190
  union
1191
  {
1192
    File* mFile;
1193
    const nsCString* mString;
1194
    const FileRequestMetadata* mMetadata;
1195
    const JS::Handle<JS::Value>* mJSValHandle;
1196
  } mResult;
1197
1198
  enum
1199
  {
1200
    ResultTypeFile,
1201
    ResultTypeString,
1202
    ResultTypeMetadata,
1203
    ResultTypeJSValHandle,
1204
  } mResultType;
1205
1206
public:
1207
  FileHandleResultHelper(IDBFileRequest* aFileRequest,
1208
                         IDBFileHandle* aFileHandle,
1209
                         File* aResult)
1210
    : mFileRequest(aFileRequest)
1211
    , mAutoFileHandle(aFileHandle)
1212
    , mResultType(ResultTypeFile)
1213
0
  {
1214
0
    MOZ_ASSERT(aFileRequest);
1215
0
    MOZ_ASSERT(aFileHandle);
1216
0
    MOZ_ASSERT(aResult);
1217
0
1218
0
    mResult.mFile = aResult;
1219
0
  }
1220
1221
  FileHandleResultHelper(IDBFileRequest* aFileRequest,
1222
                         IDBFileHandle* aFileHandle,
1223
                         const nsCString* aResult)
1224
    : mFileRequest(aFileRequest)
1225
    , mAutoFileHandle(aFileHandle)
1226
    , mResultType(ResultTypeString)
1227
0
  {
1228
0
    MOZ_ASSERT(aFileRequest);
1229
0
    MOZ_ASSERT(aFileHandle);
1230
0
    MOZ_ASSERT(aResult);
1231
0
1232
0
    mResult.mString = aResult;
1233
0
  }
1234
1235
  FileHandleResultHelper(IDBFileRequest* aFileRequest,
1236
                         IDBFileHandle* aFileHandle,
1237
                         const FileRequestMetadata* aResult)
1238
    : mFileRequest(aFileRequest)
1239
    , mAutoFileHandle(aFileHandle)
1240
    , mResultType(ResultTypeMetadata)
1241
0
  {
1242
0
    MOZ_ASSERT(aFileRequest);
1243
0
    MOZ_ASSERT(aFileHandle);
1244
0
    MOZ_ASSERT(aResult);
1245
0
1246
0
    mResult.mMetadata = aResult;
1247
0
  }
1248
1249
1250
  FileHandleResultHelper(IDBFileRequest* aFileRequest,
1251
                         IDBFileHandle* aFileHandle,
1252
                         const JS::Handle<JS::Value>* aResult)
1253
    : mFileRequest(aFileRequest)
1254
    , mAutoFileHandle(aFileHandle)
1255
    , mResultType(ResultTypeJSValHandle)
1256
0
  {
1257
0
    MOZ_ASSERT(aFileRequest);
1258
0
    MOZ_ASSERT(aFileHandle);
1259
0
    MOZ_ASSERT(aResult);
1260
0
1261
0
    mResult.mJSValHandle = aResult;
1262
0
  }
1263
1264
  IDBFileRequest*
1265
  FileRequest() const
1266
0
  {
1267
0
    return mFileRequest;
1268
0
  }
1269
1270
  IDBFileHandle*
1271
  FileHandle() const
1272
0
  {
1273
0
    return mAutoFileHandle.FileHandle();
1274
0
  }
1275
1276
  virtual nsresult
1277
  GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) override
1278
0
  {
1279
0
    MOZ_ASSERT(aCx);
1280
0
    MOZ_ASSERT(mFileRequest);
1281
0
1282
0
    switch (mResultType) {
1283
0
      case ResultTypeFile:
1284
0
        return GetResult(aCx, mResult.mFile, aResult);
1285
0
1286
0
      case ResultTypeString:
1287
0
        return GetResult(aCx, mResult.mString, aResult);
1288
0
1289
0
      case ResultTypeMetadata:
1290
0
        return GetResult(aCx, mResult.mMetadata, aResult);
1291
0
1292
0
      case ResultTypeJSValHandle:
1293
0
        aResult.set(*mResult.mJSValHandle);
1294
0
        return NS_OK;
1295
0
1296
0
      default:
1297
0
        MOZ_CRASH("Unknown result type!");
1298
0
    }
1299
0
1300
0
    MOZ_CRASH("Should never get here!");
1301
0
  }
1302
1303
private:
1304
  nsresult
1305
  GetResult(JSContext* aCx,
1306
            File* aFile,
1307
            JS::MutableHandle<JS::Value> aResult)
1308
0
  {
1309
0
    bool ok = GetOrCreateDOMReflector(aCx, aFile, aResult);
1310
0
    if (NS_WARN_IF(!ok)) {
1311
0
      return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1312
0
    }
1313
0
1314
0
    return NS_OK;
1315
0
  }
1316
1317
  nsresult
1318
  GetResult(JSContext* aCx,
1319
            const nsCString* aString,
1320
            JS::MutableHandle<JS::Value> aResult)
1321
0
  {
1322
0
    const nsCString& data = *aString;
1323
0
1324
0
    nsresult rv;
1325
0
1326
0
    if (!mFileRequest->HasEncoding()) {
1327
0
      JS::Rooted<JSObject*> arrayBuffer(aCx);
1328
0
      rv = nsContentUtils::CreateArrayBuffer(aCx, data, arrayBuffer.address());
1329
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
1330
0
        return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1331
0
      }
1332
0
1333
0
      aResult.setObject(*arrayBuffer);
1334
0
      return NS_OK;
1335
0
    }
1336
0
1337
0
    // Try the API argument.
1338
0
    const Encoding* encoding =
1339
0
      Encoding::ForLabel(mFileRequest->GetEncoding());
1340
0
    if (!encoding) {
1341
0
      // API argument failed. Since we are dealing with a file system file,
1342
0
      // we don't have a meaningful type attribute for the blob available,
1343
0
      // so proceeding to the next step, which is defaulting to UTF-8.
1344
0
      encoding = UTF_8_ENCODING;
1345
0
    }
1346
0
1347
0
    nsString tmpString;
1348
0
    Tie(rv, encoding) = encoding->Decode(data, tmpString);
1349
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
1350
0
      return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1351
0
    }
1352
0
    rv = NS_OK;
1353
0
1354
0
    if (NS_WARN_IF(!xpc::StringToJsval(aCx, tmpString, aResult))) {
1355
0
      return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1356
0
    }
1357
0
1358
0
    return NS_OK;
1359
0
  }
1360
1361
  nsresult
1362
  GetResult(JSContext* aCx,
1363
            const FileRequestMetadata* aMetadata,
1364
            JS::MutableHandle<JS::Value> aResult)
1365
0
  {
1366
0
    JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
1367
0
    if (NS_WARN_IF(!obj)) {
1368
0
      return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1369
0
    }
1370
0
1371
0
    const FileRequestSize& size = aMetadata->size();
1372
0
    if (size.type() != FileRequestSize::Tvoid_t) {
1373
0
      MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
1374
0
1375
0
      JS::Rooted<JS::Value> number(aCx, JS_NumberValue(size.get_uint64_t()));
1376
0
1377
0
      if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "size", number, 0))) {
1378
0
        return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1379
0
      }
1380
0
    }
1381
0
1382
0
    const FileRequestLastModified& lastModified = aMetadata->lastModified();
1383
0
    if (lastModified.type() != FileRequestLastModified::Tvoid_t) {
1384
0
      MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
1385
0
1386
0
      JS::Rooted<JSObject*> date(aCx,
1387
0
        JS::NewDateObject(aCx, JS::TimeClip(lastModified.get_int64_t())));
1388
0
      if (NS_WARN_IF(!date)) {
1389
0
        return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1390
0
      }
1391
0
1392
0
      if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "lastModified", date, 0))) {
1393
0
        return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
1394
0
      }
1395
0
    }
1396
0
1397
0
    aResult.setObject(*obj);
1398
0
    return NS_OK;
1399
0
  }
1400
};
1401
1402
already_AddRefed<File>
1403
ConvertActorToFile(IDBFileHandle* aFileHandle,
1404
                   const FileRequestGetFileResponse& aResponse)
1405
0
{
1406
0
  auto* actor = static_cast<PendingIPCBlobChild*>(aResponse.fileChild());
1407
0
1408
0
  IDBMutableFile* mutableFile = aFileHandle->GetMutableFile();
1409
0
  MOZ_ASSERT(mutableFile);
1410
0
1411
0
  const FileRequestMetadata& metadata = aResponse.metadata();
1412
0
1413
0
  const FileRequestSize& size = metadata.size();
1414
0
  MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
1415
0
1416
0
  const FileRequestLastModified& lastModified = metadata.lastModified();
1417
0
  MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
1418
0
1419
0
  RefPtr<BlobImpl> blobImpl =
1420
0
    actor->SetPendingInfoAndDeleteActor(mutableFile->Name(),
1421
0
                                        mutableFile->Type(),
1422
0
                                        size.get_uint64_t(),
1423
0
                                        lastModified.get_int64_t());
1424
0
  MOZ_ASSERT(blobImpl);
1425
0
1426
0
  RefPtr<BlobImpl> blobImplSnapshot =
1427
0
    new BlobImplSnapshot(blobImpl, static_cast<IDBFileHandle*>(aFileHandle));
1428
0
1429
0
  RefPtr<File> file = File::Create(mutableFile->GetOwner(), blobImplSnapshot);
1430
0
  return file.forget();
1431
0
}
1432
1433
void
1434
DispatchFileHandleErrorEvent(IDBFileRequest* aFileRequest,
1435
                             nsresult aErrorCode,
1436
                             IDBFileHandle* aFileHandle)
1437
0
{
1438
0
  MOZ_ASSERT(aFileRequest);
1439
0
  aFileRequest->AssertIsOnOwningThread();
1440
0
  MOZ_ASSERT(NS_FAILED(aErrorCode));
1441
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_FILEHANDLE);
1442
0
  MOZ_ASSERT(aFileHandle);
1443
0
1444
0
  RefPtr<IDBFileRequest> fileRequest = aFileRequest;
1445
0
  RefPtr<IDBFileHandle> fileHandle = aFileHandle;
1446
0
1447
0
  AutoSetCurrentFileHandle ascfh(aFileHandle);
1448
0
1449
0
  fileRequest->FireError(aErrorCode);
1450
0
1451
0
  MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
1452
0
}
1453
1454
void
1455
DispatchFileHandleSuccessEvent(FileHandleResultHelper* aResultHelper)
1456
0
{
1457
0
  MOZ_ASSERT(aResultHelper);
1458
0
1459
0
  RefPtr<IDBFileRequest> fileRequest = aResultHelper->FileRequest();
1460
0
  MOZ_ASSERT(fileRequest);
1461
0
  fileRequest->AssertIsOnOwningThread();
1462
0
1463
0
  RefPtr<IDBFileHandle> fileHandle = aResultHelper->FileHandle();
1464
0
  MOZ_ASSERT(fileHandle);
1465
0
1466
0
  if (fileHandle->IsAborted()) {
1467
0
    fileRequest->FireError(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
1468
0
    return;
1469
0
  }
1470
0
1471
0
  MOZ_ASSERT(fileHandle->IsOpen());
1472
0
1473
0
  fileRequest->SetResultCallback(aResultHelper);
1474
0
1475
0
  MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
1476
0
}
1477
1478
} // namespace
1479
1480
/*******************************************************************************
1481
 * Actor class declarations
1482
 ******************************************************************************/
1483
1484
// CancelableRunnable is used to make workers happy.
1485
class BackgroundRequestChild::PreprocessHelper final
1486
  : public CancelableRunnable
1487
  , public nsIInputStreamCallback
1488
  , public nsIFileMetadataCallback
1489
{
1490
  nsCOMPtr<nsIEventTarget> mOwningEventTarget;
1491
  nsTArray<nsCOMPtr<nsIInputStream>> mStreams;
1492
  nsTArray<RefPtr<JS::WasmModule>> mModuleSet;
1493
  BackgroundRequestChild* mActor;
1494
1495
  // This is populated when the processing of the stream runs.
1496
  PRFileDesc* mCurrentBytecodeFileDesc;
1497
1498
  RefPtr<TaskQueue> mTaskQueue;
1499
  nsCOMPtr<nsIEventTarget> mTaskQueueEventTarget;
1500
1501
  uint32_t mModuleSetIndex;
1502
  nsresult mResultCode;
1503
1504
public:
1505
  PreprocessHelper(uint32_t aModuleSetIndex, BackgroundRequestChild* aActor)
1506
    : CancelableRunnable("indexedDB::BackgroundRequestChild::PreprocessHelper")
1507
    , mOwningEventTarget(aActor->GetActorEventTarget())
1508
    , mActor(aActor)
1509
    , mCurrentBytecodeFileDesc(nullptr)
1510
    , mModuleSetIndex(aModuleSetIndex)
1511
    , mResultCode(NS_OK)
1512
0
  {
1513
0
    AssertIsOnOwningThread();
1514
0
    MOZ_ASSERT(aActor);
1515
0
    aActor->AssertIsOnOwningThread();
1516
0
  }
1517
1518
  bool
1519
  IsOnOwningThread() const
1520
0
  {
1521
0
    MOZ_ASSERT(mOwningEventTarget);
1522
0
1523
0
    bool current;
1524
0
    return NS_SUCCEEDED(mOwningEventTarget->IsOnCurrentThread(&current)) && current;
1525
0
  }
1526
1527
  void
1528
  AssertIsOnOwningThread() const
1529
0
  {
1530
0
    MOZ_ASSERT(IsOnOwningThread());
1531
0
  }
1532
1533
  void
1534
  ClearActor()
1535
0
  {
1536
0
    AssertIsOnOwningThread();
1537
0
1538
0
    mActor = nullptr;
1539
0
  }
1540
1541
  nsresult
1542
  Init(const nsTArray<StructuredCloneFile>& aFiles);
1543
1544
  nsresult
1545
  Dispatch();
1546
1547
private:
1548
  ~PreprocessHelper()
1549
0
  {
1550
0
    if (mTaskQueue) {
1551
0
      mTaskQueue->BeginShutdown();
1552
0
    }
1553
0
  }
1554
1555
  void
1556
  RunOnOwningThread();
1557
1558
  void
1559
  ProcessCurrentStream();
1560
1561
  nsresult
1562
  WaitForStreamReady(nsIInputStream* aInputStream);
1563
1564
  void
1565
  ContinueWithStatus(nsresult aStatus);
1566
1567
  nsresult
1568
  DataIsReady(nsIInputStream* aInputStream);
1569
1570
  NS_DECL_ISUPPORTS_INHERITED
1571
  NS_DECL_NSIRUNNABLE
1572
  NS_DECL_NSIINPUTSTREAMCALLBACK
1573
  NS_DECL_NSIFILEMETADATACALLBACK
1574
1575
  virtual nsresult
1576
  Cancel() override;
1577
};
1578
1579
/*******************************************************************************
1580
 * Local class implementations
1581
 ******************************************************************************/
1582
1583
void
1584
PermissionRequestMainProcessHelper::OnPromptComplete(
1585
                                               PermissionValue aPermissionValue)
1586
0
{
1587
0
  MOZ_ASSERT(mActor);
1588
0
  mActor->AssertIsOnOwningThread();
1589
0
1590
0
  MaybeCollectGarbageOnIPCMessage();
1591
0
1592
0
  mActor->SendPermissionRetry();
1593
0
1594
0
  mActor = nullptr;
1595
0
  mFactory = nullptr;
1596
0
}
1597
1598
mozilla::ipc::IPCResult
1599
PermissionRequestChildProcessActor::Recv__delete__(
1600
                                              const uint32_t& /* aPermission */)
1601
0
{
1602
0
  MOZ_ASSERT(mActor);
1603
0
  mActor->AssertIsOnOwningThread();
1604
0
  MOZ_ASSERT(mFactory);
1605
0
1606
0
  MaybeCollectGarbageOnIPCMessage();
1607
0
1608
0
  RefPtr<IDBFactory> factory;
1609
0
  mFactory.swap(factory);
1610
0
1611
0
  mActor->SendPermissionRetry();
1612
0
  mActor = nullptr;
1613
0
1614
0
  return IPC_OK();
1615
0
}
1616
1617
/*******************************************************************************
1618
 * BackgroundRequestChildBase
1619
 ******************************************************************************/
1620
1621
BackgroundRequestChildBase::BackgroundRequestChildBase(IDBRequest* aRequest)
1622
  : mRequest(aRequest)
1623
0
{
1624
0
  MOZ_ASSERT(aRequest);
1625
0
  aRequest->AssertIsOnOwningThread();
1626
0
1627
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChildBase);
1628
0
}
1629
1630
BackgroundRequestChildBase::~BackgroundRequestChildBase()
1631
0
{
1632
0
  AssertIsOnOwningThread();
1633
0
1634
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChildBase);
1635
0
}
1636
1637
#ifdef DEBUG
1638
1639
void
1640
BackgroundRequestChildBase::AssertIsOnOwningThread() const
1641
{
1642
  MOZ_ASSERT(mRequest);
1643
  mRequest->AssertIsOnOwningThread();
1644
}
1645
1646
#endif // DEBUG
1647
1648
/*******************************************************************************
1649
 * BackgroundFactoryChild
1650
 ******************************************************************************/
1651
1652
BackgroundFactoryChild::BackgroundFactoryChild(IDBFactory* aFactory)
1653
  : mFactory(aFactory)
1654
0
{
1655
0
  AssertIsOnOwningThread();
1656
0
  MOZ_ASSERT(aFactory);
1657
0
  aFactory->AssertIsOnOwningThread();
1658
0
1659
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryChild);
1660
0
}
1661
1662
BackgroundFactoryChild::~BackgroundFactoryChild()
1663
0
{
1664
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryChild);
1665
0
}
1666
1667
void
1668
BackgroundFactoryChild::SendDeleteMeInternal()
1669
0
{
1670
0
  AssertIsOnOwningThread();
1671
0
1672
0
  if (mFactory) {
1673
0
    mFactory->ClearBackgroundActor();
1674
0
    mFactory = nullptr;
1675
0
1676
0
    MOZ_ALWAYS_TRUE(PBackgroundIDBFactoryChild::SendDeleteMe());
1677
0
  }
1678
0
}
1679
1680
void
1681
BackgroundFactoryChild::ActorDestroy(ActorDestroyReason aWhy)
1682
0
{
1683
0
  AssertIsOnOwningThread();
1684
0
1685
0
  MaybeCollectGarbageOnIPCMessage();
1686
0
1687
0
  if (mFactory) {
1688
0
    mFactory->ClearBackgroundActor();
1689
#ifdef DEBUG
1690
    mFactory = nullptr;
1691
#endif
1692
  }
1693
0
}
1694
1695
PBackgroundIDBFactoryRequestChild*
1696
BackgroundFactoryChild::AllocPBackgroundIDBFactoryRequestChild(
1697
                                            const FactoryRequestParams& aParams)
1698
0
{
1699
0
  MOZ_CRASH("PBackgroundIDBFactoryRequestChild actors should be manually "
1700
0
            "constructed!");
1701
0
}
1702
1703
bool
1704
BackgroundFactoryChild::DeallocPBackgroundIDBFactoryRequestChild(
1705
                                      PBackgroundIDBFactoryRequestChild* aActor)
1706
0
{
1707
0
  MOZ_ASSERT(aActor);
1708
0
1709
0
  delete static_cast<BackgroundFactoryRequestChild*>(aActor);
1710
0
  return true;
1711
0
}
1712
1713
PBackgroundIDBDatabaseChild*
1714
BackgroundFactoryChild::AllocPBackgroundIDBDatabaseChild(
1715
                                    const DatabaseSpec& aSpec,
1716
                                    PBackgroundIDBFactoryRequestChild* aRequest)
1717
0
{
1718
0
  AssertIsOnOwningThread();
1719
0
1720
0
  auto request = static_cast<BackgroundFactoryRequestChild*>(aRequest);
1721
0
  MOZ_ASSERT(request);
1722
0
1723
0
  return new BackgroundDatabaseChild(aSpec, request);
1724
0
}
1725
1726
bool
1727
BackgroundFactoryChild::DeallocPBackgroundIDBDatabaseChild(
1728
                                            PBackgroundIDBDatabaseChild* aActor)
1729
0
{
1730
0
  MOZ_ASSERT(aActor);
1731
0
1732
0
  delete static_cast<BackgroundDatabaseChild*>(aActor);
1733
0
  return true;
1734
0
}
1735
1736
mozilla::ipc::IPCResult
1737
BackgroundFactoryChild::RecvPBackgroundIDBDatabaseConstructor(
1738
                                    PBackgroundIDBDatabaseChild* aActor,
1739
                                    const DatabaseSpec& aSpec,
1740
                                    PBackgroundIDBFactoryRequestChild* aRequest)
1741
0
{
1742
0
  AssertIsOnOwningThread();
1743
0
  MOZ_ASSERT(aActor);
1744
0
  MOZ_ASSERT(aActor->GetActorEventTarget(),
1745
0
    "The event target shall be inherited from its manager actor.");
1746
0
1747
0
  return IPC_OK();
1748
0
}
1749
1750
/*******************************************************************************
1751
 * BackgroundFactoryRequestChild
1752
 ******************************************************************************/
1753
1754
BackgroundFactoryRequestChild::BackgroundFactoryRequestChild(
1755
                                               IDBFactory* aFactory,
1756
                                               IDBOpenDBRequest* aOpenRequest,
1757
                                               bool aIsDeleteOp,
1758
                                               uint64_t aRequestedVersion)
1759
  : BackgroundRequestChildBase(aOpenRequest)
1760
  , mFactory(aFactory)
1761
  , mDatabaseActor(nullptr)
1762
  , mRequestedVersion(aRequestedVersion)
1763
  , mIsDeleteOp(aIsDeleteOp)
1764
0
{
1765
0
  // Can't assert owning thread here because IPDL has not yet set our manager!
1766
0
  MOZ_ASSERT(aFactory);
1767
0
  aFactory->AssertIsOnOwningThread();
1768
0
  MOZ_ASSERT(aOpenRequest);
1769
0
1770
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryRequestChild);
1771
0
}
1772
1773
BackgroundFactoryRequestChild::~BackgroundFactoryRequestChild()
1774
0
{
1775
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryRequestChild);
1776
0
}
1777
1778
IDBOpenDBRequest*
1779
BackgroundFactoryRequestChild::GetOpenDBRequest() const
1780
0
{
1781
0
  AssertIsOnOwningThread();
1782
0
1783
0
  return static_cast<IDBOpenDBRequest*>(mRequest.get());
1784
0
}
1785
1786
void
1787
BackgroundFactoryRequestChild::SetDatabaseActor(BackgroundDatabaseChild* aActor)
1788
0
{
1789
0
  AssertIsOnOwningThread();
1790
0
  MOZ_ASSERT(!aActor || !mDatabaseActor);
1791
0
1792
0
  mDatabaseActor = aActor;
1793
0
}
1794
1795
bool
1796
BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse)
1797
0
{
1798
0
  AssertIsOnOwningThread();
1799
0
  MOZ_ASSERT(NS_FAILED(aResponse));
1800
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
1801
0
1802
0
  mRequest->Reset();
1803
0
1804
0
  DispatchErrorEvent(mRequest, aResponse);
1805
0
1806
0
  if (mDatabaseActor) {
1807
0
    mDatabaseActor->ReleaseDOMObject();
1808
0
    MOZ_ASSERT(!mDatabaseActor);
1809
0
  }
1810
0
1811
0
  return true;
1812
0
}
1813
1814
bool
1815
BackgroundFactoryRequestChild::HandleResponse(
1816
                                   const OpenDatabaseRequestResponse& aResponse)
1817
0
{
1818
0
  AssertIsOnOwningThread();
1819
0
1820
0
  mRequest->Reset();
1821
0
1822
0
  auto databaseActor =
1823
0
    static_cast<BackgroundDatabaseChild*>(aResponse.databaseChild());
1824
0
  MOZ_ASSERT(databaseActor);
1825
0
1826
0
  IDBDatabase* database = databaseActor->GetDOMObject();
1827
0
  if (!database) {
1828
0
    databaseActor->EnsureDOMObject();
1829
0
    MOZ_ASSERT(mDatabaseActor);
1830
0
1831
0
    database = databaseActor->GetDOMObject();
1832
0
    MOZ_ASSERT(database);
1833
0
1834
0
    MOZ_ASSERT(!database->IsClosed());
1835
0
  }
1836
0
1837
0
  MOZ_ASSERT(mDatabaseActor == databaseActor);
1838
0
1839
0
  if (database->IsClosed()) {
1840
0
    // If the database was closed already, which is only possible if we fired an
1841
0
    // "upgradeneeded" event, then we shouldn't fire a "success" event here.
1842
0
    // Instead we fire an error event with AbortErr.
1843
0
    DispatchErrorEvent(mRequest, NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
1844
0
  } else {
1845
0
    ResultHelper helper(mRequest, nullptr, database);
1846
0
1847
0
    DispatchSuccessEvent(&helper);
1848
0
  }
1849
0
1850
0
  databaseActor->ReleaseDOMObject();
1851
0
  MOZ_ASSERT(!mDatabaseActor);
1852
0
1853
0
  return true;
1854
0
}
1855
1856
bool
1857
BackgroundFactoryRequestChild::HandleResponse(
1858
                                 const DeleteDatabaseRequestResponse& aResponse)
1859
0
{
1860
0
  AssertIsOnOwningThread();
1861
0
1862
0
  ResultHelper helper(mRequest, nullptr, &JS::UndefinedHandleValue);
1863
0
1864
0
  RefPtr<Event> successEvent =
1865
0
    IDBVersionChangeEvent::Create(mRequest,
1866
0
                                  nsDependentString(kSuccessEventType),
1867
0
                                  aResponse.previousVersion());
1868
0
  MOZ_ASSERT(successEvent);
1869
0
1870
0
  DispatchSuccessEvent(&helper, successEvent);
1871
0
1872
0
  MOZ_ASSERT(!mDatabaseActor);
1873
0
1874
0
  return true;
1875
0
}
1876
1877
void
1878
BackgroundFactoryRequestChild::ActorDestroy(ActorDestroyReason aWhy)
1879
0
{
1880
0
  AssertIsOnOwningThread();
1881
0
1882
0
  MaybeCollectGarbageOnIPCMessage();
1883
0
1884
0
  if (aWhy != Deletion) {
1885
0
    IDBOpenDBRequest* openRequest = GetOpenDBRequest();
1886
0
    if (openRequest) {
1887
0
      openRequest->NoteComplete();
1888
0
    }
1889
0
  }
1890
0
}
1891
1892
mozilla::ipc::IPCResult
1893
BackgroundFactoryRequestChild::Recv__delete__(
1894
                                        const FactoryRequestResponse& aResponse)
1895
0
{
1896
0
  AssertIsOnOwningThread();
1897
0
  MOZ_ASSERT(mRequest);
1898
0
1899
0
  MaybeCollectGarbageOnIPCMessage();
1900
0
1901
0
  bool result;
1902
0
1903
0
  switch (aResponse.type()) {
1904
0
    case FactoryRequestResponse::Tnsresult:
1905
0
      result = HandleResponse(aResponse.get_nsresult());
1906
0
      break;
1907
0
1908
0
    case FactoryRequestResponse::TOpenDatabaseRequestResponse:
1909
0
      result = HandleResponse(aResponse.get_OpenDatabaseRequestResponse());
1910
0
      break;
1911
0
1912
0
    case FactoryRequestResponse::TDeleteDatabaseRequestResponse:
1913
0
      result = HandleResponse(aResponse.get_DeleteDatabaseRequestResponse());
1914
0
      break;
1915
0
1916
0
    default:
1917
0
      MOZ_CRASH("Unknown response type!");
1918
0
  }
1919
0
1920
0
  IDBOpenDBRequest* request = GetOpenDBRequest();
1921
0
  MOZ_ASSERT(request);
1922
0
1923
0
  request->NoteComplete();
1924
0
1925
0
  if (NS_WARN_IF(!result)) {
1926
0
    return IPC_FAIL_NO_REASON(this);
1927
0
  }
1928
0
1929
0
  return IPC_OK();
1930
0
}
1931
1932
mozilla::ipc::IPCResult
1933
BackgroundFactoryRequestChild::RecvPermissionChallenge(
1934
                                            const PrincipalInfo& aPrincipalInfo)
1935
0
{
1936
0
  AssertIsOnOwningThread();
1937
0
1938
0
  MaybeCollectGarbageOnIPCMessage();
1939
0
1940
0
  if (!NS_IsMainThread()) {
1941
0
    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
1942
0
    MOZ_ASSERT(workerPrivate);
1943
0
    workerPrivate->AssertIsOnWorkerThread();
1944
0
1945
0
    RefPtr<WorkerPermissionChallenge> challenge =
1946
0
      new WorkerPermissionChallenge(workerPrivate, this, mFactory,
1947
0
                                    aPrincipalInfo);
1948
0
    if (!challenge->Dispatch()) {
1949
0
      return IPC_FAIL_NO_REASON(this);
1950
0
    }
1951
0
    return IPC_OK();
1952
0
  }
1953
0
1954
0
  nsresult rv;
1955
0
  nsCOMPtr<nsIPrincipal> principal =
1956
0
    mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
1957
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
1958
0
    return IPC_FAIL_NO_REASON(this);
1959
0
  }
1960
0
1961
0
  if (XRE_IsParentProcess()) {
1962
0
    nsCOMPtr<nsPIDOMWindowInner> window = mFactory->GetParentObject();
1963
0
    MOZ_ASSERT(window);
1964
0
1965
0
    nsCOMPtr<Element> ownerElement =
1966
0
      do_QueryInterface(window->GetChromeEventHandler());
1967
0
    if (NS_WARN_IF(!ownerElement)) {
1968
0
      // If this fails, the page was navigated. Fail the permission check by
1969
0
      // forcing an immediate retry.
1970
0
      if (!SendPermissionRetry()) {
1971
0
        return IPC_FAIL_NO_REASON(this);
1972
0
      }
1973
0
      return IPC_OK();
1974
0
    }
1975
0
1976
0
    RefPtr<PermissionRequestMainProcessHelper> helper =
1977
0
      new PermissionRequestMainProcessHelper(this, mFactory, ownerElement, principal);
1978
0
1979
0
    PermissionRequestBase::PermissionValue permission;
1980
0
    if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {
1981
0
      return IPC_FAIL_NO_REASON(this);
1982
0
    }
1983
0
1984
0
    MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
1985
0
               permission == PermissionRequestBase::kPermissionDenied ||
1986
0
               permission == PermissionRequestBase::kPermissionPrompt);
1987
0
1988
0
    if (permission != PermissionRequestBase::kPermissionPrompt) {
1989
0
      SendPermissionRetry();
1990
0
    }
1991
0
    return IPC_OK();
1992
0
  }
1993
0
1994
0
  RefPtr<TabChild> tabChild = mFactory->GetTabChild();
1995
0
  MOZ_ASSERT(tabChild);
1996
0
1997
0
  IPC::Principal ipcPrincipal(principal);
1998
0
1999
0
  auto* actor = new PermissionRequestChildProcessActor(this, mFactory);
2000
0
2001
0
  tabChild->SetEventTargetForActor(actor, this->GetActorEventTarget());
2002
0
  MOZ_ASSERT(actor->GetActorEventTarget());
2003
0
  tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
2004
0
2005
0
  return IPC_OK();
2006
0
}
2007
2008
mozilla::ipc::IPCResult
2009
BackgroundFactoryRequestChild::RecvBlocked(const uint64_t& aCurrentVersion)
2010
0
{
2011
0
  AssertIsOnOwningThread();
2012
0
  MOZ_ASSERT(mRequest);
2013
0
2014
0
  MaybeCollectGarbageOnIPCMessage();
2015
0
2016
0
  const nsDependentString type(kBlockedEventType);
2017
0
2018
0
  RefPtr<Event> blockedEvent;
2019
0
  if (mIsDeleteOp) {
2020
0
    blockedEvent =
2021
0
      IDBVersionChangeEvent::Create(mRequest, type, aCurrentVersion);
2022
0
    MOZ_ASSERT(blockedEvent);
2023
0
  } else {
2024
0
    blockedEvent =
2025
0
      IDBVersionChangeEvent::Create(mRequest,
2026
0
                                    type,
2027
0
                                    aCurrentVersion,
2028
0
                                    mRequestedVersion);
2029
0
    MOZ_ASSERT(blockedEvent);
2030
0
  }
2031
0
2032
0
  RefPtr<IDBRequest> kungFuDeathGrip = mRequest;
2033
0
2034
0
  IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: Firing \"blocked\" event",
2035
0
               "IndexedDB %s: C R[%llu]: \"blocked\"",
2036
0
               IDB_LOG_ID_STRING(),
2037
0
               kungFuDeathGrip->LoggingSerialNumber());
2038
0
2039
0
  IgnoredErrorResult rv;
2040
0
  kungFuDeathGrip->DispatchEvent(*blockedEvent, rv);
2041
0
  if (rv.Failed()) {
2042
0
    NS_WARNING("Failed to dispatch event!");
2043
0
  }
2044
0
2045
0
  return IPC_OK();
2046
0
}
2047
2048
/*******************************************************************************
2049
 * BackgroundDatabaseChild
2050
 ******************************************************************************/
2051
2052
BackgroundDatabaseChild::BackgroundDatabaseChild(
2053
                               const DatabaseSpec& aSpec,
2054
                               BackgroundFactoryRequestChild* aOpenRequestActor)
2055
  : mSpec(new DatabaseSpec(aSpec))
2056
  , mOpenRequestActor(aOpenRequestActor)
2057
  , mDatabase(nullptr)
2058
0
{
2059
0
  // Can't assert owning thread here because IPDL has not yet set our manager!
2060
0
  MOZ_ASSERT(aOpenRequestActor);
2061
0
2062
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseChild);
2063
0
}
2064
2065
BackgroundDatabaseChild::~BackgroundDatabaseChild()
2066
0
{
2067
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseChild);
2068
0
}
2069
2070
#ifdef DEBUG
2071
2072
void
2073
BackgroundDatabaseChild::AssertIsOnOwningThread() const
2074
{
2075
  static_cast<BackgroundFactoryChild*>(Manager())->AssertIsOnOwningThread();
2076
}
2077
2078
#endif // DEBUG
2079
2080
void
2081
BackgroundDatabaseChild::SendDeleteMeInternal()
2082
0
{
2083
0
  AssertIsOnOwningThread();
2084
0
  MOZ_ASSERT(!mTemporaryStrongDatabase);
2085
0
  MOZ_ASSERT(!mOpenRequestActor);
2086
0
2087
0
  if (mDatabase) {
2088
0
    mDatabase->ClearBackgroundActor();
2089
0
    mDatabase = nullptr;
2090
0
2091
0
    MOZ_ALWAYS_TRUE(PBackgroundIDBDatabaseChild::SendDeleteMe());
2092
0
  }
2093
0
}
2094
2095
void
2096
BackgroundDatabaseChild::EnsureDOMObject()
2097
0
{
2098
0
  AssertIsOnOwningThread();
2099
0
  MOZ_ASSERT(mOpenRequestActor);
2100
0
2101
0
  if (mTemporaryStrongDatabase) {
2102
0
    MOZ_ASSERT(!mSpec);
2103
0
    return;
2104
0
  }
2105
0
2106
0
  MOZ_ASSERT(mSpec);
2107
0
2108
0
  auto request = mOpenRequestActor->GetOpenDBRequest();
2109
0
  MOZ_ASSERT(request);
2110
0
2111
0
  auto factory =
2112
0
    static_cast<BackgroundFactoryChild*>(Manager())->GetDOMObject();
2113
0
  MOZ_ASSERT(factory);
2114
0
2115
0
  mTemporaryStrongDatabase =
2116
0
    IDBDatabase::Create(request, factory, this, mSpec);
2117
0
2118
0
  MOZ_ASSERT(mTemporaryStrongDatabase);
2119
0
  mTemporaryStrongDatabase->AssertIsOnOwningThread();
2120
0
2121
0
  mDatabase = mTemporaryStrongDatabase;
2122
0
  mSpec.forget();
2123
0
2124
0
  mOpenRequestActor->SetDatabaseActor(this);
2125
0
}
2126
2127
void
2128
BackgroundDatabaseChild::ReleaseDOMObject()
2129
0
{
2130
0
  AssertIsOnOwningThread();
2131
0
  MOZ_ASSERT(mTemporaryStrongDatabase);
2132
0
  mTemporaryStrongDatabase->AssertIsOnOwningThread();
2133
0
  MOZ_ASSERT(mOpenRequestActor);
2134
0
  MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
2135
0
2136
0
  mOpenRequestActor->SetDatabaseActor(nullptr);
2137
0
2138
0
  mOpenRequestActor = nullptr;
2139
0
2140
0
  // This may be the final reference to the IDBDatabase object so we may end up
2141
0
  // calling SendDeleteMeInternal() here. Make sure everything is cleaned up
2142
0
  // properly before proceeding.
2143
0
  mTemporaryStrongDatabase = nullptr;
2144
0
}
2145
2146
void
2147
BackgroundDatabaseChild::ActorDestroy(ActorDestroyReason aWhy)
2148
0
{
2149
0
  AssertIsOnOwningThread();
2150
0
2151
0
  MaybeCollectGarbageOnIPCMessage();
2152
0
2153
0
  if (mDatabase) {
2154
0
    mDatabase->ClearBackgroundActor();
2155
#ifdef DEBUG
2156
    mDatabase = nullptr;
2157
#endif
2158
  }
2159
0
}
2160
2161
PBackgroundIDBDatabaseFileChild*
2162
BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseFileChild(
2163
                                                        const IPCBlob& aIPCBlob)
2164
0
{
2165
0
  MOZ_CRASH("PBackgroundIDBFileChild actors should be manually constructed!");
2166
0
}
2167
2168
bool
2169
BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseFileChild(
2170
                                        PBackgroundIDBDatabaseFileChild* aActor)
2171
0
{
2172
0
  AssertIsOnOwningThread();
2173
0
  MOZ_ASSERT(aActor);
2174
0
2175
0
  delete aActor;
2176
0
  return true;
2177
0
}
2178
2179
PBackgroundIDBDatabaseRequestChild*
2180
BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseRequestChild(
2181
                                           const DatabaseRequestParams& aParams)
2182
0
{
2183
0
  MOZ_CRASH("PBackgroundIDBDatabaseRequestChild actors should be manually "
2184
0
            "constructed!");
2185
0
}
2186
2187
bool
2188
BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseRequestChild(
2189
                                     PBackgroundIDBDatabaseRequestChild* aActor)
2190
0
{
2191
0
  MOZ_ASSERT(aActor);
2192
0
2193
0
  delete static_cast<BackgroundDatabaseRequestChild*>(aActor);
2194
0
  return true;
2195
0
}
2196
2197
PBackgroundIDBTransactionChild*
2198
BackgroundDatabaseChild::AllocPBackgroundIDBTransactionChild(
2199
                                    const nsTArray<nsString>& aObjectStoreNames,
2200
                                    const Mode& aMode)
2201
0
{
2202
0
  MOZ_CRASH("PBackgroundIDBTransactionChild actors should be manually "
2203
0
            "constructed!");
2204
0
}
2205
2206
bool
2207
BackgroundDatabaseChild::DeallocPBackgroundIDBTransactionChild(
2208
                                         PBackgroundIDBTransactionChild* aActor)
2209
0
{
2210
0
  MOZ_ASSERT(aActor);
2211
0
2212
0
  delete static_cast<BackgroundTransactionChild*>(aActor);
2213
0
  return true;
2214
0
}
2215
2216
PBackgroundIDBVersionChangeTransactionChild*
2217
BackgroundDatabaseChild::AllocPBackgroundIDBVersionChangeTransactionChild(
2218
                                              const uint64_t& aCurrentVersion,
2219
                                              const uint64_t& aRequestedVersion,
2220
                                              const int64_t& aNextObjectStoreId,
2221
                                              const int64_t& aNextIndexId)
2222
0
{
2223
0
  AssertIsOnOwningThread();
2224
0
2225
0
  IDBOpenDBRequest* request = mOpenRequestActor->GetOpenDBRequest();
2226
0
  MOZ_ASSERT(request);
2227
0
2228
0
  return new BackgroundVersionChangeTransactionChild(request);
2229
0
}
2230
2231
mozilla::ipc::IPCResult
2232
BackgroundDatabaseChild::RecvPBackgroundIDBVersionChangeTransactionConstructor(
2233
                            PBackgroundIDBVersionChangeTransactionChild* aActor,
2234
                            const uint64_t& aCurrentVersion,
2235
                            const uint64_t& aRequestedVersion,
2236
                            const int64_t& aNextObjectStoreId,
2237
                            const int64_t& aNextIndexId)
2238
0
{
2239
0
  AssertIsOnOwningThread();
2240
0
  MOZ_ASSERT(aActor);
2241
0
  MOZ_ASSERT(aActor->GetActorEventTarget(),
2242
0
    "The event target shall be inherited from its manager actor.");
2243
0
  MOZ_ASSERT(mOpenRequestActor);
2244
0
2245
0
  MaybeCollectGarbageOnIPCMessage();
2246
0
2247
0
  EnsureDOMObject();
2248
0
2249
0
  auto* actor = static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
2250
0
2251
0
  RefPtr<IDBOpenDBRequest> request = mOpenRequestActor->GetOpenDBRequest();
2252
0
  MOZ_ASSERT(request);
2253
0
2254
0
  RefPtr<IDBTransaction> transaction =
2255
0
    IDBTransaction::CreateVersionChange(mDatabase,
2256
0
                                        actor,
2257
0
                                        request,
2258
0
                                        aNextObjectStoreId,
2259
0
                                        aNextIndexId);
2260
0
  MOZ_ASSERT(transaction);
2261
0
2262
0
  transaction->AssertIsOnOwningThread();
2263
0
2264
0
  actor->SetDOMTransaction(transaction);
2265
0
2266
0
  mDatabase->EnterSetVersionTransaction(aRequestedVersion);
2267
0
2268
0
  request->SetTransaction(transaction);
2269
0
2270
0
  RefPtr<Event> upgradeNeededEvent =
2271
0
    IDBVersionChangeEvent::Create(request,
2272
0
                                  nsDependentString(kUpgradeNeededEventType),
2273
0
                                  aCurrentVersion,
2274
0
                                  aRequestedVersion);
2275
0
  MOZ_ASSERT(upgradeNeededEvent);
2276
0
2277
0
  ResultHelper helper(request, transaction, mDatabase);
2278
0
2279
0
  DispatchSuccessEvent(&helper, upgradeNeededEvent);
2280
0
2281
0
  return IPC_OK();
2282
0
}
2283
2284
bool
2285
BackgroundDatabaseChild::DeallocPBackgroundIDBVersionChangeTransactionChild(
2286
                            PBackgroundIDBVersionChangeTransactionChild* aActor)
2287
0
{
2288
0
  MOZ_ASSERT(aActor);
2289
0
2290
0
  delete static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
2291
0
  return true;
2292
0
}
2293
2294
PBackgroundMutableFileChild*
2295
BackgroundDatabaseChild::AllocPBackgroundMutableFileChild(const nsString& aName,
2296
                                                          const nsString& aType)
2297
0
{
2298
0
  AssertIsOnOwningThread();
2299
0
2300
0
  return new BackgroundMutableFileChild(aName, aType);
2301
0
}
2302
2303
bool
2304
BackgroundDatabaseChild::DeallocPBackgroundMutableFileChild(
2305
                                            PBackgroundMutableFileChild* aActor)
2306
0
{
2307
0
  MOZ_ASSERT(aActor);
2308
0
2309
0
  delete static_cast<BackgroundMutableFileChild*>(aActor);
2310
0
  return true;
2311
0
}
2312
2313
mozilla::ipc::IPCResult
2314
BackgroundDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion,
2315
                                           const NullableVersion& aNewVersion)
2316
0
{
2317
0
  AssertIsOnOwningThread();
2318
0
2319
0
  MaybeCollectGarbageOnIPCMessage();
2320
0
2321
0
  if (!mDatabase || mDatabase->IsClosed()) {
2322
0
    return IPC_OK();
2323
0
  }
2324
0
2325
0
  RefPtr<IDBDatabase> kungFuDeathGrip = mDatabase;
2326
0
2327
0
  // Handle bfcache'd windows.
2328
0
  if (nsPIDOMWindowInner* owner = kungFuDeathGrip->GetOwner()) {
2329
0
    // The database must be closed if the window is already frozen.
2330
0
    bool shouldAbortAndClose = owner->IsFrozen();
2331
0
2332
0
    // Anything in the bfcache has to be evicted and then we have to close the
2333
0
    // database also.
2334
0
    if (nsCOMPtr<nsIDocument> doc = owner->GetExtantDoc()) {
2335
0
      if (nsCOMPtr<nsIBFCacheEntry> bfCacheEntry = doc->GetBFCacheEntry()) {
2336
0
        bfCacheEntry->RemoveFromBFCacheSync();
2337
0
        shouldAbortAndClose = true;
2338
0
      }
2339
0
    }
2340
0
2341
0
    if (shouldAbortAndClose) {
2342
0
      // Invalidate() doesn't close the database in the parent, so we have
2343
0
      // to call Close() and AbortTransactions() manually.
2344
0
      kungFuDeathGrip->AbortTransactions(/* aShouldWarn */ false);
2345
0
      kungFuDeathGrip->Close();
2346
0
      return IPC_OK();
2347
0
    }
2348
0
  }
2349
0
2350
0
  // Otherwise fire a versionchange event.
2351
0
  const nsDependentString type(kVersionChangeEventType);
2352
0
2353
0
  RefPtr<Event> versionChangeEvent;
2354
0
2355
0
  switch (aNewVersion.type()) {
2356
0
    case NullableVersion::Tnull_t:
2357
0
      versionChangeEvent =
2358
0
        IDBVersionChangeEvent::Create(kungFuDeathGrip, type, aOldVersion);
2359
0
      MOZ_ASSERT(versionChangeEvent);
2360
0
      break;
2361
0
2362
0
    case NullableVersion::Tuint64_t:
2363
0
      versionChangeEvent =
2364
0
        IDBVersionChangeEvent::Create(kungFuDeathGrip,
2365
0
                                      type,
2366
0
                                      aOldVersion,
2367
0
                                      aNewVersion.get_uint64_t());
2368
0
      MOZ_ASSERT(versionChangeEvent);
2369
0
      break;
2370
0
2371
0
    default:
2372
0
      MOZ_CRASH("Should never get here!");
2373
0
  }
2374
0
2375
0
  IDB_LOG_MARK("IndexedDB %s: Child : Firing \"versionchange\" event",
2376
0
               "IndexedDB %s: C: IDBDatabase \"versionchange\" event",
2377
0
               IDB_LOG_ID_STRING());
2378
0
2379
0
  IgnoredErrorResult rv;
2380
0
  kungFuDeathGrip->DispatchEvent(*versionChangeEvent, rv);
2381
0
  if (rv.Failed()) {
2382
0
    NS_WARNING("Failed to dispatch event!");
2383
0
  }
2384
0
2385
0
  if (!kungFuDeathGrip->IsClosed()) {
2386
0
    SendBlocked();
2387
0
  }
2388
0
2389
0
  return IPC_OK();
2390
0
}
2391
2392
mozilla::ipc::IPCResult
2393
BackgroundDatabaseChild::RecvInvalidate()
2394
0
{
2395
0
  AssertIsOnOwningThread();
2396
0
2397
0
  MaybeCollectGarbageOnIPCMessage();
2398
0
2399
0
  if (mDatabase) {
2400
0
    mDatabase->Invalidate();
2401
0
  }
2402
0
2403
0
  return IPC_OK();
2404
0
}
2405
2406
mozilla::ipc::IPCResult
2407
BackgroundDatabaseChild::RecvCloseAfterInvalidationComplete()
2408
0
{
2409
0
  AssertIsOnOwningThread();
2410
0
2411
0
  MaybeCollectGarbageOnIPCMessage();
2412
0
2413
0
  if (mDatabase) {
2414
0
    mDatabase->DispatchTrustedEvent(nsDependentString(kCloseEventType));
2415
0
  }
2416
0
2417
0
  return IPC_OK();
2418
0
}
2419
2420
/*******************************************************************************
2421
 * BackgroundDatabaseRequestChild
2422
 ******************************************************************************/
2423
2424
BackgroundDatabaseRequestChild::BackgroundDatabaseRequestChild(
2425
                                                         IDBDatabase* aDatabase,
2426
                                                         IDBRequest* aRequest)
2427
  : BackgroundRequestChildBase(aRequest)
2428
  , mDatabase(aDatabase)
2429
0
{
2430
0
  // Can't assert owning thread here because IPDL has not yet set our manager!
2431
0
  MOZ_ASSERT(aDatabase);
2432
0
  aDatabase->AssertIsOnOwningThread();
2433
0
  MOZ_ASSERT(aRequest);
2434
0
2435
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseRequestChild);
2436
0
}
2437
2438
BackgroundDatabaseRequestChild::~BackgroundDatabaseRequestChild()
2439
0
{
2440
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseRequestChild);
2441
0
}
2442
2443
bool
2444
BackgroundDatabaseRequestChild::HandleResponse(nsresult aResponse)
2445
0
{
2446
0
  AssertIsOnOwningThread();
2447
0
  MOZ_ASSERT(NS_FAILED(aResponse));
2448
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
2449
0
2450
0
  mRequest->Reset();
2451
0
2452
0
  DispatchErrorEvent(mRequest, aResponse);
2453
0
2454
0
  return true;
2455
0
}
2456
2457
bool
2458
BackgroundDatabaseRequestChild::HandleResponse(
2459
                                     const CreateFileRequestResponse& aResponse)
2460
0
{
2461
0
  AssertIsOnOwningThread();
2462
0
2463
0
  mRequest->Reset();
2464
0
2465
0
  auto mutableFileActor =
2466
0
    static_cast<BackgroundMutableFileChild*>(aResponse.mutableFileChild());
2467
0
  MOZ_ASSERT(mutableFileActor);
2468
0
2469
0
  mutableFileActor->EnsureDOMObject();
2470
0
2471
0
  auto mutableFile =
2472
0
    static_cast<IDBMutableFile*>(mutableFileActor->GetDOMObject());
2473
0
  MOZ_ASSERT(mutableFile);
2474
0
2475
0
  ResultHelper helper(mRequest, nullptr, mutableFile);
2476
0
2477
0
  DispatchSuccessEvent(&helper);
2478
0
2479
0
  mutableFileActor->ReleaseDOMObject();
2480
0
2481
0
  return true;
2482
0
}
2483
2484
mozilla::ipc::IPCResult
2485
BackgroundDatabaseRequestChild::Recv__delete__(
2486
                                       const DatabaseRequestResponse& aResponse)
2487
0
{
2488
0
  AssertIsOnOwningThread();
2489
0
  MOZ_ASSERT(mRequest);
2490
0
2491
0
  switch (aResponse.type()) {
2492
0
    case DatabaseRequestResponse::Tnsresult:
2493
0
      if (!HandleResponse(aResponse.get_nsresult())) {
2494
0
        return IPC_FAIL_NO_REASON(this);
2495
0
      }
2496
0
      return IPC_OK();
2497
0
2498
0
    case DatabaseRequestResponse::TCreateFileRequestResponse:
2499
0
      if (!HandleResponse(aResponse.get_CreateFileRequestResponse())) {
2500
0
        return IPC_FAIL_NO_REASON(this);
2501
0
      }
2502
0
      return IPC_OK();
2503
0
2504
0
    default:
2505
0
      MOZ_CRASH("Unknown response type!");
2506
0
  }
2507
0
2508
0
  MOZ_CRASH("Should never get here!");
2509
0
}
2510
2511
/*******************************************************************************
2512
 * BackgroundTransactionBase
2513
 ******************************************************************************/
2514
2515
BackgroundTransactionBase::BackgroundTransactionBase()
2516
: mTransaction(nullptr)
2517
0
{
2518
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionBase);
2519
0
}
2520
2521
BackgroundTransactionBase::BackgroundTransactionBase(
2522
                                                   IDBTransaction* aTransaction)
2523
  : mTemporaryStrongTransaction(aTransaction)
2524
  , mTransaction(aTransaction)
2525
0
{
2526
0
  MOZ_ASSERT(aTransaction);
2527
0
  aTransaction->AssertIsOnOwningThread();
2528
0
2529
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionBase);
2530
0
}
2531
2532
BackgroundTransactionBase::~BackgroundTransactionBase()
2533
0
{
2534
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundTransactionBase);
2535
0
}
2536
2537
#ifdef DEBUG
2538
2539
void
2540
BackgroundTransactionBase::AssertIsOnOwningThread() const
2541
{
2542
  MOZ_ASSERT(mTransaction);
2543
  mTransaction->AssertIsOnOwningThread();
2544
}
2545
2546
#endif // DEBUG
2547
2548
void
2549
BackgroundTransactionBase::NoteActorDestroyed()
2550
0
{
2551
0
  AssertIsOnOwningThread();
2552
0
  MOZ_ASSERT_IF(mTemporaryStrongTransaction, mTransaction);
2553
0
2554
0
  if (mTransaction) {
2555
0
    mTransaction->ClearBackgroundActor();
2556
0
2557
0
    // Normally this would be DEBUG-only but NoteActorDestroyed is also called
2558
0
    // from SendDeleteMeInternal. In that case we're going to receive an actual
2559
0
    // ActorDestroy call later and we don't want to touch a dead object.
2560
0
    mTemporaryStrongTransaction = nullptr;
2561
0
    mTransaction = nullptr;
2562
0
  }
2563
0
}
2564
2565
void
2566
BackgroundTransactionBase::SetDOMTransaction(IDBTransaction* aTransaction)
2567
0
{
2568
0
  AssertIsOnOwningThread();
2569
0
  MOZ_ASSERT(aTransaction);
2570
0
  aTransaction->AssertIsOnOwningThread();
2571
0
  MOZ_ASSERT(!mTemporaryStrongTransaction);
2572
0
  MOZ_ASSERT(!mTransaction);
2573
0
2574
0
  mTemporaryStrongTransaction = aTransaction;
2575
0
  mTransaction = aTransaction;
2576
0
}
2577
2578
void
2579
BackgroundTransactionBase::NoteComplete()
2580
0
{
2581
0
  AssertIsOnOwningThread();
2582
0
  MOZ_ASSERT_IF(mTransaction, mTemporaryStrongTransaction);
2583
0
2584
0
  mTemporaryStrongTransaction = nullptr;
2585
0
}
2586
2587
/*******************************************************************************
2588
 * BackgroundTransactionChild
2589
 ******************************************************************************/
2590
2591
BackgroundTransactionChild::BackgroundTransactionChild(
2592
                                                   IDBTransaction* aTransaction)
2593
  : BackgroundTransactionBase(aTransaction)
2594
0
{
2595
0
  MOZ_ASSERT(aTransaction);
2596
0
  aTransaction->AssertIsOnOwningThread();
2597
0
2598
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionChild);
2599
0
}
2600
2601
BackgroundTransactionChild::~BackgroundTransactionChild()
2602
0
{
2603
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundTransactionChild);
2604
0
}
2605
2606
#ifdef DEBUG
2607
2608
void
2609
BackgroundTransactionChild::AssertIsOnOwningThread() const
2610
{
2611
  static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
2612
}
2613
2614
#endif // DEBUG
2615
2616
void
2617
BackgroundTransactionChild::SendDeleteMeInternal()
2618
0
{
2619
0
  AssertIsOnOwningThread();
2620
0
2621
0
  if (mTransaction) {
2622
0
    NoteActorDestroyed();
2623
0
2624
0
    MOZ_ALWAYS_TRUE(PBackgroundIDBTransactionChild::SendDeleteMe());
2625
0
  }
2626
0
}
2627
2628
void
2629
BackgroundTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
2630
0
{
2631
0
  AssertIsOnOwningThread();
2632
0
2633
0
  MaybeCollectGarbageOnIPCMessage();
2634
0
2635
0
  NoteActorDestroyed();
2636
0
}
2637
2638
mozilla::ipc::IPCResult
2639
BackgroundTransactionChild::RecvComplete(const nsresult& aResult)
2640
0
{
2641
0
  AssertIsOnOwningThread();
2642
0
  MOZ_ASSERT(mTransaction);
2643
0
2644
0
  MaybeCollectGarbageOnIPCMessage();
2645
0
2646
0
  mTransaction->FireCompleteOrAbortEvents(aResult);
2647
0
2648
0
  NoteComplete();
2649
0
  return IPC_OK();
2650
0
}
2651
2652
PBackgroundIDBRequestChild*
2653
BackgroundTransactionChild::AllocPBackgroundIDBRequestChild(
2654
                                                   const RequestParams& aParams)
2655
0
{
2656
0
  MOZ_CRASH("PBackgroundIDBRequestChild actors should be manually "
2657
0
            "constructed!");
2658
0
}
2659
2660
bool
2661
BackgroundTransactionChild::DeallocPBackgroundIDBRequestChild(
2662
                                             PBackgroundIDBRequestChild* aActor)
2663
0
{
2664
0
  MOZ_ASSERT(aActor);
2665
0
2666
0
  delete static_cast<BackgroundRequestChild*>(aActor);
2667
0
  return true;
2668
0
}
2669
2670
PBackgroundIDBCursorChild*
2671
BackgroundTransactionChild::AllocPBackgroundIDBCursorChild(
2672
                                                const OpenCursorParams& aParams)
2673
0
{
2674
0
  AssertIsOnOwningThread();
2675
0
2676
0
  MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
2677
0
}
2678
2679
bool
2680
BackgroundTransactionChild::DeallocPBackgroundIDBCursorChild(
2681
                                              PBackgroundIDBCursorChild* aActor)
2682
0
{
2683
0
  MOZ_ASSERT(aActor);
2684
0
2685
0
  delete static_cast<BackgroundCursorChild*>(aActor);
2686
0
  return true;
2687
0
}
2688
2689
/*******************************************************************************
2690
 * BackgroundVersionChangeTransactionChild
2691
 ******************************************************************************/
2692
2693
BackgroundVersionChangeTransactionChild::
2694
BackgroundVersionChangeTransactionChild(IDBOpenDBRequest* aOpenDBRequest)
2695
  : mOpenDBRequest(aOpenDBRequest)
2696
0
{
2697
0
  MOZ_ASSERT(aOpenDBRequest);
2698
0
  aOpenDBRequest->AssertIsOnOwningThread();
2699
0
2700
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundVersionChangeTransactionChild);
2701
0
}
2702
2703
BackgroundVersionChangeTransactionChild::
2704
~BackgroundVersionChangeTransactionChild()
2705
0
{
2706
0
  AssertIsOnOwningThread();
2707
0
2708
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundVersionChangeTransactionChild);
2709
0
}
2710
2711
#ifdef DEBUG
2712
2713
void
2714
BackgroundVersionChangeTransactionChild::AssertIsOnOwningThread() const
2715
{
2716
  static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
2717
}
2718
2719
#endif // DEBUG
2720
2721
void
2722
BackgroundVersionChangeTransactionChild::SendDeleteMeInternal(
2723
                                                        bool aFailedConstructor)
2724
0
{
2725
0
  AssertIsOnOwningThread();
2726
0
2727
0
  if (mTransaction || aFailedConstructor) {
2728
0
    NoteActorDestroyed();
2729
0
2730
0
    MOZ_ALWAYS_TRUE(PBackgroundIDBVersionChangeTransactionChild::
2731
0
                      SendDeleteMe());
2732
0
  }
2733
0
}
2734
2735
void
2736
BackgroundVersionChangeTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
2737
0
{
2738
0
  AssertIsOnOwningThread();
2739
0
2740
0
  MaybeCollectGarbageOnIPCMessage();
2741
0
2742
0
  mOpenDBRequest = nullptr;
2743
0
2744
0
  NoteActorDestroyed();
2745
0
}
2746
2747
mozilla::ipc::IPCResult
2748
BackgroundVersionChangeTransactionChild::RecvComplete(const nsresult& aResult)
2749
0
{
2750
0
  AssertIsOnOwningThread();
2751
0
2752
0
  MaybeCollectGarbageOnIPCMessage();
2753
0
2754
0
  if (!mTransaction) {
2755
0
    return IPC_OK();
2756
0
  }
2757
0
2758
0
  MOZ_ASSERT(mOpenDBRequest);
2759
0
2760
0
  IDBDatabase* database = mTransaction->Database();
2761
0
  MOZ_ASSERT(database);
2762
0
2763
0
  database->ExitSetVersionTransaction();
2764
0
2765
0
  if (NS_FAILED(aResult)) {
2766
0
    database->Close();
2767
0
  }
2768
0
2769
0
  mTransaction->FireCompleteOrAbortEvents(aResult);
2770
0
2771
0
  mOpenDBRequest->SetTransaction(nullptr);
2772
0
  mOpenDBRequest = nullptr;
2773
0
2774
0
  NoteComplete();
2775
0
  return IPC_OK();
2776
0
}
2777
2778
PBackgroundIDBRequestChild*
2779
BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBRequestChild(
2780
                                                   const RequestParams& aParams)
2781
0
{
2782
0
  MOZ_CRASH("PBackgroundIDBRequestChild actors should be manually "
2783
0
            "constructed!");
2784
0
}
2785
2786
bool
2787
BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBRequestChild(
2788
                                             PBackgroundIDBRequestChild* aActor)
2789
0
{
2790
0
  MOZ_ASSERT(aActor);
2791
0
2792
0
  delete static_cast<BackgroundRequestChild*>(aActor);
2793
0
  return true;
2794
0
}
2795
2796
PBackgroundIDBCursorChild*
2797
BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBCursorChild(
2798
                                                const OpenCursorParams& aParams)
2799
0
{
2800
0
  AssertIsOnOwningThread();
2801
0
2802
0
  MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
2803
0
}
2804
2805
bool
2806
BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBCursorChild(
2807
                                              PBackgroundIDBCursorChild* aActor)
2808
0
{
2809
0
  MOZ_ASSERT(aActor);
2810
0
2811
0
  delete static_cast<BackgroundCursorChild*>(aActor);
2812
0
  return true;
2813
0
}
2814
2815
/*******************************************************************************
2816
 * BackgroundMutableFileChild
2817
 ******************************************************************************/
2818
2819
BackgroundMutableFileChild::BackgroundMutableFileChild(const nsAString& aName,
2820
                                                       const nsAString& aType)
2821
  : mMutableFile(nullptr)
2822
  , mName(aName)
2823
  , mType(aType)
2824
0
{
2825
0
  // Can't assert owning thread here because IPDL has not yet set our manager!
2826
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundMutableFileChild);
2827
0
}
2828
2829
BackgroundMutableFileChild::~BackgroundMutableFileChild()
2830
0
{
2831
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundMutableFileChild);
2832
0
}
2833
2834
#ifdef DEBUG
2835
2836
void
2837
BackgroundMutableFileChild::AssertIsOnOwningThread() const
2838
{
2839
  static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
2840
}
2841
2842
#endif // DEBUG
2843
2844
void
2845
BackgroundMutableFileChild::EnsureDOMObject()
2846
0
{
2847
0
  AssertIsOnOwningThread();
2848
0
2849
0
  if (mTemporaryStrongMutableFile) {
2850
0
    return;
2851
0
  }
2852
0
2853
0
  auto database =
2854
0
    static_cast<BackgroundDatabaseChild*>(Manager())->GetDOMObject();
2855
0
  MOZ_ASSERT(database);
2856
0
2857
0
  mTemporaryStrongMutableFile =
2858
0
    new IDBMutableFile(database, this, mName, mType);
2859
0
2860
0
  MOZ_ASSERT(mTemporaryStrongMutableFile);
2861
0
  mTemporaryStrongMutableFile->AssertIsOnOwningThread();
2862
0
2863
0
  mMutableFile = mTemporaryStrongMutableFile;
2864
0
}
2865
2866
void
2867
BackgroundMutableFileChild::ReleaseDOMObject()
2868
0
{
2869
0
  AssertIsOnOwningThread();
2870
0
  MOZ_ASSERT(mTemporaryStrongMutableFile);
2871
0
  mTemporaryStrongMutableFile->AssertIsOnOwningThread();
2872
0
  MOZ_ASSERT(mMutableFile == mTemporaryStrongMutableFile);
2873
0
2874
0
  mTemporaryStrongMutableFile = nullptr;
2875
0
}
2876
2877
void
2878
BackgroundMutableFileChild::SendDeleteMeInternal()
2879
0
{
2880
0
  AssertIsOnOwningThread();
2881
0
  MOZ_ASSERT(!mTemporaryStrongMutableFile);
2882
0
2883
0
  if (mMutableFile) {
2884
0
    mMutableFile->ClearBackgroundActor();
2885
0
    mMutableFile = nullptr;
2886
0
2887
0
    MOZ_ALWAYS_TRUE(PBackgroundMutableFileChild::SendDeleteMe());
2888
0
  }
2889
0
}
2890
2891
void
2892
BackgroundMutableFileChild::ActorDestroy(ActorDestroyReason aWhy)
2893
0
{
2894
0
  AssertIsOnOwningThread();
2895
0
2896
0
  if (mMutableFile) {
2897
0
    mMutableFile->ClearBackgroundActor();
2898
#ifdef DEBUG
2899
    mMutableFile = nullptr;
2900
#endif
2901
  }
2902
0
}
2903
2904
PBackgroundFileHandleChild*
2905
BackgroundMutableFileChild::AllocPBackgroundFileHandleChild(
2906
                                                          const FileMode& aMode)
2907
0
{
2908
0
  MOZ_CRASH("PBackgroundFileHandleChild actors should be manually "
2909
0
            "constructed!");
2910
0
}
2911
2912
bool
2913
BackgroundMutableFileChild::DeallocPBackgroundFileHandleChild(
2914
                                             PBackgroundFileHandleChild* aActor)
2915
0
{
2916
0
  AssertIsOnOwningThread();
2917
0
  MOZ_ASSERT(aActor);
2918
0
2919
0
  delete static_cast<BackgroundFileHandleChild*>(aActor);
2920
0
  return true;
2921
0
}
2922
2923
/*******************************************************************************
2924
 * BackgroundRequestChild
2925
 ******************************************************************************/
2926
2927
BackgroundRequestChild::BackgroundRequestChild(IDBRequest* aRequest)
2928
  : BackgroundRequestChildBase(aRequest)
2929
  , mTransaction(aRequest->GetTransaction())
2930
  , mRunningPreprocessHelpers(0)
2931
  , mCurrentModuleSetIndex(0)
2932
  , mPreprocessResultCode(NS_OK)
2933
  , mGetAll(false)
2934
0
{
2935
0
  MOZ_ASSERT(mTransaction);
2936
0
  mTransaction->AssertIsOnOwningThread();
2937
0
2938
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChild);
2939
0
}
2940
2941
BackgroundRequestChild::~BackgroundRequestChild()
2942
0
{
2943
0
  AssertIsOnOwningThread();
2944
0
  MOZ_ASSERT(!mTransaction);
2945
0
2946
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
2947
0
}
2948
2949
void
2950
BackgroundRequestChild::MaybeSendContinue()
2951
0
{
2952
0
  AssertIsOnOwningThread();
2953
0
  MOZ_ASSERT(mRunningPreprocessHelpers > 0);
2954
0
2955
0
  if (--mRunningPreprocessHelpers == 0) {
2956
0
    PreprocessResponse response;
2957
0
2958
0
    if (NS_SUCCEEDED(mPreprocessResultCode)) {
2959
0
      if (mGetAll) {
2960
0
        response = ObjectStoreGetAllPreprocessResponse();
2961
0
      } else {
2962
0
        response = ObjectStoreGetPreprocessResponse();
2963
0
      }
2964
0
    } else {
2965
0
      response = mPreprocessResultCode;
2966
0
    }
2967
0
2968
0
    MOZ_ALWAYS_TRUE(SendContinue(response));
2969
0
  }
2970
0
}
2971
2972
void
2973
BackgroundRequestChild::OnPreprocessFinished(
2974
                                   uint32_t aModuleSetIndex,
2975
                                   nsTArray<RefPtr<JS::WasmModule>>& aModuleSet)
2976
0
{
2977
0
  AssertIsOnOwningThread();
2978
0
  MOZ_ASSERT(aModuleSetIndex < mPreprocessHelpers.Length());
2979
0
  MOZ_ASSERT(!aModuleSet.IsEmpty());
2980
0
  MOZ_ASSERT(mPreprocessHelpers[aModuleSetIndex]);
2981
0
  MOZ_ASSERT(mModuleSets[aModuleSetIndex].IsEmpty());
2982
0
2983
0
  mModuleSets[aModuleSetIndex].SwapElements(aModuleSet);
2984
0
2985
0
  MaybeSendContinue();
2986
0
2987
0
  mPreprocessHelpers[aModuleSetIndex] = nullptr;
2988
0
}
2989
2990
void
2991
BackgroundRequestChild::OnPreprocessFailed(uint32_t aModuleSetIndex,
2992
                                           nsresult aErrorCode)
2993
0
{
2994
0
  AssertIsOnOwningThread();
2995
0
  MOZ_ASSERT(aModuleSetIndex < mPreprocessHelpers.Length());
2996
0
  MOZ_ASSERT(NS_FAILED(aErrorCode));
2997
0
  MOZ_ASSERT(mPreprocessHelpers[aModuleSetIndex]);
2998
0
  MOZ_ASSERT(mModuleSets[aModuleSetIndex].IsEmpty());
2999
0
3000
0
  if (NS_SUCCEEDED(mPreprocessResultCode)) {
3001
0
    mPreprocessResultCode = aErrorCode;
3002
0
  }
3003
0
3004
0
  MaybeSendContinue();
3005
0
3006
0
  mPreprocessHelpers[aModuleSetIndex] = nullptr;
3007
0
}
3008
3009
const nsTArray<RefPtr<JS::WasmModule>>*
3010
BackgroundRequestChild::GetNextModuleSet(const StructuredCloneReadInfo& aInfo)
3011
0
{
3012
0
  if (!aInfo.mHasPreprocessInfo) {
3013
0
    return nullptr;
3014
0
  }
3015
0
3016
0
  MOZ_ASSERT(mCurrentModuleSetIndex < mModuleSets.Length());
3017
0
  MOZ_ASSERT(!mModuleSets[mCurrentModuleSetIndex].IsEmpty());
3018
0
  return &mModuleSets[mCurrentModuleSetIndex++];
3019
0
}
3020
3021
void
3022
BackgroundRequestChild::HandleResponse(nsresult aResponse)
3023
0
{
3024
0
  AssertIsOnOwningThread();
3025
0
  MOZ_ASSERT(NS_FAILED(aResponse));
3026
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
3027
0
  MOZ_ASSERT(mTransaction);
3028
0
3029
0
  DispatchErrorEvent(mRequest, aResponse, mTransaction);
3030
0
}
3031
3032
void
3033
BackgroundRequestChild::HandleResponse(const Key& aResponse)
3034
0
{
3035
0
  AssertIsOnOwningThread();
3036
0
3037
0
  ResultHelper helper(mRequest, mTransaction, &aResponse);
3038
0
3039
0
  DispatchSuccessEvent(&helper);
3040
0
}
3041
3042
void
3043
BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
3044
0
{
3045
0
  AssertIsOnOwningThread();
3046
0
3047
0
  ResultHelper helper(mRequest, mTransaction, &aResponse);
3048
0
3049
0
  DispatchSuccessEvent(&helper);
3050
0
}
3051
3052
void
3053
BackgroundRequestChild::HandleResponse(
3054
                             const SerializedStructuredCloneReadInfo& aResponse)
3055
0
{
3056
0
  AssertIsOnOwningThread();
3057
0
3058
0
  // XXX Fix this somehow...
3059
0
  auto& serializedCloneInfo =
3060
0
    const_cast<SerializedStructuredCloneReadInfo&>(aResponse);
3061
0
3062
0
  StructuredCloneReadInfo cloneReadInfo(std::move(serializedCloneInfo));
3063
0
3064
0
  DeserializeStructuredCloneFiles(mTransaction->Database(),
3065
0
                                  aResponse.files(),
3066
0
                                  GetNextModuleSet(cloneReadInfo),
3067
0
                                  cloneReadInfo.mFiles);
3068
0
3069
0
  ResultHelper helper(mRequest, mTransaction, &cloneReadInfo);
3070
0
3071
0
  DispatchSuccessEvent(&helper);
3072
0
}
3073
3074
void
3075
BackgroundRequestChild::HandleResponse(
3076
                   const nsTArray<SerializedStructuredCloneReadInfo>& aResponse)
3077
0
{
3078
0
  AssertIsOnOwningThread();
3079
0
3080
0
  nsTArray<StructuredCloneReadInfo> cloneReadInfos;
3081
0
3082
0
  if (!aResponse.IsEmpty()) {
3083
0
    const uint32_t count = aResponse.Length();
3084
0
3085
0
    cloneReadInfos.SetCapacity(count);
3086
0
3087
0
    IDBDatabase* database = mTransaction->Database();
3088
0
3089
0
    for (uint32_t index = 0; index < count; index++) {
3090
0
      // XXX Fix this somehow...
3091
0
      auto& serializedCloneInfo =
3092
0
        const_cast<SerializedStructuredCloneReadInfo&>(aResponse[index]);
3093
0
3094
0
      StructuredCloneReadInfo* cloneReadInfo = cloneReadInfos.AppendElement();
3095
0
3096
0
      // Move relevant data into the cloneReadInfo
3097
0
      *cloneReadInfo = std::move(serializedCloneInfo);
3098
0
3099
0
      // Get the files
3100
0
      nsTArray<StructuredCloneFile> files;
3101
0
      DeserializeStructuredCloneFiles(database,
3102
0
                                      serializedCloneInfo.files(),
3103
0
                                      GetNextModuleSet(*cloneReadInfo),
3104
0
                                      files);
3105
0
3106
0
      cloneReadInfo->mFiles = std::move(files);
3107
0
    }
3108
0
  }
3109
0
3110
0
  ResultHelper helper(mRequest, mTransaction, &cloneReadInfos);
3111
0
3112
0
  DispatchSuccessEvent(&helper);
3113
0
}
3114
3115
void
3116
BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
3117
0
{
3118
0
  AssertIsOnOwningThread();
3119
0
3120
0
  ResultHelper helper(mRequest, mTransaction, &aResponse);
3121
0
3122
0
  DispatchSuccessEvent(&helper);
3123
0
}
3124
3125
void
3126
BackgroundRequestChild::HandleResponse(uint64_t aResponse)
3127
0
{
3128
0
  AssertIsOnOwningThread();
3129
0
3130
0
  JS::Value response(JS::NumberValue(aResponse));
3131
0
3132
0
  ResultHelper helper(mRequest, mTransaction, &response);
3133
0
3134
0
  DispatchSuccessEvent(&helper);
3135
0
}
3136
3137
nsresult
3138
BackgroundRequestChild::HandlePreprocess(
3139
                                const WasmModulePreprocessInfo& aPreprocessInfo)
3140
0
{
3141
0
  AssertIsOnOwningThread();
3142
0
3143
0
  IDBDatabase* database = mTransaction->Database();
3144
0
3145
0
  mPreprocessHelpers.SetLength(1);
3146
0
3147
0
  nsTArray<StructuredCloneFile> files;
3148
0
  DeserializeStructuredCloneFiles(database,
3149
0
                                  aPreprocessInfo.files(),
3150
0
                                  nullptr,
3151
0
                                  files);
3152
0
3153
0
3154
0
  RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[0];
3155
0
  preprocessHelper = new PreprocessHelper(0, this);
3156
0
3157
0
  nsresult rv = preprocessHelper->Init(files);
3158
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
3159
0
    return rv;
3160
0
  }
3161
0
3162
0
  rv = preprocessHelper->Dispatch();
3163
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
3164
0
    return rv;
3165
0
  }
3166
0
3167
0
  mRunningPreprocessHelpers++;
3168
0
3169
0
  mModuleSets.SetLength(1);
3170
0
3171
0
  return NS_OK;
3172
0
}
3173
3174
nsresult
3175
BackgroundRequestChild::HandlePreprocess(
3176
                     const nsTArray<WasmModulePreprocessInfo>& aPreprocessInfos)
3177
0
{
3178
0
  AssertIsOnOwningThread();
3179
0
3180
0
  IDBDatabase* database = mTransaction->Database();
3181
0
3182
0
  uint32_t count = aPreprocessInfos.Length();
3183
0
3184
0
  mPreprocessHelpers.SetLength(count);
3185
0
3186
0
  // TODO: Since we use the stream transport service, this can spawn 25 threads
3187
0
  //       and has the potential to cause some annoying browser hiccups.
3188
0
  //       Consider using a single thread or a very small threadpool.
3189
0
  for (uint32_t index = 0; index < count; index++) {
3190
0
    const WasmModulePreprocessInfo& preprocessInfo = aPreprocessInfos[index];
3191
0
3192
0
    nsTArray<StructuredCloneFile> files;
3193
0
    DeserializeStructuredCloneFiles(database,
3194
0
                                    preprocessInfo.files(),
3195
0
                                    nullptr,
3196
0
                                    files);
3197
0
3198
0
3199
0
    RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[index];
3200
0
    preprocessHelper = new PreprocessHelper(index, this);
3201
0
3202
0
    nsresult rv = preprocessHelper->Init(files);
3203
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
3204
0
      return rv;
3205
0
    }
3206
0
3207
0
    rv = preprocessHelper->Dispatch();
3208
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
3209
0
      return rv;
3210
0
    }
3211
0
3212
0
    mRunningPreprocessHelpers++;
3213
0
  }
3214
0
3215
0
  mModuleSets.SetLength(count);
3216
0
3217
0
  mGetAll = true;
3218
0
3219
0
  return NS_OK;
3220
0
}
3221
3222
void
3223
BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy)
3224
0
{
3225
0
  AssertIsOnOwningThread();
3226
0
3227
0
  MaybeCollectGarbageOnIPCMessage();
3228
0
3229
0
  for (uint32_t count = mPreprocessHelpers.Length(), index = 0;
3230
0
       index < count;
3231
0
       index++) {
3232
0
    RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[index];
3233
0
3234
0
    if (preprocessHelper) {
3235
0
      preprocessHelper->ClearActor();
3236
0
3237
0
      preprocessHelper = nullptr;
3238
0
    }
3239
0
  }
3240
0
3241
0
  if (mTransaction) {
3242
0
    mTransaction->AssertIsOnOwningThread();
3243
0
3244
0
    mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
3245
0
                                    aWhy == Deletion);
3246
#ifdef DEBUG
3247
    mTransaction = nullptr;
3248
#endif
3249
  }
3250
0
}
3251
3252
mozilla::ipc::IPCResult
3253
BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
3254
0
{
3255
0
  AssertIsOnOwningThread();
3256
0
  MOZ_ASSERT(mRequest);
3257
0
  MOZ_ASSERT(mTransaction);
3258
0
3259
0
  MaybeCollectGarbageOnIPCMessage();
3260
0
3261
0
  if (mTransaction->IsAborted()) {
3262
0
    // Always fire an "error" event with ABORT_ERR if the transaction was
3263
0
    // aborted, even if the request succeeded or failed with another error.
3264
0
    HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
3265
0
  } else {
3266
0
    switch (aResponse.type()) {
3267
0
      case RequestResponse::Tnsresult:
3268
0
        HandleResponse(aResponse.get_nsresult());
3269
0
        break;
3270
0
3271
0
      case RequestResponse::TObjectStoreAddResponse:
3272
0
        HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
3273
0
        break;
3274
0
3275
0
      case RequestResponse::TObjectStorePutResponse:
3276
0
        HandleResponse(aResponse.get_ObjectStorePutResponse().key());
3277
0
        break;
3278
0
3279
0
      case RequestResponse::TObjectStoreGetResponse:
3280
0
        HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
3281
0
        break;
3282
0
3283
0
      case RequestResponse::TObjectStoreGetKeyResponse:
3284
0
        HandleResponse(aResponse.get_ObjectStoreGetKeyResponse().key());
3285
0
        break;
3286
0
3287
0
      case RequestResponse::TObjectStoreGetAllResponse:
3288
0
        HandleResponse(aResponse.get_ObjectStoreGetAllResponse().cloneInfos());
3289
0
        break;
3290
0
3291
0
      case RequestResponse::TObjectStoreGetAllKeysResponse:
3292
0
        HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys());
3293
0
        break;
3294
0
3295
0
      case RequestResponse::TObjectStoreDeleteResponse:
3296
0
        HandleResponse(JS::UndefinedHandleValue);
3297
0
        break;
3298
0
3299
0
      case RequestResponse::TObjectStoreClearResponse:
3300
0
        HandleResponse(JS::UndefinedHandleValue);
3301
0
        break;
3302
0
3303
0
      case RequestResponse::TObjectStoreCountResponse:
3304
0
        HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
3305
0
        break;
3306
0
3307
0
      case RequestResponse::TIndexGetResponse:
3308
0
        HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
3309
0
        break;
3310
0
3311
0
      case RequestResponse::TIndexGetKeyResponse:
3312
0
        HandleResponse(aResponse.get_IndexGetKeyResponse().key());
3313
0
        break;
3314
0
3315
0
      case RequestResponse::TIndexGetAllResponse:
3316
0
        HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
3317
0
        break;
3318
0
3319
0
      case RequestResponse::TIndexGetAllKeysResponse:
3320
0
        HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
3321
0
        break;
3322
0
3323
0
      case RequestResponse::TIndexCountResponse:
3324
0
        HandleResponse(aResponse.get_IndexCountResponse().count());
3325
0
        break;
3326
0
3327
0
      default:
3328
0
        MOZ_CRASH("Unknown response type!");
3329
0
    }
3330
0
  }
3331
0
3332
0
  mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
3333
0
3334
0
  // Null this out so that we don't try to call OnRequestFinished() again in
3335
0
  // ActorDestroy.
3336
0
  mTransaction = nullptr;
3337
0
3338
0
  return IPC_OK();
3339
0
}
3340
3341
mozilla::ipc::IPCResult
3342
BackgroundRequestChild::RecvPreprocess(const PreprocessParams& aParams)
3343
0
{
3344
0
  AssertIsOnOwningThread();
3345
0
  MOZ_ASSERT(mTransaction);
3346
0
3347
0
  MaybeCollectGarbageOnIPCMessage();
3348
0
3349
0
  nsresult rv;
3350
0
3351
0
  switch (aParams.type()) {
3352
0
    case PreprocessParams::TObjectStoreGetPreprocessParams: {
3353
0
      ObjectStoreGetPreprocessParams params =
3354
0
        aParams.get_ObjectStoreGetPreprocessParams();
3355
0
3356
0
      rv = HandlePreprocess(params.preprocessInfo());
3357
0
3358
0
      break;
3359
0
    }
3360
0
3361
0
    case PreprocessParams::TObjectStoreGetAllPreprocessParams: {
3362
0
      ObjectStoreGetAllPreprocessParams params =
3363
0
        aParams.get_ObjectStoreGetAllPreprocessParams();
3364
0
3365
0
      rv = HandlePreprocess(params.preprocessInfos());
3366
0
3367
0
      break;
3368
0
    }
3369
0
3370
0
    default:
3371
0
      MOZ_CRASH("Unknown params type!");
3372
0
  }
3373
0
3374
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
3375
0
    if (!SendContinue(rv)) {
3376
0
      return IPC_FAIL_NO_REASON(this);
3377
0
    }
3378
0
    return IPC_OK();
3379
0
  }
3380
0
3381
0
  return IPC_OK();
3382
0
}
3383
3384
nsresult
3385
BackgroundRequestChild::
3386
PreprocessHelper::Init(const nsTArray<StructuredCloneFile>& aFiles)
3387
0
{
3388
0
  AssertIsOnOwningThread();
3389
0
  MOZ_ASSERT(!aFiles.IsEmpty());
3390
0
3391
0
  nsTArray<nsCOMPtr<nsIInputStream>> streams;
3392
0
  for (uint32_t index = 0; index < aFiles.Length(); index++) {
3393
0
    const StructuredCloneFile& bytecodeFile = aFiles[index];
3394
0
3395
0
    MOZ_ASSERT(bytecodeFile.mType == StructuredCloneFile::eWasmBytecode);
3396
0
    MOZ_ASSERT(bytecodeFile.mBlob);
3397
0
3398
0
    ErrorResult errorResult;
3399
0
3400
0
    nsCOMPtr<nsIInputStream> bytecodeStream;
3401
0
    bytecodeFile.mBlob->CreateInputStream(getter_AddRefs(bytecodeStream),
3402
0
                                          errorResult);
3403
0
    if (NS_WARN_IF(errorResult.Failed())) {
3404
0
      return errorResult.StealNSResult();
3405
0
    }
3406
0
3407
0
    streams.AppendElement(bytecodeStream);
3408
0
  }
3409
0
3410
0
  mStreams = std::move(streams);
3411
0
3412
0
  return NS_OK;
3413
0
}
3414
3415
nsresult
3416
BackgroundRequestChild::
3417
PreprocessHelper::Dispatch()
3418
0
{
3419
0
  AssertIsOnOwningThread();
3420
0
3421
0
  if (!mTaskQueue) {
3422
0
    // The stream transport service is used for asynchronous processing. It has
3423
0
    // a threadpool with a high cap of 25 threads. Fortunately, the service can
3424
0
    // be used on workers too.
3425
0
    nsCOMPtr<nsIEventTarget> target =
3426
0
      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
3427
0
    MOZ_ASSERT(target);
3428
0
3429
0
    // We use a TaskQueue here in order to be sure that the events are
3430
0
    // dispatched in the correct order. This is not guaranteed in case we use
3431
0
    // the I/O thread directly.
3432
0
    mTaskQueue = new TaskQueue(target.forget());
3433
0
    mTaskQueueEventTarget = mTaskQueue->WrapAsEventTarget();
3434
0
  }
3435
0
3436
0
  nsresult rv = mTaskQueueEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
3437
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
3438
0
    return rv;
3439
0
  }
3440
0
3441
0
  return NS_OK;
3442
0
}
3443
3444
void
3445
BackgroundRequestChild::
3446
PreprocessHelper::RunOnOwningThread()
3447
0
{
3448
0
  AssertIsOnOwningThread();
3449
0
3450
0
  if (mActor) {
3451
0
    if (NS_SUCCEEDED(mResultCode)) {
3452
0
      mActor->OnPreprocessFinished(mModuleSetIndex, mModuleSet);
3453
0
3454
0
      MOZ_ASSERT(mModuleSet.IsEmpty());
3455
0
    } else {
3456
0
      mActor->OnPreprocessFailed(mModuleSetIndex, mResultCode);
3457
0
    }
3458
0
  }
3459
0
}
3460
3461
void
3462
BackgroundRequestChild::
3463
PreprocessHelper::ProcessCurrentStream()
3464
0
{
3465
0
  MOZ_ASSERT(!IsOnOwningThread());
3466
0
  MOZ_ASSERT(!mStreams.IsEmpty());
3467
0
3468
0
  // We still don't have the current bytecode FileDesc.
3469
0
  if (!mCurrentBytecodeFileDesc) {
3470
0
    const nsCOMPtr<nsIInputStream>& bytecodeStream = mStreams[0];
3471
0
    MOZ_ASSERT(bytecodeStream);
3472
0
3473
0
    mCurrentBytecodeFileDesc = GetFileDescriptorFromStream(bytecodeStream);
3474
0
    if (!mCurrentBytecodeFileDesc) {
3475
0
      nsresult rv = WaitForStreamReady(bytecodeStream);
3476
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
3477
0
        ContinueWithStatus(rv);
3478
0
      }
3479
0
      return;
3480
0
    }
3481
0
  }
3482
0
3483
0
  MOZ_ASSERT(mCurrentBytecodeFileDesc);
3484
0
3485
0
  RefPtr<JS::WasmModule> module =
3486
0
    JS::DeserializeWasmModule(mCurrentBytecodeFileDesc,
3487
0
                              nullptr,
3488
0
                              0);
3489
0
  if (NS_WARN_IF(!module)) {
3490
0
    ContinueWithStatus(NS_ERROR_FAILURE);
3491
0
    return;
3492
0
  }
3493
0
3494
0
  mModuleSet.AppendElement(module);
3495
0
  mStreams.RemoveElementAt(0);
3496
0
3497
0
  ContinueWithStatus(NS_OK);
3498
0
}
3499
3500
nsresult
3501
BackgroundRequestChild::
3502
PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
3503
0
{
3504
0
  MOZ_ASSERT(!IsOnOwningThread());
3505
0
  MOZ_ASSERT(aInputStream);
3506
0
3507
0
  nsCOMPtr<nsIAsyncFileMetadata> asyncFileMetadata =
3508
0
    do_QueryInterface(aInputStream);
3509
0
  if (asyncFileMetadata) {
3510
0
    nsresult rv =
3511
0
      asyncFileMetadata->AsyncFileMetadataWait(this, mTaskQueueEventTarget);
3512
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
3513
0
      return rv;
3514
0
    }
3515
0
3516
0
    return NS_OK;
3517
0
  }
3518
0
3519
0
  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aInputStream);
3520
0
  if (!asyncStream) {
3521
0
    return NS_ERROR_NO_INTERFACE;
3522
0
  }
3523
0
3524
0
  nsresult rv = asyncStream->AsyncWait(this, 0, 0, mTaskQueueEventTarget);
3525
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
3526
0
    return rv;
3527
0
  }
3528
0
3529
0
  return NS_OK;
3530
0
}
3531
3532
void
3533
BackgroundRequestChild::
3534
PreprocessHelper::ContinueWithStatus(nsresult aStatus)
3535
0
{
3536
0
  MOZ_ASSERT(!IsOnOwningThread());
3537
0
3538
0
  // Let's reset the value for the next operation.
3539
0
  mCurrentBytecodeFileDesc = nullptr;
3540
0
3541
0
  nsCOMPtr<nsIEventTarget> eventTarget;
3542
0
3543
0
  if (NS_WARN_IF(NS_FAILED(aStatus))) {
3544
0
    // If the previous operation failed, we don't continue the processing of the
3545
0
    // other streams.
3546
0
    MOZ_ASSERT(mResultCode == NS_OK);
3547
0
    mResultCode = aStatus;
3548
0
3549
0
    eventTarget = mOwningEventTarget;
3550
0
  } else if (mStreams.IsEmpty()) {
3551
0
    // If all the streams have been processed, we can go back to the owning
3552
0
    // thread.
3553
0
    eventTarget = mOwningEventTarget;
3554
0
  } else {
3555
0
    // Continue the processing.
3556
0
    eventTarget = mTaskQueueEventTarget;
3557
0
  }
3558
0
3559
0
  nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
3560
0
  Unused <<  NS_WARN_IF(NS_FAILED(rv));
3561
0
}
3562
3563
NS_IMPL_ISUPPORTS_INHERITED(BackgroundRequestChild::PreprocessHelper,
3564
                            CancelableRunnable, nsIInputStreamCallback,
3565
                            nsIFileMetadataCallback)
3566
3567
NS_IMETHODIMP
3568
BackgroundRequestChild::
3569
PreprocessHelper::Run()
3570
0
{
3571
0
  if (IsOnOwningThread()) {
3572
0
    RunOnOwningThread();
3573
0
  } else {
3574
0
    ProcessCurrentStream();
3575
0
  }
3576
0
3577
0
  return NS_OK;
3578
0
}
3579
3580
NS_IMETHODIMP
3581
BackgroundRequestChild::
3582
PreprocessHelper::OnInputStreamReady(nsIAsyncInputStream* aStream)
3583
0
{
3584
0
  return DataIsReady(aStream);
3585
0
}
3586
3587
NS_IMETHODIMP
3588
BackgroundRequestChild::
3589
PreprocessHelper::OnFileMetadataReady(nsIAsyncFileMetadata* aObject)
3590
0
{
3591
0
  nsCOMPtr<nsIInputStream> stream = do_QueryInterface(aObject);
3592
0
  MOZ_ASSERT(stream, "It was a stream before!");
3593
0
3594
0
  return DataIsReady(stream);
3595
0
}
3596
3597
nsresult
3598
BackgroundRequestChild::
3599
PreprocessHelper::DataIsReady(nsIInputStream* aStream)
3600
0
{
3601
0
  MOZ_ASSERT(!IsOnOwningThread());
3602
0
  MOZ_ASSERT(aStream);
3603
0
  MOZ_ASSERT(!mStreams.IsEmpty());
3604
0
3605
0
  // We still don't have the current bytecode FileDesc.
3606
0
  if (!mCurrentBytecodeFileDesc) {
3607
0
    mCurrentBytecodeFileDesc = GetFileDescriptorFromStream(aStream);
3608
0
    if (!mCurrentBytecodeFileDesc) {
3609
0
      ContinueWithStatus(NS_ERROR_FAILURE);
3610
0
      return NS_OK;
3611
0
    }
3612
0
3613
0
    // Let's continue with the processing of the current stream.
3614
0
    ProcessCurrentStream();
3615
0
    return NS_OK;
3616
0
  }
3617
0
3618
0
  MOZ_CRASH("If we have both fileDescs why are we here?");
3619
0
}
3620
3621
nsresult
3622
BackgroundRequestChild::
3623
PreprocessHelper::Cancel()
3624
0
{
3625
0
  return NS_OK;
3626
0
}
3627
3628
/*******************************************************************************
3629
 * BackgroundCursorChild
3630
 ******************************************************************************/
3631
3632
// Does not need to be threadsafe since this only runs on one thread, but
3633
// inheriting from CancelableRunnable is easy.
3634
class BackgroundCursorChild::DelayedActionRunnable final
3635
  : public CancelableRunnable
3636
{
3637
  using ActionFunc = void (BackgroundCursorChild::*)();
3638
3639
  BackgroundCursorChild* mActor;
3640
  RefPtr<IDBRequest> mRequest;
3641
  ActionFunc mActionFunc;
3642
3643
public:
3644
  explicit
3645
  DelayedActionRunnable(BackgroundCursorChild* aActor, ActionFunc aActionFunc)
3646
    : CancelableRunnable("indexedDB::BackgroundCursorChild::DelayedActionRunnable")
3647
    , mActor(aActor)
3648
    , mRequest(aActor->mRequest)
3649
    , mActionFunc(aActionFunc)
3650
0
  {
3651
0
    MOZ_ASSERT(aActor);
3652
0
    aActor->AssertIsOnOwningThread();
3653
0
    MOZ_ASSERT(mRequest);
3654
0
    MOZ_ASSERT(mActionFunc);
3655
0
  }
3656
3657
private:
3658
  ~DelayedActionRunnable()
3659
0
  { }
3660
3661
  NS_DECL_NSIRUNNABLE
3662
  nsresult Cancel() override;
3663
};
3664
3665
BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
3666
                                             IDBObjectStore* aObjectStore,
3667
                                             Direction aDirection)
3668
  : mRequest(aRequest)
3669
  , mTransaction(aRequest->GetTransaction())
3670
  , mObjectStore(aObjectStore)
3671
  , mIndex(nullptr)
3672
  , mCursor(nullptr)
3673
  , mStrongRequest(aRequest)
3674
  , mDirection(aDirection)
3675
0
{
3676
0
  MOZ_ASSERT(aObjectStore);
3677
0
  aObjectStore->AssertIsOnOwningThread();
3678
0
  MOZ_ASSERT(mTransaction);
3679
0
3680
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
3681
0
}
3682
3683
BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
3684
                                             IDBIndex* aIndex,
3685
                                             Direction aDirection)
3686
  : mRequest(aRequest)
3687
  , mTransaction(aRequest->GetTransaction())
3688
  , mObjectStore(nullptr)
3689
  , mIndex(aIndex)
3690
  , mCursor(nullptr)
3691
  , mStrongRequest(aRequest)
3692
  , mDirection(aDirection)
3693
0
{
3694
0
  MOZ_ASSERT(aIndex);
3695
0
  aIndex->AssertIsOnOwningThread();
3696
0
  MOZ_ASSERT(mTransaction);
3697
0
3698
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
3699
0
}
3700
3701
BackgroundCursorChild::~BackgroundCursorChild()
3702
0
{
3703
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundCursorChild);
3704
0
}
3705
3706
void
3707
BackgroundCursorChild::SendContinueInternal(const CursorRequestParams& aParams)
3708
0
{
3709
0
  AssertIsOnOwningThread();
3710
0
  MOZ_ASSERT(mRequest);
3711
0
  MOZ_ASSERT(mTransaction);
3712
0
  MOZ_ASSERT(mCursor);
3713
0
  MOZ_ASSERT(!mStrongRequest);
3714
0
  MOZ_ASSERT(!mStrongCursor);
3715
0
3716
0
  // Make sure all our DOM objects stay alive.
3717
0
  mStrongCursor = mCursor;
3718
0
3719
0
  MOZ_ASSERT(mRequest->ReadyState() == IDBRequestReadyState::Done);
3720
0
  mRequest->Reset();
3721
0
3722
0
  mTransaction->OnNewRequest();
3723
0
3724
0
  MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendContinue(aParams));
3725
0
}
3726
3727
void
3728
BackgroundCursorChild::SendDeleteMeInternal()
3729
0
{
3730
0
  AssertIsOnOwningThread();
3731
0
  MOZ_ASSERT(!mStrongRequest);
3732
0
  MOZ_ASSERT(!mStrongCursor);
3733
0
3734
0
  mRequest = nullptr;
3735
0
  mTransaction = nullptr;
3736
0
  mObjectStore = nullptr;
3737
0
  mIndex = nullptr;
3738
0
3739
0
  if (mCursor) {
3740
0
    mCursor->ClearBackgroundActor();
3741
0
    mCursor = nullptr;
3742
0
3743
0
    MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendDeleteMe());
3744
0
  }
3745
0
}
3746
3747
void
3748
BackgroundCursorChild::HandleResponse(nsresult aResponse)
3749
0
{
3750
0
  AssertIsOnOwningThread();
3751
0
  MOZ_ASSERT(NS_FAILED(aResponse));
3752
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
3753
0
  MOZ_ASSERT(mRequest);
3754
0
  MOZ_ASSERT(mTransaction);
3755
0
  MOZ_ASSERT(!mStrongRequest);
3756
0
  MOZ_ASSERT(!mStrongCursor);
3757
0
3758
0
  DispatchErrorEvent(mRequest, aResponse, mTransaction);
3759
0
}
3760
3761
void
3762
BackgroundCursorChild::HandleResponse(const void_t& aResponse)
3763
0
{
3764
0
  AssertIsOnOwningThread();
3765
0
  MOZ_ASSERT(mRequest);
3766
0
  MOZ_ASSERT(mTransaction);
3767
0
  MOZ_ASSERT(!mStrongRequest);
3768
0
  MOZ_ASSERT(!mStrongCursor);
3769
0
3770
0
  if (mCursor) {
3771
0
    mCursor->Reset();
3772
0
  }
3773
0
3774
0
  ResultHelper helper(mRequest, mTransaction, &JS::NullHandleValue);
3775
0
  DispatchSuccessEvent(&helper);
3776
0
3777
0
  if (!mCursor) {
3778
0
    nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedActionRunnable(
3779
0
      this, &BackgroundCursorChild::SendDeleteMeInternal);
3780
0
      MOZ_ALWAYS_SUCCEEDS(this->GetActorEventTarget()->
3781
0
        Dispatch(deleteRunnable.forget(), NS_DISPATCH_NORMAL));
3782
0
  }
3783
0
}
3784
3785
void
3786
BackgroundCursorChild::HandleResponse(
3787
    const nsTArray<ObjectStoreCursorResponse>& aResponses)
3788
0
{
3789
0
  AssertIsOnOwningThread();
3790
0
  MOZ_ASSERT(mRequest);
3791
0
  MOZ_ASSERT(mTransaction);
3792
0
  MOZ_ASSERT(mObjectStore);
3793
0
  MOZ_ASSERT(!mStrongRequest);
3794
0
  MOZ_ASSERT(!mStrongCursor);
3795
0
3796
0
  MOZ_ASSERT(aResponses.Length() == 1);
3797
0
3798
0
  // XXX Fix this somehow...
3799
0
  auto& responses =
3800
0
    const_cast<nsTArray<ObjectStoreCursorResponse>&>(aResponses);
3801
0
3802
0
  for (ObjectStoreCursorResponse& response : responses) {
3803
0
    StructuredCloneReadInfo cloneReadInfo(std::move(response.cloneInfo()));
3804
0
    cloneReadInfo.mDatabase = mTransaction->Database();
3805
0
3806
0
    DeserializeStructuredCloneFiles(mTransaction->Database(),
3807
0
                                    response.cloneInfo().files(),
3808
0
                                    nullptr,
3809
0
                                    cloneReadInfo.mFiles);
3810
0
3811
0
    RefPtr<IDBCursor> newCursor;
3812
0
3813
0
    if (mCursor) {
3814
0
      mCursor->Reset(std::move(response.key()), std::move(cloneReadInfo));
3815
0
    } else {
3816
0
      newCursor = IDBCursor::Create(this,
3817
0
                                    std::move(response.key()),
3818
0
                                    std::move(cloneReadInfo));
3819
0
      mCursor = newCursor;
3820
0
    }
3821
0
  }
3822
0
3823
0
  ResultHelper helper(mRequest, mTransaction, mCursor);
3824
0
  DispatchSuccessEvent(&helper);
3825
0
}
3826
3827
void
3828
BackgroundCursorChild::HandleResponse(
3829
                                  const ObjectStoreKeyCursorResponse& aResponse)
3830
0
{
3831
0
  AssertIsOnOwningThread();
3832
0
  MOZ_ASSERT(mRequest);
3833
0
  MOZ_ASSERT(mTransaction);
3834
0
  MOZ_ASSERT(mObjectStore);
3835
0
  MOZ_ASSERT(!mStrongRequest);
3836
0
  MOZ_ASSERT(!mStrongCursor);
3837
0
3838
0
  // XXX Fix this somehow...
3839
0
  auto& response = const_cast<ObjectStoreKeyCursorResponse&>(aResponse);
3840
0
3841
0
  RefPtr<IDBCursor> newCursor;
3842
0
3843
0
  if (mCursor) {
3844
0
    mCursor->Reset(std::move(response.key()));
3845
0
  } else {
3846
0
    newCursor = IDBCursor::Create(this, std::move(response.key()));
3847
0
    mCursor = newCursor;
3848
0
  }
3849
0
3850
0
  ResultHelper helper(mRequest, mTransaction, mCursor);
3851
0
  DispatchSuccessEvent(&helper);
3852
0
}
3853
3854
void
3855
BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
3856
0
{
3857
0
  AssertIsOnOwningThread();
3858
0
  MOZ_ASSERT(mRequest);
3859
0
  MOZ_ASSERT(mTransaction);
3860
0
  MOZ_ASSERT(mIndex);
3861
0
  MOZ_ASSERT(!mStrongRequest);
3862
0
  MOZ_ASSERT(!mStrongCursor);
3863
0
3864
0
  // XXX Fix this somehow...
3865
0
  auto& response = const_cast<IndexCursorResponse&>(aResponse);
3866
0
3867
0
  StructuredCloneReadInfo cloneReadInfo(std::move(response.cloneInfo()));
3868
0
  cloneReadInfo.mDatabase = mTransaction->Database();
3869
0
3870
0
  DeserializeStructuredCloneFiles(mTransaction->Database(),
3871
0
                                  aResponse.cloneInfo().files(),
3872
0
                                  nullptr,
3873
0
                                  cloneReadInfo.mFiles);
3874
0
3875
0
  RefPtr<IDBCursor> newCursor;
3876
0
3877
0
  if (mCursor) {
3878
0
    mCursor->Reset(std::move(response.key()),
3879
0
                   std::move(response.sortKey()),
3880
0
                   std::move(response.objectKey()),
3881
0
                   std::move(cloneReadInfo));
3882
0
  } else {
3883
0
    newCursor = IDBCursor::Create(this,
3884
0
                                  std::move(response.key()),
3885
0
                                  std::move(response.sortKey()),
3886
0
                                  std::move(response.objectKey()),
3887
0
                                  std::move(cloneReadInfo));
3888
0
    mCursor = newCursor;
3889
0
  }
3890
0
3891
0
  ResultHelper helper(mRequest, mTransaction, mCursor);
3892
0
  DispatchSuccessEvent(&helper);
3893
0
}
3894
3895
void
3896
BackgroundCursorChild::HandleResponse(const IndexKeyCursorResponse& aResponse)
3897
0
{
3898
0
  AssertIsOnOwningThread();
3899
0
  MOZ_ASSERT(mRequest);
3900
0
  MOZ_ASSERT(mTransaction);
3901
0
  MOZ_ASSERT(mIndex);
3902
0
  MOZ_ASSERT(!mStrongRequest);
3903
0
  MOZ_ASSERT(!mStrongCursor);
3904
0
3905
0
  // XXX Fix this somehow...
3906
0
  auto& response = const_cast<IndexKeyCursorResponse&>(aResponse);
3907
0
3908
0
  RefPtr<IDBCursor> newCursor;
3909
0
3910
0
  if (mCursor) {
3911
0
    mCursor->Reset(std::move(response.key()),
3912
0
                   std::move(response.sortKey()),
3913
0
                   std::move(response.objectKey()));
3914
0
  } else {
3915
0
    newCursor = IDBCursor::Create(this,
3916
0
                                  std::move(response.key()),
3917
0
                                  std::move(response.sortKey()),
3918
0
                                  std::move(response.objectKey()));
3919
0
    mCursor = newCursor;
3920
0
  }
3921
0
3922
0
  ResultHelper helper(mRequest, mTransaction, mCursor);
3923
0
  DispatchSuccessEvent(&helper);
3924
0
}
3925
3926
void
3927
BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy)
3928
0
{
3929
0
  AssertIsOnOwningThread();
3930
0
  MOZ_ASSERT_IF(aWhy == Deletion, !mStrongRequest);
3931
0
  MOZ_ASSERT_IF(aWhy == Deletion, !mStrongCursor);
3932
0
3933
0
  MaybeCollectGarbageOnIPCMessage();
3934
0
3935
0
  if (mStrongRequest && !mStrongCursor && mTransaction) {
3936
0
    mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
3937
0
                                    aWhy == Deletion);
3938
0
  }
3939
0
3940
0
  if (mCursor) {
3941
0
    mCursor->ClearBackgroundActor();
3942
#ifdef DEBUG
3943
    mCursor = nullptr;
3944
#endif
3945
  }
3946
0
3947
#ifdef DEBUG
3948
  mRequest = nullptr;
3949
  mTransaction = nullptr;
3950
  mObjectStore = nullptr;
3951
  mIndex = nullptr;
3952
#endif
3953
}
3954
3955
mozilla::ipc::IPCResult
3956
BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
3957
0
{
3958
0
  AssertIsOnOwningThread();
3959
0
  MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
3960
0
  MOZ_ASSERT(mRequest);
3961
0
  MOZ_ASSERT(mTransaction);
3962
0
  MOZ_ASSERT_IF(mCursor, mStrongCursor);
3963
0
  MOZ_ASSERT_IF(!mCursor, mStrongRequest);
3964
0
3965
0
  MaybeCollectGarbageOnIPCMessage();
3966
0
3967
0
  RefPtr<IDBRequest> request;
3968
0
  mStrongRequest.swap(request);
3969
0
3970
0
  RefPtr<IDBCursor> cursor;
3971
0
  mStrongCursor.swap(cursor);
3972
0
3973
0
  switch (aResponse.type()) {
3974
0
    case CursorResponse::Tnsresult:
3975
0
      HandleResponse(aResponse.get_nsresult());
3976
0
      break;
3977
0
3978
0
    case CursorResponse::Tvoid_t:
3979
0
      HandleResponse(aResponse.get_void_t());
3980
0
      break;
3981
0
3982
0
    case CursorResponse::TArrayOfObjectStoreCursorResponse:
3983
0
      HandleResponse(aResponse.get_ArrayOfObjectStoreCursorResponse());
3984
0
      break;
3985
0
3986
0
    case CursorResponse::TObjectStoreKeyCursorResponse:
3987
0
      HandleResponse(aResponse.get_ObjectStoreKeyCursorResponse());
3988
0
      break;
3989
0
3990
0
    case CursorResponse::TIndexCursorResponse:
3991
0
      HandleResponse(aResponse.get_IndexCursorResponse());
3992
0
      break;
3993
0
3994
0
    case CursorResponse::TIndexKeyCursorResponse:
3995
0
      HandleResponse(aResponse.get_IndexKeyCursorResponse());
3996
0
      break;
3997
0
3998
0
    default:
3999
0
      MOZ_CRASH("Should never get here!");
4000
0
  }
4001
0
4002
0
  mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
4003
0
4004
0
  return IPC_OK();
4005
0
}
4006
4007
NS_IMETHODIMP
4008
BackgroundCursorChild::
4009
DelayedActionRunnable::Run()
4010
0
{
4011
0
  MOZ_ASSERT(mActor);
4012
0
  mActor->AssertIsOnOwningThread();
4013
0
  MOZ_ASSERT(mRequest);
4014
0
  MOZ_ASSERT(mActionFunc);
4015
0
4016
0
  (mActor->*mActionFunc)();
4017
0
4018
0
  mActor = nullptr;
4019
0
  mRequest = nullptr;
4020
0
4021
0
  return NS_OK;
4022
0
}
4023
4024
nsresult
4025
BackgroundCursorChild::
4026
DelayedActionRunnable::Cancel()
4027
0
{
4028
0
  if (NS_WARN_IF(!mActor)) {
4029
0
    return NS_ERROR_UNEXPECTED;
4030
0
  }
4031
0
4032
0
  // This must always run to clean up our state.
4033
0
  Run();
4034
0
4035
0
  return NS_OK;
4036
0
}
4037
4038
/*******************************************************************************
4039
 * BackgroundFileHandleChild
4040
 ******************************************************************************/
4041
4042
BackgroundFileHandleChild::BackgroundFileHandleChild(IDBFileHandle* aFileHandle)
4043
  : mTemporaryStrongFileHandle(aFileHandle)
4044
  , mFileHandle(aFileHandle)
4045
0
{
4046
0
  MOZ_ASSERT(aFileHandle);
4047
0
  aFileHandle->AssertIsOnOwningThread();
4048
0
4049
0
  MOZ_COUNT_CTOR(BackgroundFileHandleChild);
4050
0
}
4051
4052
BackgroundFileHandleChild::~BackgroundFileHandleChild()
4053
0
{
4054
0
  AssertIsOnOwningThread();
4055
0
4056
0
  MOZ_COUNT_DTOR(BackgroundFileHandleChild);
4057
0
}
4058
4059
#ifdef DEBUG
4060
4061
void
4062
BackgroundFileHandleChild::AssertIsOnOwningThread() const
4063
{
4064
  static_cast<BackgroundMutableFileChild*>(Manager())->AssertIsOnOwningThread();
4065
}
4066
4067
#endif // DEBUG
4068
4069
void
4070
BackgroundFileHandleChild::SendDeleteMeInternal()
4071
0
{
4072
0
  AssertIsOnOwningThread();
4073
0
4074
0
  if (mFileHandle) {
4075
0
    NoteActorDestroyed();
4076
0
4077
0
    MOZ_ALWAYS_TRUE(PBackgroundFileHandleChild::SendDeleteMe());
4078
0
  }
4079
0
}
4080
4081
void
4082
BackgroundFileHandleChild::NoteActorDestroyed()
4083
0
{
4084
0
  AssertIsOnOwningThread();
4085
0
  MOZ_ASSERT_IF(mTemporaryStrongFileHandle, mFileHandle);
4086
0
4087
0
  if (mFileHandle) {
4088
0
    mFileHandle->ClearBackgroundActor();
4089
0
4090
0
    // Normally this would be DEBUG-only but NoteActorDestroyed is also called
4091
0
    // from SendDeleteMeInternal. In that case we're going to receive an actual
4092
0
    // ActorDestroy call later and we don't want to touch a dead object.
4093
0
    mTemporaryStrongFileHandle = nullptr;
4094
0
    mFileHandle = nullptr;
4095
0
  }
4096
0
}
4097
4098
void
4099
BackgroundFileHandleChild::NoteComplete()
4100
0
{
4101
0
  AssertIsOnOwningThread();
4102
0
  MOZ_ASSERT_IF(mFileHandle, mTemporaryStrongFileHandle);
4103
0
4104
0
  mTemporaryStrongFileHandle = nullptr;
4105
0
}
4106
4107
void
4108
BackgroundFileHandleChild::ActorDestroy(ActorDestroyReason aWhy)
4109
0
{
4110
0
  AssertIsOnOwningThread();
4111
0
4112
0
  NoteActorDestroyed();
4113
0
}
4114
4115
mozilla::ipc::IPCResult
4116
BackgroundFileHandleChild::RecvComplete(const bool& aAborted)
4117
0
{
4118
0
  AssertIsOnOwningThread();
4119
0
  MOZ_ASSERT(mFileHandle);
4120
0
4121
0
  mFileHandle->FireCompleteOrAbortEvents(aAborted);
4122
0
4123
0
  NoteComplete();
4124
0
  return IPC_OK();
4125
0
}
4126
4127
PBackgroundFileRequestChild*
4128
BackgroundFileHandleChild::AllocPBackgroundFileRequestChild(
4129
                                               const FileRequestParams& aParams)
4130
0
{
4131
0
  MOZ_CRASH("PBackgroundFileRequestChild actors should be manually "
4132
0
            "constructed!");
4133
0
}
4134
4135
bool
4136
BackgroundFileHandleChild::DeallocPBackgroundFileRequestChild(
4137
                                            PBackgroundFileRequestChild* aActor)
4138
0
{
4139
0
  MOZ_ASSERT(aActor);
4140
0
4141
0
  delete static_cast<BackgroundFileRequestChild*>(aActor);
4142
0
  return true;
4143
0
}
4144
4145
/*******************************************************************************
4146
 * BackgroundFileRequestChild
4147
 ******************************************************************************/
4148
4149
BackgroundFileRequestChild::BackgroundFileRequestChild(
4150
                                                   IDBFileRequest* aFileRequest)
4151
  : mFileRequest(aFileRequest)
4152
  , mFileHandle(aFileRequest->GetFileHandle())
4153
  , mActorDestroyed(false)
4154
0
{
4155
0
  MOZ_ASSERT(aFileRequest);
4156
0
  aFileRequest->AssertIsOnOwningThread();
4157
0
  MOZ_ASSERT(mFileHandle);
4158
0
  mFileHandle->AssertIsOnOwningThread();
4159
0
4160
0
  MOZ_COUNT_CTOR(BackgroundFileRequestChild);
4161
0
}
4162
4163
BackgroundFileRequestChild::~BackgroundFileRequestChild()
4164
0
{
4165
0
  AssertIsOnOwningThread();
4166
0
  MOZ_ASSERT(!mFileHandle);
4167
0
4168
0
  MOZ_COUNT_DTOR(BackgroundFileRequestChild);
4169
0
}
4170
4171
#ifdef DEBUG
4172
4173
void
4174
BackgroundFileRequestChild::AssertIsOnOwningThread() const
4175
{
4176
  MOZ_ASSERT(mFileRequest);
4177
  mFileRequest->AssertIsOnOwningThread();
4178
}
4179
4180
#endif // DEBUG
4181
4182
void
4183
BackgroundFileRequestChild::HandleResponse(nsresult aResponse)
4184
0
{
4185
0
  AssertIsOnOwningThread();
4186
0
  MOZ_ASSERT(NS_FAILED(aResponse));
4187
0
  MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_FILEHANDLE);
4188
0
  MOZ_ASSERT(mFileHandle);
4189
0
4190
0
  DispatchFileHandleErrorEvent(mFileRequest, aResponse, mFileHandle);
4191
0
}
4192
4193
void
4194
BackgroundFileRequestChild::HandleResponse(
4195
                                    const FileRequestGetFileResponse& aResponse)
4196
0
{
4197
0
  AssertIsOnOwningThread();
4198
0
4199
0
  RefPtr<File> file = ConvertActorToFile(mFileHandle, aResponse);
4200
0
4201
0
  FileHandleResultHelper helper(mFileRequest, mFileHandle, file);
4202
0
4203
0
  DispatchFileHandleSuccessEvent(&helper);
4204
0
}
4205
4206
void
4207
BackgroundFileRequestChild::HandleResponse(const nsCString& aResponse)
4208
0
{
4209
0
  AssertIsOnOwningThread();
4210
0
4211
0
  FileHandleResultHelper helper(mFileRequest, mFileHandle, &aResponse);
4212
0
4213
0
  DispatchFileHandleSuccessEvent(&helper);
4214
0
}
4215
4216
void
4217
BackgroundFileRequestChild::HandleResponse(const FileRequestMetadata& aResponse)
4218
0
{
4219
0
  AssertIsOnOwningThread();
4220
0
4221
0
  FileHandleResultHelper helper(mFileRequest, mFileHandle, &aResponse);
4222
0
4223
0
  DispatchFileHandleSuccessEvent(&helper);
4224
0
}
4225
4226
void
4227
BackgroundFileRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
4228
0
{
4229
0
  AssertIsOnOwningThread();
4230
0
4231
0
  FileHandleResultHelper helper(mFileRequest, mFileHandle, &aResponse);
4232
0
4233
0
  DispatchFileHandleSuccessEvent(&helper);
4234
0
}
4235
4236
void
4237
BackgroundFileRequestChild::ActorDestroy(ActorDestroyReason aWhy)
4238
0
{
4239
0
  AssertIsOnOwningThread();
4240
0
4241
0
  MOZ_ASSERT(!mActorDestroyed);
4242
0
4243
0
  mActorDestroyed = true;
4244
0
4245
0
  if (mFileHandle) {
4246
0
    mFileHandle->AssertIsOnOwningThread();
4247
0
4248
0
    mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */
4249
0
                                   aWhy == Deletion);
4250
0
4251
#ifdef DEBUG
4252
    mFileHandle = nullptr;
4253
#endif
4254
  }
4255
0
}
4256
4257
mozilla::ipc::IPCResult
4258
BackgroundFileRequestChild::Recv__delete__(const FileRequestResponse& aResponse)
4259
0
{
4260
0
  AssertIsOnOwningThread();
4261
0
  MOZ_ASSERT(mFileRequest);
4262
0
  MOZ_ASSERT(mFileHandle);
4263
0
4264
0
  if (mFileHandle->IsAborted()) {
4265
0
    // Always handle an "error" with ABORT_ERR if the file handle was aborted,
4266
0
    // even if the request succeeded or failed with another error.
4267
0
    HandleResponse(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
4268
0
  } else {
4269
0
    switch (aResponse.type()) {
4270
0
      case FileRequestResponse::Tnsresult:
4271
0
        HandleResponse(aResponse.get_nsresult());
4272
0
        break;
4273
0
4274
0
      case FileRequestResponse::TFileRequestGetFileResponse:
4275
0
        HandleResponse(aResponse.get_FileRequestGetFileResponse());
4276
0
        break;
4277
0
4278
0
      case FileRequestResponse::TFileRequestReadResponse:
4279
0
        HandleResponse(aResponse.get_FileRequestReadResponse().data());
4280
0
        break;
4281
0
4282
0
      case FileRequestResponse::TFileRequestWriteResponse:
4283
0
        HandleResponse(JS::UndefinedHandleValue);
4284
0
        break;
4285
0
4286
0
      case FileRequestResponse::TFileRequestTruncateResponse:
4287
0
        HandleResponse(JS::UndefinedHandleValue);
4288
0
        break;
4289
0
4290
0
      case FileRequestResponse::TFileRequestFlushResponse:
4291
0
        HandleResponse(JS::UndefinedHandleValue);
4292
0
        break;
4293
0
4294
0
      case FileRequestResponse::TFileRequestGetMetadataResponse:
4295
0
        HandleResponse(aResponse.get_FileRequestGetMetadataResponse()
4296
0
                                .metadata());
4297
0
        break;
4298
0
4299
0
      default:
4300
0
        MOZ_CRASH("Unknown response type!");
4301
0
    }
4302
0
  }
4303
0
4304
0
  mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
4305
0
4306
0
  // Null this out so that we don't try to call OnRequestFinished() again in
4307
0
  // ActorDestroy.
4308
0
  mFileHandle = nullptr;
4309
0
4310
0
  return IPC_OK();
4311
0
}
4312
4313
mozilla::ipc::IPCResult
4314
BackgroundFileRequestChild::RecvProgress(const uint64_t& aProgress,
4315
                                         const uint64_t& aProgressMax)
4316
0
{
4317
0
  AssertIsOnOwningThread();
4318
0
  MOZ_ASSERT(mFileRequest);
4319
0
4320
0
  mFileRequest->FireProgressEvent(aProgress, aProgressMax);
4321
0
4322
0
  return IPC_OK();
4323
0
}
4324
4325
/*******************************************************************************
4326
 * BackgroundUtilsChild
4327
 ******************************************************************************/
4328
4329
BackgroundUtilsChild::BackgroundUtilsChild(IndexedDatabaseManager* aManager)
4330
  : mManager(aManager)
4331
0
{
4332
0
  AssertIsOnOwningThread();
4333
0
  MOZ_ASSERT(aManager);
4334
0
4335
0
  MOZ_COUNT_CTOR(indexedDB::BackgroundUtilsChild);
4336
0
}
4337
4338
BackgroundUtilsChild::~BackgroundUtilsChild()
4339
0
{
4340
0
  MOZ_COUNT_DTOR(indexedDB::BackgroundUtilsChild);
4341
0
}
4342
4343
void
4344
BackgroundUtilsChild::SendDeleteMeInternal()
4345
0
{
4346
0
  AssertIsOnOwningThread();
4347
0
4348
0
  if (mManager) {
4349
0
    mManager->ClearBackgroundActor();
4350
0
    mManager = nullptr;
4351
0
4352
0
    MOZ_ALWAYS_TRUE(PBackgroundIndexedDBUtilsChild::SendDeleteMe());
4353
0
  }
4354
0
}
4355
4356
void
4357
BackgroundUtilsChild::ActorDestroy(ActorDestroyReason aWhy)
4358
0
{
4359
0
  AssertIsOnOwningThread();
4360
0
4361
0
  if (mManager) {
4362
0
    mManager->ClearBackgroundActor();
4363
#ifdef DEBUG
4364
    mManager = nullptr;
4365
#endif
4366
  }
4367
0
}
4368
4369
} // namespace indexedDB
4370
} // namespace dom
4371
} // namespace mozilla