Bug 1396395 - Part 1, resume input pump after callback finished. r=dragana

OnStartRequest callback chain is interrupted by add-on during the "http-on-modify-request" observer event.
Therefore, nsInputStreamPump think OnStartRequest is finished.  After resuming http channel, nsHttpChannel
asynchronously continue the OnStartRequest procedure and synchronously resume the nsInputStreamPump. Before
nsDocumentOpenInfo invoke the next OnStartRequest on the listener chain, sync XHR in web content is executed
on the call stack. This will spin main thread event queue and will eventually callback OnDataAvailable/OnStopRequest
on the same call stack.

nsHttpChannel should not resume the nsInputStreamPump before |mCallOnResume| is complete, to ensure that
no input stream event can interrupt the resumed call stack before it finished.

MozReview-Commit-ID: 6Q9EtMhcff9

--HG--
extra : rebase_source : 5685bacd9fbc95207a2a1349a8db66d53e3cc524
This commit is contained in:
Shih-Chiang Chien 2017-09-13 18:34:04 +08:00
parent f65cc04a0b
commit da9b96697d

View File

@ -9023,9 +9023,32 @@ nsHttpChannel::ResumeInternal()
ToMilliseconds();
if (mCallOnResume) {
nsresult rv = AsyncCall(mCallOnResume);
// Resume the interrupted procedure first, then resume
// the pump to continue process the input stream.
RefPtr<nsRunnableMethod<nsHttpChannel>> callOnResume=
NewRunnableMethod("CallOnResume", this, mCallOnResume);
// Should not resume pump that created after resumption.
RefPtr<nsInputStreamPump> transactionPump = mTransactionPump;
RefPtr<nsInputStreamPump> cachePump = mCachePump;
nsresult rv =
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"nsHttpChannel::CallOnResume",
[callOnResume, transactionPump, cachePump]() {
callOnResume->Run();
if (transactionPump) {
transactionPump->Resume();
}
if (cachePump) {
cachePump->Resume();
}
})
);
mCallOnResume = nullptr;
NS_ENSURE_SUCCESS(rv, rv);
return rv;
}
}