Bug 1360052 handle cancel during http-on-examine-response, r=mayhemer
authorShane Caraveo <scaraveo@mozilla.com>
Fri, 05 May 2017 15:54:19 -0700
changeset 357114 0087592da59a9ea2384d6ef5cda296f8b84af54e
parent 357074 8b2071046994cd846da7ea2d3f4991050f30b8aa
child 357115 b37b9dda65fd81a8f9a4b11cfaadff732e5529dd
push id31783
push usercbook@mozilla.com
push dateTue, 09 May 2017 12:03:48 +0000
treeherdermozilla-central@b0ff0c5c0a35 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1360052
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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]