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