| LEFT | RIGHT | 
|    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 {createSandbox} = require("./_common"); |   20 const {createSandbox} = require("./_common"); | 
 |   21 const {withNAD} = require("./_test-utils"); | 
|   21  |   22  | 
|   22 let ElemHideEmulationFilter = null; |   23 let ElemHideEmulationFilter = null; | 
|   23 let ElemHideEmulation = null; |   24 let ElemHideEmulation = null; | 
|   24 let ElemHide = null; |   25 let ElemHide = null; | 
|   25 let Filter = null; |   26 let Filter = null; | 
|   26  |   27  | 
|   27 exports.setUp = function(callback) |   28 exports.setUp = function(callback) | 
|   28 { |   29 { | 
|   29   let sandboxedRequire = createSandbox(); |   30   let sandboxedRequire = createSandbox(); | 
|   30   ( |   31   ( | 
|   31     {Filter, |   32     {Filter, | 
|   32      ElemHideEmulationFilter} = sandboxedRequire("../lib/filterClasses"), |   33      ElemHideEmulationFilter} = sandboxedRequire("../lib/filterClasses"), | 
|   33     {ElemHideEmulation} = sandboxedRequire("../lib/elemHideEmulation"), |   34     {ElemHideEmulation} = sandboxedRequire("../lib/elemHideEmulation"), | 
|   34     {ElemHide} = sandboxedRequire("../lib/elemHide") |   35     {ElemHide} = sandboxedRequire("../lib/elemHide") | 
|   35   ); |   36   ); | 
|   36  |   37  | 
|   37   callback(); |   38   callback(); | 
|   38 }; |   39 }; | 
|   39  |   40  | 
|   40 exports.testElemHideAPI = function(test) |   41 exports.testElemHideAPI = function(test) | 
|   41 { |   42 { | 
 |   43   withNAD(0, elemHide => | 
|   42   { |   44   { | 
|   43     let filter = Filter.fromText("###ads"); |   45     withNAD(0, filter => | 
|   44     ElemHide.add(filter); |   46     { | 
|   45  |   47       elemHide.add(filter); | 
|   46     test.equal(filter.selectorDomain, ""); |   48       test.equal(filter.selectorDomain, ""); | 
|   47     let unconditionals = ElemHide.getUnconditionalSelectors(); |   49     })(Filter.fromText("###ads")); | 
|   48     test.equal(unconditionals.selectorCount, 1); |   50  | 
|   49     test.equal(unconditionals.selectorAt(0), "#ads"); |   51     withNAD(0, unconditionals => | 
|   50     test.equal(unconditionals.filterKeyAt(0), "###ads"); |   52     { | 
|   51     filter.delete(); |   53       test.equal(unconditionals.selectorCount, 1); | 
|   52     unconditionals.delete(); |   54       test.equal(unconditionals.selectorAt(0), "#ads"); | 
|   53   } |   55       test.equal(unconditionals.filterKeyAt(0), "###ads"); | 
|   54  |   56     })(elemHide.getUnconditionalSelectors()); | 
|   55   { |   57  | 
|   56     let filter2 = Filter.fromText("example.com##.foo"); |   58     withNAD(0, filter => | 
|   57     ElemHide.add(filter2); |   59     { | 
|   58     test.equal(filter2.selectorDomain, "example.com"); |   60       elemHide.add(filter); | 
|   59     filter2.delete(); |   61       test.equal(filter.selectorDomain, "example.com"); | 
|   60   } |   62     })(Filter.fromText("example.com##.foo")); | 
|   61  |   63  | 
|   62   let unconditionals = ElemHide.getUnconditionalSelectors(); |   64     withNAD( | 
|   63   test.equal(unconditionals.selectorCount, 1); |   65       0, unconditionals => | 
|   64   unconditionals.delete(); |   66         test.equal(unconditionals.selectorCount, 1))(elemHide.getUnconditionalSe
     lectors()); | 
|   65  |   67  | 
|   66   let selectors = ElemHide.getSelectorsForDomain("example.com", 1); |   68     withNAD(0, selectors => | 
|   67   test.equal(selectors.selectorCount, 1); |   69     { | 
|   68   test.equal(selectors.selectorAt(0), ".foo"); |   70       test.equal(selectors.selectorCount, 1); | 
|   69   test.equal(selectors.filterKeyAt(0), "example.com##.foo"); |   71       test.equal(selectors.selectorAt(0), ".foo"); | 
|   70   selectors.delete(); |   72       test.equal(selectors.filterKeyAt(0), "example.com##.foo"); | 
|   71  |   73     })(elemHide.getSelectorsForDomain("example.com", 1)); | 
|   72   selectors = ElemHide.getSelectorsForDomain("example.com", 0); |   74  | 
|   73   test.equal(selectors.selectorCount, 2); |   75     withNAD(0, selectors => | 
|   74   test.equal(selectors.selectorAt(0), "#ads"); |   76     { | 
|   75   test.equal(selectors.filterKeyAt(0), "###ads"); |   77       test.equal(selectors.selectorCount, 2); | 
|   76   test.equal(selectors.selectorAt(1), ".foo"); |   78       test.equal(selectors.selectorAt(0), "#ads"); | 
|   77   test.equal(selectors.filterKeyAt(1), "example.com##.foo"); |   79       test.equal(selectors.filterKeyAt(0), "###ads"); | 
|   78   selectors.delete(); |   80       test.equal(selectors.selectorAt(1), ".foo"); | 
|   79  |   81       test.equal(selectors.filterKeyAt(1), "example.com##.foo"); | 
|   80   let filter3 = Filter.fromText("example.com##.message"); |   82     })(elemHide.getSelectorsForDomain("example.com", 0)); | 
|   81   ElemHide.add(filter3); |   83  | 
|   82   selectors = ElemHide.getSelectorsForDomain("example.com", 0); |   84     withNAD(0, filter3 => | 
|   83   test.equal(selectors.selectorCount, 3); |   85     { | 
|   84   selectors.delete(); |   86       elemHide.add(filter3); | 
|   85   selectors = ElemHide.getSelectorsForDomain("mail.example.com", 0); |   87  | 
|   86   test.equal(selectors.selectorCount, 3); |   88       withNAD( | 
|   87   selectors.delete(); |   89         0, selectors => | 
|   88  |   90         { | 
|   89   let filter4 = Filter.fromText("mail.example.com#@#.message"); |   91           test.equal(selectors.selectorCount, 3); | 
|   90   ElemHide.add(filter4); |   92           test.equal(selectors.selectorAt(0), "#ads"); | 
|   91   selectors = ElemHide.getSelectorsForDomain("example.com", 0); |   93           test.equal(selectors.selectorAt(1), ".message"); | 
|   92   test.equal(selectors.selectorCount, 3); |   94           test.equal(selectors.selectorAt(2), ".foo"); | 
|   93   selectors.delete(); |   95         })( | 
|   94   selectors = ElemHide.getSelectorsForDomain("mail.example.com", 0); |   96         elemHide.getSelectorsForDomain("example.com", 0)); | 
|   95   test.equal(selectors.selectorCount, 2); |   97  | 
|   96   selectors.delete(); |   98       withNAD( | 
|   97  |   99         0, selectors => | 
|   98   unconditionals = ElemHide.getUnconditionalSelectors(); |  100         { | 
|   99   test.equal(unconditionals.selectorCount, 1); |  101           test.equal(selectors.selectorCount, 3); | 
|  100   unconditionals.delete(); |  102           test.equal(selectors.selectorAt(0), "#ads"); | 
|  101  |  103           test.equal(selectors.selectorAt(1), ".message"); | 
|  102   ElemHide.remove(filter4); |  104           test.equal(selectors.selectorAt(2), ".foo"); | 
|  103   filter4.delete(); |  105         })( | 
|  104   selectors = ElemHide.getSelectorsForDomain("example.com", 0); |  106         elemHide.getSelectorsForDomain("mail.example.com", 0)); | 
|  105   test.equal(selectors.selectorCount, 3); |  107  | 
|  106   selectors.delete(); |  108       withNAD(0, filter4 => | 
|  107   selectors = ElemHide.getSelectorsForDomain("mail.example.com", 0); |  109       { | 
|  108   test.equal(selectors.selectorCount, 3); |  110         elemHide.add(filter4); | 
|  109   selectors.delete(); |  111         withNAD( | 
|  110  |  112           0, selectors => | 
|  111   ElemHide.remove(filter3); |  113           { | 
|  112   filter3.delete(); |  114             test.equal(selectors.selectorCount, 3); | 
|  113   selectors = ElemHide.getSelectorsForDomain("example.com", 0); |  115             test.equal(selectors.selectorAt(0), "#ads"); | 
|  114   test.equal(selectors.selectorCount, 2); |  116             test.equal(selectors.selectorAt(1), ".message"); | 
|  115   selectors.delete(); |  117             test.equal(selectors.selectorAt(2), ".foo"); | 
 |  118           })( | 
 |  119           elemHide.getSelectorsForDomain("example.com", 0)); | 
 |  120  | 
 |  121         withNAD( | 
 |  122           0, selectors => | 
 |  123           { | 
 |  124             test.equal(selectors.selectorCount, 2); | 
 |  125             test.equal(selectors.selectorAt(0), "#ads"); | 
 |  126             test.equal(selectors.selectorAt(1), ".foo"); | 
 |  127           })( | 
 |  128           elemHide.getSelectorsForDomain("mail.example.com", 0)); | 
 |  129  | 
 |  130         withNAD( | 
 |  131           0, | 
 |  132           unconditionals => | 
 |  133           { | 
 |  134             test.equal(unconditionals.selectorCount, 1); | 
 |  135             test.equal(unconditionals.selectorAt(0), "#ads"); | 
 |  136           })(elemHide.getUnconditionalSelectors()); | 
 |  137  | 
 |  138         elemHide.remove(filter4); | 
 |  139       })(Filter.fromText("mail.example.com#@#.message")); | 
 |  140  | 
 |  141       withNAD( | 
 |  142         0, selectors => | 
 |  143         { | 
 |  144           test.equal(selectors.selectorCount, 3); | 
 |  145           test.equal(selectors.selectorAt(0), "#ads"); | 
 |  146           test.equal(selectors.selectorAt(1), ".message"); | 
 |  147           test.equal(selectors.selectorAt(2), ".foo"); | 
 |  148         })(elemHide.getSelectorsForDomain("example.com", 0)); | 
 |  149  | 
 |  150       withNAD( | 
 |  151         0, selectors => | 
 |  152         { | 
 |  153           test.equal(selectors.selectorCount, 3); | 
 |  154           test.equal(selectors.selectorAt(0), "#ads"); | 
 |  155           test.equal(selectors.selectorAt(1), ".message"); | 
 |  156           test.equal(selectors.selectorAt(2), ".foo"); | 
 |  157         })(elemHide.getSelectorsForDomain("mail.example.com", 0)); | 
 |  158  | 
 |  159       elemHide.remove(filter3); | 
 |  160     })(Filter.fromText("example.com##.message")); | 
 |  161  | 
 |  162     withNAD( | 
 |  163       0, selectors => | 
 |  164         test.equal(selectors.selectorCount, 2))( | 
 |  165       elemHide.getSelectorsForDomain("example.com", 0)); | 
 |  166   })(ElemHide.create()); | 
|  116  |  167  | 
|  117   test.done(); |  168   test.done(); | 
|  118 }; |  169 }; | 
|  119  |  170  | 
|  120 exports.testSyntaxConversion = function(test) |  171 exports.testSyntaxConversion = function(test) | 
|  121 { |  172 { | 
|  122   function checkConvertedFilter(old, converted) |  173   function checkConvertedFilter(old, converted) | 
|  123   { |  174   { | 
|  124     let filter = Filter.fromText(old); |  175     withNAD( | 
|  125  |  176       0, filter => test.equal(filter.text, converted))(Filter.fromText(old)); | 
|  126     test.equal(filter.text, converted); |  | 
|  127   } |  177   } | 
|  128  |  178  | 
|  129   checkConvertedFilter("example.com#?#foo[-abp-properties='something']bar", "exa
     mple.com#?#foo:-abp-properties(something)bar"); |  179   checkConvertedFilter("example.com##foo[-abp-properties='something']bar", "exam
     ple.com#?#foo:-abp-properties(something)bar"); | 
|  130   checkConvertedFilter("example.com#@#foo[-abp-properties='something']bar", "exa
     mple.com#@#foo:-abp-properties(something)bar"); |  180   checkConvertedFilter("example.com#@#foo[-abp-properties='something']bar", "exa
     mple.com#@#foo:-abp-properties(something)bar"); | 
|  131   checkConvertedFilter("example.com#?#[-abp-properties=\"something\"]", "example
     .com#?#:-abp-properties(something)"); |  181   checkConvertedFilter("example.com##[-abp-properties=\"something\"]", "example.
     com#?#:-abp-properties(something)"); | 
|  132   checkConvertedFilter("example.com#?#[-abp-properties=(something)]", "example.c
     om#?#:-abp-properties((something))"); |  182   checkConvertedFilter("example.com##[-abp-properties='(something)']", "example.
     com#?#:-abp-properties((something))"); | 
|  133  |  183  | 
|  134   test.done(); |  184   test.done(); | 
|  135 }; |  185 }; | 
|  136  |  186  | 
|  137 exports.testDomainRestrictions = function(test) |  187 exports.testDomainRestrictions = function(test) | 
|  138 { |  188 { | 
|  139   function testSelectorMatches(description, filters, domain, expectedMatches) |  189   function testSelectorMatches(description, filters, domain, expectedMatches) | 
|  140   { |  190   { | 
|  141     for (let text of filters) |  191     withNAD([0, 1], (elemHide, elemHideEmulation) => | 
|  142     { |  192     { | 
|  143       let filter = Filter.fromText(text); |  193       let addFilter = withNAD(0, filter => | 
|  144       if (filter instanceof ElemHideEmulationFilter) |  194       { | 
|  145         ElemHideEmulation.add(filter); |  195         if (filter instanceof ElemHideEmulationFilter) | 
|  146       else |  196           elemHideEmulation.add(filter); | 
|  147         ElemHide.add(filter); |  197         else | 
|  148       filter.delete(); |  198           elemHide.add(filter); | 
|  149     } |  199       }); | 
|  150  |  200  | 
|  151     let rules = ElemHideEmulation.getRulesForDomain(domain); |  201       for (let text of filters) | 
|  152     let matches = []; |  202         addFilter(Filter.fromText(text)); | 
|  153     for (let i = 0; i < rules.filterCount; i++) |  203  | 
|  154     { |  204       withNAD(0, rules => | 
|  155       let filter = rules.filterAt(i); |  205       { | 
|  156       matches.push(filter.text); |  206         let matches = []; | 
|  157       filter.delete(); |  207         let push = withNAD(0, filter => matches.push(filter.text)); | 
|  158     } |  208  | 
|  159     test.deepEqual(matches.sort(), expectedMatches.sort(), description); |  209         for (let i = 0; i < rules.filterCount; i++) | 
|  160     rules.delete(); |  210           push(rules.filterAt(i)); | 
|  161  |  211  | 
|  162     ElemHideEmulation.clear(); |  212         test.deepEqual(matches.sort(), expectedMatches.sort(), description); | 
|  163     ElemHide.clear(); |  213       })(elemHideEmulation.getRulesForDomain(elemHide, domain)); | 
 |  214  | 
 |  215       elemHideEmulation.clear(); | 
 |  216     })(ElemHide.create(), ElemHideEmulation.create()); | 
|  164   } |  217   } | 
|  165  |  218  | 
|  166   testSelectorMatches( |  219   testSelectorMatches( | 
|  167     "Ignore generic filters", |  220     "Ignore generic filters", | 
|  168     [ |  221     [ | 
|  169       "#?#:-abp-properties(foo)", "example.com#?#:-abp-properties(foo)", |  222       "#?#:-abp-properties(foo)", "example.com#?#:-abp-properties(foo)", | 
|  170       "~example.com##:-abp-properties(foo)" |  223       "~example.com##:-abp-properties(foo)" | 
|  171     ], |  224     ], | 
|  172     "example.com", |  225     "example.com", | 
|  173     ["example.com#?#:-abp-properties(foo)"] |  226     ["example.com#?#:-abp-properties(foo)"] | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  207     ], |  260     ], | 
|  208     "other.example.com", |  261     "other.example.com", | 
|  209     ["other.example.com#?#:-abp-properties(foo)"] |  262     ["other.example.com#?#:-abp-properties(foo)"] | 
|  210   ); |  263   ); | 
|  211  |  264  | 
|  212   test.done(); |  265   test.done(); | 
|  213 }; |  266 }; | 
|  214  |  267  | 
|  215 exports.testElemHideEmulationFiltersContainer = function(test) |  268 exports.testElemHideEmulationFiltersContainer = function(test) | 
|  216 { |  269 { | 
|  217   function compareRules(description, domain, expectedMatches) |  270   withNAD([0, 1], (elemHide, elemHideEmulation) => | 
|  218   { |  271   { | 
|  219     let rules = ElemHideEmulation.getRulesForDomain(domain); |  272     function compareRules(description, domain, expectedMatches) | 
|  220     let result = []; |  273     { | 
|  221     for (let i = 0; i < rules.filterCount; i++) |  274       withNAD(0, rules => | 
|  222     { |  275       { | 
|  223       let filter = rules.filterAt(i); |  276         let result = []; | 
|  224       result.push(filter.text); |  277         for (let i = 0; i < rules.filterCount; i++) | 
|  225       filter.delete(); |  278           withNAD(0, filter => result.push(filter.text))(rules.filterAt(i)); | 
 |  279  | 
 |  280         expectedMatches = expectedMatches.map(filter => filter.text); | 
 |  281         test.deepEqual(result.sort(), expectedMatches.sort(), description); | 
 |  282       })(elemHideEmulation.getRulesForDomain(elemHide, domain)); | 
|  226     } |  283     } | 
|  227     expectedMatches = expectedMatches.map(filter => filter.text); |  284  | 
|  228     test.deepEqual(result.sort(), expectedMatches.sort(), description); |  285     withNAD([0, 1, 2], (domainFilter, subdomainFilter, otherDomainFilter) => | 
|  229  |  286     { | 
|  230     rules.delete(); |  287       elemHideEmulation.add(domainFilter); | 
|  231   } |  288       elemHideEmulation.add(subdomainFilter); | 
|  232  |  289       elemHideEmulation.add(otherDomainFilter); | 
|  233   let domainFilter = Filter.fromText("example.com##filter1"); |  290       compareRules( | 
|  234   let subdomainFilter = Filter.fromText("www.example.com##filter2"); |  291         "Return all matching filters", | 
|  235   let otherDomainFilter = Filter.fromText("other.example.com##filter3"); |  292         "www.example.com", | 
|  236  |  293         [domainFilter, subdomainFilter] | 
|  237   ElemHideEmulation.add(domainFilter); |  294       ); | 
|  238   ElemHideEmulation.add(subdomainFilter); |  295  | 
|  239   ElemHideEmulation.add(otherDomainFilter); |  296       elemHideEmulation.remove(domainFilter); | 
|  240   compareRules( |  297       compareRules( | 
|  241     "Return all matching filters", |  298         "Return all matching filters after removing one", | 
|  242     "www.example.com", |  299         "www.example.com", | 
|  243     [domainFilter, subdomainFilter] |  300         [subdomainFilter] | 
|  244   ); |  301       ); | 
|  245  |  302  | 
|  246   ElemHideEmulation.remove(domainFilter); |  303       elemHideEmulation.clear(); | 
|  247   compareRules( |  304       compareRules( | 
|  248     "Return all matching filters after removing one", |  305         "Return no filters after clearing", | 
|  249     "www.example.com", |  306         "www.example.com", | 
|  250     [subdomainFilter] |  307         [] | 
|  251   ); |  308       ); | 
|  252  |  309     })(Filter.fromText("example.com##filter1"), | 
|  253   ElemHideEmulation.clear(); |  310        Filter.fromText("www.example.com##filter2"), | 
|  254   compareRules( |  311        Filter.fromText("other.example.com##filter3")); | 
|  255     "Return no filters after clearing", |  312   })(ElemHide.create(), ElemHideEmulation.create()); | 
|  256     "www.example.com", |  | 
|  257     [] |  | 
|  258   ); |  | 
|  259  |  313  | 
|  260   test.done(); |  314   test.done(); | 
|  261 }; |  315 }; | 
| LEFT | RIGHT |