|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=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 "base/basictypes.h" |
|
8 |
|
9 #include "AsyncConnectionHelper.h" |
|
10 |
|
11 #include "mozilla/dom/quota/QuotaManager.h" |
|
12 #include "mozilla/storage.h" |
|
13 #include "nsComponentManagerUtils.h" |
|
14 #include "nsContentUtils.h" |
|
15 #include "nsProxyRelease.h" |
|
16 #include "nsThreadUtils.h" |
|
17 #include "nsWrapperCacheInlines.h" |
|
18 |
|
19 #include "IDBEvents.h" |
|
20 #include "IDBTransaction.h" |
|
21 #include "IndexedDatabaseManager.h" |
|
22 #include "ProfilerHelpers.h" |
|
23 #include "ReportInternalError.h" |
|
24 #include "TransactionThreadPool.h" |
|
25 |
|
26 #include "ipc/IndexedDBChild.h" |
|
27 #include "ipc/IndexedDBParent.h" |
|
28 |
|
29 using namespace mozilla; |
|
30 USING_INDEXEDDB_NAMESPACE |
|
31 using mozilla::dom::quota::QuotaManager; |
|
32 |
|
33 namespace { |
|
34 |
|
35 IDBTransaction* gCurrentTransaction = nullptr; |
|
36 |
|
37 const uint32_t kProgressHandlerGranularity = 1000; |
|
38 |
|
39 class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget |
|
40 { |
|
41 public: |
|
42 NS_DECL_NSIEVENTTARGET |
|
43 |
|
44 TransactionPoolEventTarget(IDBTransaction* aTransaction) |
|
45 : mTransaction(aTransaction) |
|
46 { } |
|
47 |
|
48 private: |
|
49 IDBTransaction* mTransaction; |
|
50 }; |
|
51 |
|
52 // This inline is just so that we always clear aBuffers appropriately even if |
|
53 // something fails. |
|
54 inline |
|
55 nsresult |
|
56 ConvertCloneReadInfosToArrayInternal( |
|
57 JSContext* aCx, |
|
58 nsTArray<StructuredCloneReadInfo>& aReadInfos, |
|
59 JS::MutableHandle<JS::Value> aResult) |
|
60 { |
|
61 JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0)); |
|
62 if (!array) { |
|
63 IDB_WARNING("Failed to make array!"); |
|
64 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
65 } |
|
66 |
|
67 if (!aReadInfos.IsEmpty()) { |
|
68 if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) { |
|
69 IDB_WARNING("Failed to set array length!"); |
|
70 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
71 } |
|
72 |
|
73 for (uint32_t index = 0, count = aReadInfos.Length(); index < count; |
|
74 index++) { |
|
75 StructuredCloneReadInfo& readInfo = aReadInfos[index]; |
|
76 |
|
77 JS::Rooted<JS::Value> val(aCx); |
|
78 if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) { |
|
79 NS_WARNING("Failed to decode!"); |
|
80 return NS_ERROR_DOM_DATA_CLONE_ERR; |
|
81 } |
|
82 |
|
83 if (!JS_SetElement(aCx, array, index, val)) { |
|
84 IDB_WARNING("Failed to set array element!"); |
|
85 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
86 } |
|
87 } |
|
88 } |
|
89 |
|
90 aResult.setObject(*array); |
|
91 return NS_OK; |
|
92 } |
|
93 |
|
94 } // anonymous namespace |
|
95 |
|
96 HelperBase::~HelperBase() |
|
97 { |
|
98 if (!NS_IsMainThread()) { |
|
99 IDBRequest* request; |
|
100 mRequest.forget(&request); |
|
101 |
|
102 if (request) { |
|
103 nsCOMPtr<nsIThread> mainThread; |
|
104 NS_GetMainThread(getter_AddRefs(mainThread)); |
|
105 NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); |
|
106 |
|
107 if (mainThread) { |
|
108 NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request)); |
|
109 } |
|
110 } |
|
111 } |
|
112 } |
|
113 |
|
114 nsresult |
|
115 HelperBase::WrapNative(JSContext* aCx, |
|
116 nsISupports* aNative, |
|
117 JS::MutableHandle<JS::Value> aResult) |
|
118 { |
|
119 NS_ASSERTION(aCx, "Null context!"); |
|
120 NS_ASSERTION(aNative, "Null pointer!"); |
|
121 NS_ASSERTION(aResult.address(), "Null pointer!"); |
|
122 NS_ASSERTION(mRequest, "Null request!"); |
|
123 |
|
124 nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult); |
|
125 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); |
|
126 |
|
127 return NS_OK; |
|
128 } |
|
129 |
|
130 void |
|
131 HelperBase::ReleaseMainThreadObjects() |
|
132 { |
|
133 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
134 |
|
135 mRequest = nullptr; |
|
136 } |
|
137 |
|
138 AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase, |
|
139 IDBRequest* aRequest) |
|
140 : HelperBase(aRequest), |
|
141 mDatabase(aDatabase), |
|
142 mResultCode(NS_OK), |
|
143 mDispatched(false) |
|
144 { |
|
145 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
146 } |
|
147 |
|
148 AsyncConnectionHelper::AsyncConnectionHelper(IDBTransaction* aTransaction, |
|
149 IDBRequest* aRequest) |
|
150 : HelperBase(aRequest), |
|
151 mDatabase(aTransaction->mDatabase), |
|
152 mTransaction(aTransaction), |
|
153 mResultCode(NS_OK), |
|
154 mDispatched(false) |
|
155 { |
|
156 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
157 } |
|
158 |
|
159 AsyncConnectionHelper::~AsyncConnectionHelper() |
|
160 { |
|
161 if (!NS_IsMainThread()) { |
|
162 IDBDatabase* database; |
|
163 mDatabase.forget(&database); |
|
164 |
|
165 IDBTransaction* transaction; |
|
166 mTransaction.forget(&transaction); |
|
167 |
|
168 nsCOMPtr<nsIThread> mainThread; |
|
169 NS_GetMainThread(getter_AddRefs(mainThread)); |
|
170 NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); |
|
171 |
|
172 if (mainThread) { |
|
173 if (database) { |
|
174 NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(database)); |
|
175 } |
|
176 if (transaction) { |
|
177 NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(transaction)); |
|
178 } |
|
179 } |
|
180 } |
|
181 |
|
182 NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!"); |
|
183 } |
|
184 |
|
185 NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable, |
|
186 mozIStorageProgressHandler) |
|
187 |
|
188 NS_IMETHODIMP |
|
189 AsyncConnectionHelper::Run() |
|
190 { |
|
191 if (NS_IsMainThread()) { |
|
192 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run"); |
|
193 |
|
194 if (mTransaction && |
|
195 mTransaction->IsAborted()) { |
|
196 // Always fire a "error" event with ABORT_ERR if the transaction was |
|
197 // aborted, even if the request succeeded or failed with another error. |
|
198 mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR; |
|
199 } |
|
200 |
|
201 IDBTransaction* oldTransaction = gCurrentTransaction; |
|
202 gCurrentTransaction = mTransaction; |
|
203 |
|
204 ChildProcessSendResult sendResult = |
|
205 IndexedDatabaseManager::IsMainProcess() ? |
|
206 MaybeSendResponseToChildProcess(mResultCode) : |
|
207 Success_NotSent; |
|
208 |
|
209 switch (sendResult) { |
|
210 case Success_Sent: { |
|
211 if (mRequest) { |
|
212 mRequest->NotifyHelperSentResultsToChildProcess(NS_OK); |
|
213 } |
|
214 break; |
|
215 } |
|
216 |
|
217 case Success_NotSent: { |
|
218 if (mRequest) { |
|
219 nsresult rv = mRequest->NotifyHelperCompleted(this); |
|
220 if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { |
|
221 mResultCode = rv; |
|
222 } |
|
223 |
|
224 IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread " |
|
225 "response (rv = %lu)", |
|
226 "IDBRequest[%llu] MT Done", |
|
227 mRequest->GetSerialNumber(), mResultCode); |
|
228 } |
|
229 |
|
230 // Call OnError if the database had an error or if the OnSuccess |
|
231 // handler has an error. |
|
232 if (NS_FAILED(mResultCode) || |
|
233 NS_FAILED((mResultCode = OnSuccess()))) { |
|
234 OnError(); |
|
235 } |
|
236 break; |
|
237 } |
|
238 |
|
239 case Success_ActorDisconnected: { |
|
240 // Nothing needs to be done here. |
|
241 break; |
|
242 } |
|
243 |
|
244 case Error: { |
|
245 IDB_WARNING("MaybeSendResultsToChildProcess failed!"); |
|
246 mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
247 if (mRequest) { |
|
248 mRequest->NotifyHelperSentResultsToChildProcess(mResultCode); |
|
249 } |
|
250 break; |
|
251 } |
|
252 |
|
253 default: |
|
254 MOZ_CRASH("Unknown value for ChildProcessSendResult!"); |
|
255 } |
|
256 |
|
257 NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!"); |
|
258 gCurrentTransaction = oldTransaction; |
|
259 |
|
260 if (mDispatched && mTransaction) { |
|
261 mTransaction->OnRequestFinished(); |
|
262 } |
|
263 |
|
264 ReleaseMainThreadObjects(); |
|
265 |
|
266 NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't " |
|
267 "call AsyncConnectionHelper::ReleaseMainThreadObjects!"); |
|
268 |
|
269 return NS_OK; |
|
270 } |
|
271 |
|
272 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); |
|
273 |
|
274 PROFILER_LABEL("IndexedDB", "AsyncConnectionHelper::Run"); |
|
275 |
|
276 IDB_PROFILER_MARK_IF(mRequest, |
|
277 "IndexedDB Request %llu: Beginning database work", |
|
278 "IDBRequest[%llu] DT Start", |
|
279 mRequest->GetSerialNumber()); |
|
280 |
|
281 nsresult rv = NS_OK; |
|
282 nsCOMPtr<mozIStorageConnection> connection; |
|
283 |
|
284 if (mTransaction) { |
|
285 rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection)); |
|
286 if (NS_SUCCEEDED(rv)) { |
|
287 NS_ASSERTION(connection, "This should never be null!"); |
|
288 } |
|
289 } |
|
290 |
|
291 bool setProgressHandler = false; |
|
292 if (connection) { |
|
293 rv = connection->SetProgressHandler(kProgressHandlerGranularity, this, |
|
294 getter_AddRefs(mOldProgressHandler)); |
|
295 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!"); |
|
296 if (NS_SUCCEEDED(rv)) { |
|
297 setProgressHandler = true; |
|
298 } |
|
299 } |
|
300 |
|
301 if (NS_SUCCEEDED(rv)) { |
|
302 bool hasSavepoint = false; |
|
303 if (mDatabase) { |
|
304 QuotaManager::SetCurrentWindow(mDatabase->GetOwner()); |
|
305 |
|
306 // Make the first savepoint. |
|
307 if (mTransaction) { |
|
308 if (!(hasSavepoint = mTransaction->StartSavepoint())) { |
|
309 NS_WARNING("Failed to make savepoint!"); |
|
310 } |
|
311 } |
|
312 } |
|
313 |
|
314 mResultCode = DoDatabaseWork(connection); |
|
315 |
|
316 if (mDatabase) { |
|
317 // Release or roll back the savepoint depending on the error code. |
|
318 if (hasSavepoint) { |
|
319 NS_ASSERTION(mTransaction, "Huh?!"); |
|
320 if (NS_SUCCEEDED(mResultCode)) { |
|
321 mTransaction->ReleaseSavepoint(); |
|
322 } |
|
323 else { |
|
324 mTransaction->RollbackSavepoint(); |
|
325 } |
|
326 } |
|
327 |
|
328 // Don't unset this until we're sure that all SQLite activity has |
|
329 // completed! |
|
330 QuotaManager::SetCurrentWindow(nullptr); |
|
331 } |
|
332 } |
|
333 else { |
|
334 // NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated" |
|
335 // and we should fail with RECOVERABLE_ERR. |
|
336 if (rv == NS_ERROR_NOT_AVAILABLE) { |
|
337 mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR; |
|
338 } |
|
339 else { |
|
340 IDB_REPORT_INTERNAL_ERR(); |
|
341 mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
342 } |
|
343 } |
|
344 |
|
345 if (setProgressHandler) { |
|
346 nsCOMPtr<mozIStorageProgressHandler> handler; |
|
347 rv = connection->RemoveProgressHandler(getter_AddRefs(handler)); |
|
348 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!"); |
|
349 #ifdef DEBUG |
|
350 if (NS_SUCCEEDED(rv)) { |
|
351 NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)), |
|
352 "Mismatch!"); |
|
353 } |
|
354 #endif |
|
355 } |
|
356 |
|
357 IDB_PROFILER_MARK_IF(mRequest, |
|
358 "IndexedDB Request %llu: Finished database work " |
|
359 "(rv = %lu)", |
|
360 "IDBRequest[%llu] DT Done", mRequest->GetSerialNumber(), |
|
361 mResultCode); |
|
362 |
|
363 return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); |
|
364 } |
|
365 |
|
366 NS_IMETHODIMP |
|
367 AsyncConnectionHelper::OnProgress(mozIStorageConnection* aConnection, |
|
368 bool* _retval) |
|
369 { |
|
370 if (mDatabase && mDatabase->IsInvalidated()) { |
|
371 // Someone is trying to delete the database file. Exit lightningfast! |
|
372 *_retval = true; |
|
373 return NS_OK; |
|
374 } |
|
375 |
|
376 if (mOldProgressHandler) { |
|
377 return mOldProgressHandler->OnProgress(aConnection, _retval); |
|
378 } |
|
379 |
|
380 *_retval = false; |
|
381 return NS_OK; |
|
382 } |
|
383 |
|
384 nsresult |
|
385 AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget) |
|
386 { |
|
387 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
388 |
|
389 nsresult rv = Init(); |
|
390 if (NS_FAILED(rv)) { |
|
391 return rv; |
|
392 } |
|
393 |
|
394 rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL); |
|
395 NS_ENSURE_SUCCESS(rv, rv); |
|
396 |
|
397 if (mTransaction) { |
|
398 mTransaction->OnNewRequest(); |
|
399 } |
|
400 |
|
401 mDispatched = true; |
|
402 |
|
403 return NS_OK; |
|
404 } |
|
405 |
|
406 nsresult |
|
407 AsyncConnectionHelper::DispatchToTransactionPool() |
|
408 { |
|
409 NS_ASSERTION(mTransaction, "Only ok to call this with a transaction!"); |
|
410 TransactionPoolEventTarget target(mTransaction); |
|
411 return Dispatch(&target); |
|
412 } |
|
413 |
|
414 // static |
|
415 void |
|
416 AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction) |
|
417 { |
|
418 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
419 NS_ASSERTION(!aTransaction || !gCurrentTransaction, |
|
420 "Stepping on another transaction!"); |
|
421 |
|
422 gCurrentTransaction = aTransaction; |
|
423 } |
|
424 |
|
425 // static |
|
426 IDBTransaction* |
|
427 AsyncConnectionHelper::GetCurrentTransaction() |
|
428 { |
|
429 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
430 |
|
431 return gCurrentTransaction; |
|
432 } |
|
433 |
|
434 nsresult |
|
435 AsyncConnectionHelper::Init() |
|
436 { |
|
437 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
438 |
|
439 return NS_OK; |
|
440 } |
|
441 |
|
442 already_AddRefed<nsIDOMEvent> |
|
443 AsyncConnectionHelper::CreateSuccessEvent(mozilla::dom::EventTarget* aOwner) |
|
444 { |
|
445 return CreateGenericEvent(mRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR), |
|
446 eDoesNotBubble, eNotCancelable); |
|
447 } |
|
448 |
|
449 nsresult |
|
450 AsyncConnectionHelper::OnSuccess() |
|
451 { |
|
452 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
453 NS_ASSERTION(mRequest, "Null request!"); |
|
454 |
|
455 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnSuccess"); |
|
456 |
|
457 nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest); |
|
458 if (!event) { |
|
459 IDB_WARNING("Failed to create event!"); |
|
460 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; |
|
461 } |
|
462 |
|
463 bool dummy; |
|
464 nsresult rv = mRequest->DispatchEvent(event, &dummy); |
|
465 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); |
|
466 |
|
467 WidgetEvent* internalEvent = event->GetInternalNSEvent(); |
|
468 NS_ASSERTION(internalEvent, "This should never be null!"); |
|
469 |
|
470 NS_ASSERTION(!mTransaction || |
|
471 mTransaction->IsOpen() || |
|
472 mTransaction->IsAborted(), |
|
473 "How else can this be closed?!"); |
|
474 |
|
475 if (internalEvent->mFlags.mExceptionHasBeenRisen && |
|
476 mTransaction && |
|
477 mTransaction->IsOpen()) { |
|
478 rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR); |
|
479 NS_ENSURE_SUCCESS(rv, rv); |
|
480 } |
|
481 |
|
482 return NS_OK; |
|
483 } |
|
484 |
|
485 void |
|
486 AsyncConnectionHelper::OnError() |
|
487 { |
|
488 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
489 NS_ASSERTION(mRequest, "Null request!"); |
|
490 |
|
491 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnError"); |
|
492 |
|
493 // Make an error event and fire it at the target. |
|
494 nsRefPtr<nsIDOMEvent> event = |
|
495 CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble, |
|
496 eCancelable); |
|
497 if (!event) { |
|
498 NS_ERROR("Failed to create event!"); |
|
499 return; |
|
500 } |
|
501 |
|
502 bool doDefault; |
|
503 nsresult rv = mRequest->DispatchEvent(event, &doDefault); |
|
504 if (NS_SUCCEEDED(rv)) { |
|
505 NS_ASSERTION(!mTransaction || |
|
506 mTransaction->IsOpen() || |
|
507 mTransaction->IsAborted(), |
|
508 "How else can this be closed?!"); |
|
509 |
|
510 WidgetEvent* internalEvent = event->GetInternalNSEvent(); |
|
511 NS_ASSERTION(internalEvent, "This should never be null!"); |
|
512 |
|
513 if (internalEvent->mFlags.mExceptionHasBeenRisen && |
|
514 mTransaction && |
|
515 mTransaction->IsOpen() && |
|
516 NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) { |
|
517 NS_WARNING("Failed to abort transaction!"); |
|
518 } |
|
519 |
|
520 if (doDefault && |
|
521 mTransaction && |
|
522 mTransaction->IsOpen() && |
|
523 NS_FAILED(mTransaction->Abort(mRequest))) { |
|
524 NS_WARNING("Failed to abort transaction!"); |
|
525 } |
|
526 } |
|
527 else { |
|
528 NS_WARNING("DispatchEvent failed!"); |
|
529 } |
|
530 } |
|
531 |
|
532 nsresult |
|
533 AsyncConnectionHelper::GetSuccessResult(JSContext* aCx, |
|
534 JS::MutableHandle<JS::Value> aVal) |
|
535 { |
|
536 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
537 |
|
538 aVal.setUndefined(); |
|
539 return NS_OK; |
|
540 } |
|
541 |
|
542 void |
|
543 AsyncConnectionHelper::ReleaseMainThreadObjects() |
|
544 { |
|
545 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
546 |
|
547 mDatabase = nullptr; |
|
548 mTransaction = nullptr; |
|
549 |
|
550 HelperBase::ReleaseMainThreadObjects(); |
|
551 } |
|
552 |
|
553 AsyncConnectionHelper::ChildProcessSendResult |
|
554 AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode) |
|
555 { |
|
556 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
557 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); |
|
558 |
|
559 // If there's no request, there could never have been an actor, and so there |
|
560 // is nothing to do. |
|
561 if (!mRequest) { |
|
562 return Success_NotSent; |
|
563 } |
|
564 |
|
565 IDBTransaction* trans = GetCurrentTransaction(); |
|
566 // We may not have a transaction, e.g. for deleteDatabase |
|
567 if (!trans) { |
|
568 return Success_NotSent; |
|
569 } |
|
570 |
|
571 // Are we shutting down the child? |
|
572 IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent(); |
|
573 if (dbActor && dbActor->IsDisconnected()) { |
|
574 return Success_ActorDisconnected; |
|
575 } |
|
576 |
|
577 IndexedDBRequestParentBase* actor = mRequest->GetActorParent(); |
|
578 if (!actor) { |
|
579 return Success_NotSent; |
|
580 } |
|
581 |
|
582 IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child " |
|
583 "process (rv = %lu)", |
|
584 "IDBRequest[%llu] MT Done", |
|
585 mRequest->GetSerialNumber(), aResultCode); |
|
586 |
|
587 return SendResponseToChildProcess(aResultCode); |
|
588 } |
|
589 |
|
590 nsresult |
|
591 AsyncConnectionHelper::OnParentProcessRequestComplete( |
|
592 const ResponseValue& aResponseValue) |
|
593 { |
|
594 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); |
|
595 |
|
596 if (aResponseValue.type() == ResponseValue::Tnsresult) { |
|
597 NS_ASSERTION(NS_FAILED(aResponseValue.get_nsresult()), "Huh?"); |
|
598 SetError(aResponseValue.get_nsresult()); |
|
599 } |
|
600 else { |
|
601 nsresult rv = UnpackResponseFromParentProcess(aResponseValue); |
|
602 NS_ENSURE_SUCCESS(rv, rv); |
|
603 } |
|
604 |
|
605 return Run(); |
|
606 } |
|
607 |
|
608 // static |
|
609 nsresult |
|
610 AsyncConnectionHelper::ConvertToArrayAndCleanup( |
|
611 JSContext* aCx, |
|
612 nsTArray<StructuredCloneReadInfo>& aReadInfos, |
|
613 JS::MutableHandle<JS::Value> aResult) |
|
614 { |
|
615 NS_ASSERTION(aCx, "Null context!"); |
|
616 NS_ASSERTION(aResult.address(), "Null pointer!"); |
|
617 |
|
618 nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult); |
|
619 |
|
620 for (uint32_t index = 0; index < aReadInfos.Length(); index++) { |
|
621 aReadInfos[index].mCloneBuffer.clear(); |
|
622 } |
|
623 aReadInfos.Clear(); |
|
624 |
|
625 return rv; |
|
626 } |
|
627 |
|
628 NS_IMETHODIMP_(MozExternalRefCountType) |
|
629 StackBasedEventTarget::AddRef() |
|
630 { |
|
631 NS_NOTREACHED("Don't call me!"); |
|
632 return 2; |
|
633 } |
|
634 |
|
635 NS_IMETHODIMP_(MozExternalRefCountType) |
|
636 StackBasedEventTarget::Release() |
|
637 { |
|
638 NS_NOTREACHED("Don't call me!"); |
|
639 return 1; |
|
640 } |
|
641 |
|
642 NS_IMETHODIMP |
|
643 StackBasedEventTarget::QueryInterface(REFNSIID aIID, |
|
644 void** aInstancePtr) |
|
645 { |
|
646 NS_NOTREACHED("Don't call me!"); |
|
647 return NS_NOINTERFACE; |
|
648 } |
|
649 |
|
650 NS_IMETHODIMP |
|
651 ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable, |
|
652 uint32_t aFlags) |
|
653 { |
|
654 NS_ASSERTION(aRunnable, "Null pointer!"); |
|
655 |
|
656 nsCOMPtr<nsIRunnable> runnable(aRunnable); |
|
657 DebugOnly<nsresult> rv = |
|
658 runnable->Run(); |
|
659 MOZ_ASSERT(NS_SUCCEEDED(rv)); |
|
660 return NS_OK; |
|
661 } |
|
662 |
|
663 NS_IMETHODIMP |
|
664 ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) |
|
665 { |
|
666 *aIsOnCurrentThread = true; |
|
667 return NS_OK; |
|
668 } |
|
669 |
|
670 NS_IMETHODIMP |
|
671 TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable, |
|
672 uint32_t aFlags) |
|
673 { |
|
674 NS_ASSERTION(aRunnable, "Null pointer!"); |
|
675 NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!"); |
|
676 |
|
677 TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate(); |
|
678 NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED); |
|
679 |
|
680 nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr); |
|
681 NS_ENSURE_SUCCESS(rv, rv); |
|
682 |
|
683 return NS_OK; |
|
684 } |
|
685 |
|
686 NS_IMETHODIMP |
|
687 TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) |
|
688 { |
|
689 *aIsOnCurrentThread = false; |
|
690 return NS_OK; |
|
691 } |
|
692 |
|
693 NS_IMETHODIMP |
|
694 NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable, |
|
695 uint32_t aFlags) |
|
696 { |
|
697 nsCOMPtr<nsIRunnable> runnable = aRunnable; |
|
698 return NS_OK; |
|
699 } |
|
700 |
|
701 NS_IMETHODIMP |
|
702 NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) |
|
703 { |
|
704 *aIsOnCurrentThread = true; |
|
705 return NS_OK; |
|
706 } |