Bug 1360052 handle cancel during http-on-examine-response, r?mayhemer draft
authorShane Caraveo <scaraveo@mozilla.com>
Fri, 05 May 2017 15:54:19 -0700
changeset 573538 ced98934f84f8adf80574d0a74bdf586a125d3a9
parent 573510 e7bf9443be2c4a5187c37440e35f3526148d7fa8
child 574483 8ce712ad5310642ae57ac840419026e90d7e5c00
push id57423
push usermixedpuppy@gmail.com
push dateFri, 05 May 2017 22:54:33 +0000
reviewersmayhemer
bugs1360052
milestone55.0a1
Bug 1360052 handle cancel during http-on-examine-response, r?mayhemer MozReview-Commit-ID: 607FLbUWjxT
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/test/unit/test_suspend_channel_on_examine.js
netwerk/test/unit/xpcshell.ini
--- 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]