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