diff options
-rw-r--r-- | netwerk/protocol/http/nsHttpChannel.cpp | 24 | ||||
-rw-r--r-- | netwerk/test/mochitests/mochitest.ini | 1 | ||||
-rw-r--r-- | netwerk/test/mochitests/test_1396395.html | 52 |
3 files changed, 76 insertions, 1 deletions
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 0e570e8cb..1c9093495 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -8335,9 +8335,31 @@ nsHttpChannel::ResumeInternal() LOG(("nsHttpChannel::ResumeInternal [this=%p]\n", this)); if (--mSuspendCount == 0 && 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(this, mCallOnResume); + // Should not resume pump that created after resumption. + RefPtr<nsInputStreamPump> transactionPump = mTransactionPump; + RefPtr<nsInputStreamPump> cachePump = mCachePump; + + nsresult rv = + NS_DispatchToCurrentThread(NS_NewRunnableFunction( + [callOnResume, transactionPump, cachePump]() { + callOnResume->Run(); + + if (transactionPump) { + transactionPump->Resume(); + } + + if (cachePump) { + cachePump->Resume(); + } + }) + ); mCallOnResume = nullptr; NS_ENSURE_SUCCESS(rv, rv); + return rv; } nsresult rvTransaction = NS_OK; diff --git a/netwerk/test/mochitests/mochitest.ini b/netwerk/test/mochitests/mochitest.ini index 98d406c80..f8a919031 100644 --- a/netwerk/test/mochitests/mochitest.ini +++ b/netwerk/test/mochitests/mochitest.ini @@ -24,3 +24,4 @@ support-files = [test_user_agent_updates_reset.html] [test_viewsource_unlinkable.html] [test_xhr_method_case.html] +[test_1396395.html] diff --git a/netwerk/test/mochitests/test_1396395.html b/netwerk/test/mochitests/test_1396395.html new file mode 100644 index 000000000..193ef219c --- /dev/null +++ b/netwerk/test/mochitests/test_1396395.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<!-- vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: --> +<html> + <!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +<head> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + <iframe id="f" src="http://example.com"></iframe> + <script type="text/javascript"> +SimpleTest.waitForExplicitFinish(); + +var script = SpecialPowers.loadChromeScript(() => { + const Ci = Components.interfaces; + const Cc = Components.classes; + const Cu = Components.utils; + Cu.import('resource://gre/modules/Services.jsm'); + + Services.obs.addObserver(function onExamResp(subject, topic, data) { + let channel = subject.QueryInterface(Ci.nsIHttpChannel); + if (!channel.URI.spec.startsWith("http://example.org")) { + return; + } + Services.obs.removeObserver(onExamResp, 'http-on-examine-response'); + channel.suspend(); + Promise.resolve().then(() => { + channel.resume(); + }); + }, 'http-on-examine-response'); + + sendAsyncMessage('start-test'); +}); + +script.addMessageListener('start-test', () => { + const iframe = document.getElementById('f'); + + iframe.contentWindow.onunload = function () { + xhr = new XMLHttpRequest(); + xhr.open('GET', window.location, false); + xhr.send(null); + ok(true, 'complete without crash'); + script.destroy(); + SimpleTest.finish(); + } + + iframe.src = 'http://example.org'; +}); + </script> +</body> +</html> + |