NS_IMETHODIMP OpenDatabaseHelper::Run() { NS_ASSERTION(mState != eCreated, "Dispatch was not called?!?"); if (NS_IsMainThread()) { // If we need to queue up a SetVersionHelper, do that here. if (mState == eSetVersionPending) { nsresult rv = StartSetVersion(); if (NS_SUCCEEDED(rv)) { return rv; } SetError(rv); // fall through and run the default error processing } // We've done whatever work we need to do on the DB thread, and any // SetVersion stuff is done by now. NS_ASSERTION(mState == eFiringEvents || mState == eSetVersionCompleted, "Why are we here?"); if (mState == eSetVersionCompleted) { // Allow transaction creation/other version change transactions to proceed // before we fire events. Other version changes will be postd to the end // of the event loop, and will be behind whatever the page does in // its error/success event handlers. mDatabase->ExitSetVersionTransaction(); mState = eFiringEvents; } else { // Notify the request that we're done, but only if we didn't just finish // a SetVersionHelper. In the SetVersionHelper case, that helper tells // the request that it is done, and we avoid calling NotifyHandlerCompleted // twice. nsresult rv = mOpenDBRequest->NotifyHelperCompleted(this); if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { mResultCode = rv; } } NS_ASSERTION(mState == eFiringEvents, "Why are we here?"); if (NS_FAILED(mResultCode)) { DispatchErrorEvent(); } else { DispatchSuccessEvent(); } IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); NS_ASSERTION(manager, "This should never be null!"); manager->AllowNextSynchronizedOp(mASCIIOrigin, mDatabaseId); ReleaseMainThreadObjects(); return NS_OK; } // If we're on the DB thread, do that NS_ASSERTION(mState == eDBWork, "Why are we here?"); mResultCode = DoDatabaseWork(); NS_ASSERTION(mState != eDBWork, "We should be doing something else now."); return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); }
NS_IMETHODIMP AsyncConnectionHelper::Run() { if (NS_IsMainThread()) { if (mTransaction && mTransaction->IsAborted()) { // Always fire a "error" event with ABORT_ERR if the transaction was // aborted, even if the request succeeded or failed with another error. mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR; } IDBTransaction* oldTransaction = gCurrentTransaction; gCurrentTransaction = mTransaction; if (mRequest) { nsresult rv = mRequest->NotifyHelperCompleted(this); if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { mResultCode = rv; } } // Call OnError if the database had an error or if the OnSuccess handler // has an error. if (NS_FAILED(mResultCode) || NS_FAILED((mResultCode = OnSuccess()))) { OnError(); } NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!"); gCurrentTransaction = oldTransaction; if (mDispatched && mTransaction) { mTransaction->OnRequestFinished(); } ReleaseMainThreadObjects(); NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't " "call AsyncConnectionHelper::ReleaseMainThreadObjects!"); return NS_OK; } nsresult rv = NS_OK; nsCOMPtr<mozIStorageConnection> connection; if (mTransaction) { rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection)); if (NS_SUCCEEDED(rv)) { NS_ASSERTION(connection, "This should never be null!"); } } bool setProgressHandler = false; if (connection) { rv = connection->SetProgressHandler(kProgressHandlerGranularity, this, getter_AddRefs(mOldProgressHandler)); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!"); if (NS_SUCCEEDED(rv)) { setProgressHandler = true; } } if (NS_SUCCEEDED(rv)) { bool hasSavepoint = false; if (mDatabase) { IndexedDatabaseManager::SetCurrentDatabase(mDatabase); // Make the first savepoint. if (mTransaction) { if (!(hasSavepoint = mTransaction->StartSavepoint())) { NS_WARNING("Failed to make savepoint!"); } } } mResultCode = DoDatabaseWork(connection); if (mDatabase) { IndexedDatabaseManager::SetCurrentDatabase(nsnull); // Release or roll back the savepoint depending on the error code. if (hasSavepoint) { NS_ASSERTION(mTransaction, "Huh?!"); if (NS_SUCCEEDED(mResultCode)) { mTransaction->ReleaseSavepoint(); } else { mTransaction->RollbackSavepoint(); } } } } else { // NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated" // and we should fail with RECOVERABLE_ERR. if (rv == NS_ERROR_NOT_AVAILABLE) { mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR; } else { mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } if (setProgressHandler) { nsCOMPtr<mozIStorageProgressHandler> handler; rv = connection->RemoveProgressHandler(getter_AddRefs(handler)); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!"); #ifdef DEBUG if (NS_SUCCEEDED(rv)) { NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)), "Mismatch!"); } #endif } return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); }