1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/indexedDB/AsyncConnectionHelper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,706 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "base/basictypes.h" 1.11 + 1.12 +#include "AsyncConnectionHelper.h" 1.13 + 1.14 +#include "mozilla/dom/quota/QuotaManager.h" 1.15 +#include "mozilla/storage.h" 1.16 +#include "nsComponentManagerUtils.h" 1.17 +#include "nsContentUtils.h" 1.18 +#include "nsProxyRelease.h" 1.19 +#include "nsThreadUtils.h" 1.20 +#include "nsWrapperCacheInlines.h" 1.21 + 1.22 +#include "IDBEvents.h" 1.23 +#include "IDBTransaction.h" 1.24 +#include "IndexedDatabaseManager.h" 1.25 +#include "ProfilerHelpers.h" 1.26 +#include "ReportInternalError.h" 1.27 +#include "TransactionThreadPool.h" 1.28 + 1.29 +#include "ipc/IndexedDBChild.h" 1.30 +#include "ipc/IndexedDBParent.h" 1.31 + 1.32 +using namespace mozilla; 1.33 +USING_INDEXEDDB_NAMESPACE 1.34 +using mozilla::dom::quota::QuotaManager; 1.35 + 1.36 +namespace { 1.37 + 1.38 +IDBTransaction* gCurrentTransaction = nullptr; 1.39 + 1.40 +const uint32_t kProgressHandlerGranularity = 1000; 1.41 + 1.42 +class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget 1.43 +{ 1.44 +public: 1.45 + NS_DECL_NSIEVENTTARGET 1.46 + 1.47 + TransactionPoolEventTarget(IDBTransaction* aTransaction) 1.48 + : mTransaction(aTransaction) 1.49 + { } 1.50 + 1.51 +private: 1.52 + IDBTransaction* mTransaction; 1.53 +}; 1.54 + 1.55 +// This inline is just so that we always clear aBuffers appropriately even if 1.56 +// something fails. 1.57 +inline 1.58 +nsresult 1.59 +ConvertCloneReadInfosToArrayInternal( 1.60 + JSContext* aCx, 1.61 + nsTArray<StructuredCloneReadInfo>& aReadInfos, 1.62 + JS::MutableHandle<JS::Value> aResult) 1.63 +{ 1.64 + JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0)); 1.65 + if (!array) { 1.66 + IDB_WARNING("Failed to make array!"); 1.67 + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.68 + } 1.69 + 1.70 + if (!aReadInfos.IsEmpty()) { 1.71 + if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) { 1.72 + IDB_WARNING("Failed to set array length!"); 1.73 + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.74 + } 1.75 + 1.76 + for (uint32_t index = 0, count = aReadInfos.Length(); index < count; 1.77 + index++) { 1.78 + StructuredCloneReadInfo& readInfo = aReadInfos[index]; 1.79 + 1.80 + JS::Rooted<JS::Value> val(aCx); 1.81 + if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) { 1.82 + NS_WARNING("Failed to decode!"); 1.83 + return NS_ERROR_DOM_DATA_CLONE_ERR; 1.84 + } 1.85 + 1.86 + if (!JS_SetElement(aCx, array, index, val)) { 1.87 + IDB_WARNING("Failed to set array element!"); 1.88 + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.89 + } 1.90 + } 1.91 + } 1.92 + 1.93 + aResult.setObject(*array); 1.94 + return NS_OK; 1.95 +} 1.96 + 1.97 +} // anonymous namespace 1.98 + 1.99 +HelperBase::~HelperBase() 1.100 +{ 1.101 + if (!NS_IsMainThread()) { 1.102 + IDBRequest* request; 1.103 + mRequest.forget(&request); 1.104 + 1.105 + if (request) { 1.106 + nsCOMPtr<nsIThread> mainThread; 1.107 + NS_GetMainThread(getter_AddRefs(mainThread)); 1.108 + NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); 1.109 + 1.110 + if (mainThread) { 1.111 + NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request)); 1.112 + } 1.113 + } 1.114 + } 1.115 +} 1.116 + 1.117 +nsresult 1.118 +HelperBase::WrapNative(JSContext* aCx, 1.119 + nsISupports* aNative, 1.120 + JS::MutableHandle<JS::Value> aResult) 1.121 +{ 1.122 + NS_ASSERTION(aCx, "Null context!"); 1.123 + NS_ASSERTION(aNative, "Null pointer!"); 1.124 + NS_ASSERTION(aResult.address(), "Null pointer!"); 1.125 + NS_ASSERTION(mRequest, "Null request!"); 1.126 + 1.127 + nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult); 1.128 + IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); 1.129 + 1.130 + return NS_OK; 1.131 +} 1.132 + 1.133 +void 1.134 +HelperBase::ReleaseMainThreadObjects() 1.135 +{ 1.136 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.137 + 1.138 + mRequest = nullptr; 1.139 +} 1.140 + 1.141 +AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase, 1.142 + IDBRequest* aRequest) 1.143 +: HelperBase(aRequest), 1.144 + mDatabase(aDatabase), 1.145 + mResultCode(NS_OK), 1.146 + mDispatched(false) 1.147 +{ 1.148 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.149 +} 1.150 + 1.151 +AsyncConnectionHelper::AsyncConnectionHelper(IDBTransaction* aTransaction, 1.152 + IDBRequest* aRequest) 1.153 +: HelperBase(aRequest), 1.154 + mDatabase(aTransaction->mDatabase), 1.155 + mTransaction(aTransaction), 1.156 + mResultCode(NS_OK), 1.157 + mDispatched(false) 1.158 +{ 1.159 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.160 +} 1.161 + 1.162 +AsyncConnectionHelper::~AsyncConnectionHelper() 1.163 +{ 1.164 + if (!NS_IsMainThread()) { 1.165 + IDBDatabase* database; 1.166 + mDatabase.forget(&database); 1.167 + 1.168 + IDBTransaction* transaction; 1.169 + mTransaction.forget(&transaction); 1.170 + 1.171 + nsCOMPtr<nsIThread> mainThread; 1.172 + NS_GetMainThread(getter_AddRefs(mainThread)); 1.173 + NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); 1.174 + 1.175 + if (mainThread) { 1.176 + if (database) { 1.177 + NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(database)); 1.178 + } 1.179 + if (transaction) { 1.180 + NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(transaction)); 1.181 + } 1.182 + } 1.183 + } 1.184 + 1.185 + NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!"); 1.186 +} 1.187 + 1.188 +NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable, 1.189 + mozIStorageProgressHandler) 1.190 + 1.191 +NS_IMETHODIMP 1.192 +AsyncConnectionHelper::Run() 1.193 +{ 1.194 + if (NS_IsMainThread()) { 1.195 + PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run"); 1.196 + 1.197 + if (mTransaction && 1.198 + mTransaction->IsAborted()) { 1.199 + // Always fire a "error" event with ABORT_ERR if the transaction was 1.200 + // aborted, even if the request succeeded or failed with another error. 1.201 + mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR; 1.202 + } 1.203 + 1.204 + IDBTransaction* oldTransaction = gCurrentTransaction; 1.205 + gCurrentTransaction = mTransaction; 1.206 + 1.207 + ChildProcessSendResult sendResult = 1.208 + IndexedDatabaseManager::IsMainProcess() ? 1.209 + MaybeSendResponseToChildProcess(mResultCode) : 1.210 + Success_NotSent; 1.211 + 1.212 + switch (sendResult) { 1.213 + case Success_Sent: { 1.214 + if (mRequest) { 1.215 + mRequest->NotifyHelperSentResultsToChildProcess(NS_OK); 1.216 + } 1.217 + break; 1.218 + } 1.219 + 1.220 + case Success_NotSent: { 1.221 + if (mRequest) { 1.222 + nsresult rv = mRequest->NotifyHelperCompleted(this); 1.223 + if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { 1.224 + mResultCode = rv; 1.225 + } 1.226 + 1.227 + IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread " 1.228 + "response (rv = %lu)", 1.229 + "IDBRequest[%llu] MT Done", 1.230 + mRequest->GetSerialNumber(), mResultCode); 1.231 + } 1.232 + 1.233 + // Call OnError if the database had an error or if the OnSuccess 1.234 + // handler has an error. 1.235 + if (NS_FAILED(mResultCode) || 1.236 + NS_FAILED((mResultCode = OnSuccess()))) { 1.237 + OnError(); 1.238 + } 1.239 + break; 1.240 + } 1.241 + 1.242 + case Success_ActorDisconnected: { 1.243 + // Nothing needs to be done here. 1.244 + break; 1.245 + } 1.246 + 1.247 + case Error: { 1.248 + IDB_WARNING("MaybeSendResultsToChildProcess failed!"); 1.249 + mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.250 + if (mRequest) { 1.251 + mRequest->NotifyHelperSentResultsToChildProcess(mResultCode); 1.252 + } 1.253 + break; 1.254 + } 1.255 + 1.256 + default: 1.257 + MOZ_CRASH("Unknown value for ChildProcessSendResult!"); 1.258 + } 1.259 + 1.260 + NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!"); 1.261 + gCurrentTransaction = oldTransaction; 1.262 + 1.263 + if (mDispatched && mTransaction) { 1.264 + mTransaction->OnRequestFinished(); 1.265 + } 1.266 + 1.267 + ReleaseMainThreadObjects(); 1.268 + 1.269 + NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't " 1.270 + "call AsyncConnectionHelper::ReleaseMainThreadObjects!"); 1.271 + 1.272 + return NS_OK; 1.273 + } 1.274 + 1.275 + NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); 1.276 + 1.277 + PROFILER_LABEL("IndexedDB", "AsyncConnectionHelper::Run"); 1.278 + 1.279 + IDB_PROFILER_MARK_IF(mRequest, 1.280 + "IndexedDB Request %llu: Beginning database work", 1.281 + "IDBRequest[%llu] DT Start", 1.282 + mRequest->GetSerialNumber()); 1.283 + 1.284 + nsresult rv = NS_OK; 1.285 + nsCOMPtr<mozIStorageConnection> connection; 1.286 + 1.287 + if (mTransaction) { 1.288 + rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection)); 1.289 + if (NS_SUCCEEDED(rv)) { 1.290 + NS_ASSERTION(connection, "This should never be null!"); 1.291 + } 1.292 + } 1.293 + 1.294 + bool setProgressHandler = false; 1.295 + if (connection) { 1.296 + rv = connection->SetProgressHandler(kProgressHandlerGranularity, this, 1.297 + getter_AddRefs(mOldProgressHandler)); 1.298 + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!"); 1.299 + if (NS_SUCCEEDED(rv)) { 1.300 + setProgressHandler = true; 1.301 + } 1.302 + } 1.303 + 1.304 + if (NS_SUCCEEDED(rv)) { 1.305 + bool hasSavepoint = false; 1.306 + if (mDatabase) { 1.307 + QuotaManager::SetCurrentWindow(mDatabase->GetOwner()); 1.308 + 1.309 + // Make the first savepoint. 1.310 + if (mTransaction) { 1.311 + if (!(hasSavepoint = mTransaction->StartSavepoint())) { 1.312 + NS_WARNING("Failed to make savepoint!"); 1.313 + } 1.314 + } 1.315 + } 1.316 + 1.317 + mResultCode = DoDatabaseWork(connection); 1.318 + 1.319 + if (mDatabase) { 1.320 + // Release or roll back the savepoint depending on the error code. 1.321 + if (hasSavepoint) { 1.322 + NS_ASSERTION(mTransaction, "Huh?!"); 1.323 + if (NS_SUCCEEDED(mResultCode)) { 1.324 + mTransaction->ReleaseSavepoint(); 1.325 + } 1.326 + else { 1.327 + mTransaction->RollbackSavepoint(); 1.328 + } 1.329 + } 1.330 + 1.331 + // Don't unset this until we're sure that all SQLite activity has 1.332 + // completed! 1.333 + QuotaManager::SetCurrentWindow(nullptr); 1.334 + } 1.335 + } 1.336 + else { 1.337 + // NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated" 1.338 + // and we should fail with RECOVERABLE_ERR. 1.339 + if (rv == NS_ERROR_NOT_AVAILABLE) { 1.340 + mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR; 1.341 + } 1.342 + else { 1.343 + IDB_REPORT_INTERNAL_ERR(); 1.344 + mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.345 + } 1.346 + } 1.347 + 1.348 + if (setProgressHandler) { 1.349 + nsCOMPtr<mozIStorageProgressHandler> handler; 1.350 + rv = connection->RemoveProgressHandler(getter_AddRefs(handler)); 1.351 + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!"); 1.352 +#ifdef DEBUG 1.353 + if (NS_SUCCEEDED(rv)) { 1.354 + NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)), 1.355 + "Mismatch!"); 1.356 + } 1.357 +#endif 1.358 + } 1.359 + 1.360 + IDB_PROFILER_MARK_IF(mRequest, 1.361 + "IndexedDB Request %llu: Finished database work " 1.362 + "(rv = %lu)", 1.363 + "IDBRequest[%llu] DT Done", mRequest->GetSerialNumber(), 1.364 + mResultCode); 1.365 + 1.366 + return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); 1.367 +} 1.368 + 1.369 +NS_IMETHODIMP 1.370 +AsyncConnectionHelper::OnProgress(mozIStorageConnection* aConnection, 1.371 + bool* _retval) 1.372 +{ 1.373 + if (mDatabase && mDatabase->IsInvalidated()) { 1.374 + // Someone is trying to delete the database file. Exit lightningfast! 1.375 + *_retval = true; 1.376 + return NS_OK; 1.377 + } 1.378 + 1.379 + if (mOldProgressHandler) { 1.380 + return mOldProgressHandler->OnProgress(aConnection, _retval); 1.381 + } 1.382 + 1.383 + *_retval = false; 1.384 + return NS_OK; 1.385 +} 1.386 + 1.387 +nsresult 1.388 +AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget) 1.389 +{ 1.390 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.391 + 1.392 + nsresult rv = Init(); 1.393 + if (NS_FAILED(rv)) { 1.394 + return rv; 1.395 + } 1.396 + 1.397 + rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL); 1.398 + NS_ENSURE_SUCCESS(rv, rv); 1.399 + 1.400 + if (mTransaction) { 1.401 + mTransaction->OnNewRequest(); 1.402 + } 1.403 + 1.404 + mDispatched = true; 1.405 + 1.406 + return NS_OK; 1.407 +} 1.408 + 1.409 +nsresult 1.410 +AsyncConnectionHelper::DispatchToTransactionPool() 1.411 +{ 1.412 + NS_ASSERTION(mTransaction, "Only ok to call this with a transaction!"); 1.413 + TransactionPoolEventTarget target(mTransaction); 1.414 + return Dispatch(&target); 1.415 +} 1.416 + 1.417 +// static 1.418 +void 1.419 +AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction) 1.420 +{ 1.421 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.422 + NS_ASSERTION(!aTransaction || !gCurrentTransaction, 1.423 + "Stepping on another transaction!"); 1.424 + 1.425 + gCurrentTransaction = aTransaction; 1.426 +} 1.427 + 1.428 +// static 1.429 +IDBTransaction* 1.430 +AsyncConnectionHelper::GetCurrentTransaction() 1.431 +{ 1.432 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.433 + 1.434 + return gCurrentTransaction; 1.435 +} 1.436 + 1.437 +nsresult 1.438 +AsyncConnectionHelper::Init() 1.439 +{ 1.440 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.441 + 1.442 + return NS_OK; 1.443 +} 1.444 + 1.445 +already_AddRefed<nsIDOMEvent> 1.446 +AsyncConnectionHelper::CreateSuccessEvent(mozilla::dom::EventTarget* aOwner) 1.447 +{ 1.448 + return CreateGenericEvent(mRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR), 1.449 + eDoesNotBubble, eNotCancelable); 1.450 +} 1.451 + 1.452 +nsresult 1.453 +AsyncConnectionHelper::OnSuccess() 1.454 +{ 1.455 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.456 + NS_ASSERTION(mRequest, "Null request!"); 1.457 + 1.458 + PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnSuccess"); 1.459 + 1.460 + nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest); 1.461 + if (!event) { 1.462 + IDB_WARNING("Failed to create event!"); 1.463 + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; 1.464 + } 1.465 + 1.466 + bool dummy; 1.467 + nsresult rv = mRequest->DispatchEvent(event, &dummy); 1.468 + IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); 1.469 + 1.470 + WidgetEvent* internalEvent = event->GetInternalNSEvent(); 1.471 + NS_ASSERTION(internalEvent, "This should never be null!"); 1.472 + 1.473 + NS_ASSERTION(!mTransaction || 1.474 + mTransaction->IsOpen() || 1.475 + mTransaction->IsAborted(), 1.476 + "How else can this be closed?!"); 1.477 + 1.478 + if (internalEvent->mFlags.mExceptionHasBeenRisen && 1.479 + mTransaction && 1.480 + mTransaction->IsOpen()) { 1.481 + rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR); 1.482 + NS_ENSURE_SUCCESS(rv, rv); 1.483 + } 1.484 + 1.485 + return NS_OK; 1.486 +} 1.487 + 1.488 +void 1.489 +AsyncConnectionHelper::OnError() 1.490 +{ 1.491 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.492 + NS_ASSERTION(mRequest, "Null request!"); 1.493 + 1.494 + PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnError"); 1.495 + 1.496 + // Make an error event and fire it at the target. 1.497 + nsRefPtr<nsIDOMEvent> event = 1.498 + CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble, 1.499 + eCancelable); 1.500 + if (!event) { 1.501 + NS_ERROR("Failed to create event!"); 1.502 + return; 1.503 + } 1.504 + 1.505 + bool doDefault; 1.506 + nsresult rv = mRequest->DispatchEvent(event, &doDefault); 1.507 + if (NS_SUCCEEDED(rv)) { 1.508 + NS_ASSERTION(!mTransaction || 1.509 + mTransaction->IsOpen() || 1.510 + mTransaction->IsAborted(), 1.511 + "How else can this be closed?!"); 1.512 + 1.513 + WidgetEvent* internalEvent = event->GetInternalNSEvent(); 1.514 + NS_ASSERTION(internalEvent, "This should never be null!"); 1.515 + 1.516 + if (internalEvent->mFlags.mExceptionHasBeenRisen && 1.517 + mTransaction && 1.518 + mTransaction->IsOpen() && 1.519 + NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) { 1.520 + NS_WARNING("Failed to abort transaction!"); 1.521 + } 1.522 + 1.523 + if (doDefault && 1.524 + mTransaction && 1.525 + mTransaction->IsOpen() && 1.526 + NS_FAILED(mTransaction->Abort(mRequest))) { 1.527 + NS_WARNING("Failed to abort transaction!"); 1.528 + } 1.529 + } 1.530 + else { 1.531 + NS_WARNING("DispatchEvent failed!"); 1.532 + } 1.533 +} 1.534 + 1.535 +nsresult 1.536 +AsyncConnectionHelper::GetSuccessResult(JSContext* aCx, 1.537 + JS::MutableHandle<JS::Value> aVal) 1.538 +{ 1.539 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.540 + 1.541 + aVal.setUndefined(); 1.542 + return NS_OK; 1.543 +} 1.544 + 1.545 +void 1.546 +AsyncConnectionHelper::ReleaseMainThreadObjects() 1.547 +{ 1.548 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.549 + 1.550 + mDatabase = nullptr; 1.551 + mTransaction = nullptr; 1.552 + 1.553 + HelperBase::ReleaseMainThreadObjects(); 1.554 +} 1.555 + 1.556 +AsyncConnectionHelper::ChildProcessSendResult 1.557 +AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode) 1.558 +{ 1.559 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.560 + NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); 1.561 + 1.562 + // If there's no request, there could never have been an actor, and so there 1.563 + // is nothing to do. 1.564 + if (!mRequest) { 1.565 + return Success_NotSent; 1.566 + } 1.567 + 1.568 + IDBTransaction* trans = GetCurrentTransaction(); 1.569 + // We may not have a transaction, e.g. for deleteDatabase 1.570 + if (!trans) { 1.571 + return Success_NotSent; 1.572 + } 1.573 + 1.574 + // Are we shutting down the child? 1.575 + IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent(); 1.576 + if (dbActor && dbActor->IsDisconnected()) { 1.577 + return Success_ActorDisconnected; 1.578 + } 1.579 + 1.580 + IndexedDBRequestParentBase* actor = mRequest->GetActorParent(); 1.581 + if (!actor) { 1.582 + return Success_NotSent; 1.583 + } 1.584 + 1.585 + IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child " 1.586 + "process (rv = %lu)", 1.587 + "IDBRequest[%llu] MT Done", 1.588 + mRequest->GetSerialNumber(), aResultCode); 1.589 + 1.590 + return SendResponseToChildProcess(aResultCode); 1.591 +} 1.592 + 1.593 +nsresult 1.594 +AsyncConnectionHelper::OnParentProcessRequestComplete( 1.595 + const ResponseValue& aResponseValue) 1.596 +{ 1.597 + NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); 1.598 + 1.599 + if (aResponseValue.type() == ResponseValue::Tnsresult) { 1.600 + NS_ASSERTION(NS_FAILED(aResponseValue.get_nsresult()), "Huh?"); 1.601 + SetError(aResponseValue.get_nsresult()); 1.602 + } 1.603 + else { 1.604 + nsresult rv = UnpackResponseFromParentProcess(aResponseValue); 1.605 + NS_ENSURE_SUCCESS(rv, rv); 1.606 + } 1.607 + 1.608 + return Run(); 1.609 +} 1.610 + 1.611 +// static 1.612 +nsresult 1.613 +AsyncConnectionHelper::ConvertToArrayAndCleanup( 1.614 + JSContext* aCx, 1.615 + nsTArray<StructuredCloneReadInfo>& aReadInfos, 1.616 + JS::MutableHandle<JS::Value> aResult) 1.617 +{ 1.618 + NS_ASSERTION(aCx, "Null context!"); 1.619 + NS_ASSERTION(aResult.address(), "Null pointer!"); 1.620 + 1.621 + nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult); 1.622 + 1.623 + for (uint32_t index = 0; index < aReadInfos.Length(); index++) { 1.624 + aReadInfos[index].mCloneBuffer.clear(); 1.625 + } 1.626 + aReadInfos.Clear(); 1.627 + 1.628 + return rv; 1.629 +} 1.630 + 1.631 +NS_IMETHODIMP_(MozExternalRefCountType) 1.632 +StackBasedEventTarget::AddRef() 1.633 +{ 1.634 + NS_NOTREACHED("Don't call me!"); 1.635 + return 2; 1.636 +} 1.637 + 1.638 +NS_IMETHODIMP_(MozExternalRefCountType) 1.639 +StackBasedEventTarget::Release() 1.640 +{ 1.641 + NS_NOTREACHED("Don't call me!"); 1.642 + return 1; 1.643 +} 1.644 + 1.645 +NS_IMETHODIMP 1.646 +StackBasedEventTarget::QueryInterface(REFNSIID aIID, 1.647 + void** aInstancePtr) 1.648 +{ 1.649 + NS_NOTREACHED("Don't call me!"); 1.650 + return NS_NOINTERFACE; 1.651 +} 1.652 + 1.653 +NS_IMETHODIMP 1.654 +ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable, 1.655 + uint32_t aFlags) 1.656 +{ 1.657 + NS_ASSERTION(aRunnable, "Null pointer!"); 1.658 + 1.659 + nsCOMPtr<nsIRunnable> runnable(aRunnable); 1.660 + DebugOnly<nsresult> rv = 1.661 + runnable->Run(); 1.662 + MOZ_ASSERT(NS_SUCCEEDED(rv)); 1.663 + return NS_OK; 1.664 +} 1.665 + 1.666 +NS_IMETHODIMP 1.667 +ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) 1.668 +{ 1.669 + *aIsOnCurrentThread = true; 1.670 + return NS_OK; 1.671 +} 1.672 + 1.673 +NS_IMETHODIMP 1.674 +TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable, 1.675 + uint32_t aFlags) 1.676 +{ 1.677 + NS_ASSERTION(aRunnable, "Null pointer!"); 1.678 + NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!"); 1.679 + 1.680 + TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate(); 1.681 + NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED); 1.682 + 1.683 + nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr); 1.684 + NS_ENSURE_SUCCESS(rv, rv); 1.685 + 1.686 + return NS_OK; 1.687 +} 1.688 + 1.689 +NS_IMETHODIMP 1.690 +TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) 1.691 +{ 1.692 + *aIsOnCurrentThread = false; 1.693 + return NS_OK; 1.694 +} 1.695 + 1.696 +NS_IMETHODIMP 1.697 +NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable, 1.698 + uint32_t aFlags) 1.699 +{ 1.700 + nsCOMPtr<nsIRunnable> runnable = aRunnable; 1.701 + return NS_OK; 1.702 +} 1.703 + 1.704 +NS_IMETHODIMP 1.705 +NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) 1.706 +{ 1.707 + *aIsOnCurrentThread = true; 1.708 + return NS_OK; 1.709 +}