dom/indexedDB/AsyncConnectionHelper.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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/. */
     7 #include "base/basictypes.h"
     9 #include "AsyncConnectionHelper.h"
    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"
    19 #include "IDBEvents.h"
    20 #include "IDBTransaction.h"
    21 #include "IndexedDatabaseManager.h"
    22 #include "ProfilerHelpers.h"
    23 #include "ReportInternalError.h"
    24 #include "TransactionThreadPool.h"
    26 #include "ipc/IndexedDBChild.h"
    27 #include "ipc/IndexedDBParent.h"
    29 using namespace mozilla;
    30 USING_INDEXEDDB_NAMESPACE
    31 using mozilla::dom::quota::QuotaManager;
    33 namespace {
    35 IDBTransaction* gCurrentTransaction = nullptr;
    37 const uint32_t kProgressHandlerGranularity = 1000;
    39 class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget
    40 {
    41 public:
    42   NS_DECL_NSIEVENTTARGET
    44   TransactionPoolEventTarget(IDBTransaction* aTransaction)
    45   : mTransaction(aTransaction)
    46   { }
    48 private:
    49   IDBTransaction* mTransaction;
    50 };
    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   }
    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     }
    73     for (uint32_t index = 0, count = aReadInfos.Length(); index < count;
    74          index++) {
    75       StructuredCloneReadInfo& readInfo = aReadInfos[index];
    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       }
    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   }
    90   aResult.setObject(*array);
    91   return NS_OK;
    92 }
    94 } // anonymous namespace
    96 HelperBase::~HelperBase()
    97 {
    98   if (!NS_IsMainThread()) {
    99     IDBRequest* request;
   100     mRequest.forget(&request);
   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!");
   107       if (mainThread) {
   108         NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request));
   109       }
   110     }
   111   }
   112 }
   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!");
   124   nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult);
   125   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   127   return NS_OK;
   128 }
   130 void
   131 HelperBase::ReleaseMainThreadObjects()
   132 {
   133   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   135   mRequest = nullptr;
   136 }
   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 }
   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 }
   159 AsyncConnectionHelper::~AsyncConnectionHelper()
   160 {
   161   if (!NS_IsMainThread()) {
   162     IDBDatabase* database;
   163     mDatabase.forget(&database);
   165     IDBTransaction* transaction;
   166     mTransaction.forget(&transaction);
   168     nsCOMPtr<nsIThread> mainThread;
   169     NS_GetMainThread(getter_AddRefs(mainThread));
   170     NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
   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   }
   182   NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!");
   183 }
   185 NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable,
   186                   mozIStorageProgressHandler)
   188 NS_IMETHODIMP
   189 AsyncConnectionHelper::Run()
   190 {
   191   if (NS_IsMainThread()) {
   192     PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
   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     }
   201     IDBTransaction* oldTransaction = gCurrentTransaction;
   202     gCurrentTransaction = mTransaction;
   204     ChildProcessSendResult sendResult =
   205       IndexedDatabaseManager::IsMainProcess() ?
   206       MaybeSendResponseToChildProcess(mResultCode) :
   207       Success_NotSent;
   209     switch (sendResult) {
   210       case Success_Sent: {
   211         if (mRequest) {
   212           mRequest->NotifyHelperSentResultsToChildProcess(NS_OK);
   213         }
   214         break;
   215       }
   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           }
   224           IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread "
   225                             "response (rv = %lu)",
   226                             "IDBRequest[%llu] MT Done",
   227                             mRequest->GetSerialNumber(), mResultCode);
   228         }
   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       }
   239       case Success_ActorDisconnected: {
   240         // Nothing needs to be done here.
   241         break;
   242       }
   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       }
   253       default:
   254         MOZ_CRASH("Unknown value for ChildProcessSendResult!");
   255     }
   257     NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
   258     gCurrentTransaction = oldTransaction;
   260     if (mDispatched && mTransaction) {
   261       mTransaction->OnRequestFinished();
   262     }
   264     ReleaseMainThreadObjects();
   266     NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't "
   267                  "call AsyncConnectionHelper::ReleaseMainThreadObjects!");
   269     return NS_OK;
   270   }
   272   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   274   PROFILER_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
   276   IDB_PROFILER_MARK_IF(mRequest,
   277                        "IndexedDB Request %llu: Beginning database work",
   278                        "IDBRequest[%llu] DT Start",
   279                        mRequest->GetSerialNumber());
   281   nsresult rv = NS_OK;
   282   nsCOMPtr<mozIStorageConnection> connection;
   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   }
   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   }
   301   if (NS_SUCCEEDED(rv)) {
   302     bool hasSavepoint = false;
   303     if (mDatabase) {
   304       QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
   306       // Make the first savepoint.
   307       if (mTransaction) {
   308         if (!(hasSavepoint = mTransaction->StartSavepoint())) {
   309           NS_WARNING("Failed to make savepoint!");
   310         }
   311       }
   312     }
   314     mResultCode = DoDatabaseWork(connection);
   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       }
   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   }
   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   }
   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);
   363   return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
   364 }
   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   }
   376   if (mOldProgressHandler) {
   377     return mOldProgressHandler->OnProgress(aConnection, _retval);
   378   }
   380   *_retval = false;
   381   return NS_OK;
   382 }
   384 nsresult
   385 AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget)
   386 {
   387   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   389   nsresult rv = Init();
   390   if (NS_FAILED(rv)) {
   391     return rv;
   392   }
   394   rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
   395   NS_ENSURE_SUCCESS(rv, rv);
   397   if (mTransaction) {
   398     mTransaction->OnNewRequest();
   399   }
   401   mDispatched = true;
   403   return NS_OK;
   404 }
   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 }
   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!");
   422   gCurrentTransaction = aTransaction;
   423 }
   425 // static
   426 IDBTransaction*
   427 AsyncConnectionHelper::GetCurrentTransaction()
   428 {
   429   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   431   return gCurrentTransaction;
   432 }
   434 nsresult
   435 AsyncConnectionHelper::Init()
   436 {
   437   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   439   return NS_OK;
   440 }
   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 }
   449 nsresult
   450 AsyncConnectionHelper::OnSuccess()
   451 {
   452   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   453   NS_ASSERTION(mRequest, "Null request!");
   455   PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnSuccess");
   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   }
   463   bool dummy;
   464   nsresult rv = mRequest->DispatchEvent(event, &dummy);
   465   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   467   WidgetEvent* internalEvent = event->GetInternalNSEvent();
   468   NS_ASSERTION(internalEvent, "This should never be null!");
   470   NS_ASSERTION(!mTransaction ||
   471                mTransaction->IsOpen() ||
   472                mTransaction->IsAborted(),
   473                "How else can this be closed?!");
   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   }
   482   return NS_OK;
   483 }
   485 void
   486 AsyncConnectionHelper::OnError()
   487 {
   488   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   489   NS_ASSERTION(mRequest, "Null request!");
   491   PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnError");
   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   }
   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?!");
   510     WidgetEvent* internalEvent = event->GetInternalNSEvent();
   511     NS_ASSERTION(internalEvent, "This should never be null!");
   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     }
   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 }
   532 nsresult
   533 AsyncConnectionHelper::GetSuccessResult(JSContext* aCx,
   534                                         JS::MutableHandle<JS::Value> aVal)
   535 {
   536   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   538   aVal.setUndefined();
   539   return NS_OK;
   540 }
   542 void
   543 AsyncConnectionHelper::ReleaseMainThreadObjects()
   544 {
   545   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   547   mDatabase = nullptr;
   548   mTransaction = nullptr;
   550   HelperBase::ReleaseMainThreadObjects();
   551 }
   553 AsyncConnectionHelper::ChildProcessSendResult
   554 AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
   555 {
   556   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   557   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   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   }
   565   IDBTransaction* trans = GetCurrentTransaction();
   566   // We may not have a transaction, e.g. for deleteDatabase
   567   if (!trans) {
   568     return Success_NotSent;
   569   }
   571   // Are we shutting down the child?
   572   IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent();
   573   if (dbActor && dbActor->IsDisconnected()) {
   574     return Success_ActorDisconnected;
   575   }
   577   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   578   if (!actor) {
   579     return Success_NotSent;
   580   }
   582   IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child "
   583                     "process (rv = %lu)",
   584                     "IDBRequest[%llu] MT Done",
   585                     mRequest->GetSerialNumber(), aResultCode);
   587   return SendResponseToChildProcess(aResultCode);
   588 }
   590 nsresult
   591 AsyncConnectionHelper::OnParentProcessRequestComplete(
   592                                             const ResponseValue& aResponseValue)
   593 {
   594   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   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   }
   605   return Run();
   606 }
   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!");
   618   nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult);
   620   for (uint32_t index = 0; index < aReadInfos.Length(); index++) {
   621     aReadInfos[index].mCloneBuffer.clear();
   622   }
   623   aReadInfos.Clear();
   625   return rv;
   626 }
   628 NS_IMETHODIMP_(MozExternalRefCountType)
   629 StackBasedEventTarget::AddRef()
   630 {
   631   NS_NOTREACHED("Don't call me!");
   632   return 2;
   633 }
   635 NS_IMETHODIMP_(MozExternalRefCountType)
   636 StackBasedEventTarget::Release()
   637 {
   638   NS_NOTREACHED("Don't call me!");
   639   return 1;
   640 }
   642 NS_IMETHODIMP
   643 StackBasedEventTarget::QueryInterface(REFNSIID aIID,
   644                                       void** aInstancePtr)
   645 {
   646   NS_NOTREACHED("Don't call me!");
   647   return NS_NOINTERFACE;
   648 }
   650 NS_IMETHODIMP
   651 ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable,
   652                                   uint32_t aFlags)
   653 {
   654   NS_ASSERTION(aRunnable, "Null pointer!");
   656   nsCOMPtr<nsIRunnable> runnable(aRunnable);
   657   DebugOnly<nsresult> rv =
   658     runnable->Run();
   659   MOZ_ASSERT(NS_SUCCEEDED(rv));
   660   return NS_OK;
   661 }
   663 NS_IMETHODIMP
   664 ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
   665 {
   666   *aIsOnCurrentThread = true;
   667   return NS_OK;
   668 }
   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!");
   677   TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
   678   NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED);
   680   nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr);
   681   NS_ENSURE_SUCCESS(rv, rv);
   683   return NS_OK;
   684 }
   686 NS_IMETHODIMP
   687 TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
   688 {
   689   *aIsOnCurrentThread = false;
   690   return NS_OK;
   691 }
   693 NS_IMETHODIMP
   694 NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable,
   695                                 uint32_t aFlags)
   696 {
   697   nsCOMPtr<nsIRunnable> runnable = aRunnable;
   698   return NS_OK;
   699 }
   701 NS_IMETHODIMP
   702 NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
   703 {
   704   *aIsOnCurrentThread = true;
   705   return NS_OK;
   706 }

mercurial