Wed, 31 Dec 2014 06:09:35 +0100
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();