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
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "IDBRequest.h"
8 :
9 : #include "BackgroundChildImpl.h"
10 : #include "IDBCursor.h"
11 : #include "IDBDatabase.h"
12 : #include "IDBEvents.h"
13 : #include "IDBFactory.h"
14 : #include "IDBIndex.h"
15 : #include "IDBObjectStore.h"
16 : #include "IDBTransaction.h"
17 : #include "IndexedDatabaseManager.h"
18 : #include "mozilla/ContentEvents.h"
19 : #include "mozilla/ErrorResult.h"
20 : #include "mozilla/EventDispatcher.h"
21 : #include "mozilla/Move.h"
22 : #include "mozilla/dom/DOMError.h"
23 : #include "mozilla/dom/ErrorEventBinding.h"
24 : #include "mozilla/dom/IDBOpenDBRequestBinding.h"
25 : #include "mozilla/dom/ScriptSettings.h"
26 : #include "nsCOMPtr.h"
27 : #include "nsContentUtils.h"
28 : #include "nsIScriptContext.h"
29 : #include "nsJSUtils.h"
30 : #include "nsPIDOMWindow.h"
31 : #include "nsString.h"
32 : #include "ReportInternalError.h"
33 : #include "WorkerHolder.h"
34 : #include "WorkerPrivate.h"
35 :
36 : // Include this last to avoid path problems on Windows.
37 : #include "ActorsChild.h"
38 :
39 : namespace mozilla {
40 : namespace dom {
41 :
42 : using namespace mozilla::dom::indexedDB;
43 : using namespace mozilla::dom::workers;
44 : using namespace mozilla::ipc;
45 :
46 : namespace {
47 :
48 : NS_DEFINE_IID(kIDBRequestIID, PRIVATE_IDBREQUEST_IID);
49 :
50 : } // namespace
51 :
52 0 : IDBRequest::IDBRequest(IDBDatabase* aDatabase)
53 : : IDBWrapperCache(aDatabase)
54 : , mLoggingSerialNumber(0)
55 : , mLineNo(0)
56 : , mColumn(0)
57 0 : , mHaveResultOrErrorCode(false)
58 : {
59 0 : MOZ_ASSERT(aDatabase);
60 0 : aDatabase->AssertIsOnOwningThread();
61 :
62 0 : InitMembers();
63 0 : }
64 :
65 0 : IDBRequest::IDBRequest(nsPIDOMWindowInner* aOwner)
66 : : IDBWrapperCache(aOwner)
67 : , mLoggingSerialNumber(0)
68 : , mLineNo(0)
69 : , mColumn(0)
70 0 : , mHaveResultOrErrorCode(false)
71 : {
72 0 : InitMembers();
73 0 : }
74 :
75 0 : IDBRequest::~IDBRequest()
76 : {
77 0 : AssertIsOnOwningThread();
78 0 : }
79 :
80 : void
81 0 : IDBRequest::InitMembers()
82 : {
83 0 : AssertIsOnOwningThread();
84 :
85 0 : mResultVal.setUndefined();
86 0 : mLoggingSerialNumber = NextSerialNumber();
87 0 : mErrorCode = NS_OK;
88 0 : mLineNo = 0;
89 0 : mColumn = 0;
90 0 : mHaveResultOrErrorCode = false;
91 0 : }
92 :
93 : // static
94 : already_AddRefed<IDBRequest>
95 0 : IDBRequest::Create(JSContext* aCx,
96 : IDBDatabase* aDatabase,
97 : IDBTransaction* aTransaction)
98 : {
99 0 : MOZ_ASSERT(aCx);
100 0 : MOZ_ASSERT(aDatabase);
101 0 : aDatabase->AssertIsOnOwningThread();
102 :
103 0 : RefPtr<IDBRequest> request = new IDBRequest(aDatabase);
104 0 : CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
105 :
106 0 : request->mTransaction = aTransaction;
107 0 : request->SetScriptOwner(aDatabase->GetScriptOwner());
108 :
109 0 : return request.forget();
110 : }
111 :
112 : // static
113 : already_AddRefed<IDBRequest>
114 0 : IDBRequest::Create(JSContext* aCx,
115 : IDBObjectStore* aSourceAsObjectStore,
116 : IDBDatabase* aDatabase,
117 : IDBTransaction* aTransaction)
118 : {
119 0 : MOZ_ASSERT(aSourceAsObjectStore);
120 0 : aSourceAsObjectStore->AssertIsOnOwningThread();
121 :
122 0 : RefPtr<IDBRequest> request = Create(aCx, aDatabase, aTransaction);
123 :
124 0 : request->mSourceAsObjectStore = aSourceAsObjectStore;
125 :
126 0 : return request.forget();
127 : }
128 :
129 : // static
130 : already_AddRefed<IDBRequest>
131 0 : IDBRequest::Create(JSContext* aCx,
132 : IDBIndex* aSourceAsIndex,
133 : IDBDatabase* aDatabase,
134 : IDBTransaction* aTransaction)
135 : {
136 0 : MOZ_ASSERT(aSourceAsIndex);
137 0 : aSourceAsIndex->AssertIsOnOwningThread();
138 :
139 0 : RefPtr<IDBRequest> request = Create(aCx, aDatabase, aTransaction);
140 :
141 0 : request->mSourceAsIndex = aSourceAsIndex;
142 :
143 0 : return request.forget();
144 : }
145 :
146 : // static
147 : uint64_t
148 0 : IDBRequest::NextSerialNumber()
149 : {
150 : BackgroundChildImpl::ThreadLocal* threadLocal =
151 0 : BackgroundChildImpl::GetThreadLocalForCurrentThread();
152 0 : MOZ_ASSERT(threadLocal);
153 :
154 0 : ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
155 0 : MOZ_ASSERT(idbThreadLocal);
156 :
157 0 : return idbThreadLocal->NextRequestSN();
158 : }
159 :
160 : void
161 0 : IDBRequest::SetLoggingSerialNumber(uint64_t aLoggingSerialNumber)
162 : {
163 0 : AssertIsOnOwningThread();
164 0 : MOZ_ASSERT(aLoggingSerialNumber > mLoggingSerialNumber);
165 :
166 0 : mLoggingSerialNumber = aLoggingSerialNumber;
167 0 : }
168 :
169 : void
170 0 : IDBRequest::CaptureCaller(JSContext* aCx, nsAString& aFilename,
171 : uint32_t* aLineNo, uint32_t* aColumn)
172 : {
173 0 : MOZ_ASSERT(aFilename.IsEmpty());
174 0 : MOZ_ASSERT(aLineNo);
175 0 : MOZ_ASSERT(aColumn);
176 :
177 0 : nsJSUtils::GetCallingLocation(aCx, aFilename, aLineNo, aColumn);
178 0 : }
179 :
180 : void
181 0 : IDBRequest::GetSource(
182 : Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
183 : {
184 0 : AssertIsOnOwningThread();
185 :
186 0 : MOZ_ASSERT_IF(mSourceAsObjectStore, !mSourceAsIndex);
187 0 : MOZ_ASSERT_IF(mSourceAsIndex, !mSourceAsObjectStore);
188 0 : MOZ_ASSERT_IF(mSourceAsCursor, mSourceAsObjectStore || mSourceAsIndex);
189 :
190 : // Always check cursor first since cursor requests hold both the cursor and
191 : // the objectStore or index the cursor came from.
192 0 : if (mSourceAsCursor) {
193 0 : aSource.SetValue().SetAsIDBCursor() = mSourceAsCursor;
194 0 : } else if (mSourceAsObjectStore) {
195 0 : aSource.SetValue().SetAsIDBObjectStore() = mSourceAsObjectStore;
196 0 : } else if (mSourceAsIndex) {
197 0 : aSource.SetValue().SetAsIDBIndex() = mSourceAsIndex;
198 : } else {
199 0 : aSource.SetNull();
200 : }
201 0 : }
202 :
203 : void
204 0 : IDBRequest::Reset()
205 : {
206 0 : AssertIsOnOwningThread();
207 :
208 0 : mResultVal.setUndefined();
209 0 : mHaveResultOrErrorCode = false;
210 0 : mError = nullptr;
211 0 : }
212 :
213 : void
214 0 : IDBRequest::SetError(nsresult aRv)
215 : {
216 0 : AssertIsOnOwningThread();
217 0 : MOZ_ASSERT(NS_FAILED(aRv));
218 0 : MOZ_ASSERT(NS_ERROR_GET_MODULE(aRv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
219 0 : MOZ_ASSERT(!mError);
220 :
221 0 : mHaveResultOrErrorCode = true;
222 0 : mError = new DOMError(GetOwner(), aRv);
223 0 : mErrorCode = aRv;
224 :
225 0 : mResultVal.setUndefined();
226 0 : }
227 :
228 : #ifdef DEBUG
229 :
230 : nsresult
231 0 : IDBRequest::GetErrorCode() const
232 : {
233 0 : AssertIsOnOwningThread();
234 0 : MOZ_ASSERT(mHaveResultOrErrorCode);
235 :
236 0 : return mErrorCode;
237 : }
238 :
239 : DOMError*
240 0 : IDBRequest::GetErrorAfterResult() const
241 : {
242 0 : AssertIsOnOwningThread();
243 0 : MOZ_ASSERT(mHaveResultOrErrorCode);
244 :
245 0 : return mError;
246 : }
247 :
248 : #endif // DEBUG
249 :
250 : void
251 0 : IDBRequest::GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo,
252 : uint32_t* aColumn) const
253 : {
254 0 : AssertIsOnOwningThread();
255 0 : MOZ_ASSERT(aLineNo);
256 0 : MOZ_ASSERT(aColumn);
257 :
258 0 : aFilename = mFilename;
259 0 : *aLineNo = mLineNo;
260 0 : *aColumn = mColumn;
261 0 : }
262 :
263 : IDBRequestReadyState
264 0 : IDBRequest::ReadyState() const
265 : {
266 0 : AssertIsOnOwningThread();
267 :
268 0 : return IsPending() ?
269 : IDBRequestReadyState::Pending :
270 0 : IDBRequestReadyState::Done;
271 : }
272 :
273 : void
274 0 : IDBRequest::SetSource(IDBCursor* aSource)
275 : {
276 0 : AssertIsOnOwningThread();
277 0 : MOZ_ASSERT(aSource);
278 0 : MOZ_ASSERT(mSourceAsObjectStore || mSourceAsIndex);
279 0 : MOZ_ASSERT(!mSourceAsCursor);
280 :
281 0 : mSourceAsCursor = aSource;
282 0 : }
283 :
284 : JSObject*
285 0 : IDBRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
286 : {
287 0 : return IDBRequestBinding::Wrap(aCx, this, aGivenProto);
288 : }
289 :
290 : void
291 0 : IDBRequest::GetResult(JS::MutableHandle<JS::Value> aResult,
292 : ErrorResult& aRv) const
293 : {
294 0 : AssertIsOnOwningThread();
295 :
296 0 : if (!mHaveResultOrErrorCode) {
297 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
298 0 : return;
299 : }
300 :
301 0 : aResult.set(mResultVal);
302 : }
303 :
304 : void
305 0 : IDBRequest::SetResultCallback(ResultCallback* aCallback)
306 : {
307 0 : AssertIsOnOwningThread();
308 0 : MOZ_ASSERT(aCallback);
309 0 : MOZ_ASSERT(!mHaveResultOrErrorCode);
310 0 : MOZ_ASSERT(mResultVal.isUndefined());
311 0 : MOZ_ASSERT(!mError);
312 :
313 : // See if our window is still valid.
314 0 : if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
315 0 : SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
316 0 : return;
317 : }
318 :
319 0 : AutoJSAPI autoJS;
320 0 : Maybe<JSAutoCompartment> ac;
321 :
322 0 : if (GetScriptOwner()) {
323 : // If we have a script owner we want the SafeJSContext and then to enter the
324 : // script owner's compartment.
325 0 : autoJS.Init();
326 0 : ac.emplace(autoJS.cx(), GetScriptOwner());
327 : } else {
328 : // Otherwise our owner is a window and we use that to initialize.
329 0 : MOZ_ASSERT(GetOwner());
330 0 : if (!autoJS.Init(GetOwner())) {
331 0 : IDB_WARNING("Failed to initialize AutoJSAPI!");
332 0 : SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
333 0 : return;
334 : }
335 : }
336 :
337 0 : JSContext* cx = autoJS.cx();
338 :
339 0 : AssertIsRooted();
340 :
341 0 : JS::Rooted<JS::Value> result(cx);
342 0 : nsresult rv = aCallback->GetResult(cx, &result);
343 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
344 : // This can only fail if the structured clone contains a mutable file
345 : // and the child is not in the main thread and main process.
346 : // In that case CreateAndWrapMutableFile() returns false which shows up
347 : // as NS_ERROR_DOM_DATA_CLONE_ERR here.
348 0 : MOZ_ASSERT(rv == NS_ERROR_DOM_DATA_CLONE_ERR);
349 :
350 : // We are not setting a result or an error object here since we want to
351 : // throw an exception when the 'result' property is being touched.
352 0 : return;
353 : }
354 :
355 0 : mError = nullptr;
356 0 : mResultVal = result;
357 :
358 0 : mHaveResultOrErrorCode = true;
359 : }
360 :
361 : DOMError*
362 0 : IDBRequest::GetError(ErrorResult& aRv)
363 : {
364 0 : AssertIsOnOwningThread();
365 :
366 0 : if (!mHaveResultOrErrorCode) {
367 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
368 0 : return nullptr;
369 : }
370 :
371 0 : return mError;
372 : }
373 :
374 : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest)
375 :
376 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
377 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsObjectStore)
378 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsIndex)
379 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsCursor)
380 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
381 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
382 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
383 :
384 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
385 0 : tmp->mResultVal.setUndefined();
386 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsObjectStore)
387 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsIndex)
388 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceAsCursor)
389 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransaction)
390 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
391 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
392 :
393 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
394 : // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
395 : // DOMEventTargetHelper does it for us.
396 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultVal)
397 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
398 :
399 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBRequest)
400 0 : if (aIID.Equals(kIDBRequestIID)) {
401 0 : foundInterface = this;
402 : } else
403 0 : NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
404 :
405 0 : NS_IMPL_ADDREF_INHERITED(IDBRequest, IDBWrapperCache)
406 0 : NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
407 :
408 : nsresult
409 0 : IDBRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
410 : {
411 0 : AssertIsOnOwningThread();
412 :
413 0 : aVisitor.mCanHandle = true;
414 0 : aVisitor.mParentTarget = mTransaction;
415 0 : return NS_OK;
416 : }
417 :
418 : class IDBOpenDBRequest::WorkerHolder final
419 : : public mozilla::dom::workers::WorkerHolder
420 : {
421 : WorkerPrivate* mWorkerPrivate;
422 : #ifdef DEBUG
423 : // This is only here so that assertions work in the destructor even if
424 : // NoteAddWorkerHolderFailed was called.
425 : WorkerPrivate* mWorkerPrivateDEBUG;
426 : #endif
427 :
428 : public:
429 : explicit
430 0 : WorkerHolder(WorkerPrivate* aWorkerPrivate)
431 0 : : mWorkerPrivate(aWorkerPrivate)
432 : #ifdef DEBUG
433 0 : , mWorkerPrivateDEBUG(aWorkerPrivate)
434 : #endif
435 : {
436 0 : MOZ_ASSERT(aWorkerPrivate);
437 0 : aWorkerPrivate->AssertIsOnWorkerThread();
438 :
439 0 : MOZ_COUNT_CTOR(IDBOpenDBRequest::WorkerHolder);
440 0 : }
441 :
442 0 : ~WorkerHolder()
443 0 : {
444 : #ifdef DEBUG
445 0 : mWorkerPrivateDEBUG->AssertIsOnWorkerThread();
446 : #endif
447 :
448 0 : MOZ_COUNT_DTOR(IDBOpenDBRequest::WorkerHolder);
449 0 : }
450 :
451 : void
452 0 : NoteAddWorkerHolderFailed()
453 : {
454 0 : MOZ_ASSERT(mWorkerPrivate);
455 0 : mWorkerPrivate->AssertIsOnWorkerThread();
456 :
457 0 : mWorkerPrivate = nullptr;
458 0 : }
459 :
460 : private:
461 : virtual bool
462 : Notify(Status aStatus) override;
463 : };
464 :
465 0 : IDBOpenDBRequest::IDBOpenDBRequest(IDBFactory* aFactory,
466 : nsPIDOMWindowInner* aOwner,
467 0 : bool aFileHandleDisabled)
468 : : IDBRequest(aOwner)
469 : , mFactory(aFactory)
470 : , mFileHandleDisabled(aFileHandleDisabled)
471 0 : , mIncreasedActiveDatabaseCount(false)
472 : {
473 0 : AssertIsOnOwningThread();
474 0 : MOZ_ASSERT(aFactory);
475 :
476 : // aOwner may be null.
477 0 : }
478 :
479 0 : IDBOpenDBRequest::~IDBOpenDBRequest()
480 : {
481 0 : AssertIsOnOwningThread();
482 0 : MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
483 0 : }
484 :
485 : // static
486 : already_AddRefed<IDBOpenDBRequest>
487 0 : IDBOpenDBRequest::CreateForWindow(JSContext* aCx,
488 : IDBFactory* aFactory,
489 : nsPIDOMWindowInner* aOwner,
490 : JS::Handle<JSObject*> aScriptOwner)
491 : {
492 0 : MOZ_ASSERT(aFactory);
493 0 : aFactory->AssertIsOnOwningThread();
494 0 : MOZ_ASSERT(aOwner);
495 0 : MOZ_ASSERT(aScriptOwner);
496 :
497 0 : bool fileHandleDisabled = !IndexedDatabaseManager::IsFileHandleEnabled();
498 :
499 : RefPtr<IDBOpenDBRequest> request =
500 0 : new IDBOpenDBRequest(aFactory, aOwner, fileHandleDisabled);
501 0 : CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
502 :
503 0 : request->SetScriptOwner(aScriptOwner);
504 :
505 0 : request->IncreaseActiveDatabaseCount();
506 :
507 0 : return request.forget();
508 : }
509 :
510 : // static
511 : already_AddRefed<IDBOpenDBRequest>
512 0 : IDBOpenDBRequest::CreateForJS(JSContext* aCx,
513 : IDBFactory* aFactory,
514 : JS::Handle<JSObject*> aScriptOwner)
515 : {
516 0 : MOZ_ASSERT(aFactory);
517 0 : aFactory->AssertIsOnOwningThread();
518 0 : MOZ_ASSERT(aScriptOwner);
519 :
520 0 : bool fileHandleDisabled = !IndexedDatabaseManager::IsFileHandleEnabled();
521 :
522 : RefPtr<IDBOpenDBRequest> request =
523 0 : new IDBOpenDBRequest(aFactory, nullptr, fileHandleDisabled);
524 0 : CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
525 :
526 0 : request->SetScriptOwner(aScriptOwner);
527 :
528 0 : if (!NS_IsMainThread()) {
529 0 : WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
530 0 : MOZ_ASSERT(workerPrivate);
531 :
532 0 : workerPrivate->AssertIsOnWorkerThread();
533 :
534 0 : nsAutoPtr<WorkerHolder> workerHolder(new WorkerHolder(workerPrivate));
535 0 : if (NS_WARN_IF(!workerHolder->HoldWorker(workerPrivate, Canceling))) {
536 0 : workerHolder->NoteAddWorkerHolderFailed();
537 0 : return nullptr;
538 : }
539 :
540 0 : request->mWorkerHolder = Move(workerHolder);
541 : }
542 :
543 0 : request->IncreaseActiveDatabaseCount();
544 :
545 0 : return request.forget();
546 : }
547 :
548 : void
549 0 : IDBOpenDBRequest::SetTransaction(IDBTransaction* aTransaction)
550 : {
551 0 : AssertIsOnOwningThread();
552 :
553 0 : MOZ_ASSERT(!aTransaction || !mTransaction);
554 :
555 0 : mTransaction = aTransaction;
556 0 : }
557 :
558 : void
559 0 : IDBOpenDBRequest::DispatchNonTransactionError(nsresult aErrorCode)
560 : {
561 0 : AssertIsOnOwningThread();
562 0 : MOZ_ASSERT(NS_FAILED(aErrorCode));
563 0 : MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
564 :
565 : // The actor failed to initiate, decrease the number of active IDBOpenRequests
566 : // here since NoteComplete won't be called.
567 0 : MaybeDecreaseActiveDatabaseCount();
568 :
569 0 : SetError(aErrorCode);
570 :
571 : // Make an error event and fire it at the target.
572 : nsCOMPtr<nsIDOMEvent> event =
573 0 : CreateGenericEvent(this,
574 0 : nsDependentString(kErrorEventType),
575 : eDoesBubble,
576 0 : eCancelable);
577 0 : MOZ_ASSERT(event);
578 :
579 : bool ignored;
580 0 : if (NS_FAILED(DispatchEvent(event, &ignored))) {
581 0 : NS_WARNING("Failed to dispatch event!");
582 : }
583 0 : }
584 :
585 : void
586 0 : IDBOpenDBRequest::NoteComplete()
587 : {
588 0 : AssertIsOnOwningThread();
589 0 : MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolder);
590 :
591 : // Normally, we decrease the number of active IDBOpenRequests here.
592 0 : MaybeDecreaseActiveDatabaseCount();
593 :
594 : // If we have a WorkerHolder installed on the worker then nulling this out
595 : // will uninstall it from the worker.
596 0 : mWorkerHolder = nullptr;
597 0 : }
598 :
599 : void
600 0 : IDBOpenDBRequest::IncreaseActiveDatabaseCount()
601 : {
602 0 : AssertIsOnOwningThread();
603 0 : MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
604 :
605 : // Increase the number of active IDBOpenRequests.
606 : // Note: We count here instead of the actor's ctor because the preemption
607 : // could happen at next JS interrupt but its BackgroundFactoryRequestChild
608 : // could be created asynchronously from IDBFactory::BackgroundCreateCallback
609 : // ::ActorCreated() if its PBackgroundChild is not created yet on this thread.
610 0 : mFactory->UpdateActiveDatabaseCount(1);
611 0 : mIncreasedActiveDatabaseCount = true;
612 0 : }
613 :
614 : void
615 0 : IDBOpenDBRequest::MaybeDecreaseActiveDatabaseCount()
616 : {
617 0 : AssertIsOnOwningThread();
618 :
619 0 : if (mIncreasedActiveDatabaseCount) {
620 : // Decrease the number of active IDBOpenRequests.
621 0 : mFactory->UpdateActiveDatabaseCount(-1);
622 0 : mIncreasedActiveDatabaseCount = false;
623 : }
624 0 : }
625 :
626 : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBOpenDBRequest)
627 :
628 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBOpenDBRequest,
629 : IDBRequest)
630 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
631 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
632 :
633 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBOpenDBRequest,
634 : IDBRequest)
635 : // Don't unlink mFactory!
636 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
637 :
638 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBOpenDBRequest)
639 0 : NS_INTERFACE_MAP_END_INHERITING(IDBRequest)
640 :
641 0 : NS_IMPL_ADDREF_INHERITED(IDBOpenDBRequest, IDBRequest)
642 0 : NS_IMPL_RELEASE_INHERITED(IDBOpenDBRequest, IDBRequest)
643 :
644 : nsresult
645 0 : IDBOpenDBRequest::PostHandleEvent(EventChainPostVisitor& aVisitor)
646 : {
647 : nsresult rv =
648 0 : IndexedDatabaseManager::CommonPostHandleEvent(aVisitor, mFactory);
649 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
650 0 : return rv;
651 : }
652 :
653 0 : return NS_OK;
654 : }
655 :
656 : JSObject*
657 0 : IDBOpenDBRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
658 : {
659 0 : AssertIsOnOwningThread();
660 :
661 0 : return IDBOpenDBRequestBinding::Wrap(aCx, this, aGivenProto);
662 : }
663 :
664 : bool
665 0 : IDBOpenDBRequest::
666 : WorkerHolder::Notify(Status aStatus)
667 : {
668 0 : MOZ_ASSERT(mWorkerPrivate);
669 0 : mWorkerPrivate->AssertIsOnWorkerThread();
670 0 : MOZ_ASSERT(aStatus > Running);
671 :
672 : // There's nothing we can really do here at the moment...
673 0 : NS_WARNING("Worker closing but IndexedDB is waiting to open a database!");
674 :
675 0 : return true;
676 : }
677 :
678 : } // namespace dom
679 : } // namespace mozilla
|