Bug 1360052 handle cancel during http-on-examine-response, r?mayhemer
MozReview-Commit-ID: 607FLbUWjxT
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -2080,16 +2080,21 @@ nsHttpChannel::ContinueProcessResponse1(
nsresult rv;
if (mSuspendCount) {
LOG(("Waiting until resume to finish processing response [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::AsyncContinueProcessResponse;
return NS_OK;
}
+ // Check if request was cancelled during http-on-examine-response.
+ if (mCanceled) {
+ return CallOnStartRequest();
+ }
+
uint32_t httpStatus = mResponseHead->Status();
// Cookies and Alt-Service should not be handled on proxy failure either.
// This would be consolidated with ProcessSecurityHeaders but it should
// happen after OnExamineResponse.
if (!mTransaction->ProxyConnectFailed() && (httpStatus != 407)) {
nsAutoCString cookie;
if (NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Cookie, cookie))) {
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_suspend_channel_on_examine.js
@@ -0,0 +1,74 @@
+// This file tests async handling of a channel suspended in http-on-modify-request.
+
+var CC = Components.Constructor;
+
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+var obs = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+
+var baseUrl;
+
+function responseHandler(metadata, response)
+{
+ var text = "testing";
+ response.setHeader("Content-Type", "text/plain", false);
+ response.setHeader("Set-Cookie", "chewy", false);
+ response.bodyOutputStream.write(text, text.length);
+}
+
+function onExamineListener(callback) {
+ obs.addObserver({
+ observe: function(subject, topic, data) {
+ var obs = Cc["@mozilla.org/observer-service;1"].getService();
+ obs = obs.QueryInterface(Ci.nsIObserverService);
+ obs.removeObserver(this, "http-on-examine-response");
+ callback(subject.QueryInterface(Ci.nsIHttpChannel));
+ }
+ }, "http-on-examine-response");
+}
+
+function startChannelRequest(baseUrl, flags, callback) {
+ var chan = NetUtil.newChannel({
+ uri: baseUrl,
+ loadUsingSystemPrincipal: true
+ });
+ chan.asyncOpen2(new ChannelListener(callback, null, flags));
+}
+
+// We first make a request that we'll cancel asynchronously. The response will
+// still contain the set-cookie header. Then verify the cookie was not actually
+// retained.
+add_test(function testAsyncCancel() {
+ onExamineListener(chan => {
+ // Suspend the channel then yield to make this async.
+ chan.suspend();
+ Promise.resolve().then(() => {
+ chan.cancel(Cr.NS_BINDING_ABORTED);
+ chan.resume();
+ });
+ });
+ startChannelRequest(baseUrl, CL_EXPECT_FAILURE, (request, data, context) => {
+ do_check_true(!!!data, "no response");
+
+ var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
+ do_check_eq(cm.countCookiesFromHost("localhost"), 0, "no cookies set");
+
+ do_execute_soon(run_next_test);
+ });
+});
+
+function run_test() {
+ var httpServer = new HttpServer();
+ httpServer.registerPathHandler("/", responseHandler);
+ httpServer.start(-1);
+
+ baseUrl = `http://localhost:${httpServer.identity.primaryPort}`;
+
+ run_next_test();
+
+ do_register_cleanup(function(){
+ httpServer.stop(() => {});
+ });
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -360,16 +360,17 @@ skip-if = os == "android" || (os == "win
reason = bug 1190674
firefox-appdir = browser
[test_tls_server_multiple_clients.js]
# The local cert service used by this test is not currently shipped on Android
skip-if = os == "android"
[test_1073747.js]
[test_safeoutputstream_append.js]
[test_suspend_channel_before_connect.js]
+[test_suspend_channel_on_examine.js]
[test_suspend_channel_on_modified.js]
[test_inhibit_caching.js]
[test_dns_disable_ipv4.js]
[test_dns_disable_ipv6.js]
[test_bug1195415.js]
[test_cookie_blacklist.js]
[test_getHost.js]
[test_bug412457.js]