Bug 1601671 - make websocket support proxying on SOCKS/HTTPS, r=michal
authorJunior Hsu <juhsu@mozilla.com>
Tue, 24 Dec 2019 19:51:09 +0000
changeset 508357 7f813996c32ae933d94ee69e1c1373fa3ceb4a33
parent 508356 48159e53bfb85d9b22e94ecaaa6590ab4abd9545
child 508358 4230c41e4ae077e82d07ea7ad3ad1a57d4c149cb
push id36948
push userbtara@mozilla.com
push dateWed, 25 Dec 2019 04:47:43 +0000
treeherdermozilla-central@af9a67687311 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs1601671
milestone73.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 1601671 - make websocket support proxying on SOCKS/HTTPS, r=michal This is something less hacky to the best of my knowledge. Both passing preferable proxy table and letting system setting handle `ws`/`wss` touch the code of all platforms, which is more fragile. Differential Revision: https://phabricator.services.mozilla.com/D57176
netwerk/base/nsProtocolProxyService.cpp
netwerk/test/unit/test_bug1177909.js
--- a/netwerk/base/nsProtocolProxyService.cpp
+++ b/netwerk/base/nsProtocolProxyService.cpp
@@ -2104,17 +2104,36 @@ nsresult nsProtocolProxyService::Resolve
       scheme.AssignLiteral("https");
     } else if (flags & RESOLVE_IGNORE_URI_SCHEME) {
       scheme.AssignLiteral("http");
     }
 
     // now try the system proxy settings for this particular url
     if (NS_SUCCEEDED(mSystemProxySettings->GetProxyForURI(spec, scheme, host,
                                                           port, pacString))) {
-      ProcessPACString(pacString, 0, result);
+      nsCOMPtr<nsIProxyInfo> pi;
+      ProcessPACString(pacString, 0, getter_AddRefs(pi));
+
+      if (flags & RESOLVE_PREFER_SOCKS_PROXY &&
+          flags & RESOLVE_PREFER_HTTPS_PROXY) {
+        nsAutoCString type;
+        pi->GetType(type);
+        // DIRECT from ProcessPACString indicates that system proxy settings
+        // are not configured to use SOCKS proxy. Try https proxy as a
+        // secondary preferrable proxy. This is mainly for websocket whose
+        // proxy precedence is SOCKS > HTTPS > DIRECT.
+        if (type.EqualsLiteral(kProxyType_DIRECT)) {
+          scheme.AssignLiteral(kProxyType_HTTPS);
+          if (NS_SUCCEEDED(mSystemProxySettings->GetProxyForURI(
+                  spec, scheme, host, port, pacString))) {
+            ProcessPACString(pacString, 0, getter_AddRefs(pi));
+          }
+        }
+      }
+      pi.forget(result);
       return NS_OK;
     }
   }
 
   // if proxies are enabled and this host:port combo is supposed to use a
   // proxy, check for a proxy.
   if (mProxyConfig == PROXYCONFIG_DIRECT ||
       (mProxyConfig == PROXYCONFIG_MANUAL &&
--- a/netwerk/test/unit/test_bug1177909.js
+++ b/netwerk/test/unit/test_bug1177909.js
@@ -17,19 +17,22 @@ XPCOMUtils.defineLazyGetter(this, "syste
 
     mainThreadOnly: true,
     PACURI: null,
 
     getProxyForURI(aSpec, aScheme, aHost, aPort) {
       if (aPort != -1) {
         return "SOCKS5 http://localhost:9050";
       }
-      if (aScheme == "http" || aScheme == "https" || aScheme == "ftp") {
+      if (aScheme == "http" || aScheme == "ftp") {
         return "PROXY http://localhost:8080";
       }
+      if (aScheme == "https") {
+        return "HTTPS https://localhost:8080";
+      }
       return "DIRECT";
     },
   };
 });
 
 let gMockProxy = MockRegistrar.register(
   "@mozilla.org/system-proxy-settings;1",
   systemSettings
@@ -74,17 +77,17 @@ add_task(async function testHttpProxy() 
   equal(pi.port, 8080, "Expected proxy port to be 8080");
   equal(pi.type, "http", "Expected proxy type to be http");
 });
 
 add_task(async function testHttpsProxy() {
   let pi = await TestProxyTypeByURI("https://www.mozilla.org/");
   equal(pi.host, "localhost", "Expected proxy host to be localhost");
   equal(pi.port, 8080, "Expected proxy port to be 8080");
-  equal(pi.type, "http", "Expected proxy type to be http");
+  equal(pi.type, "https", "Expected proxy type to be https");
 });
 
 add_task(async function testFtpProxy() {
   let pi = await TestProxyTypeByURI("ftp://ftp.mozilla.org/");
   equal(pi.host, "localhost", "Expected proxy host to be localhost");
   equal(pi.port, 8080, "Expected proxy port to be 8080");
   equal(pi.type, "http", "Expected proxy type to be http");
 });
@@ -132,16 +135,17 @@ add_task(async function testWebSocketPro
     .setSpec("wss://ws.mozilla.org/")
     .finalize();
   let uri = proxyURI
     .mutate()
     .setScheme("https")
     .finalize();
 
   let proxyFlags =
+    Ci.nsIProtocolProxyService.RESOLVE_PREFER_SOCKS_PROXY |
     Ci.nsIProtocolProxyService.RESOLVE_PREFER_HTTPS_PROXY |
     Ci.nsIProtocolProxyService.RESOLVE_ALWAYS_TUNNEL;
 
   let ioService = Cc["@mozilla.org/network/io-service;1"].getService(
     Ci.nsIIOService
   );
   let chan = ioService.newChannelFromURIWithProxyFlags(
     uri,
@@ -152,10 +156,37 @@ add_task(async function testWebSocketPro
     null,
     Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
     Ci.nsIContentPolicy.TYPE_OTHER
   );
 
   let pi = await TestProxyType(chan, proxyFlags);
   equal(pi.host, "localhost", "Expected proxy host to be localhost");
   equal(pi.port, 8080, "Expected proxy port to be 8080");
-  equal(pi.type, "http", "Expected proxy type to be http");
+  equal(pi.type, "https", "Expected proxy type to be https");
 });
+
+add_task(async function testPreferHttpsProxy() {
+  let uri = Cc["@mozilla.org/network/standard-url-mutator;1"]
+    .createInstance(Ci.nsIURIMutator)
+    .setSpec("http://mozilla.org/")
+    .finalize();
+  let proxyFlags = Ci.nsIProtocolProxyService.RESOLVE_PREFER_HTTPS_PROXY;
+
+  let ioService = Cc["@mozilla.org/network/io-service;1"].getService(
+    Ci.nsIIOService
+  );
+  let chan = ioService.newChannelFromURIWithProxyFlags(
+    uri,
+    null,
+    proxyFlags,
+    null,
+    Services.scriptSecurityManager.getSystemPrincipal(),
+    null,
+    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+    Ci.nsIContentPolicy.TYPE_OTHER
+  );
+
+  let pi = await TestProxyType(chan, proxyFlags);
+  equal(pi.host, "localhost", "Expected proxy host to be localhost");
+  equal(pi.port, 8080, "Expected proxy port to be 8080");
+  equal(pi.type, "https", "Expected proxy type to be https");
+});