Bug 1334443 - Add gtest for nsProtocolProxyService::{LoadHostFilters,CanUseProxy} and fix IPv6 parsing r=bagder
While writing a gtest I discovered the parsing an IPv6 address didn't work due to the brackets.
MozReview-Commit-ID: 9mmKS72hf7Y
--- a/netwerk/base/nsProtocolProxyService.cpp
+++ b/netwerk/base/nsProtocolProxyService.cpp
@@ -1524,18 +1524,24 @@ nsProtocolProxyService::LoadHostFilters(
// Continue to next host filter;
continue;
}
// For all other host filters, create HostInfo object and add to list
HostInfo *hinfo = new HostInfo();
hinfo->port = portLocation ? atoi(portLocation + 1) : 0;
+ // PR_StringToNetAddr can't parse brackets enclosed IPv6
+ nsAutoCString addrString = str;
+ if (str.Length() > 0 && str.First() == '[' && str.Last() == ']') {
+ addrString = Substring(str, 1, str.Length() - 2);
+ }
+
PRNetAddr addr;
- if (PR_StringToNetAddr(str.get(), &addr) == PR_SUCCESS) {
+ if (PR_StringToNetAddr(addrString.get(), &addr) == PR_SUCCESS) {
hinfo->is_ipaddr = true;
hinfo->ip.family = PR_AF_INET6; // we always store address as IPv6
hinfo->ip.mask_len = maskLocation ? atoi(maskLocation + 1) : 128;
if (hinfo->ip.mask_len == 0) {
NS_WARNING("invalid mask");
goto loser;
}
@@ -1573,17 +1579,17 @@ nsProtocolProxyService::LoadHostFilters(
if (!hinfo->name.host)
goto loser;
hinfo->name.host_len = endIndex - startIndex;
}
//#define DEBUG_DUMP_FILTERS
#ifdef DEBUG_DUMP_FILTERS
- printf("loaded filter[%u]:\n", mHostFiltersArray.Length());
+ printf("loaded filter[%zu]:\n", mHostFiltersArray.Length());
printf(" is_ipaddr = %u\n", hinfo->is_ipaddr);
printf(" port = %u\n", hinfo->port);
if (hinfo->is_ipaddr) {
printf(" ip.family = %x\n", hinfo->ip.family);
printf(" ip.mask_len = %u\n", hinfo->ip.mask_len);
PRNetAddr netAddr;
PR_SetNetAddr(PR_IpAddrNull, PR_AF_INET6, 0, &netAddr);
--- a/netwerk/base/nsProtocolProxyService.h
+++ b/netwerk/base/nsProtocolProxyService.h
@@ -49,16 +49,17 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
nsProtocolProxyService();
nsresult Init();
protected:
friend class nsAsyncResolveRequest;
+ friend class TestProtocolProxyService_LoadHostFilters_Test; // for gtest
~nsProtocolProxyService();
/**
* This method is called whenever a preference may have changed or
* to initialize all preferences.
*
* @param prefs
new file mode 100644
--- /dev/null
+++ b/netwerk/test/gtest/TestProtocolProxyService.cpp
@@ -0,0 +1,123 @@
+#include "gtest/gtest.h"
+
+#include "nsCOMPtr.h"
+#include "nsNetCID.h"
+#include "nsIURL.h"
+#include "nsString.h"
+#include "nsComponentManagerUtils.h"
+#include "../../base/nsProtocolProxyService.h"
+#include "nsServiceManagerUtils.h"
+#include "mozilla/Preferences.h"
+
+namespace mozilla {
+namespace net {
+
+TEST(TestProtocolProxyService, LoadHostFilters) {
+ nsCOMPtr<nsIProtocolProxyService2> ps = do_GetService(NS_PROTOCOLPROXYSERVICE_CID);
+ ASSERT_TRUE(ps);
+ mozilla::net::nsProtocolProxyService* pps = static_cast<mozilla::net::nsProtocolProxyService*>(ps.get());
+
+ nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
+ ASSERT_TRUE(url) << "couldn't create URL";
+
+ nsAutoCString spec;
+
+ auto CheckLoopbackURLs = [&](bool expected)
+ {
+ // loopback IPs are always filtered
+ spec = "http://127.0.0.1";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+ spec = "http://[::1]";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+ };
+
+ auto CheckURLs = [&](bool expected)
+ {
+ spec = "http://example.com";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "https://10.2.3.4";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 443), expected);
+
+ spec = "http://1.2.3.4";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "http://1.2.3.4:8080";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "http://[2001::1]";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "http://2.3.4.5:7777";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "http://[abcd::2]:123";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+
+ spec = "http://bla.test.com";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+ };
+
+ auto CheckPortDomain = [&](bool expected)
+ {
+ spec = "http://blabla.com:10";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+ };
+
+ auto CheckLocalDomain = [&](bool expected)
+ {
+ spec = "http://test";
+ ASSERT_EQ(url->SetSpec(spec), NS_OK);
+ ASSERT_EQ(pps->CanUseProxy(url, 80), expected);
+ };
+
+ // --------------------------------------------------------------------------
+
+ nsAutoCString filter;
+
+ // Anything is allowed when there are no filters set
+ printf("Testing empty filter: %s\n", filter.get());
+ pps->LoadHostFilters(filter.get());
+
+ CheckLoopbackURLs(true); // only time when loopbacks can be proxied. bug?
+ CheckLocalDomain(true);
+ CheckURLs(true);
+ CheckPortDomain(true);
+
+ // --------------------------------------------------------------------------
+
+ filter = "example.com, 1.2.3.4/16, [2001::1], 10.0.0.0/8, 2.3.0.0/16:7777, [abcd::1]/64:123, *.test.com";
+ printf("Testing filter: %s\n", filter.get());
+ pps->LoadHostFilters(filter.get());
+ // Check URLs can no longer use filtered proxy
+ CheckURLs(false);
+ CheckLoopbackURLs(false);
+ CheckLocalDomain(true);
+ CheckPortDomain(true);
+
+ // --------------------------------------------------------------------------
+
+ // This is space separated. See bug 1346711 comment 4. We check this to keep
+ // backwards compatibility.
+ filter = "<local> blabla.com:10";
+ printf("Testing filter: %s\n", filter.get());
+ pps->LoadHostFilters(filter.get());
+ CheckURLs(true);
+ CheckLoopbackURLs(false);
+ CheckLocalDomain(false);
+ CheckPortDomain(false);
+}
+
+} // namespace net
+} // namespace mozila
--- a/netwerk/test/gtest/moz.build
+++ b/netwerk/test/gtest/moz.build
@@ -1,13 +1,14 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
+ 'TestProtocolProxyService.cpp',
'TestStandardURL.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'