mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1143885 - Fix transaction handling when requests are killed prematurely, r=khuey.
This commit is contained in:
parent
f04229dfdd
commit
d405a7eb4f
@ -1828,18 +1828,14 @@ BackgroundRequestChild::BackgroundRequestChild(IDBRequest* aRequest)
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChild);
|
||||
|
||||
mTransaction->OnNewRequest();
|
||||
}
|
||||
|
||||
BackgroundRequestChild::~BackgroundRequestChild()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT_IF(!IsActorDestroyed(), mTransaction);
|
||||
MOZ_ASSERT(!mTransaction);
|
||||
|
||||
MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
|
||||
|
||||
MaybeFinishTransactionEarly();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1853,19 +1849,6 @@ BackgroundRequestChild::HoldFileInfosUntilComplete(
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::MaybeFinishTransactionEarly()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundRequestChild::HandleResponse(nsresult aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -1874,10 +1857,9 @@ BackgroundRequestChild::HandleResponse(nsresult aResponse)
|
||||
MOZ_ASSERT(mTransaction);
|
||||
|
||||
DispatchErrorEvent(mRequest, aResponse, mTransaction);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(const Key& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -1885,10 +1867,9 @@ BackgroundRequestChild::HandleResponse(const Key& aResponse)
|
||||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -1896,10 +1877,9 @@ BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
|
||||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(
|
||||
const SerializedStructuredCloneReadInfo& aResponse)
|
||||
{
|
||||
@ -1919,10 +1899,9 @@ BackgroundRequestChild::HandleResponse(
|
||||
ResultHelper helper(mRequest, mTransaction, &cloneReadInfo);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(
|
||||
const nsTArray<SerializedStructuredCloneReadInfo>& aResponse)
|
||||
{
|
||||
@ -1957,10 +1936,9 @@ BackgroundRequestChild::HandleResponse(
|
||||
ResultHelper helper(mRequest, mTransaction, &cloneReadInfos);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -1968,10 +1946,9 @@ BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
|
||||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(uint64_t aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -1981,7 +1958,6 @@ BackgroundRequestChild::HandleResponse(uint64_t aResponse)
|
||||
ResultHelper helper(mRequest, mTransaction, &response);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1991,9 +1967,17 @@ BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
MaybeFinishTransactionEarly();
|
||||
|
||||
NoteActorDestroyed();
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
|
||||
aWhy == Deletion);
|
||||
#ifdef DEBUG
|
||||
mTransaction = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2005,62 +1989,80 @@ BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
|
||||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
// Always fire an "error" event with ABORT_ERR if the transaction was aborted,
|
||||
// even if the request succeeded or failed with another error.
|
||||
if (mTransaction->IsAborted()) {
|
||||
return HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
||||
// Always fire an "error" event with ABORT_ERR if the transaction was
|
||||
// aborted, even if the request succeeded or failed with another error.
|
||||
HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
||||
} else {
|
||||
switch (aResponse.type()) {
|
||||
case RequestResponse::Tnsresult:
|
||||
HandleResponse(aResponse.get_nsresult());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreAddResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStorePutResponse:
|
||||
HandleResponse(aResponse.get_ObjectStorePutResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetAllResponse().cloneInfos());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllKeysResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreDeleteResponse:
|
||||
HandleResponse(JS::UndefinedHandleValue);
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreClearResponse:
|
||||
HandleResponse(JS::UndefinedHandleValue);
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreCountResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetResponse:
|
||||
HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetKeyResponse:
|
||||
HandleResponse(aResponse.get_IndexGetKeyResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetAllResponse:
|
||||
HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetAllKeysResponse:
|
||||
HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexCountResponse:
|
||||
HandleResponse(aResponse.get_IndexCountResponse().count());
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown response type!");
|
||||
}
|
||||
}
|
||||
|
||||
switch (aResponse.type()) {
|
||||
case RequestResponse::Tnsresult:
|
||||
return HandleResponse(aResponse.get_nsresult());
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
|
||||
|
||||
case RequestResponse::TObjectStoreAddResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
|
||||
// Null this out so that we don't try to call OnRequestFinished() again in
|
||||
// ActorDestroy.
|
||||
mTransaction = nullptr;
|
||||
|
||||
case RequestResponse::TObjectStorePutResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStorePutResponse().key());
|
||||
|
||||
case RequestResponse::TObjectStoreGetResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetAllResponse()
|
||||
.cloneInfos());
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllKeysResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse()
|
||||
.keys());
|
||||
|
||||
case RequestResponse::TObjectStoreDeleteResponse:
|
||||
return HandleResponse(JS::UndefinedHandleValue);
|
||||
|
||||
case RequestResponse::TObjectStoreClearResponse:
|
||||
return HandleResponse(JS::UndefinedHandleValue);
|
||||
|
||||
case RequestResponse::TObjectStoreCountResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
|
||||
|
||||
case RequestResponse::TIndexGetResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
|
||||
|
||||
case RequestResponse::TIndexGetKeyResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetKeyResponse().key());
|
||||
|
||||
case RequestResponse::TIndexGetAllResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
|
||||
|
||||
case RequestResponse::TIndexGetAllKeysResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
|
||||
|
||||
case RequestResponse::TIndexCountResponse:
|
||||
return HandleResponse(aResponse.get_IndexCountResponse().count());
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown response type!");
|
||||
}
|
||||
|
||||
MOZ_CRASH("Should never get here!");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -2370,7 +2372,8 @@ BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
if (mStrongRequest && !mStrongCursor && mTransaction) {
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
|
||||
aWhy == Deletion);
|
||||
}
|
||||
|
||||
if (mCursor) {
|
||||
@ -2435,7 +2438,7 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -561,43 +561,43 @@ class BackgroundRequestChild MOZ_FINAL
|
||||
{
|
||||
friend class BackgroundTransactionChild;
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
friend class IDBTransaction;
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsTArray<nsRefPtr<FileInfo>> mFileInfos;
|
||||
|
||||
public:
|
||||
explicit BackgroundRequestChild(IDBRequest* aRequest);
|
||||
|
||||
void
|
||||
HoldFileInfosUntilComplete(nsTArray<nsRefPtr<FileInfo>>& aFileInfos);
|
||||
|
||||
private:
|
||||
// Only created by IDBTransaction.
|
||||
explicit
|
||||
BackgroundRequestChild(IDBRequest* aRequest);
|
||||
|
||||
// Only destroyed by BackgroundTransactionChild or
|
||||
// BackgroundVersionChangeTransactionChild.
|
||||
~BackgroundRequestChild();
|
||||
|
||||
void
|
||||
MaybeFinishTransactionEarly();
|
||||
|
||||
bool
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const Key& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const nsTArray<Key>& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const SerializedStructuredCloneReadInfo& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const nsTArray<SerializedStructuredCloneReadInfo>& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(JS::Handle<JS::Value> aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(uint64_t aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
|
@ -292,9 +292,7 @@ IDBIndex::GetInternal(bool aKeyOnly,
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -375,9 +373,7 @@ IDBIndex::GetAllInternal(bool aKeysOnly,
|
||||
IDB_LOG_STRINGIFY(aLimit));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -527,9 +523,7 @@ IDBIndex::Count(JSContext* aCx,
|
||||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -1279,9 +1279,8 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
BackgroundRequestChild* actor = mTransaction->StartRequest(request, params);
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
if (!fileInfosToKeepAlive.IsEmpty()) {
|
||||
nsTArray<nsRefPtr<FileInfo>> fileInfos;
|
||||
@ -1365,9 +1364,7 @@ IDBObjectStore::GetAllInternal(bool aKeysOnly,
|
||||
IDB_LOG_STRINGIFY(aLimit));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -1403,9 +1400,7 @@ IDBObjectStore::Clear(ErrorResult& aRv)
|
||||
IDB_LOG_STRINGIFY(mTransaction),
|
||||
IDB_LOG_STRINGIFY(this));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -1600,9 +1595,7 @@ IDBObjectStore::Get(JSContext* aCx,
|
||||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -1657,9 +1650,7 @@ IDBObjectStore::DeleteInternal(JSContext* aCx,
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
@ -1899,9 +1890,7 @@ IDBObjectStore::Count(JSContext* aCx,
|
||||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -325,25 +325,31 @@ IDBTransaction::SetBackgroundActor(BackgroundTransactionChild* aBackgroundActor)
|
||||
mBackgroundActor.mNormalBackgroundActor = aBackgroundActor;
|
||||
}
|
||||
|
||||
void
|
||||
IDBTransaction::StartRequest(BackgroundRequestChild* aBackgroundActor,
|
||||
const RequestParams& aParams)
|
||||
BackgroundRequestChild*
|
||||
IDBTransaction::StartRequest(IDBRequest* aRequest, const RequestParams& aParams)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aBackgroundActor);
|
||||
MOZ_ASSERT(aRequest);
|
||||
MOZ_ASSERT(aParams.type() != RequestParams::T__None);
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(aRequest);
|
||||
|
||||
if (mMode == VERSION_CHANGE) {
|
||||
MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
|
||||
|
||||
mBackgroundActor.mVersionChangeBackgroundActor->
|
||||
SendPBackgroundIDBRequestConstructor(aBackgroundActor, aParams);
|
||||
SendPBackgroundIDBRequestConstructor(actor, aParams);
|
||||
} else {
|
||||
MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
|
||||
|
||||
mBackgroundActor.mNormalBackgroundActor->
|
||||
SendPBackgroundIDBRequestConstructor(aBackgroundActor, aParams);
|
||||
SendPBackgroundIDBRequestConstructor(actor, aParams);
|
||||
}
|
||||
|
||||
// Balanced in BackgroundRequestChild::Recv__delete__().
|
||||
OnNewRequest();
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
void
|
||||
@ -402,7 +408,7 @@ IDBTransaction::OnNewRequest()
|
||||
}
|
||||
|
||||
void
|
||||
IDBTransaction::OnRequestFinished()
|
||||
IDBTransaction::OnRequestFinished(bool aActorDestroyedNormally)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mPendingRequestCount);
|
||||
@ -412,10 +418,24 @@ IDBTransaction::OnRequestFinished()
|
||||
if (!mPendingRequestCount && !mDatabase->IsInvalidated()) {
|
||||
mReadyState = COMMITTING;
|
||||
|
||||
if (NS_SUCCEEDED(mAbortCode)) {
|
||||
SendCommit();
|
||||
if (aActorDestroyedNormally) {
|
||||
if (NS_SUCCEEDED(mAbortCode)) {
|
||||
SendCommit();
|
||||
} else {
|
||||
SendAbort(mAbortCode);
|
||||
}
|
||||
} else {
|
||||
SendAbort(mAbortCode);
|
||||
// Don't try to send any more messages to the parent if the request actor
|
||||
// was killed.
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!mSentCommitOrAbort);
|
||||
mSentCommitOrAbort = true;
|
||||
#endif
|
||||
IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: "
|
||||
"Request actor was killed, transaction will be aborted",
|
||||
"IndexedDB %s: C T[%lld]: IDBTransaction abort",
|
||||
IDB_LOG_ID_STRING(),
|
||||
LoggingSerialNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,9 @@ class IDBTransaction MOZ_FINAL
|
||||
: public IDBWrapperCache
|
||||
, public nsIRunnable
|
||||
{
|
||||
friend class BackgroundCursorChild;
|
||||
friend class BackgroundRequestChild;
|
||||
|
||||
class WorkerFeature;
|
||||
friend class WorkerFeature;
|
||||
|
||||
@ -150,9 +153,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StartRequest(BackgroundRequestChild* aBackgroundActor,
|
||||
const RequestParams& aParams);
|
||||
BackgroundRequestChild*
|
||||
StartRequest(IDBRequest* aRequest, const RequestParams& aParams);
|
||||
|
||||
void
|
||||
OpenCursor(BackgroundCursorChild* aBackgroundActor,
|
||||
@ -161,12 +163,6 @@ public:
|
||||
void
|
||||
RefreshSpec(bool aMayDelete);
|
||||
|
||||
void
|
||||
OnNewRequest();
|
||||
|
||||
void
|
||||
OnRequestFinished();
|
||||
|
||||
bool
|
||||
IsOpen() const;
|
||||
|
||||
@ -314,6 +310,12 @@ private:
|
||||
|
||||
void
|
||||
SendAbort(nsresult aResultCode);
|
||||
|
||||
void
|
||||
OnNewRequest();
|
||||
|
||||
void
|
||||
OnRequestFinished(bool aActorDestroyedNormally);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
Loading…
Reference in New Issue
Block a user