toolkit/components/url-classifier/tests/unit/head_urlclassifier.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 //* -*- Mode: Javascript; tab-width: 8; indent-tabs-mode: nil; js-indent-level: 2 -*- *
     2 function dumpn(s) {
     3   dump(s + "\n");
     4 }
     6 const NS_APP_USER_PROFILE_50_DIR = "ProfD";
     7 const NS_APP_USER_PROFILE_LOCAL_50_DIR = "ProfLD";
     9 const Cc = Components.classes;
    10 const Ci = Components.interfaces;
    11 const Cu = Components.utils;
    12 const Cr = Components.results;
    14 Cu.import("resource://testing-common/httpd.js");
    16 do_get_profile();
    18 var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
    20 var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
    22 var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
    23                .getService(Ci.nsIScriptSecurityManager);
    25 // Disable hashcompleter noise for tests
    26 var prefBranch = Cc["@mozilla.org/preferences-service;1"].
    27                  getService(Ci.nsIPrefBranch);
    28 prefBranch.setIntPref("urlclassifier.gethashnoise", 0);
    30 // Enable malware/phishing checking for tests
    31 prefBranch.setBoolPref("browser.safebrowsing.malware.enabled", true);
    32 prefBranch.setBoolPref("browser.safebrowsing.enabled", true);
    34 // Enable all completions for tests
    35 prefBranch.setCharPref("urlclassifier.disallow_completions", "");
    37 function delFile(name) {
    38   try {
    39     // Delete a previously created sqlite file
    40     var file = dirSvc.get('ProfLD', Ci.nsIFile);
    41     file.append(name);
    42     if (file.exists())
    43       file.remove(false);
    44   } catch(e) {
    45   }
    46 }
    48 function cleanUp() {
    49   delFile("urlclassifier3.sqlite");
    50   delFile("safebrowsing/classifier.hashkey");
    51   delFile("safebrowsing/test-phish-simple.sbstore");
    52   delFile("safebrowsing/test-malware-simple.sbstore");
    53   delFile("safebrowsing/test-phish-simple.cache");
    54   delFile("safebrowsing/test-malware-simple.cache");
    55   delFile("safebrowsing/test-phish-simple.pset");
    56   delFile("safebrowsing/test-malware-simple.pset");
    57 }
    59 var allTables = "test-phish-simple,test-malware-simple";
    61 var dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService);
    62 var streamUpdater = Cc["@mozilla.org/url-classifier/streamupdater;1"]
    63                     .getService(Ci.nsIUrlClassifierStreamUpdater);
    66 /*
    67  * Builds an update from an object that looks like:
    68  *{ "test-phish-simple" : [{
    69  *    "chunkType" : "a",  // 'a' is assumed if not specified
    70  *    "chunkNum" : 1,     // numerically-increasing chunk numbers are assumed
    71  *                        // if not specified
    72  *    "urls" : [ "foo.com/a", "foo.com/b", "bar.com/" ]
    73  * }
    74  */
    76 function buildUpdate(update, hashSize) {
    77   if (!hashSize) {
    78     hashSize = 32;
    79   }
    80   var updateStr = "n:1000\n";
    82   for (var tableName in update) {
    83     if (tableName != "")
    84       updateStr += "i:" + tableName + "\n";
    85     var chunks = update[tableName];
    86     for (var j = 0; j < chunks.length; j++) {
    87       var chunk = chunks[j];
    88       var chunkType = chunk.chunkType ? chunk.chunkType : 'a';
    89       var chunkNum = chunk.chunkNum ? chunk.chunkNum : j;
    90       updateStr += chunkType + ':' + chunkNum + ':' + hashSize;
    92       if (chunk.urls) {
    93         var chunkData = chunk.urls.join("\n");
    94         updateStr += ":" + chunkData.length + "\n" + chunkData;
    95       }
    97       updateStr += "\n";
    98     }
    99   }
   101   return updateStr;
   102 }
   104 function buildPhishingUpdate(chunks, hashSize) {
   105   return buildUpdate({"test-phish-simple" : chunks}, hashSize);
   106 }
   108 function buildMalwareUpdate(chunks, hashSize) {
   109   return buildUpdate({"test-malware-simple" : chunks}, hashSize);
   110 }
   112 function buildBareUpdate(chunks, hashSize) {
   113   return buildUpdate({"" : chunks}, hashSize);
   114 }
   116 /**
   117  * Performs an update of the dbservice manually, bypassing the stream updater
   118  */
   119 function doSimpleUpdate(updateText, success, failure) {
   120   var listener = {
   121     QueryInterface: function(iid)
   122     {
   123       if (iid.equals(Ci.nsISupports) ||
   124           iid.equals(Ci.nsIUrlClassifierUpdateObserver))
   125         return this;
   126       throw Cr.NS_ERROR_NO_INTERFACE;
   127     },
   129     updateUrlRequested: function(url) { },
   130     streamFinished: function(status) { },
   131     updateError: function(errorCode) { failure(errorCode); },
   132     updateSuccess: function(requestedTimeout) { success(requestedTimeout); }
   133   };
   135   dbservice.beginUpdate(listener,
   136                         "test-phish-simple,test-malware-simple");
   137   dbservice.beginStream("", "");
   138   dbservice.updateStream(updateText);
   139   dbservice.finishStream();
   140   dbservice.finishUpdate();
   141 }
   143 /**
   144  * Simulates a failed database update.
   145  */
   146 function doErrorUpdate(tables, success, failure) {
   147   var listener = {
   148     QueryInterface: function(iid)
   149     {
   150       if (iid.equals(Ci.nsISupports) ||
   151           iid.equals(Ci.nsIUrlClassifierUpdateObserver))
   152         return this;
   153       throw Cr.NS_ERROR_NO_INTERFACE;
   154     },
   156     updateUrlRequested: function(url) { },
   157     streamFinished: function(status) { },
   158     updateError: function(errorCode) { success(errorCode); },
   159     updateSuccess: function(requestedTimeout) { failure(requestedTimeout); }
   160   };
   162   dbservice.beginUpdate(listener, tables, null);
   163   dbservice.beginStream("", "");
   164   dbservice.cancelUpdate();
   165 }
   167 /**
   168  * Performs an update of the dbservice using the stream updater and a
   169  * data: uri
   170  */
   171 function doStreamUpdate(updateText, success, failure, downloadFailure) {
   172   var dataUpdate = "data:," + encodeURIComponent(updateText);
   174   if (!downloadFailure)
   175     downloadFailure = failure;
   177   streamUpdater.updateUrl = dataUpdate;
   178   streamUpdater.downloadUpdates("test-phish-simple,test-malware-simple", "",
   179                                 success, failure, downloadFailure);
   180 }
   182 var gAssertions = {
   184 tableData : function(expectedTables, cb)
   185 {
   186   dbservice.getTables(function(tables) {
   187       // rebuild the tables in a predictable order.
   188       var parts = tables.split("\n");
   189       while (parts[parts.length - 1] == '') {
   190         parts.pop();
   191       }
   192       parts.sort();
   193       tables = parts.join("\n");
   195       do_check_eq(tables, expectedTables);
   196       cb();
   197     });
   198 },
   200 checkUrls: function(urls, expected, cb)
   201 {
   202   // work with a copy of the list.
   203   urls = urls.slice(0);
   204   var doLookup = function() {
   205     if (urls.length > 0) {
   206       var fragment = urls.shift();
   207       var principal = secMan.getNoAppCodebasePrincipal(iosvc.newURI("http://" + fragment, null, null));
   208       dbservice.lookup(principal, allTables,
   209                                 function(arg) {
   210                                   do_check_eq(expected, arg);
   211                                   doLookup();
   212                                 }, true);
   213     } else {
   214       cb();
   215     }
   216   };
   217   doLookup();
   218 },
   220 urlsDontExist: function(urls, cb)
   221 {
   222   this.checkUrls(urls, '', cb);
   223 },
   225 urlsExist: function(urls, cb)
   226 {
   227   this.checkUrls(urls, 'test-phish-simple', cb);
   228 },
   230 malwareUrlsExist: function(urls, cb)
   231 {
   232   this.checkUrls(urls, 'test-malware-simple', cb);
   233 },
   235 subsDontExist: function(urls, cb)
   236 {
   237   // XXX: there's no interface for checking items in the subs table
   238   cb();
   239 },
   241 subsExist: function(urls, cb)
   242 {
   243   // XXX: there's no interface for checking items in the subs table
   244   cb();
   245 }
   247 };
   249 /**
   250  * Check a set of assertions against the gAssertions table.
   251  */
   252 function checkAssertions(assertions, doneCallback)
   253 {
   254   var checkAssertion = function() {
   255     for (var i in assertions) {
   256       var data = assertions[i];
   257       delete assertions[i];
   258       gAssertions[i](data, checkAssertion);
   259       return;
   260     }
   262     doneCallback();
   263   }
   265   checkAssertion();
   266 }
   268 function updateError(arg)
   269 {
   270   do_throw(arg);
   271 }
   273 // Runs a set of updates, and then checks a set of assertions.
   274 function doUpdateTest(updates, assertions, successCallback, errorCallback) {
   275   var errorUpdate = function() {
   276     checkAssertions(assertions, errorCallback);
   277   }
   279   var runUpdate = function() {
   280     if (updates.length > 0) {
   281       var update = updates.shift();
   282       doStreamUpdate(update, runUpdate, errorUpdate, null);
   283     } else {
   284       checkAssertions(assertions, successCallback);
   285     }
   286   }
   288   runUpdate();
   289 }
   291 var gTests;
   292 var gNextTest = 0;
   294 function runNextTest()
   295 {
   296   if (gNextTest >= gTests.length) {
   297     do_test_finished();
   298     return;
   299   }
   301   dbservice.resetDatabase();
   302   dbservice.setHashCompleter('test-phish-simple', null);
   304   let test = gTests[gNextTest++];
   305   dump("running " + test.name + "\n");
   306   test();
   307 }
   309 function runTests(tests)
   310 {
   311   gTests = tests;
   312   runNextTest();
   313 }
   315 var timerArray = [];
   317 function Timer(delay, cb) {
   318   this.cb = cb;
   319   var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   320   timer.initWithCallback(this, delay, timer.TYPE_ONE_SHOT);
   321   timerArray.push(timer);
   322 }
   324 Timer.prototype = {
   325 QueryInterface: function(iid) {
   326     if (!iid.equals(Ci.nsISupports) && !iid.equals(Ci.nsITimerCallback)) {
   327       throw Cr.NS_ERROR_NO_INTERFACE;
   328     }
   329     return this;
   330   },
   331 notify: function(timer) {
   332     this.cb();
   333   }
   334 }
   336 // LFSRgenerator is a 32-bit linear feedback shift register random number
   337 // generator. It is highly predictable and is not intended to be used for
   338 // cryptography but rather to allow easier debugging than a test that uses
   339 // Math.random().
   340 function LFSRgenerator(seed) {
   341   // Force |seed| to be a number.
   342   seed = +seed;
   343   // LFSR generators do not work with a value of 0.
   344   if (seed == 0)
   345     seed = 1;
   347   this._value = seed;
   348 }
   349 LFSRgenerator.prototype = {
   350   // nextNum returns a random unsigned integer of in the range [0,2^|bits|].
   351   nextNum: function(bits) {
   352     if (!bits)
   353       bits = 32;
   355     let val = this._value;
   356     // Taps are 32, 22, 2 and 1.
   357     let bit = ((val >>> 0) ^ (val >>> 10) ^ (val >>> 30) ^ (val >>> 31)) & 1;
   358     val = (val >>> 1) | (bit << 31);
   359     this._value = val;
   361     return (val >>> (32 - bits));
   362   },
   363 };
   365 cleanUp();

mercurial