| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * This file is part of Adblock Plus <https://adblockplus.org/>, |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|    3  * Copyright (C) 2006-present eyeo GmbH |    3  * Copyright (C) 2006-present eyeo GmbH | 
|    4  * |    4  * | 
|    5  * Adblock Plus is free software: you can redistribute it and/or modify |    5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|    6  * it under the terms of the GNU General Public License version 3 as |    6  * it under the terms of the GNU General Public License version 3 as | 
|    7  * published by the Free Software Foundation. |    7  * published by the Free Software Foundation. | 
|    8  * |    8  * | 
|    9  * Adblock Plus is distributed in the hope that it will be useful, |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
|   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|   12  * GNU General Public License for more details. |   12  * GNU General Public License for more details. | 
|   13  * |   13  * | 
|   14  * You should have received a copy of the GNU General Public License |   14  * You should have received a copy of the GNU General Public License | 
|   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|   16  */ |   16  */ | 
|   17  |   17  | 
|   18 "use strict"; |   18 "use strict"; | 
|   19  |   19  | 
 |   20 const assert = require("assert"); | 
|   20 // Only starting NodeJS 10 that URL is in the global space. |   21 // Only starting NodeJS 10 that URL is in the global space. | 
|   21 const {URL} = require("url"); |   22 const {URL} = require("url"); | 
|   22 const {createSandbox} = require("./_common"); |   23 const {createSandbox} = require("./_common"); | 
|   23  |  | 
|   24 const publicSuffixes = require("../data/publicSuffixList.json"); |   24 const publicSuffixes = require("../data/publicSuffixList.json"); | 
|   25  |   25  | 
|   26 let parseURL = null; |   26 let parseURL = null; | 
|   27 let normalizeHostname = null; |   27 let normalizeHostname = null; | 
|   28 let domainSuffixes = null; |   28 let domainSuffixes = null; | 
|   29 let isThirdParty = null; |   29 let isThirdParty = null; | 
|   30 let getBaseDomain = null; |   30 let getBaseDomain = null; | 
|   31  |   31  | 
|   32 exports.setUp = function(callback) |   32 describe("URL", () => | 
|   33 { |   33 { | 
|   34   let sandboxedRequire = createSandbox({ |   34   beforeEach(() => | 
|   35     extraExports: { |   35   { | 
|   36       domain: ["getBaseDomain"] |   36     let sandboxedRequire = createSandbox({ | 
 |   37       extraExports: { | 
 |   38         domain: ["getBaseDomain"] | 
 |   39       } | 
 |   40     }); | 
 |   41     ( | 
 |   42       {parseURL, normalizeHostname, domainSuffixes, isThirdParty, | 
 |   43        getBaseDomain} = sandboxedRequire("../lib/url") | 
 |   44     ); | 
 |   45   }); | 
 |   46  | 
 |   47   it("Normalize Hostname", () => | 
 |   48   { | 
 |   49     assert.equal(normalizeHostname("example.com"), "example.com"); | 
 |   50     assert.equal(normalizeHostname("example.com."), "example.com"); | 
 |   51     assert.equal(normalizeHostname("example.com.."), "example.com"); | 
 |   52     assert.equal(normalizeHostname("example.com..."), "example.com"); | 
 |   53  | 
 |   54     assert.equal(normalizeHostname("Example.com"), "example.com"); | 
 |   55     assert.equal(normalizeHostname("ExaMple.Com"), "example.com"); | 
 |   56     assert.equal(normalizeHostname("ExaMple.Com.."), "example.com"); | 
 |   57  | 
 |   58     assert.equal(normalizeHostname("192.168.1.1"), "192.168.1.1"); | 
 |   59     assert.equal(normalizeHostname("192.168.1.1."), "192.168.1.1"); | 
 |   60  | 
 |   61     assert.equal(normalizeHostname("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), | 
 |   62                "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); | 
 |   63     assert.equal(normalizeHostname("2001:0db8:85a3:0000:0000:8a2e:0370:7334."), | 
 |   64                "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); | 
 |   65     assert.equal(normalizeHostname("2001:0DB8:85A3:0000:0000:8A2E:0370:7334"), | 
 |   66                "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); | 
 |   67   }); | 
 |   68  | 
 |   69   it("Domain Suffixes", () => | 
 |   70   { | 
 |   71     assert.deepEqual([...domainSuffixes("localhost")], ["localhost"]); | 
 |   72     assert.deepEqual([...domainSuffixes("example.com")], ["example.com", "com"])
     ; | 
 |   73     assert.deepEqual([...domainSuffixes("www.example.com")], | 
 |   74                    ["www.example.com", "example.com", "com"]); | 
 |   75     assert.deepEqual([...domainSuffixes("www.example.co.in")], | 
 |   76                    ["www.example.co.in", "example.co.in", "co.in", "in"]); | 
 |   77  | 
 |   78     // With blank. | 
 |   79     assert.deepEqual([...domainSuffixes("localhost", true)], ["localhost", ""]); | 
 |   80     assert.deepEqual([...domainSuffixes("example.com", true)], | 
 |   81                    ["example.com", "com", ""]); | 
 |   82     assert.deepEqual([...domainSuffixes("www.example.com", true)], | 
 |   83                    ["www.example.com", "example.com", "com", ""]); | 
 |   84     assert.deepEqual([...domainSuffixes("www.example.co.in", true)], | 
 |   85                    ["www.example.co.in", "example.co.in", "co.in", "in", ""]); | 
 |   86  | 
 |   87     // Quirks and edge cases. | 
 |   88     assert.deepEqual([...domainSuffixes("")], []); | 
 |   89     assert.deepEqual([...domainSuffixes(".")], ["."]); | 
 |   90     assert.deepEqual([...domainSuffixes(".localhost")], | 
 |   91                    [".localhost", "localhost"]); | 
 |   92     assert.deepEqual([...domainSuffixes(".example.com")], | 
 |   93                    [".example.com", "example.com", "com"]); | 
 |   94     assert.deepEqual([...domainSuffixes("localhost.")], | 
 |   95                    ["localhost."]); | 
 |   96     assert.deepEqual([...domainSuffixes("example.com.")], | 
 |   97                    ["example.com.", "com."]); | 
 |   98     assert.deepEqual([...domainSuffixes("..localhost")], | 
 |   99                    ["..localhost", ".localhost", "localhost"]); | 
 |  100     assert.deepEqual( | 
 |  101       [...domainSuffixes("..example..com")], | 
 |  102       ["..example..com", ".example..com", "example..com", ".com", "com"] | 
 |  103     ); | 
 |  104     assert.deepEqual([...domainSuffixes("localhost..")], ["localhost..", "."]); | 
 |  105     assert.deepEqual([...domainSuffixes("example..com..")], | 
 |  106                    ["example..com..", ".com..", "com..", "."]); | 
 |  107   }); | 
 |  108  | 
 |  109   it("URL parsing", () => | 
 |  110   { | 
 |  111     function testURLParsing(url) | 
 |  112     { | 
 |  113       // Note: The function expects a normalized URL. | 
 |  114       // e.g. "http:example.com:80?foo" should already be normalized to | 
 |  115       // "http://example.com/?foo". If not, the tests will fail. | 
 |  116       let urlInfo = parseURL(url); | 
 |  117  | 
 |  118       // We need to ensure only that our implementation matches that of the URL | 
 |  119       // object. | 
 |  120       let urlObject = new URL(url); | 
 |  121  | 
 |  122       assert.equal(urlInfo.href, urlObject.href); | 
 |  123       assert.equal(urlInfo.protocol, urlObject.protocol); | 
 |  124       assert.equal(urlInfo.hostname, urlObject.hostname); | 
 |  125  | 
 |  126       assert.equal(urlInfo.toString(), urlObject.toString()); | 
 |  127       assert.equal(String(urlInfo), String(urlObject)); | 
 |  128       assert.equal(urlInfo + "", urlObject + ""); | 
|   37     } |  129     } | 
|   38   }); |  130  | 
|   39   ( |  131     testURLParsing("https://example.com/"); | 
|   40     {parseURL, normalizeHostname, domainSuffixes, isThirdParty, |  132     testURLParsing("https://example.com/foo"); | 
|   41      getBaseDomain} = sandboxedRequire("../lib/url") |  133     testURLParsing("https://example.com/foo/bar"); | 
|   42   ); |  134     testURLParsing( | 
|   43  |  135       "https://example.com/foo/bar?https://random/foo/bar" | 
|   44   callback(); |  136     ); | 
|   45 }; |  137  | 
|   46  |  138     testURLParsing("https://example.com:8080/"); | 
|   47 function hostnameToURL(hostname) |  139     testURLParsing("https://example.com:8080/foo"); | 
|   48 { |  140     testURLParsing("https://example.com:8080/foo/bar"); | 
|   49   return new URL("http://" + hostname); |  141     testURLParsing( | 
|   50 } |  142       "https://example.com:8080/foo/bar?https://random/foo/bar" | 
|   51  |  143     ); | 
|   52 function testURLParsing(test, url) |  144  | 
|   53 { |  145     testURLParsing("http://localhost/"); | 
|   54   // Note: The function expects a normalized URL. |  146     testURLParsing("http://localhost/foo"); | 
|   55   // e.g. "http:example.com:80?foo" should already be normalized to |  147     testURLParsing("http://localhost/foo/bar"); | 
|   56   // "http://example.com/?foo". If not, the tests will fail. |  148     testURLParsing( | 
|   57   let urlInfo = parseURL(url); |  149       "http://localhost/foo/bar?https://random/foo/bar" | 
|   58  |  150     ); | 
|   59   // We need to ensure only that our implementation matches that of the URL |  151  | 
|   60   // object. |  152     testURLParsing("https://user@example.com/"); | 
|   61   let urlObject = new URL(url); |  153     testURLParsing("https://user@example.com/foo"); | 
|   62  |  154     testURLParsing("https://user@example.com/foo/bar"); | 
|   63   test.equal(urlInfo.href, urlObject.href); |  155     testURLParsing( | 
|   64   test.equal(urlInfo.protocol, urlObject.protocol); |  156       "https://user@example.com/foo/bar?https://random/foo/bar" | 
|   65   test.equal(urlInfo.hostname, urlObject.hostname); |  157     ); | 
|   66  |  158  | 
|   67   test.equal(urlInfo.toString(), urlObject.toString()); |  159     testURLParsing("https://user@example.com:8080/"); | 
|   68   test.equal(String(urlInfo), String(urlObject)); |  160     testURLParsing("https://user@example.com:8080/foo"); | 
|   69   test.equal(urlInfo + "", urlObject + ""); |  161     testURLParsing("https://user@example.com:8080/foo/bar"); | 
|   70 } |  162     testURLParsing( | 
|   71  |  163       "https://user@example.com:8080/foo/bar?https://random/foo/bar" | 
|   72 function testThirdParty(test, requestHostname, documentHostname, expected, |  164     ); | 
|   73                         message) |  165  | 
|   74 { |  166     testURLParsing("https://user:pass@example.com/"); | 
|   75   test.equal( |  167     testURLParsing("https://user:pass@example.com/foo"); | 
|   76     isThirdParty( |  168     testURLParsing("https://user:pass@example.com/foo/bar"); | 
|   77       hostnameToURL(requestHostname).hostname, |  169     testURLParsing( | 
|   78  |  170       "https://user:pass@example.com/foo/bar?https://random/foo/bar" | 
|   79       // Chrome's URL object normalizes IP addresses. So some test |  171     ); | 
|   80       // will fail if we don't normalize the document host as well. |  172  | 
|   81       hostnameToURL(documentHostname).hostname |  173     testURLParsing("https://user:pass@example.com:8080/"); | 
|   82     ), |  174     testURLParsing("https://user:pass@example.com:8080/foo"); | 
|   83     expected, |  175     testURLParsing("https://user:pass@example.com:8080/foo/bar"); | 
|   84     message |  176     testURLParsing( | 
|   85   ); |  177       "https://user:pass@example.com:8080/foo/bar?https://random/foo/bar" | 
|   86 } |  178     ); | 
|   87  |  179  | 
|   88 exports.testParseURL = function(test) |  180     testURLParsing("https://us%40er:pa%40ss@example.com/"); | 
|   89 { |  181     testURLParsing("https://us%40er:pa%40ss@example.com/foo"); | 
|   90   testURLParsing(test, "https://example.com/"); |  182     testURLParsing("https://us%40er:pa%40ss@example.com/foo/bar"); | 
|   91   testURLParsing(test, "https://example.com/foo"); |  183     testURLParsing( | 
|   92   testURLParsing(test, "https://example.com/foo/bar"); |  184       "https://us%40er:pa%40ss@example.com/foo/bar?https://random/foo/bar" | 
|   93   testURLParsing( |  185     ); | 
|   94     test, |  186  | 
|   95     "https://example.com/foo/bar?https://random/foo/bar" |  187     testURLParsing("https://us%40er:pa%40ss@example.com:8080/"); | 
|   96   ); |  188     testURLParsing("https://us%40er:pa%40ss@example.com:8080/foo"); | 
|   97  |  189     testURLParsing("https://us%40er:pa%40ss@example.com:8080/foo/bar"); | 
|   98   testURLParsing(test, "https://example.com:8080/"); |  190     testURLParsing( | 
|   99   testURLParsing(test, "https://example.com:8080/foo"); |  191       "https://us%40er:pa%40ss@example.com:8080/foo/bar?https://random/foo/bar" | 
|  100   testURLParsing(test, "https://example.com:8080/foo/bar"); |  192     ); | 
|  101   testURLParsing( |  193  | 
|  102     test, |  194     testURLParsing("http://192.168.1.1/"); | 
|  103     "https://example.com:8080/foo/bar?https://random/foo/bar" |  195     testURLParsing("http://192.168.1.1/foo"); | 
|  104   ); |  196     testURLParsing("http://192.168.1.1/foo/bar"); | 
|  105  |  197     testURLParsing( | 
|  106   testURLParsing(test, "http://localhost/"); |  198       "http://192.168.1.1/foo/bar?https://random/foo/bar" | 
|  107   testURLParsing(test, "http://localhost/foo"); |  199     ); | 
|  108   testURLParsing(test, "http://localhost/foo/bar"); |  200     testURLParsing( | 
|  109   testURLParsing( |  201       "http://192.168.1.1:8080/foo/bar?https://random/foo/bar" | 
|  110     test, |  202     ); | 
|  111     "http://localhost/foo/bar?https://random/foo/bar" |  203     testURLParsing( | 
|  112   ); |  204       "http://user@192.168.1.1:8080/foo/bar?https://random/foo/bar" | 
|  113  |  205     ); | 
|  114   testURLParsing(test, "https://user@example.com/"); |  206     testURLParsing( | 
|  115   testURLParsing(test, "https://user@example.com/foo"); |  207       "http://user:pass@192.168.1.1:8080/foo/bar?https://random/foo/bar" | 
|  116   testURLParsing(test, "https://user@example.com/foo/bar"); |  208     ); | 
|  117   testURLParsing( |  209  | 
|  118     test, |  210     testURLParsing("http://[2001:db8:0:42:0:8a2e:370:7334]/"); | 
|  119     "https://user@example.com/foo/bar?https://random/foo/bar" |  211     testURLParsing("http://[2001:db8:0:42:0:8a2e:370:7334]/foo"); | 
|  120   ); |  212     testURLParsing( | 
|  121  |  213       "http://[2001:db8:0:42:0:8a2e:370:7334]/foo/bar" | 
|  122   testURLParsing(test, "https://user@example.com:8080/"); |  214     ); | 
|  123   testURLParsing(test, "https://user@example.com:8080/foo"); |  215     testURLParsing( | 
|  124   testURLParsing(test, "https://user@example.com:8080/foo/bar"); |  216       "http://[2001:db8:0:42:0:8a2e:370:7334]/foo/bar?https://random/foo/bar" | 
|  125   testURLParsing( |  217     ); | 
|  126     test, |  218     testURLParsing( | 
|  127     "https://user@example.com:8080/foo/bar?https://random/foo/bar" |  219       "http://[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://random/foo/ba
     r" | 
|  128   ); |  220     ); | 
|  129  |  221     testURLParsing( | 
|  130   testURLParsing(test, "https://user:pass@example.com/"); |  222       "http://user@[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://random/f
     oo/bar" | 
|  131   testURLParsing(test, "https://user:pass@example.com/foo"); |  223     ); | 
|  132   testURLParsing(test, "https://user:pass@example.com/foo/bar"); |  224     testURLParsing( | 
|  133   testURLParsing( |  225       "http://user:pass@[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://ran
     dom/foo/bar" | 
|  134     test, |  226     ); | 
|  135     "https://user:pass@example.com/foo/bar?https://random/foo/bar" |  227  | 
|  136   ); |  228     testURLParsing("ftp://user:pass@example.com:8021/"); | 
|  137  |  229     testURLParsing("ftp://user:pass@example.com:8021/foo"); | 
|  138   testURLParsing(test, "https://user:pass@example.com:8080/"); |  230     testURLParsing("ftp://user:pass@example.com:8021/foo/bar"); | 
|  139   testURLParsing(test, "https://user:pass@example.com:8080/foo"); |  231  | 
|  140   testURLParsing(test, "https://user:pass@example.com:8080/foo/bar"); |  232     testURLParsing("about:blank"); | 
|  141   testURLParsing( |  233     testURLParsing("chrome://extensions"); | 
|  142     test, |  234     testURLParsing( | 
|  143     "https://user:pass@example.com:8080/foo/bar?https://random/foo/bar" |  235       "chrome-extension://bhignfpcigccnlfapldlodmhlidjaion/options.html" | 
|  144   ); |  236     ); | 
|  145  |  237     testURLParsing("mailto:john.doe@mail.example.com"); | 
|  146   testURLParsing(test, "https://us%40er:pa%40ss@example.com/"); |  238  | 
|  147   testURLParsing(test, "https://us%40er:pa%40ss@example.com/foo"); |  239     testURLParsing("news:newsgroup"); | 
|  148   testURLParsing(test, "https://us%40er:pa%40ss@example.com/foo/bar"); |  240     testURLParsing("news:message-id"); | 
|  149   testURLParsing( |  241     testURLParsing("nntp://example.com:8119/newsgroup"); | 
|  150     test, |  242     testURLParsing("nntp://example.com:8119/message-id"); | 
|  151     "https://us%40er:pa%40ss@example.com/foo/bar?https://random/foo/bar" |  243  | 
|  152   ); |  244     testURLParsing("data:,"); | 
|  153  |  245     testURLParsing( | 
|  154   testURLParsing(test, "https://us%40er:pa%40ss@example.com:8080/"); |  246       "data:text/vnd-example+xyz;foo=bar;base64,R0lGODdh" | 
|  155   testURLParsing(test, "https://us%40er:pa%40ss@example.com:8080/foo"); |  247     ); | 
|  156   testURLParsing(test, "https://us%40er:pa%40ss@example.com:8080/foo/bar"); |  248     testURLParsing( | 
|  157   testURLParsing( |  249       "data:text/plain;charset=UTF-8;page=21,the%20data:1234,5678" | 
|  158     test, |  250     ); | 
|  159     "https://us%40er:pa%40ss@example.com:8080/foo/bar?https://random/foo/bar" |  251  | 
|  160   ); |  252     testURLParsing("javascript:"); | 
|  161  |  253     testURLParsing("javascript:alert();"); | 
|  162   testURLParsing(test, "http://192.168.1.1/"); |  254     testURLParsing("javascript:foo/bar/"); | 
|  163   testURLParsing(test, "http://192.168.1.1/foo"); |  255     testURLParsing("javascript://foo/bar/"); | 
|  164   testURLParsing(test, "http://192.168.1.1/foo/bar"); |  256  | 
|  165   testURLParsing( |  257     testURLParsing("file:///dev/random"); | 
|  166     test, |  258  | 
|  167     "http://192.168.1.1/foo/bar?https://random/foo/bar" |  259     testURLParsing("wss://example.com/"); | 
|  168   ); |  260     testURLParsing("wss://example.com:8080/"); | 
|  169   testURLParsing( |  261     testURLParsing("wss://user@example.com:8080/"); | 
|  170     test, |  262     testURLParsing("wss://user:pass@example.com:8080/"); | 
|  171     "http://192.168.1.1:8080/foo/bar?https://random/foo/bar" |  263  | 
|  172   ); |  264     testURLParsing("stuns:stuns.example.com/"); | 
|  173   testURLParsing( |  265     testURLParsing("stuns:stuns.example.com:8080/"); | 
|  174     test, |  266     testURLParsing("stuns:user@stuns.example.com:8080/"); | 
|  175     "http://user@192.168.1.1:8080/foo/bar?https://random/foo/bar" |  267     testURLParsing("stuns:user:pass@stuns.example.com:8080/"); | 
|  176   ); |  268  | 
|  177   testURLParsing( |  269     // The following tests are based on | 
|  178     test, |  270     // https://cs.chromium.org/chromium/src/url/gurl_unittest.cc?rcl=9ec7bc85e0f
     6a0bf28eff6b2eca678067da547e9 | 
|  179     "http://user:pass@192.168.1.1:8080/foo/bar?https://random/foo/bar" |  271     // Note: We do not check for "canonicalization" (normalization). parseURL() | 
|  180   ); |  272     // should be used with normalized URLs only. | 
|  181  |  273  | 
|  182   testURLParsing(test, "http://[2001:db8:0:42:0:8a2e:370:7334]/"); |  274     testURLParsing("something:///example.com/"); | 
|  183   testURLParsing(test, "http://[2001:db8:0:42:0:8a2e:370:7334]/foo"); |  275     testURLParsing("something://example.com/"); | 
|  184   testURLParsing( |  276  | 
|  185     test, |  277     testURLParsing("file:///C:/foo.txt"); | 
|  186     "http://[2001:db8:0:42:0:8a2e:370:7334]/foo/bar" |  278     testURLParsing("file://server/foo.txt"); | 
|  187   ); |  279  | 
|  188   testURLParsing( |  280     testURLParsing("http://user:pass@example.com:99/foo;bar?q=a#ref"); | 
|  189     test, |  281  | 
|  190     "http://[2001:db8:0:42:0:8a2e:370:7334]/foo/bar?https://random/foo/bar" |  282     testURLParsing("http://user:%40!$&'()*+,%3B%3D%3A@example.com:12345/"); | 
|  191   ); |  283  | 
|  192   testURLParsing( |  284     testURLParsing("filesystem:http://example.com/temporary/"); | 
|  193     test, |  285     testURLParsing( | 
|  194     "http://[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://random/foo/bar" |  286       "filesystem:http://user:%40!$&'()*+,%3B%3D%3A@example.com:12345/" | 
|  195   ); |  287     ); | 
|  196   testURLParsing( |  288  | 
|  197     test, |  289     testURLParsing("javascript:window.alert('hello, world');"); | 
|  198     "http://user@[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://random/foo
     /bar" |  290     testURLParsing("javascript:#"); | 
|  199   ); |  291  | 
|  200   testURLParsing( |  292     testURLParsing( | 
|  201     test, |  293       "blob:https://example.com/7ce70a1e-9681-4148-87a8-43cb9171b994" | 
|  202     "http://user:pass@[2001:db8:0:42:0:8a2e:370:7334]:8080/foo/bar?https://rando
     m/foo/bar" |  294     ); | 
|  203   ); |  295  | 
|  204  |  296     testURLParsing("http://[2001:db8::1]/"); | 
|  205   testURLParsing(test, "ftp://user:pass@example.com:8021/"); |  297     testURLParsing("http://[2001:db8::1]:8080/"); | 
|  206   testURLParsing(test, "ftp://user:pass@example.com:8021/foo"); |  298     testURLParsing("http://[::]:8080/"); | 
|  207   testURLParsing(test, "ftp://user:pass@example.com:8021/foo/bar"); |  299  | 
|  208  |  300     testURLParsing("not-a-standard-scheme:this is arbitrary content"); | 
|  209   testURLParsing(test, "about:blank"); |  301     testURLParsing("view-source:http://example.com/path"); | 
|  210   testURLParsing(test, "chrome://extensions"); |  302  | 
|  211   testURLParsing( |  303     testURLParsing( | 
|  212     test, |  304       "data:text/html,Question?%3Cdiv%20style=%22color:%20#bad%22%3Eidea%3C/div%
     3E" | 
|  213     "chrome-extension://bhignfpcigccnlfapldlodmhlidjaion/options.html" |  305     ); | 
|  214   ); |  306   }); | 
|  215   testURLParsing(test, "mailto:john.doe@mail.example.com"); |  307  | 
|  216  |  308   it("Is Third Party", () => | 
|  217   testURLParsing(test, "news:newsgroup"); |  309   { | 
|  218   testURLParsing(test, "news:message-id"); |  310     function hostnameToURL(hostname) | 
|  219   testURLParsing(test, "nntp://example.com:8119/newsgroup"); |  | 
|  220   testURLParsing(test, "nntp://example.com:8119/message-id"); |  | 
|  221  |  | 
|  222   testURLParsing(test, "data:,"); |  | 
|  223   testURLParsing( |  | 
|  224     test, |  | 
|  225     "data:text/vnd-example+xyz;foo=bar;base64,R0lGODdh" |  | 
|  226   ); |  | 
|  227   testURLParsing( |  | 
|  228     test, |  | 
|  229     "data:text/plain;charset=UTF-8;page=21,the%20data:1234,5678" |  | 
|  230   ); |  | 
|  231  |  | 
|  232   testURLParsing(test, "javascript:"); |  | 
|  233   testURLParsing(test, "javascript:alert();"); |  | 
|  234   testURLParsing(test, "javascript:foo/bar/"); |  | 
|  235   testURLParsing(test, "javascript://foo/bar/"); |  | 
|  236  |  | 
|  237   testURLParsing(test, "file:///dev/random"); |  | 
|  238  |  | 
|  239   testURLParsing(test, "wss://example.com/"); |  | 
|  240   testURLParsing(test, "wss://example.com:8080/"); |  | 
|  241   testURLParsing(test, "wss://user@example.com:8080/"); |  | 
|  242   testURLParsing(test, "wss://user:pass@example.com:8080/"); |  | 
|  243  |  | 
|  244   testURLParsing(test, "stuns:stuns.example.com/"); |  | 
|  245   testURLParsing(test, "stuns:stuns.example.com:8080/"); |  | 
|  246   testURLParsing(test, "stuns:user@stuns.example.com:8080/"); |  | 
|  247   testURLParsing(test, "stuns:user:pass@stuns.example.com:8080/"); |  | 
|  248  |  | 
|  249   // The following tests are based on |  | 
|  250   // https://cs.chromium.org/chromium/src/url/gurl_unittest.cc?rcl=9ec7bc85e0f6a
     0bf28eff6b2eca678067da547e9 |  | 
|  251   // Note: We do not check for "canonicalization" (normalization). parseURL() |  | 
|  252   // should be used with normalized URLs only. |  | 
|  253  |  | 
|  254   testURLParsing(test, "something:///example.com/"); |  | 
|  255   testURLParsing(test, "something://example.com/"); |  | 
|  256  |  | 
|  257   testURLParsing(test, "file:///C:/foo.txt"); |  | 
|  258   testURLParsing(test, "file://server/foo.txt"); |  | 
|  259  |  | 
|  260   testURLParsing(test, "http://user:pass@example.com:99/foo;bar?q=a#ref"); |  | 
|  261  |  | 
|  262   testURLParsing(test, "http://user:%40!$&'()*+,%3B%3D%3A@example.com:12345/"); |  | 
|  263  |  | 
|  264   testURLParsing(test, "filesystem:http://example.com/temporary/"); |  | 
|  265   testURLParsing( |  | 
|  266     test, |  | 
|  267     "filesystem:http://user:%40!$&'()*+,%3B%3D%3A@example.com:12345/" |  | 
|  268   ); |  | 
|  269  |  | 
|  270   testURLParsing(test, "javascript:window.alert('hello, world');"); |  | 
|  271   testURLParsing(test, "javascript:#"); |  | 
|  272  |  | 
|  273   testURLParsing( |  | 
|  274     test, |  | 
|  275     "blob:https://example.com/7ce70a1e-9681-4148-87a8-43cb9171b994" |  | 
|  276   ); |  | 
|  277  |  | 
|  278   testURLParsing(test, "http://[2001:db8::1]/"); |  | 
|  279   testURLParsing(test, "http://[2001:db8::1]:8080/"); |  | 
|  280   testURLParsing(test, "http://[::]:8080/"); |  | 
|  281  |  | 
|  282   testURLParsing(test, "not-a-standard-scheme:this is arbitrary content"); |  | 
|  283   testURLParsing(test, "view-source:http://example.com/path"); |  | 
|  284  |  | 
|  285   testURLParsing( |  | 
|  286     test, |  | 
|  287     "data:text/html,Question?%3Cdiv%20style=%22color:%20#bad%22%3Eidea%3C/div%3E
     " |  | 
|  288   ); |  | 
|  289  |  | 
|  290   test.done(); |  | 
|  291 }; |  | 
|  292  |  | 
|  293 exports.testNormalizeHostname = function(test) |  | 
|  294 { |  | 
|  295   test.equal(normalizeHostname("example.com"), "example.com"); |  | 
|  296   test.equal(normalizeHostname("example.com."), "example.com"); |  | 
|  297   test.equal(normalizeHostname("example.com.."), "example.com"); |  | 
|  298   test.equal(normalizeHostname("example.com..."), "example.com"); |  | 
|  299  |  | 
|  300   test.equal(normalizeHostname("Example.com"), "example.com"); |  | 
|  301   test.equal(normalizeHostname("ExaMple.Com"), "example.com"); |  | 
|  302   test.equal(normalizeHostname("ExaMple.Com.."), "example.com"); |  | 
|  303  |  | 
|  304   test.equal(normalizeHostname("192.168.1.1"), "192.168.1.1"); |  | 
|  305   test.equal(normalizeHostname("192.168.1.1."), "192.168.1.1"); |  | 
|  306  |  | 
|  307   test.equal(normalizeHostname("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), |  | 
|  308              "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); |  | 
|  309   test.equal(normalizeHostname("2001:0db8:85a3:0000:0000:8a2e:0370:7334."), |  | 
|  310              "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); |  | 
|  311   test.equal(normalizeHostname("2001:0DB8:85A3:0000:0000:8A2E:0370:7334"), |  | 
|  312              "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); |  | 
|  313  |  | 
|  314   test.done(); |  | 
|  315 }; |  | 
|  316  |  | 
|  317 exports.testDomainSuffixes = function(test) |  | 
|  318 { |  | 
|  319   test.deepEqual([...domainSuffixes("localhost")], ["localhost"]); |  | 
|  320   test.deepEqual([...domainSuffixes("example.com")], ["example.com", "com"]); |  | 
|  321   test.deepEqual([...domainSuffixes("www.example.com")], |  | 
|  322                  ["www.example.com", "example.com", "com"]); |  | 
|  323   test.deepEqual([...domainSuffixes("www.example.co.in")], |  | 
|  324                  ["www.example.co.in", "example.co.in", "co.in", "in"]); |  | 
|  325  |  | 
|  326   // With blank. |  | 
|  327   test.deepEqual([...domainSuffixes("localhost", true)], ["localhost", ""]); |  | 
|  328   test.deepEqual([...domainSuffixes("example.com", true)], |  | 
|  329                  ["example.com", "com", ""]); |  | 
|  330   test.deepEqual([...domainSuffixes("www.example.com", true)], |  | 
|  331                  ["www.example.com", "example.com", "com", ""]); |  | 
|  332   test.deepEqual([...domainSuffixes("www.example.co.in", true)], |  | 
|  333                  ["www.example.co.in", "example.co.in", "co.in", "in", ""]); |  | 
|  334  |  | 
|  335   // Quirks and edge cases. |  | 
|  336   test.deepEqual([...domainSuffixes("")], []); |  | 
|  337   test.deepEqual([...domainSuffixes(".")], ["."]); |  | 
|  338   test.deepEqual([...domainSuffixes(".localhost")], |  | 
|  339                  [".localhost", "localhost"]); |  | 
|  340   test.deepEqual([...domainSuffixes(".example.com")], |  | 
|  341                  [".example.com", "example.com", "com"]); |  | 
|  342   test.deepEqual([...domainSuffixes("localhost.")], |  | 
|  343                  ["localhost."]); |  | 
|  344   test.deepEqual([...domainSuffixes("example.com.")], |  | 
|  345                  ["example.com.", "com."]); |  | 
|  346   test.deepEqual([...domainSuffixes("..localhost")], |  | 
|  347                  ["..localhost", ".localhost", "localhost"]); |  | 
|  348   test.deepEqual( |  | 
|  349     [...domainSuffixes("..example..com")], |  | 
|  350     ["..example..com", ".example..com", "example..com", ".com", "com"] |  | 
|  351   ); |  | 
|  352   test.deepEqual([...domainSuffixes("localhost..")], ["localhost..", "."]); |  | 
|  353   test.deepEqual([...domainSuffixes("example..com..")], |  | 
|  354                  ["example..com..", ".com..", "com..", "."]); |  | 
|  355  |  | 
|  356   test.done(); |  | 
|  357 }; |  | 
|  358  |  | 
|  359 exports.testIsThirdParty = function(test) |  | 
|  360 { |  | 
|  361   testThirdParty(test, "foo", "foo", false, "same domain isn't third-party"); |  | 
|  362   testThirdParty(test, "foo", "bar", true, "different domain is third-party"); |  | 
|  363   testThirdParty(test, "foo.com", "foo.com", false, |  | 
|  364                  "same domain with TLD (.com) isn't third-party"); |  | 
|  365   testThirdParty(test, "foo.com", "bar.com", true, |  | 
|  366                  "same TLD (.com) but different domain is third-party"); |  | 
|  367   testThirdParty(test, "foo.com", "www.foo.com", false, |  | 
|  368                  "same domain but differend subdomain isn't third-party"); |  | 
|  369   testThirdParty(test, "foo.example.com", "bar.example.com", false, |  | 
|  370                  "same basedomain (example.com) isn't third-party"); |  | 
|  371   testThirdParty(test, "foo.uk", "bar.uk", true, |  | 
|  372                  "same TLD (.uk) but different domain is third-party"); |  | 
|  373   testThirdParty(test, "foo.co.uk", "bar.co.uk", true, |  | 
|  374                  "same TLD (.co.uk) but different domain is third-party"); |  | 
|  375   testThirdParty(test, "foo.example.co.uk", "bar.example.co.uk", false, |  | 
|  376                  "same basedomain (example.co.uk) isn't third-party"); |  | 
|  377   testThirdParty(test, "1.2.3.4", "1.2.3.4", false, |  | 
|  378                  "same IPv4 address isn't third-party"); |  | 
|  379   testThirdParty(test, "1.1.1.1", "2.1.1.1", true, |  | 
|  380                  "different IPv4 address is third-party"); |  | 
|  381   testThirdParty(test, "0x01ff0101", "0x01ff0101", false, |  | 
|  382                  "same IPv4 hexadecimal address isn't third-party"); |  | 
|  383   testThirdParty(test, "0x01ff0101", "0x01ff0102", true, |  | 
|  384                  "different IPv4 hexadecimal address is third-party"); |  | 
|  385   testThirdParty( |  | 
|  386     test, |  | 
|  387     "1.0xff.3.4", "1.0xff.3.4", false, |  | 
|  388     "same IPv4 address with hexadecimal octet isn't third-party" |  | 
|  389   ); |  | 
|  390   testThirdParty( |  | 
|  391     test, |  | 
|  392     "1.0xff.1.1", "2.0xff.1.1", true, |  | 
|  393     "different IPv4 address with hexadecimal octet is third-party" |  | 
|  394   ); |  | 
|  395   testThirdParty( |  | 
|  396     test, |  | 
|  397     "0xff.example.com", "example.com", false, |  | 
|  398     "domain starts like a hexadecimal IPv4 address but isn't one" |  | 
|  399   ); |  | 
|  400   testThirdParty( |  | 
|  401     test, |  | 
|  402     "[2001:db8:85a3::8a2e:370:7334]", "[2001:db8:85a3::8a2e:370:7334]", false, |  | 
|  403     "same IPv6 address isn't third-party" |  | 
|  404   ); |  | 
|  405   testThirdParty( |  | 
|  406     test, |  | 
|  407     "[2001:db8:85a3::8a2e:370:7334]", "[5001:db8:85a3::8a2e:370:7334]", true, |  | 
|  408     "different IPv6 address is third-party" |  | 
|  409   ); |  | 
|  410   testThirdParty( |  | 
|  411     test, |  | 
|  412     "[::ffff:192.0.2.128]", "[::ffff:192.0.2.128]", false, |  | 
|  413     "same IPv4-mapped IPv6 address isn't third-party" |  | 
|  414   ); |  | 
|  415   testThirdParty( |  | 
|  416     test, |  | 
|  417     "[::ffff:192.0.2.128]", "[::ffff:192.1.2.128]", true, |  | 
|  418     "different IPv4-mapped IPv6 address is third-party" |  | 
|  419   ); |  | 
|  420   testThirdParty(test, "xn--f-1gaa.com", "f\u00f6\u00f6.com", false, |  | 
|  421                  "same IDN isn't third-party"); |  | 
|  422   testThirdParty(test, "example.com..", "example.com....", false, |  | 
|  423                  "traling dots are ignored"); |  | 
|  424  |  | 
|  425   test.done(); |  | 
|  426 }; |  | 
|  427  |  | 
|  428 exports.testGetBaseDomain = function(test) |  | 
|  429 { |  | 
|  430   let parts = ["aaa", "bbb", "ccc", "ddd", "eee"]; |  | 
|  431   let levels = 3; |  | 
|  432  |  | 
|  433   for (let suffix in publicSuffixes) |  | 
|  434   { |  | 
|  435     let offset = publicSuffixes[suffix]; |  | 
|  436  |  | 
|  437     // If this fails, add more parts. |  | 
|  438     test.ok(offset <= parts.length - levels, |  | 
|  439             "Not enough domain parts for testing"); |  | 
|  440  |  | 
|  441     for (let i = 0; i < offset + levels; i++) |  | 
|  442     { |  311     { | 
|  443       let hostname = parts.slice(0, i).join("."); |  312       return new URL("http://" + hostname); | 
|  444       hostname += (hostname ? "." : "") + suffix; |  | 
|  445  |  | 
|  446       let expected = parts.slice(Math.max(0, i - offset), i).join("."); |  | 
|  447       expected += (expected ? "." : "") + suffix; |  | 
|  448  |  | 
|  449       test.equal(getBaseDomain(hostname), expected, |  | 
|  450                  `getBaseDomain("${hostname}") == "${expected}"` + |  | 
|  451                  ` with {suffix: "${suffix}", offset: ${offset}}`); |  | 
|  452     } |  313     } | 
|  453   } |  314  | 
|  454  |  315     function testThirdParty(requestHostname, documentHostname, expected, | 
|  455   // Unknown suffixes. |  316                             message) | 
|  456   test.equal(typeof publicSuffixes["localhost"], "undefined"); |  317     { | 
|  457   test.equal(typeof publicSuffixes["localhost.localdomain"], "undefined"); |  318       assert.equal( | 
|  458  |  319         isThirdParty( | 
|  459   test.equal(getBaseDomain("localhost"), "localhost"); |  320           hostnameToURL(requestHostname).hostname, | 
|  460   test.equal(getBaseDomain("localhost.localdomain"), "localhost.localdomain"); |  321  | 
|  461   test.equal( |  322           // Chrome's URL object normalizes IP addresses. So some test | 
|  462     getBaseDomain("mail.localhost.localdomain"), |  323           // will fail if we don't normalize the document host as well. | 
|  463     "localhost.localdomain" |  324           hostnameToURL(documentHostname).hostname | 
|  464   ); |  325         ), | 
|  465   test.equal(getBaseDomain("www.example.localhost.localdomain"), |  326         expected, | 
|  466              "localhost.localdomain"); |  327         message | 
|  467  |  328       ); | 
|  468   // Unknown suffixes that overlap partly with known suffixes. |  329     } | 
|  469   test.equal(typeof publicSuffixes["example.com"], "undefined"); |  330  | 
|  470   test.equal(typeof publicSuffixes["africa.com"], "number"); |  331     testThirdParty("foo", "foo", false, "same domain isn't third-party"); | 
|  471   test.equal(typeof publicSuffixes["compute.amazonaws.com"], "number"); |  332     testThirdParty("foo", "bar", true, "different domain is third-party"); | 
|  472  |  333     testThirdParty("foo.com", "foo.com", false, | 
|  473   test.equal(getBaseDomain("example.com"), "example.com"); |  334                    "same domain with TLD (.com) isn't third-party"); | 
|  474   test.equal(getBaseDomain("mail.example.com"), "example.com"); |  335     testThirdParty("foo.com", "bar.com", true, | 
|  475   test.equal(getBaseDomain("secure.mail.example.com"), "example.com"); |  336                    "same TLD (.com) but different domain is third-party"); | 
|  476  |  337     testThirdParty("foo.com", "www.foo.com", false, | 
|  477   // Cascading offsets. |  338                    "same domain but differend subdomain isn't third-party"); | 
|  478  |  339     testThirdParty("foo.example.com", "bar.example.com", false, | 
|  479   // If these sanity checks fail, look for other examles of cascading offsets |  340                    "same basedomain (example.com) isn't third-party"); | 
|  480   // from the public suffix list. |  341     testThirdParty("foo.uk", "bar.uk", true, | 
|  481   test.equal( |  342                    "same TLD (.uk) but different domain is third-party"); | 
|  482     typeof publicSuffixes[ |  343     testThirdParty("foo.co.uk", "bar.co.uk", true, | 
|  483       "images.example.s3.dualstack.us-east-1.amazonaws.com" |  344                    "same TLD (.co.uk) but different domain is third-party"); | 
|  484     ], |  345     testThirdParty("foo.example.co.uk", "bar.example.co.uk", false, | 
|  485     "undefined" |  346                    "same basedomain (example.co.uk) isn't third-party"); | 
|  486   ); |  347     testThirdParty("1.2.3.4", "1.2.3.4", false, | 
|  487   test.equal( |  348                    "same IPv4 address isn't third-party"); | 
|  488     typeof publicSuffixes["example.s3.dualstack.us-east-1.amazonaws.com"], |  349     testThirdParty("1.1.1.1", "2.1.1.1", true, | 
|  489     "undefined" |  350                    "different IPv4 address is third-party"); | 
|  490   ); |  351     testThirdParty("0x01ff0101", "0x01ff0101", false, | 
|  491   test.equal(publicSuffixes["s3.dualstack.us-east-1.amazonaws.com"], 1); |  352                    "same IPv4 hexadecimal address isn't third-party"); | 
|  492   test.equal(typeof publicSuffixes["dualstack.us-east-1.amazonaws.com"], |  353     testThirdParty("0x01ff0101", "0x01ff0102", true, | 
|  493              "undefined"); |  354                    "different IPv4 hexadecimal address is third-party"); | 
|  494   test.equal(typeof publicSuffixes["example.us-east-1.amazonaws.com"], |  355     testThirdParty( | 
|  495              "undefined"); |  356       "1.0xff.3.4", "1.0xff.3.4", false, | 
|  496   test.equal(publicSuffixes["us-east-1.amazonaws.com"], 1); |  357       "same IPv4 address with hexadecimal octet isn't third-party" | 
|  497   test.equal(typeof publicSuffixes["example.amazonaws.com"], "undefined"); |  358     ); | 
|  498   test.equal(typeof publicSuffixes["amazonaws.com"], "undefined"); |  359     testThirdParty( | 
|  499  |  360       "1.0xff.1.1", "2.0xff.1.1", true, | 
|  500   test.equal( |  361       "different IPv4 address with hexadecimal octet is third-party" | 
|  501     getBaseDomain("images.example.s3.dualstack.us-east-1.amazonaws.com"), |  362     ); | 
|  502     "example.s3.dualstack.us-east-1.amazonaws.com" |  363     testThirdParty( | 
|  503   ); |  364       "0xff.example.com", "example.com", false, | 
|  504   test.equal(getBaseDomain("example.s3.dualstack.us-east-1.amazonaws.com"), |  365       "domain starts like a hexadecimal IPv4 address but isn't one" | 
|  505             "example.s3.dualstack.us-east-1.amazonaws.com"); |  366     ); | 
|  506   test.equal(getBaseDomain("s3.dualstack.us-east-1.amazonaws.com"), |  367     testThirdParty( | 
|  507             "s3.dualstack.us-east-1.amazonaws.com"); |  368       "[2001:db8:85a3::8a2e:370:7334]", "[2001:db8:85a3::8a2e:370:7334]", false, | 
|  508   test.equal(getBaseDomain("dualstack.us-east-1.amazonaws.com"), |  369       "same IPv6 address isn't third-party" | 
|  509             "dualstack.us-east-1.amazonaws.com"); |  370     ); | 
|  510   test.equal(getBaseDomain("example.us-east-1.amazonaws.com"), |  371     testThirdParty( | 
|  511             "example.us-east-1.amazonaws.com"); |  372       "[2001:db8:85a3::8a2e:370:7334]", "[5001:db8:85a3::8a2e:370:7334]", true, | 
|  512   test.equal( |  373       "different IPv6 address is third-party" | 
|  513     getBaseDomain("us-east-1.amazonaws.com"), |  374     ); | 
|  514     "us-east-1.amazonaws.com" |  375     testThirdParty( | 
|  515   ); |  376       "[::ffff:192.0.2.128]", "[::ffff:192.0.2.128]", false, | 
|  516   test.equal(getBaseDomain("example.amazonaws.com"), "amazonaws.com"); |  377       "same IPv4-mapped IPv6 address isn't third-party" | 
|  517   test.equal(getBaseDomain("amazonaws.com"), "amazonaws.com"); |  378     ); | 
|  518  |  379     testThirdParty( | 
|  519   // Edge case. |  380       "[::ffff:192.0.2.128]", "[::ffff:192.1.2.128]", true, | 
|  520   test.equal(getBaseDomain(""), ""); |  381       "different IPv4-mapped IPv6 address is third-party" | 
|  521  |  382     ); | 
|  522   test.done(); |  383     testThirdParty("xn--f-1gaa.com", "f\u00f6\u00f6.com", false, | 
|  523 }; |  384                    "same IDN isn't third-party"); | 
 |  385     testThirdParty("example.com..", "example.com....", false, | 
 |  386                    "traling dots are ignored"); | 
 |  387   }); | 
 |  388  | 
 |  389   it("Get Base Domain", () => | 
 |  390   { | 
 |  391     let parts = ["aaa", "bbb", "ccc", "ddd", "eee"]; | 
 |  392     let levels = 3; | 
 |  393  | 
 |  394     for (let suffix in publicSuffixes) | 
 |  395     { | 
 |  396       let offset = publicSuffixes[suffix]; | 
 |  397  | 
 |  398       // If this fails, add more parts. | 
 |  399       assert.ok(offset <= parts.length - levels, | 
 |  400               "Not enough domain parts for testing"); | 
 |  401  | 
 |  402       for (let i = 0; i < offset + levels; i++) | 
 |  403       { | 
 |  404         let hostname = parts.slice(0, i).join("."); | 
 |  405         hostname += (hostname ? "." : "") + suffix; | 
 |  406  | 
 |  407         let expected = parts.slice(Math.max(0, i - offset), i).join("."); | 
 |  408         expected += (expected ? "." : "") + suffix; | 
 |  409  | 
 |  410         assert.equal(getBaseDomain(hostname), expected, | 
 |  411                    `getBaseDomain("${hostname}") == "${expected}"` + | 
 |  412                    ` with {suffix: "${suffix}", offset: ${offset}}`); | 
 |  413       } | 
 |  414     } | 
 |  415  | 
 |  416     // Unknown suffixes. | 
 |  417     assert.equal(typeof publicSuffixes["localhost"], "undefined"); | 
 |  418     assert.equal(typeof publicSuffixes["localhost.localdomain"], "undefined"); | 
 |  419  | 
 |  420     assert.equal(getBaseDomain("localhost"), "localhost"); | 
 |  421     assert.equal(getBaseDomain("localhost.localdomain"), "localhost.localdomain"
     ); | 
 |  422     assert.equal( | 
 |  423       getBaseDomain("mail.localhost.localdomain"), | 
 |  424       "localhost.localdomain" | 
 |  425     ); | 
 |  426     assert.equal(getBaseDomain("www.example.localhost.localdomain"), | 
 |  427                "localhost.localdomain"); | 
 |  428  | 
 |  429     // Unknown suffixes that overlap partly with known suffixes. | 
 |  430     assert.equal(typeof publicSuffixes["example.com"], "undefined"); | 
 |  431     assert.equal(typeof publicSuffixes["africa.com"], "number"); | 
 |  432     assert.equal(typeof publicSuffixes["compute.amazonaws.com"], "number"); | 
 |  433  | 
 |  434     assert.equal(getBaseDomain("example.com"), "example.com"); | 
 |  435     assert.equal(getBaseDomain("mail.example.com"), "example.com"); | 
 |  436     assert.equal(getBaseDomain("secure.mail.example.com"), "example.com"); | 
 |  437  | 
 |  438     // Cascading offsets. | 
 |  439  | 
 |  440     // If these sanity checks fail, look for other examles of cascading offsets | 
 |  441     // from the public suffix list. | 
 |  442     assert.equal( | 
 |  443       typeof publicSuffixes[ | 
 |  444         "images.example.s3.dualstack.us-east-1.amazonaws.com" | 
 |  445       ], | 
 |  446       "undefined" | 
 |  447     ); | 
 |  448     assert.equal( | 
 |  449       typeof publicSuffixes["example.s3.dualstack.us-east-1.amazonaws.com"], | 
 |  450       "undefined" | 
 |  451     ); | 
 |  452     assert.equal(publicSuffixes["s3.dualstack.us-east-1.amazonaws.com"], 1); | 
 |  453     assert.equal(typeof publicSuffixes["dualstack.us-east-1.amazonaws.com"], | 
 |  454                "undefined"); | 
 |  455     assert.equal(typeof publicSuffixes["example.us-east-1.amazonaws.com"], | 
 |  456                "undefined"); | 
 |  457     assert.equal(publicSuffixes["us-east-1.amazonaws.com"], 1); | 
 |  458     assert.equal(typeof publicSuffixes["example.amazonaws.com"], "undefined"); | 
 |  459     assert.equal(typeof publicSuffixes["amazonaws.com"], "undefined"); | 
 |  460  | 
 |  461     assert.equal( | 
 |  462       getBaseDomain("images.example.s3.dualstack.us-east-1.amazonaws.com"), | 
 |  463       "example.s3.dualstack.us-east-1.amazonaws.com" | 
 |  464     ); | 
 |  465     assert.equal(getBaseDomain("example.s3.dualstack.us-east-1.amazonaws.com"), | 
 |  466                "example.s3.dualstack.us-east-1.amazonaws.com"); | 
 |  467     assert.equal(getBaseDomain("s3.dualstack.us-east-1.amazonaws.com"), | 
 |  468                "s3.dualstack.us-east-1.amazonaws.com"); | 
 |  469     assert.equal(getBaseDomain("dualstack.us-east-1.amazonaws.com"), | 
 |  470                "dualstack.us-east-1.amazonaws.com"); | 
 |  471     assert.equal(getBaseDomain("example.us-east-1.amazonaws.com"), | 
 |  472                "example.us-east-1.amazonaws.com"); | 
 |  473     assert.equal( | 
 |  474       getBaseDomain("us-east-1.amazonaws.com"), | 
 |  475       "us-east-1.amazonaws.com" | 
 |  476     ); | 
 |  477     assert.equal(getBaseDomain("example.amazonaws.com"), "amazonaws.com"); | 
 |  478     assert.equal(getBaseDomain("amazonaws.com"), "amazonaws.com"); | 
 |  479  | 
 |  480     // Edge case. | 
 |  481     assert.equal(getBaseDomain(""), ""); | 
 |  482   }); | 
 |  483 }); | 
 |  484  | 
| OLD | NEW |