зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1398556 - IPCBlobInputStream should call OnInputStreamReady() on the current thread if ::AsyncWait() is called without passing nsIEventTarget, r=smaug
This commit is contained in:
Родитель
6775e78ff5
Коммит
e4901e78cc
|
@ -25,20 +25,24 @@ static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
|
|||
class InputStreamCallbackRunnable final : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
// Note that the execution can be synchronous in case the event target is
|
||||
// null.
|
||||
static void
|
||||
Execute(nsIInputStreamCallback* aCallback,
|
||||
nsIEventTarget* aEventTarget,
|
||||
IPCBlobInputStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
RefPtr<InputStreamCallbackRunnable> runnable =
|
||||
new InputStreamCallbackRunnable(aCallback, aStream);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = aEventTarget;
|
||||
if (!target) {
|
||||
target = NS_GetCurrentThread();
|
||||
if (aEventTarget) {
|
||||
target->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
target->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -73,14 +77,13 @@ public:
|
|||
nsIEventTarget* aEventTarget,
|
||||
IPCBlobInputStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(aEventTarget);
|
||||
|
||||
RefPtr<FileMetadataCallbackRunnable> runnable =
|
||||
new FileMetadataCallbackRunnable(aCallback, aStream);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = aEventTarget;
|
||||
if (!target) {
|
||||
target = NS_GetCurrentThread();
|
||||
}
|
||||
|
||||
target->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -509,6 +512,8 @@ IPCBlobInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
|||
nsCOMPtr<nsIEventTarget> callbackEventTarget;
|
||||
callbackEventTarget.swap(mInputStreamCallbackEventTarget);
|
||||
|
||||
// This must be the last operation because the execution of the callback can
|
||||
// be synchronous.
|
||||
InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -547,6 +552,13 @@ NS_IMETHODIMP
|
|||
IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
|
||||
nsIEventTarget* aEventTarget)
|
||||
{
|
||||
MOZ_ASSERT(!!aCallback == !!aEventTarget);
|
||||
|
||||
// If we have the callback, we must have the event target.
|
||||
if (NS_WARN_IF(!!aCallback != !!aEventTarget)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// See IPCBlobInputStream.h for more information about this state machine.
|
||||
|
||||
switch (mState) {
|
||||
|
|
|
@ -277,7 +277,7 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream,
|
|||
|
||||
PendingOperation* opt = mPendingOperations.AppendElement();
|
||||
opt->mStream = aStream;
|
||||
opt->mEventTarget = aEventTarget ? aEventTarget : NS_GetCurrentThread();
|
||||
opt->mEventTarget = aEventTarget;
|
||||
|
||||
if (mState == eActiveMigrating || mState == eInactiveMigrating) {
|
||||
// This operation will be continued when the migration is completed.
|
||||
|
@ -316,7 +316,16 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream)
|
|||
|
||||
RefPtr<StreamReadyRunnable> runnable =
|
||||
new StreamReadyRunnable(pendingStream, stream);
|
||||
eventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
|
||||
// If IPCBlobInputStream::AsyncWait() has been executed without passing an
|
||||
// event target, we run the callback synchronous because any thread could be
|
||||
// result to be the wrong one. See more in nsIAsyncInputStream::asyncWait
|
||||
// documentation.
|
||||
if (eventTarget) {
|
||||
eventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
|
|
@ -222,6 +222,13 @@ interface nsIAsyncFileMetadata : nsIFileMetadata
|
|||
{
|
||||
/**
|
||||
* Asynchronously wait for the object to be ready.
|
||||
*
|
||||
* @param aCallback The callback will be used when the stream is ready to
|
||||
* return File metadata. Use a nullptr to cancel a
|
||||
* previous operation.
|
||||
*
|
||||
* @param aEventTarget The event target where aCallback will be executed.
|
||||
* If aCallback is passed, aEventTarget cannot be null.
|
||||
*/
|
||||
void asyncWait(in nsIFileMetadataCallback aCallback,
|
||||
in nsIEventTarget aEventTarget);
|
||||
|
|
Загрузка…
Ссылка в новой задаче