toolkit/components/downloads/test/unit/test_app_rep.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.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 Cu.import('resource://gre/modules/NetUtil.jsm');
michael@0 8 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 9
michael@0 10 const gAppRep = Cc["@mozilla.org/downloads/application-reputation-service;1"].
michael@0 11 getService(Ci.nsIApplicationReputationService);
michael@0 12 let gHttpServ = null;
michael@0 13 let gTables = {};
michael@0 14
michael@0 15 let ALLOW_LIST = 0;
michael@0 16 let BLOCK_LIST = 1;
michael@0 17 let NO_LIST = 2;
michael@0 18
michael@0 19 function readFileToString(aFilename) {
michael@0 20 let f = do_get_file(aFilename);
michael@0 21 let stream = Cc["@mozilla.org/network/file-input-stream;1"]
michael@0 22 .createInstance(Ci.nsIFileInputStream);
michael@0 23 stream.init(f, -1, 0, 0);
michael@0 24 let buf = NetUtil.readInputStreamToString(stream, stream.available());
michael@0 25 return buf;
michael@0 26 }
michael@0 27
michael@0 28 // Registers a table for which to serve update chunks. Returns a promise that
michael@0 29 // resolves when that chunk has been downloaded.
michael@0 30 function registerTableUpdate(aTable, aFilename) {
michael@0 31 // If we haven't been given an update for this table yet, add it to the map
michael@0 32 if (!(aTable in gTables)) {
michael@0 33 gTables[aTable] = [];
michael@0 34 }
michael@0 35
michael@0 36 // The number of chunks associated with this table.
michael@0 37 let numChunks = gTables[aTable].length + 1;
michael@0 38 let redirectPath = "/" + aTable + "-" + numChunks;
michael@0 39 let redirectUrl = "localhost:4444" + redirectPath;
michael@0 40
michael@0 41 // Store redirect url for that table so we can return it later when we
michael@0 42 // process an update request.
michael@0 43 gTables[aTable].push(redirectUrl);
michael@0 44
michael@0 45 gHttpServ.registerPathHandler(redirectPath, function(request, response) {
michael@0 46 do_print("Mock safebrowsing server handling request for " + redirectPath);
michael@0 47 let contents = readFileToString(aFilename);
michael@0 48 do_print("Length of " + aFilename + ": " + contents.length);
michael@0 49 response.setHeader("Content-Type",
michael@0 50 "application/vnd.google.safebrowsing-update", false);
michael@0 51 response.setStatusLine(request.httpVersion, 200, "OK");
michael@0 52 response.bodyOutputStream.write(contents, contents.length);
michael@0 53 });
michael@0 54 }
michael@0 55
michael@0 56 function run_test() {
michael@0 57 // Set up a local HTTP server to return bad verdicts.
michael@0 58 Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
michael@0 59 "http://localhost:4444/download");
michael@0 60 // Ensure safebrowsing is enabled for this test, even if the app
michael@0 61 // doesn't have it enabled.
michael@0 62 Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", true);
michael@0 63 do_register_cleanup(function() {
michael@0 64 Services.prefs.clearUserPref("browser.safebrowsing.malware.enabled");
michael@0 65 });
michael@0 66
michael@0 67 // Set download_block_table explicitly.
michael@0 68 Services.prefs.setCharPref("urlclassifier.downloadBlockTable",
michael@0 69 "goog-badbinurl-shavar");
michael@0 70 do_register_cleanup(function() {
michael@0 71 Services.prefs.clearUserPref("urlclassifier.downloadBlockTable");
michael@0 72 });
michael@0 73
michael@0 74 gHttpServ = new HttpServer();
michael@0 75 gHttpServ.registerDirectory("/", do_get_cwd());
michael@0 76 gHttpServ.registerPathHandler("/download", function(request, response) {
michael@0 77 do_throw("This test should never make a remote lookup");
michael@0 78 });
michael@0 79 gHttpServ.start(4444);
michael@0 80
michael@0 81 run_next_test();
michael@0 82 }
michael@0 83
michael@0 84 function check_telemetry(aCount,
michael@0 85 aShouldBlockCount,
michael@0 86 aListCounts) {
michael@0 87 let count = Cc["@mozilla.org/base/telemetry;1"]
michael@0 88 .getService(Ci.nsITelemetry)
michael@0 89 .getHistogramById("APPLICATION_REPUTATION_COUNT")
michael@0 90 .snapshot();
michael@0 91 do_check_eq(count.counts[1], aCount);
michael@0 92 let local = Cc["@mozilla.org/base/telemetry;1"]
michael@0 93 .getService(Ci.nsITelemetry)
michael@0 94 .getHistogramById("APPLICATION_REPUTATION_LOCAL")
michael@0 95 .snapshot();
michael@0 96 do_check_eq(local.counts[ALLOW_LIST], aListCounts[ALLOW_LIST]);
michael@0 97 do_check_eq(local.counts[BLOCK_LIST], aListCounts[BLOCK_LIST]);
michael@0 98 do_check_eq(local.counts[NO_LIST], aListCounts[NO_LIST]);
michael@0 99 let shouldBlock = Cc["@mozilla.org/base/telemetry;1"]
michael@0 100 .getService(Ci.nsITelemetry)
michael@0 101 .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
michael@0 102 .snapshot();
michael@0 103 // SHOULD_BLOCK = true
michael@0 104 do_check_eq(shouldBlock.counts[1], aShouldBlockCount);
michael@0 105 // Sanity check that SHOULD_BLOCK total adds up to the COUNT.
michael@0 106 do_check_eq(shouldBlock.counts[0] + shouldBlock.counts[1], aCount);
michael@0 107 }
michael@0 108
michael@0 109 function get_telemetry_counts() {
michael@0 110 let count = Cc["@mozilla.org/base/telemetry;1"]
michael@0 111 .getService(Ci.nsITelemetry)
michael@0 112 .getHistogramById("APPLICATION_REPUTATION_COUNT")
michael@0 113 .snapshot();
michael@0 114 let local = Cc["@mozilla.org/base/telemetry;1"]
michael@0 115 .getService(Ci.nsITelemetry)
michael@0 116 .getHistogramById("APPLICATION_REPUTATION_LOCAL")
michael@0 117 .snapshot();
michael@0 118 let shouldBlock = Cc["@mozilla.org/base/telemetry;1"]
michael@0 119 .getService(Ci.nsITelemetry)
michael@0 120 .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
michael@0 121 .snapshot();
michael@0 122 return { total: count.counts[1],
michael@0 123 shouldBlock: shouldBlock.counts[1],
michael@0 124 listCounts: local.counts };
michael@0 125 }
michael@0 126
michael@0 127 add_test(function test_nullSourceURI() {
michael@0 128 let counts = get_telemetry_counts();
michael@0 129 gAppRep.queryReputation({
michael@0 130 // No source URI
michael@0 131 fileSize: 12,
michael@0 132 }, function onComplete(aShouldBlock, aStatus) {
michael@0 133 do_check_eq(Cr.NS_ERROR_UNEXPECTED, aStatus);
michael@0 134 do_check_false(aShouldBlock);
michael@0 135 check_telemetry(counts.total + 1, counts.shouldBlock, counts.listCounts);
michael@0 136 run_next_test();
michael@0 137 });
michael@0 138 });
michael@0 139
michael@0 140 add_test(function test_nullCallback() {
michael@0 141 let counts = get_telemetry_counts();
michael@0 142 try {
michael@0 143 gAppRep.queryReputation({
michael@0 144 sourceURI: createURI("http://example.com"),
michael@0 145 fileSize: 12,
michael@0 146 }, null);
michael@0 147 do_throw("Callback cannot be null");
michael@0 148 } catch (ex if ex.result == Cr.NS_ERROR_INVALID_POINTER) {
michael@0 149 // We don't even increment the count here, because there's no callback.
michael@0 150 check_telemetry(counts.total, counts.shouldBlock, counts.listCounts);
michael@0 151 run_next_test();
michael@0 152 }
michael@0 153 });
michael@0 154
michael@0 155 add_test(function test_disabled() {
michael@0 156 let counts = get_telemetry_counts();
michael@0 157 Services.prefs.setCharPref("browser.safebrowsing.appRepURL", "");
michael@0 158 gAppRep.queryReputation({
michael@0 159 sourceURI: createURI("http://example.com"),
michael@0 160 fileSize: 12,
michael@0 161 }, function onComplete(aShouldBlock, aStatus) {
michael@0 162 // We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
michael@0 163 do_check_eq(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
michael@0 164 do_check_false(aShouldBlock);
michael@0 165 check_telemetry(counts.total + 1, counts.shouldBlock, counts.listCounts);
michael@0 166 run_next_test();
michael@0 167 });
michael@0 168 });
michael@0 169
michael@0 170 // Set up the local whitelist.
michael@0 171 add_test(function test_local_list() {
michael@0 172 // Construct a response with redirect urls.
michael@0 173 function processUpdateRequest() {
michael@0 174 let response = "n:1000\n";
michael@0 175 for (let table in gTables) {
michael@0 176 response += "i:" + table + "\n";
michael@0 177 for (let i = 0; i < gTables[table].length; ++i) {
michael@0 178 response += "u:" + gTables[table][i] + "\n";
michael@0 179 }
michael@0 180 }
michael@0 181 do_print("Returning update response: " + response);
michael@0 182 return response;
michael@0 183 }
michael@0 184 gHttpServ.registerPathHandler("/downloads", function(request, response) {
michael@0 185 let buf = NetUtil.readInputStreamToString(request.bodyInputStream,
michael@0 186 request.bodyInputStream.available());
michael@0 187 let blob = processUpdateRequest();
michael@0 188 response.setHeader("Content-Type",
michael@0 189 "application/vnd.google.safebrowsing-update", false);
michael@0 190 response.setStatusLine(request.httpVersion, 200, "OK");
michael@0 191 response.bodyOutputStream.write(blob, blob.length);
michael@0 192 });
michael@0 193
michael@0 194 let streamUpdater = Cc["@mozilla.org/url-classifier/streamupdater;1"]
michael@0 195 .getService(Ci.nsIUrlClassifierStreamUpdater);
michael@0 196 streamUpdater.updateUrl = "http://localhost:4444/downloads";
michael@0 197
michael@0 198 // Load up some update chunks for the safebrowsing server to serve.
michael@0 199 // This chunk contains the hash of whitelisted.com/.
michael@0 200 registerTableUpdate("goog-badbinurl-shavar", "data/block_digest.chunk");
michael@0 201 // This chunk contains the hash of blocklisted.com/.
michael@0 202 registerTableUpdate("goog-downloadwhite-digest256", "data/digest.chunk");
michael@0 203
michael@0 204 // Download some updates, and don't continue until the downloads are done.
michael@0 205 function updateSuccess(aEvent) {
michael@0 206 // Timeout of n:1000 is constructed in processUpdateRequest above and
michael@0 207 // passed back in the callback in nsIUrlClassifierStreamUpdater on success.
michael@0 208 do_check_eq("1000", aEvent);
michael@0 209 do_print("All data processed");
michael@0 210 run_next_test();
michael@0 211 }
michael@0 212 // Just throw if we ever get an update or download error.
michael@0 213 function handleError(aEvent) {
michael@0 214 do_throw("We didn't download or update correctly: " + aEvent);
michael@0 215 }
michael@0 216 streamUpdater.downloadUpdates(
michael@0 217 "goog-downloadwhite-digest256,goog-badbinurl-shavar",
michael@0 218 "goog-downloadwhite-digest256,goog-badbinurl-shavar;\n",
michael@0 219 updateSuccess, handleError, handleError);
michael@0 220 });
michael@0 221
michael@0 222 add_test(function test_unlisted() {
michael@0 223 Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
michael@0 224 "http://localhost:4444/download");
michael@0 225 let counts = get_telemetry_counts();
michael@0 226 let listCounts = counts.listCounts;
michael@0 227 listCounts[NO_LIST]++;
michael@0 228 gAppRep.queryReputation({
michael@0 229 sourceURI: createURI("http://example.com"),
michael@0 230 fileSize: 12,
michael@0 231 }, function onComplete(aShouldBlock, aStatus) {
michael@0 232 do_check_eq(Cr.NS_OK, aStatus);
michael@0 233 do_check_false(aShouldBlock);
michael@0 234 check_telemetry(counts.total + 1, counts.shouldBlock, listCounts);
michael@0 235 run_next_test();
michael@0 236 });
michael@0 237 });
michael@0 238
michael@0 239 add_test(function test_local_blacklist() {
michael@0 240 Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
michael@0 241 "http://localhost:4444/download");
michael@0 242 let counts = get_telemetry_counts();
michael@0 243 let listCounts = counts.listCounts;
michael@0 244 listCounts[BLOCK_LIST]++;
michael@0 245 gAppRep.queryReputation({
michael@0 246 sourceURI: createURI("http://blocklisted.com"),
michael@0 247 fileSize: 12,
michael@0 248 }, function onComplete(aShouldBlock, aStatus) {
michael@0 249 do_check_eq(Cr.NS_OK, aStatus);
michael@0 250 do_check_true(aShouldBlock);
michael@0 251 check_telemetry(counts.total + 1, counts.shouldBlock + 1, listCounts);
michael@0 252 run_next_test();
michael@0 253 });
michael@0 254 });
michael@0 255
michael@0 256 add_test(function test_referer_blacklist() {
michael@0 257 Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
michael@0 258 "http://localhost:4444/download");
michael@0 259 let counts = get_telemetry_counts();
michael@0 260 let listCounts = counts.listCounts;
michael@0 261 listCounts[BLOCK_LIST]++;
michael@0 262 gAppRep.queryReputation({
michael@0 263 sourceURI: createURI("http://example.com"),
michael@0 264 referrerURI: createURI("http://blocklisted.com"),
michael@0 265 fileSize: 12,
michael@0 266 }, function onComplete(aShouldBlock, aStatus) {
michael@0 267 do_check_eq(Cr.NS_OK, aStatus);
michael@0 268 do_check_true(aShouldBlock);
michael@0 269 check_telemetry(counts.total + 1, counts.shouldBlock + 1, listCounts);
michael@0 270 run_next_test();
michael@0 271 });
michael@0 272 });
michael@0 273
michael@0 274 add_test(function test_blocklist_trumps_allowlist() {
michael@0 275 Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
michael@0 276 "http://localhost:4444/download");
michael@0 277 let counts = get_telemetry_counts();
michael@0 278 let listCounts = counts.listCounts;
michael@0 279 listCounts[BLOCK_LIST]++;
michael@0 280 gAppRep.queryReputation({
michael@0 281 sourceURI: createURI("http://whitelisted.com"),
michael@0 282 referrerURI: createURI("http://blocklisted.com"),
michael@0 283 fileSize: 12,
michael@0 284 }, function onComplete(aShouldBlock, aStatus) {
michael@0 285 do_check_eq(Cr.NS_OK, aStatus);
michael@0 286 do_check_true(aShouldBlock);
michael@0 287 check_telemetry(counts.total + 1, counts.shouldBlock + 1, listCounts);
michael@0 288 run_next_test();
michael@0 289 });
michael@0 290 });

mercurial