diff --git a/netwerk/dns/nsEffectiveTLDService.cpp b/netwerk/dns/nsEffectiveTLDService.cpp index f52c73971c46..1a7c8b0bafe0 100644 --- a/netwerk/dns/nsEffectiveTLDService.cpp +++ b/netwerk/dns/nsEffectiveTLDService.cpp @@ -206,6 +206,23 @@ nsEffectiveTLDService::GetSchemelessSite(nsIURI* aURI, nsACString& aSite) { return rv; } +// Variant of GetSchemelessSite which accepts a host string instead of a URI. +NS_IMETHODIMP +nsEffectiveTLDService::GetSchemelessSiteFromHost(const nsACString& aHostname, + nsACString& aSite) { + NS_ENSURE_TRUE(!aHostname.IsEmpty(), NS_ERROR_FAILURE); + + nsresult rv = GetBaseDomainFromHost(aHostname, 0, aSite); + if (rv == NS_ERROR_HOST_IS_IP_ADDRESS || + rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { + aSite.Assign(aHostname); + nsContentUtils::MaybeFixIPv6Host(aSite); + + return NS_OK; + } + return rv; +} + // External function for dealing with URIs to get site correctly. // Calls through to GetSchemelessSite(), and serializes with the scheme and // "://" prepended. diff --git a/netwerk/dns/nsIEffectiveTLDService.idl b/netwerk/dns/nsIEffectiveTLDService.idl index 82c0e7a8ce17..4e07c1642736 100644 --- a/netwerk/dns/nsIEffectiveTLDService.idl +++ b/netwerk/dns/nsIEffectiveTLDService.idl @@ -119,6 +119,28 @@ interface nsIEffectiveTLDService : nsISupports */ ACString getSchemelessSite(in nsIURI aURI); + /** + * Same as getSchemelessSite but takes a host string. Prefer the URI variant + * if possible. + * + * @param aHost + * The host to analyze. + * + * @return the Site. + * + * @throws NS_ERROR_UNEXPECTED + * or other error returned by nsIIDNService::normalize when + * the hostname contains characters disallowed in URIs + * + * @see getSchemelessSite() + * @see getBaseDomain() + * @see getSite() + * + * @warning This function should not be used without good reason. Please + * use getSite() or the Origin if you are not absolutely certain. + */ + ACString getSchemelessSiteFromHost(in AUTF8String aHost); + /** * Get the Site for the origin of aURI; e.g. for * "https://www.bbc.co.uk/index.html", this would be "https://bbc.co.uk". diff --git a/netwerk/dns/tests/unit/test_nsEffectiveTLDService_getSite.js b/netwerk/dns/tests/unit/test_nsEffectiveTLDService_getSite.js index 5f6f3b1eb362..b6253c38cb4b 100644 --- a/netwerk/dns/tests/unit/test_nsEffectiveTLDService_getSite.js +++ b/netwerk/dns/tests/unit/test_nsEffectiveTLDService_getSite.js @@ -64,7 +64,10 @@ add_task(() => { ["https://test.example.com", "example.com"], ["https://test1.test2.example.com", "example.com"], ["https://test1.test2.example.co.uk", "example.co.uk"], - ["https://test1.test2.example.公司.香港", "example.xn--55qx5d.xn--j6w193g"], + [ + "https://test1.test2.example.\u516c\u53f8.\u9999\u6e2f", + "example.xn--55qx5d.xn--j6w193g", + ], ]) { let origin = Services.io.newURI(originString); let answer = Services.eTLD.getSchemelessSite(origin); @@ -75,3 +78,29 @@ add_task(() => { ); } }); + +add_task(function test_getSchemelessSiteFromHost() { + for (let [host, result] of [ + ["com", "com"], + ["test", "test"], + ["test.", "test."], + ["::1", "[::1]"], + ["localhost", "localhost"], + ["127.0.0.1", "127.0.0.1"], + ["example.com", "example.com"], + ["test.example.com", "example.com"], + ["test1.test2.example.com", "example.com"], + ["test1.test2.example.co.uk", "example.co.uk"], + [ + "test1.test2.example.\u516c\u53f8.\u9999\u6e2f", + "example.xn--55qx5d.xn--j6w193g", + ], + ]) { + let answer = Services.eTLD.getSchemelessSiteFromHost(host); + Assert.equal( + answer, + result, + `"${host}" should have schemeless site ${result}, got ${answer}.` + ); + } +});