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.

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

mercurial