| OLD | NEW | 
| (Empty) |  | 
 |    1 /* | 
 |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
 |    3  * Copyright (C) 2006-present eyeo GmbH | 
 |    4  * | 
 |    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 | 
 |    7  * published by the Free Software Foundation. | 
 |    8  * | 
 |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
 |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |   12  * GNU General Public License for more details. | 
 |   13  * | 
 |   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/>. | 
 |   16  */ | 
 |   17  | 
 |   18 "use strict"; | 
 |   19  | 
 |   20 let { | 
 |   21   createSandbox, setupTimerAndXMLHttp, setupRandomResult, unexpectedError, Cr, | 
 |   22   MILLIS_IN_SECOND, MILLIS_IN_HOUR | 
 |   23 } = require("./_common"); | 
 |   24  | 
 |   25 let Filter = null; | 
 |   26 let FilterStorage = null; | 
 |   27 let Prefs = null; | 
 |   28 let Subscription = null; | 
 |   29  | 
 |   30 exports.setUp = function(callback) | 
 |   31 { | 
 |   32   let globals = Object.assign({}, setupTimerAndXMLHttp.call(this), | 
 |   33     setupRandomResult.call(this)); | 
 |   34  | 
 |   35   let sandboxedRequire = createSandbox({globals}); | 
 |   36   ( | 
 |   37     {Filter} = sandboxedRequire("../lib/filterClasses"), | 
 |   38     {FilterStorage} = sandboxedRequire("../lib/filterStorage"), | 
 |   39     {Prefs} = sandboxedRequire("./stub-modules/prefs"), | 
 |   40     {Subscription} = sandboxedRequire("../lib/subscriptionClasses"), | 
 |   41     sandboxedRequire("../lib/synchronizer") | 
 |   42   ); | 
 |   43  | 
 |   44   callback(); | 
 |   45 }; | 
 |   46  | 
 |   47 function resetSubscription(subscription) | 
 |   48 { | 
 |   49   FilterStorage.clearSubscriptionFilters(subscription); | 
 |   50   subscription.lastCheck = subscription.lastDownload = | 
 |   51     subscription.version = subscription.lastSuccess = | 
 |   52     subscription.expires = subscription.softExpiration = 0; | 
 |   53   subscription.title = ""; | 
 |   54   subscription.homepage = null; | 
 |   55   subscription.errors = 0; | 
 |   56   subscription.downloadStatus = null; | 
 |   57   subscription.requiredVersion = null; | 
 |   58 } | 
 |   59  | 
 |   60 function testFiltersEqual(test, subscription, expected, message) | 
 |   61 { | 
 |   62   test.deepEqual( | 
 |   63     Array.from(subscription.filters, filter => filter.text), | 
 |   64     expected.map(filter => filter.text)); | 
 |   65 } | 
 |   66  | 
 |   67 function testSubscriptionEqual(test, sub1, sub2, message) | 
 |   68 { | 
 |   69   test.equal(sub1.fixedTitle, sub2.fixedTitle, message); | 
 |   70   test.equal(sub1.homepage, sub2.homepage, message); | 
 |   71 } | 
 |   72  | 
 |   73 let initialDelay = 1 / 60; | 
 |   74  | 
 |   75 exports.testOneSubscriptionDownloads = function(test) | 
 |   76 { | 
 |   77   let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |   78   FilterStorage.addSubscription(subscription); | 
 |   79  | 
 |   80   let requests = []; | 
 |   81   this.registerHandler("/subscription", metadata => | 
 |   82   { | 
 |   83     requests.push([this.getTimeOffset(), metadata.method, metadata.path]); | 
 |   84     return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; | 
 |   85   }); | 
 |   86  | 
 |   87   this.runScheduledTasks(50).then(() => | 
 |   88   { | 
 |   89     test.deepEqual(requests, [ | 
 |   90       [0 + initialDelay, "GET", "/subscription"], | 
 |   91       [24 + initialDelay, "GET", "/subscription"], | 
 |   92       [48 + initialDelay, "GET", "/subscription"] | 
 |   93     ], "Requests after 50 hours"); | 
 |   94   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |   95 }; | 
 |   96  | 
 |   97 exports.testTwoSubscriptionsDownloads = function(test) | 
 |   98 { | 
 |   99   let subscription1 = Subscription.fromURL("http://example.com/subscription1"); | 
 |  100   FilterStorage.addSubscription(subscription1); | 
 |  101  | 
 |  102   let subscription2 = Subscription.fromURL("http://example.com/subscription2"); | 
 |  103   subscription2.expires = | 
 |  104     subscription2.softExpiration = | 
 |  105     (this.currentTime + 2 * MILLIS_IN_HOUR) / MILLIS_IN_SECOND; | 
 |  106   FilterStorage.addSubscription(subscription2); | 
 |  107  | 
 |  108   let requests = []; | 
 |  109   let handler = metadata => | 
 |  110   { | 
 |  111     requests.push([this.getTimeOffset(), metadata.method, metadata.path]); | 
 |  112     return [Cr.NS_OK, 200, "[Adblock]\n! ExPiREs: 1day\nfoo\nbar"]; | 
 |  113   }; | 
 |  114  | 
 |  115   this.registerHandler("/subscription1", handler); | 
 |  116   this.registerHandler("/subscription2", handler); | 
 |  117  | 
 |  118   this.runScheduledTasks(55).then(() => | 
 |  119   { | 
 |  120     test.deepEqual(requests, [ | 
 |  121       [0 + initialDelay, "GET", "/subscription1"], | 
 |  122       [2 + initialDelay, "GET", "/subscription2"], | 
 |  123       [24 + initialDelay, "GET", "/subscription1"], | 
 |  124       [26 + initialDelay, "GET", "/subscription2"], | 
 |  125       [48 + initialDelay, "GET", "/subscription1"], | 
 |  126       [50 + initialDelay, "GET", "/subscription2"] | 
 |  127     ], "Requests after 55 hours"); | 
 |  128   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  129 }; | 
 |  130  | 
 |  131 exports.testSubscriptionHeaders = {}; | 
 |  132  | 
 |  133 for (let currentTest of [ | 
 |  134   {header: "[Adblock]", downloadStatus: "synchronize_ok", requiredVersion: ""}, | 
 |  135   {header: "[Adblock Plus]", downloadStatus: "synchronize_ok", requiredVersion: 
     ""}, | 
 |  136   {header: "(something)[Adblock]", downloadStatus: "synchronize_ok", requiredVer
     sion: ""}, | 
 |  137   {header: "[Adblock Plus 0.0.1]", downloadStatus: "synchronize_ok", requiredVer
     sion: "0.0.1"}, | 
 |  138   {header: "[Adblock Plus 99.9]", downloadStatus: "synchronize_ok", requiredVers
     ion: "99.9"}, | 
 |  139   {header: "[Foo]", downloadStatus: "synchronize_invalid_data", requiredVersion:
      ""} | 
 |  140 ]) | 
 |  141 { | 
 |  142   exports.testSubscriptionHeaders[currentTest.header] = function(test) | 
 |  143   { | 
 |  144     let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  145     FilterStorage.addSubscription(subscription); | 
 |  146  | 
 |  147     this.registerHandler("/subscription", metadata => | 
 |  148     { | 
 |  149       return [Cr.NS_OK, 200, currentTest.header + "\n!Expires: 8 hours\nfoo\n!ba
     r\n\n@@bas\n#bam"]; | 
 |  150     }); | 
 |  151  | 
 |  152     this.runScheduledTasks(2).then(() => | 
 |  153     { | 
 |  154       test.equal(subscription.downloadStatus, currentTest.downloadStatus, "Downl
     oad status"); | 
 |  155       test.equal(subscription.requiredVersion, currentTest.requiredVersion, "Req
     uired version"); | 
 |  156  | 
 |  157       if (currentTest.downloadStatus == "synchronize_ok") | 
 |  158       { | 
 |  159         testFiltersEqual(test, subscription, [ | 
 |  160           Filter.fromText("foo"), | 
 |  161           Filter.fromText("!bar"), | 
 |  162           Filter.fromText("@@bas"), | 
 |  163           Filter.fromText("#bam") | 
 |  164         ], "Resulting subscription filters"); | 
 |  165       } | 
 |  166       else | 
 |  167       { | 
 |  168         testFiltersEqual(test, subscription, [], | 
 |  169                          "Resulting subscription filters"); | 
 |  170       } | 
 |  171     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  172   }; | 
 |  173 } | 
 |  174  | 
 |  175 exports.testsDisabledUpdates = function(test) | 
 |  176 { | 
 |  177   Prefs.subscriptions_autoupdate = false; | 
 |  178  | 
 |  179   let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  180   FilterStorage.addSubscription(subscription); | 
 |  181  | 
 |  182   let requests = 0; | 
 |  183   this.registerHandler("/subscription", metadata => | 
 |  184   { | 
 |  185     requests++; | 
 |  186     throw new Error("Unexpected request"); | 
 |  187   }); | 
 |  188  | 
 |  189   this.runScheduledTasks(50).then(() => | 
 |  190   { | 
 |  191     test.equal(requests, 0, "Request count"); | 
 |  192   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  193 }; | 
 |  194  | 
 |  195 exports.testExpirationTime = {}; | 
 |  196  | 
 |  197 for (let currentTest of [ | 
 |  198   { | 
 |  199     expiration: "default", | 
 |  200     randomResult: 0.5, | 
 |  201     requests: [0 + initialDelay, 5 * 24 + initialDelay] | 
 |  202   }, | 
 |  203   { | 
 |  204     expiration: "1 hours",  // Minimal expiration interval | 
 |  205     randomResult: 0.5, | 
 |  206     requests: [0 + initialDelay, 1 + initialDelay, 2 + initialDelay, 3 + initial
     Delay] | 
 |  207   }, | 
 |  208   { | 
 |  209     expiration: "26 hours", | 
 |  210     randomResult: 0.5, | 
 |  211     requests: [0 + initialDelay, 26 + initialDelay] | 
 |  212   }, | 
 |  213   { | 
 |  214     expiration: "2 days", | 
 |  215     randomResult: 0.5, | 
 |  216     requests: [0 + initialDelay, 48 + initialDelay] | 
 |  217   }, | 
 |  218   { | 
 |  219     expiration: "20 days",  // Too large, will be corrected | 
 |  220     randomResult: 0.5, | 
 |  221     requests: [0 + initialDelay, 14 * 24 + initialDelay] | 
 |  222   }, | 
 |  223   { | 
 |  224     expiration: "35 hours", | 
 |  225     randomResult: 0,        // Changes interval by factor 0.8 | 
 |  226     requests: [0 + initialDelay, 28 + initialDelay] | 
 |  227   }, | 
 |  228   { | 
 |  229     expiration: "35 hours", | 
 |  230     randomResult: 1,        // Changes interval by factor 1.2 | 
 |  231     requests: [0 + initialDelay, 42 + initialDelay] | 
 |  232   }, | 
 |  233   { | 
 |  234     expiration: "35 hours", | 
 |  235     randomResult: 0.25,     // Changes interval by factor 0.9 | 
 |  236     requests: [0 + initialDelay, 32 + initialDelay] | 
 |  237   }, | 
 |  238   { | 
 |  239     expiration: "40 hours", | 
 |  240     randomResult: 0.5, | 
 |  241     skipAfter: 5 + initialDelay, | 
 |  242     skip: 10,               // Short break should not increase soft expiration | 
 |  243     requests: [0 + initialDelay, 40 + initialDelay] | 
 |  244   }, | 
 |  245   { | 
 |  246     expiration: "40 hours", | 
 |  247     randomResult: 0.5, | 
 |  248     skipAfter: 5 + initialDelay, | 
 |  249     skip: 30,               // Long break should increase soft expiration | 
 |  250     requests: [0 + initialDelay, 70 + initialDelay] | 
 |  251   }, | 
 |  252   { | 
 |  253     expiration: "40 hours", | 
 |  254     randomResult: 0.5, | 
 |  255     skipAfter: 5 + initialDelay, | 
 |  256     skip: 80,               // Hitting hard expiration, immediate download | 
 |  257     requests: [0 + initialDelay, 85 + initialDelay] | 
 |  258   } | 
 |  259 ]) | 
 |  260 { | 
 |  261   let testId = `"${currentTest.expiration}"`; | 
 |  262   if (currentTest.randomResult != 0.5) | 
 |  263     testId += " with Math.random() returning " + currentTest.randomResult; | 
 |  264   if (currentTest.skip) | 
 |  265     testId += " skipping " + currentTest.skip + " hours after " + currentTest.sk
     ipAfter + " hours"; | 
 |  266   exports.testExpirationTime[testId] = function(test) | 
 |  267   { | 
 |  268     let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  269     FilterStorage.addSubscription(subscription); | 
 |  270  | 
 |  271     let requests = []; | 
 |  272     this.registerHandler("/subscription", metadata => | 
 |  273     { | 
 |  274       requests.push(this.getTimeOffset()); | 
 |  275       return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Expires: " + currentTest.expirati
     on + "\nbar"]; | 
 |  276     }); | 
 |  277  | 
 |  278     this.randomResult = currentTest.randomResult; | 
 |  279  | 
 |  280     let maxHours = Math.round(Math.max.apply(null, currentTest.requests)) + 1; | 
 |  281     this.runScheduledTasks(maxHours, currentTest.skipAfter, currentTest.skip).th
     en(() => | 
 |  282     { | 
 |  283       test.deepEqual(requests, currentTest.requests, "Requests"); | 
 |  284     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  285   }; | 
 |  286 } | 
 |  287  | 
 |  288 exports.testChecksumVerification = {}; | 
 |  289  | 
 |  290 for (let [testName, subscriptionBody, expectedResult] of [ | 
 |  291   ["Correct checksum", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\nfoo\nbar\
     n", true], | 
 |  292   ["Wrong checksum", "[Adblock]\n! Checksum: wrongggny6Fn24b7JHsq/A\nfoo\nbar\n"
     , false], | 
 |  293   ["Empty lines ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq/A\n\nfoo\
     n\nbar\n\n", true], | 
 |  294   ["CR LF line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7
     JHsq/A\nfoo\r\nbar\r\n", true], | 
 |  295   ["CR line breaks treated like LR", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHs
     q/A\nfoo\rbar\r", true], | 
 |  296   ["Trailing line break not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JH
     sq/A\nfoo\nbar", false], | 
 |  297   ["Line breaks between lines not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn
     24b7JHsq/A\nfoobar", false], | 
 |  298   ["Lines with spaces not ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn24b7JHsq
     /A\n \nfoo\n\nbar\n", false], | 
 |  299   ["Extra content in checksum line is part of the checksum", "[Adblock]\n! Check
     sum: e/JCmqXny6Fn24b7JHsq/A foobar\nfoo\nbar\n", false], | 
 |  300   ["= symbols after checksum are ignored", "[Adblock]\n! Checksum: e/JCmqXny6Fn2
     4b7JHsq/A==\nfoo\nbar\n", true], | 
 |  301   ["Header line is part of the checksum", "[Adblock Plus]\n! Checksum: e/JCmqXny
     6Fn24b7JHsq/A\nfoo\nbar\n", false], | 
 |  302   ["Special comments are part of the checksum", "[Adblock]\n! Checksum: e/JCmqXn
     y6Fn24b7JHsq/A\n! Expires: 1\nfoo\nbar\n", false] | 
 |  303 ]) | 
 |  304 { | 
 |  305   exports.testChecksumVerification[testName] = function(test) | 
 |  306   { | 
 |  307     let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  308     FilterStorage.addSubscription(subscription); | 
 |  309  | 
 |  310     this.registerHandler("/subscription", metadata => | 
 |  311     { | 
 |  312       return [Cr.NS_OK, 200, subscriptionBody]; | 
 |  313     }); | 
 |  314  | 
 |  315     this.runScheduledTasks(2).then(() => | 
 |  316     { | 
 |  317       test.equal(subscription.downloadStatus, expectedResult ? "synchronize_ok" 
     : "synchronize_checksum_mismatch"); | 
 |  318     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  319   }; | 
 |  320 } | 
 |  321  | 
 |  322 exports.testSpecialComments = {}; | 
 |  323  | 
 |  324 for (let [comment, check] of [ | 
 |  325   ["! Homepage: http://example.com/", (test, subscription) => | 
 |  326   { | 
 |  327     test.equal(subscription.homepage, "http://example.com/", "Valid homepage com
     ment"); | 
 |  328   }], | 
 |  329   ["! Homepage: ssh://example.com/", (test, subscription) => | 
 |  330   { | 
 |  331     test.equal(subscription.homepage, "", "Invalid homepage comment"); | 
 |  332   }], | 
 |  333   ["! Title: foo", (test, subscription) => | 
 |  334   { | 
 |  335     test.equal(subscription.title, "foo", "Title comment"); | 
 |  336     test.equal(subscription.fixedTitle, true, "Fixed title"); | 
 |  337   }], | 
 |  338   ["! Version: 1234", (test, subscription) => | 
 |  339   { | 
 |  340     test.equal(subscription.version, 1234, "Version comment"); | 
 |  341   }] | 
 |  342 ]) | 
 |  343 { | 
 |  344   exports.testSpecialComments[comment] = function(test) | 
 |  345   { | 
 |  346     let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  347     FilterStorage.addSubscription(subscription); | 
 |  348  | 
 |  349     this.registerHandler("/subscription", metadata => | 
 |  350     { | 
 |  351       return [Cr.NS_OK, 200, "[Adblock]\n" + comment + "\nfoo\nbar"]; | 
 |  352     }); | 
 |  353  | 
 |  354     this.runScheduledTasks(2).then(() => | 
 |  355     { | 
 |  356       check(test, subscription); | 
 |  357       testFiltersEqual(test, subscription, [Filter.fromText("foo"), Filter.fromT
     ext("bar")], "Special comment not added to filters"); | 
 |  358     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  359   }; | 
 |  360 } | 
 |  361  | 
 |  362 exports.testRedirects = function(test) | 
 |  363 { | 
 |  364   let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  365   FilterStorage.addSubscription(subscription); | 
 |  366  | 
 |  367   this.registerHandler("/subscription", metadata => | 
 |  368   { | 
 |  369     return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/redire
     cted\nbar"]; | 
 |  370   }); | 
 |  371  | 
 |  372   let requests; | 
 |  373  | 
 |  374   this.runScheduledTasks(30).then(() => | 
 |  375   { | 
 |  376     testSubscriptionEqual(test, FilterStorage.subscriptionAt(0), subscription, "
     Invalid redirect ignored"); | 
 |  377     test.equal(subscription.downloadStatus, "synchronize_connection_error", "Con
     nection error recorded"); | 
 |  378     test.equal(subscription.errors, 2, "Number of download errors"); | 
 |  379  | 
 |  380     requests = []; | 
 |  381  | 
 |  382     this.registerHandler("/redirected", metadata => | 
 |  383     { | 
 |  384       requests.push(this.getTimeOffset()); | 
 |  385       return [Cr.NS_OK, 200, "[Adblock]\nfoo\n! Expires: 8 hours\nbar"]; | 
 |  386     }); | 
 |  387  | 
 |  388     resetSubscription(subscription); | 
 |  389     return this.runScheduledTasks(15); | 
 |  390   }).then(() => | 
 |  391   { | 
 |  392     test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
     ed", "Redirect followed"); | 
 |  393     test.deepEqual(requests, [0 + initialDelay, 8 + initialDelay], "Resulting re
     quests"); | 
 |  394  | 
 |  395     this.registerHandler("/redirected", metadata => | 
 |  396     { | 
 |  397       return [Cr.NS_OK, 200, "[Adblock]\nfoo\n!Redirect: http://example.com/subs
     cription\nbar"]; | 
 |  398     }); | 
 |  399  | 
 |  400     subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  401     resetSubscription(subscription); | 
 |  402     FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); | 
 |  403     FilterStorage.addSubscription(subscription); | 
 |  404  | 
 |  405     return this.runScheduledTasks(2); | 
 |  406   }).then(() => | 
 |  407   { | 
 |  408     testSubscriptionEqual(test, FilterStorage.subscriptionAt(0), subscription, "
     Redirect not followed on redirect loop"); | 
 |  409     test.equal(subscription.downloadStatus, "synchronize_connection_error", "Dow
     nload status after redirect loop"); | 
 |  410   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  411 }; | 
 |  412  | 
 |  413 exports.testFallback = function(test) | 
 |  414 { | 
 |  415   Prefs.subscriptions_fallbackerrors = 3; | 
 |  416   Prefs.subscriptions_fallbackurl = "http://example.com/fallback?%SUBSCRIPTION%&
     %CHANNELSTATUS%&%RESPONSESTATUS%"; | 
 |  417  | 
 |  418   let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  419   FilterStorage.addSubscription(subscription); | 
 |  420  | 
 |  421   // No valid response from fallback | 
 |  422  | 
 |  423   let requests = []; | 
 |  424   let fallbackParams; | 
 |  425   let redirectedRequests; | 
 |  426   this.registerHandler("/subscription", metadata => | 
 |  427   { | 
 |  428     requests.push(this.getTimeOffset()); | 
 |  429     return [Cr.NS_OK, 404, ""]; | 
 |  430   }); | 
 |  431  | 
 |  432   this.runScheduledTasks(100).then(() => | 
 |  433   { | 
 |  434     test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
     elay, 72 + initialDelay, 96 + initialDelay], "Continue trying if the fallback do
     esn't respond"); | 
 |  435  | 
 |  436     // Fallback giving "Gone" response | 
 |  437  | 
 |  438     resetSubscription(subscription); | 
 |  439     requests = []; | 
 |  440     fallbackParams = null; | 
 |  441     this.registerHandler("/fallback", metadata => | 
 |  442     { | 
 |  443       fallbackParams = decodeURIComponent(metadata.queryString); | 
 |  444       return [Cr.NS_OK, 200, "410 Gone"]; | 
 |  445     }); | 
 |  446  | 
 |  447     return this.runScheduledTasks(100); | 
 |  448   }).then(() => | 
 |  449   { | 
 |  450     test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
     elay], "Stop trying if the fallback responds with Gone"); | 
 |  451     test.equal(fallbackParams, "http://example.com/subscription&0&404", "Fallbac
     k arguments"); | 
 |  452  | 
 |  453     // Fallback redirecting to a missing file | 
 |  454  | 
 |  455     subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  456     resetSubscription(subscription); | 
 |  457     FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); | 
 |  458     FilterStorage.addSubscription(subscription); | 
 |  459     requests = []; | 
 |  460  | 
 |  461     this.registerHandler("/fallback", metadata => | 
 |  462     { | 
 |  463       return [Cr.NS_OK, 200, "301 http://example.com/redirected"]; | 
 |  464     }); | 
 |  465     return this.runScheduledTasks(100); | 
 |  466   }).then(() => | 
 |  467   { | 
 |  468     test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/subscrip
     tion", "Ignore invalid redirect from fallback"); | 
 |  469     test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
     elay, 72 + initialDelay, 96 + initialDelay], "Requests not affected by invalid r
     edirect"); | 
 |  470  | 
 |  471     // Fallback redirecting to an existing file | 
 |  472  | 
 |  473     resetSubscription(subscription); | 
 |  474     requests = []; | 
 |  475     redirectedRequests = []; | 
 |  476     this.registerHandler("/redirected", metadata => | 
 |  477     { | 
 |  478       redirectedRequests.push(this.getTimeOffset()); | 
 |  479       return [Cr.NS_OK, 200, "[Adblock]\n!Expires: 1day\nfoo\nbar"]; | 
 |  480     }); | 
 |  481  | 
 |  482     return this.runScheduledTasks(100); | 
 |  483   }).then(() => | 
 |  484   { | 
 |  485     test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
     ed", "Valid redirect from fallback is followed"); | 
 |  486     test.deepEqual(requests, [0 + initialDelay, 24 + initialDelay, 48 + initialD
     elay], "Stop polling original URL after a valid redirect from fallback"); | 
 |  487     test.deepEqual(redirectedRequests, [48 + initialDelay, 72 + initialDelay, 96
      + initialDelay], "Request new URL after a valid redirect from fallback"); | 
 |  488  | 
 |  489     // Checksum mismatch | 
 |  490  | 
 |  491     this.registerHandler("/subscription", metadata => | 
 |  492     { | 
 |  493       return [Cr.NS_OK, 200, "[Adblock]\n! Checksum: wrong\nfoo\nbar"]; | 
 |  494     }); | 
 |  495  | 
 |  496     subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  497     resetSubscription(subscription); | 
 |  498     FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); | 
 |  499     FilterStorage.addSubscription(subscription); | 
 |  500  | 
 |  501     return this.runScheduledTasks(100); | 
 |  502   }).then(() => | 
 |  503   { | 
 |  504     test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
     ed", "Wrong checksum produces fallback request"); | 
 |  505  | 
 |  506     // Redirect loop | 
 |  507  | 
 |  508     this.registerHandler("/subscription", metadata => | 
 |  509     { | 
 |  510       return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
     tion2"]; | 
 |  511     }); | 
 |  512     this.registerHandler("/subscription2", metadata => | 
 |  513     { | 
 |  514       return [Cr.NS_OK, 200, "[Adblock]\n! Redirect: http://example.com/subscrip
     tion"]; | 
 |  515     }); | 
 |  516  | 
 |  517     subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  518     resetSubscription(subscription); | 
 |  519     FilterStorage.removeSubscription(FilterStorage.subscriptionAt(0)); | 
 |  520     FilterStorage.addSubscription(subscription); | 
 |  521  | 
 |  522     return this.runScheduledTasks(100); | 
 |  523   }).then(() => | 
 |  524   { | 
 |  525     test.equal(FilterStorage.subscriptionAt(0).url, "http://example.com/redirect
     ed", "Fallback can still redirect even after a redirect loop"); | 
 |  526   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  527 }; | 
 |  528  | 
 |  529 exports.testStateFields = function(test) | 
 |  530 { | 
 |  531   let subscription = Subscription.fromURL("http://example.com/subscription"); | 
 |  532   FilterStorage.addSubscription(subscription); | 
 |  533  | 
 |  534   this.registerHandler("/subscription", metadata => | 
 |  535   { | 
 |  536     return [Cr.NS_OK, 200, "[Adblock]\n! Expires: 2 hours\nfoo\nbar"]; | 
 |  537   }); | 
 |  538  | 
 |  539   let startTime = this.currentTime; | 
 |  540   this.runScheduledTasks(2).then(() => | 
 |  541   { | 
 |  542     test.equal(subscription.downloadStatus, "synchronize_ok", "downloadStatus af
     ter successful download"); | 
 |  543     test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + initial
     Delay * MILLIS_IN_HOUR, "lastDownload after successful download"); | 
 |  544     test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
     elay * MILLIS_IN_HOUR, "lastSuccess after successful download"); | 
 |  545     test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (1 + initi
     alDelay) * MILLIS_IN_HOUR, "lastCheck after successful download"); | 
 |  546     test.equal(subscription.errors, 0, "errors after successful download"); | 
 |  547  | 
 |  548     this.registerHandler("/subscription", metadata => | 
 |  549     { | 
 |  550       return [Cr.NS_ERROR_FAILURE, 0, ""]; | 
 |  551     }); | 
 |  552  | 
 |  553     return this.runScheduledTasks(2); | 
 |  554   }).then(() => | 
 |  555   { | 
 |  556     test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow
     nloadStatus after connection error"); | 
 |  557     test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (2 + in
     itialDelay) * MILLIS_IN_HOUR, "lastDownload after connection error"); | 
 |  558     test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
     elay * MILLIS_IN_HOUR, "lastSuccess after connection error"); | 
 |  559     test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (3 + initi
     alDelay) * MILLIS_IN_HOUR, "lastCheck after connection error"); | 
 |  560     test.equal(subscription.errors, 1, "errors after connection error"); | 
 |  561  | 
 |  562     this.registerHandler("/subscription", metadata => | 
 |  563     { | 
 |  564       return [Cr.NS_OK, 404, ""]; | 
 |  565     }); | 
 |  566  | 
 |  567     return this.runScheduledTasks(24); | 
 |  568   }).then(() => | 
 |  569   { | 
 |  570     test.equal(subscription.downloadStatus, "synchronize_connection_error", "dow
     nloadStatus after download error"); | 
 |  571     test.equal(subscription.lastDownload * MILLIS_IN_SECOND, startTime + (26 + i
     nitialDelay) * MILLIS_IN_HOUR, "lastDownload after download error"); | 
 |  572     test.equal(subscription.lastSuccess * MILLIS_IN_SECOND, startTime + initialD
     elay * MILLIS_IN_HOUR, "lastSuccess after download error"); | 
 |  573     test.equal(subscription.lastCheck * MILLIS_IN_SECOND, startTime + (27 + init
     ialDelay) * MILLIS_IN_HOUR, "lastCheck after download error"); | 
 |  574     test.equal(subscription.errors, 2, "errors after download error"); | 
 |  575   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
 |  576 }; | 
| OLD | NEW |