Bug 1388289 fix challenger info for proxy auth requests, r?kmag draft
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 17 Aug 2017 19:56:22 -0700
changeset 648625 e28763780fe6de79885cf8266a13811ecdae328a
parent 648571 2fb6d8f7bac1be26b2b49b68fc34cc6decd7f339
child 726884 fec379335080adaf11daefa603f8bb3f4e47d4d7
push id74822
push usermixedpuppy@gmail.com
push dateFri, 18 Aug 2017 02:57:00 +0000
reviewerskmag
bugs1388289
milestone57.0a1
Bug 1388289 fix challenger info for proxy auth requests, r?kmag MozReview-Commit-ID: D0Tin2bK8R4
toolkit/components/extensions/test/xpcshell/test_ext_proxy_auth.js
toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
toolkit/modules/addons/WebRequest.jsm
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_proxy_auth.js
@@ -0,0 +1,59 @@
+"use strict";
+
+const proxy = createHttpServer();
+
+// accept proxy connections for mozilla.org
+proxy.identity.add("http", "mozilla.org", 80);
+
+proxy.registerPathHandler("/", (request, response) => {
+  if (request.hasHeader("Proxy-Authorization")) {
+    response.setStatusLine(request.httpVersion, 200, "OK");
+    response.write("ok");
+  } else {
+    response.setStatusLine(request.httpVersion, 407, "Proxy authentication required");
+    response.setHeader("Proxy-Authenticate", 'Basic realm="foobar"', false);
+    response.write("ok");
+  }
+});
+
+add_task(async function test_webRequest_auth_proxy() {
+  async function background() {
+    browser.webRequest.onAuthRequired.addListener((details) => {
+      browser.test.assertTrue(details.isProxy, "proxied request");
+      browser.test.sendMessage("done", details.challenger);
+      return {authCredentials: {username: "puser", password: "ppass"}};
+    }, {urls: ["<all_urls>"]}, ["blocking"]);
+
+    await browser.proxy.register("proxy.js");
+    browser.test.sendMessage("pac-ready");
+  }
+
+  let handlingExt = ExtensionTestUtils.loadExtension({
+    manifest: {
+      permissions: [
+        "proxy",
+        "webRequest",
+        "webRequestBlocking",
+        "<all_urls>",
+      ],
+    },
+    background,
+    files: {
+      "proxy.js": `
+        function FindProxyForURL(url, host) {
+          return "PROXY localhost:${proxy.identity.primaryPort}; DIRECT";
+        }`,
+    },
+  });
+
+  await handlingExt.startup();
+  await handlingExt.awaitMessage("pac-ready");
+
+  let contentPage = await ExtensionTestUtils.loadContentPage(`http://mozilla.org/`);
+
+  let challenger = await handlingExt.awaitMessage("done");
+  equal(challenger.host, "localhost", "proxy host");
+  equal(challenger.port, proxy.identity.primaryPort, "proxy port");
+  await contentPage.close();
+  await handlingExt.unload();
+}).only();
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -39,16 +39,17 @@ skip-if = os == "android" # checking for
 [test_ext_localStorage.js]
 [test_ext_management.js]
 [test_ext_management_uninstall_self.js]
 [test_ext_onmessage_removelistener.js]
 skip-if = true # This test no longer tests what it is meant to test.
 [test_ext_privacy.js]
 [test_ext_privacy_disable.js]
 [test_ext_privacy_update.js]
+[test_ext_proxy_auth.js]
 [test_ext_redirects.js]
 [test_ext_runtime_connect_no_receiver.js]
 [test_ext_runtime_getBrowserInfo.js]
 [test_ext_runtime_getPlatformInfo.js]
 [test_ext_runtime_onInstalled_and_onStartup.js]
 [test_ext_runtime_sendMessage.js]
 [test_ext_runtime_sendMessage_errors.js]
 [test_ext_runtime_sendMessage_no_receiver.js]
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -463,23 +463,28 @@ class AuthRequestor {
       } catch (e) {}
     }
     throw Cr.NS_ERROR_NO_INTERFACE;
   }
 
   // nsIAuthPrompt2 asyncPromptAuth
   asyncPromptAuth(channel, callback, context, level, authInfo) {
     let uri = channel.URI;
+    let proxyInfo;
+    let isProxy = !!(authInfo.flags & authInfo.AUTH_PROXY);
+    if (isProxy && channel instanceof Ci.nsIProxiedChannel) {
+      proxyInfo = channel.proxyInfo;
+    }
     let data = {
       scheme: authInfo.authenticationScheme,
       realm: authInfo.realm,
-      isProxy: !!(authInfo.flags & authInfo.AUTH_PROXY),
+      isProxy,
       challenger: {
-        host: uri.host,
-        port: uri.port,
+        host: proxyInfo ? proxyInfo.host : uri.host,
+        port: proxyInfo ? proxyInfo.port : uri.port,
       },
     };
 
     let channelData = getData(channel);
     // In the case that no listener provides credentials, we fallback to the
     // previously set callback class for authentication.
     channelData.authPromptForward = () => {
       try {