tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_AttributionCode.js (5195B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/
      3 */
      4 "use strict";
      5 
      6 const { AppConstants } = ChromeUtils.importESModule(
      7  "resource://gre/modules/AppConstants.sys.mjs"
      8 );
      9 
     10 const { sinon } = ChromeUtils.importESModule(
     11  "resource://testing-common/Sinon.sys.mjs"
     12 );
     13 
     14 add_task(async () => {
     15  await setupStubs();
     16 });
     17 
     18 /**
     19 * Test validation of attribution codes,
     20 * to make sure we reject bad ones and accept good ones.
     21 */
     22 add_task(async function testValidAttrCodes() {
     23  let msixCampaignIdStub = sinon.stub(AttributionCode, "msixCampaignId");
     24 
     25  let currentCode = null;
     26  for (let entry of validAttrCodes) {
     27    currentCode = entry.code;
     28    // Attribution for MSIX builds works quite differently than regular Windows
     29    // builds: the attribution codes come from a Windows API that we've wrapped
     30    // with an XPCOM class. We don't have a way to inject codes into the build,
     31    // so instead we mock out our XPCOM class and return the desired values from
     32    // there. (A potential alternative is to have MSIX tests rely on attribution
     33    // files, but that more or less invalidates the tests.)
     34    if (
     35      AppConstants.platform === "win" &&
     36      Services.sysinfo.getProperty("hasWinPackageId")
     37    ) {
     38      // In real life, the attribution codes returned from Microsoft APIs
     39      // are not URI encoded, and the AttributionCode code that deals with
     40      // them expects that - so we have to simulate that as well.
     41      msixCampaignIdStub.callsFake(async () => decodeURIComponent(currentCode));
     42    } else if (AppConstants.platform === "macosx") {
     43      const { MacAttribution } = ChromeUtils.importESModule(
     44        "moz-src:///browser/components/attribution/MacAttribution.sys.mjs"
     45      );
     46 
     47      await MacAttribution.setAttributionString(currentCode);
     48    } else {
     49      // non-msix windows
     50      await AttributionCode.writeAttributionFile(currentCode);
     51    }
     52    AttributionCode._clearCache();
     53    let result = await AttributionCode.getAttrDataAsync();
     54 
     55    Assert.deepEqual(
     56      result,
     57      entry.parsed,
     58      "Parsed code should match expected value, code was: " + currentCode
     59    );
     60  }
     61  AttributionCode._clearCache();
     62 
     63  // Restore the msixCampaignId stub so that other tests don't fail stubbing it
     64  msixCampaignIdStub.restore();
     65 });
     66 
     67 /**
     68 * Make sure codes with various formatting errors are not seen as valid.
     69 */
     70 add_task(async function testInvalidAttrCodes() {
     71  let msixCampaignIdStub = sinon.stub(AttributionCode, "msixCampaignId");
     72  let currentCode = null;
     73 
     74  for (let code of invalidAttrCodes) {
     75    currentCode = code;
     76 
     77    if (
     78      AppConstants.platform === "win" &&
     79      Services.sysinfo.getProperty("hasWinPackageId")
     80    ) {
     81      if (code.includes("not set")) {
     82        // One of the "invalid" codes that we test is an unescaped one.
     83        // This is valid for most platforms, but we actually _expect_
     84        // unescaped codes for MSIX builds, so that particular test is not
     85        // valid for this case.
     86        continue;
     87      }
     88 
     89      msixCampaignIdStub.callsFake(async () => decodeURIComponent(currentCode));
     90    } else if (AppConstants.platform === "macosx") {
     91      const { MacAttribution } = ChromeUtils.importESModule(
     92        "moz-src:///browser/components/attribution/MacAttribution.sys.mjs"
     93      );
     94 
     95      await MacAttribution.setAttributionString(currentCode);
     96    } else {
     97      // non-msix windows
     98      await AttributionCode.writeAttributionFile(currentCode);
     99    }
    100    AttributionCode._clearCache();
    101    let result = await AttributionCode.getAttrDataAsync();
    102    Assert.deepEqual(
    103      result,
    104      {},
    105      "Code should have failed to parse: " + currentCode
    106    );
    107  }
    108  AttributionCode._clearCache();
    109 
    110  // Restore the msixCampaignId stub so that other tests don't fail stubbing it
    111  msixCampaignIdStub.restore();
    112 });
    113 
    114 /**
    115 * Test the cache by deleting the attribution data file
    116 * and making sure we still get the expected code.
    117 */
    118 let condition = {
    119  // macOS and MSIX attribution codes are not cached by us, thus this test is
    120  // unnecessary for those builds.
    121  skip_if: () =>
    122    (AppConstants.platform === "win" &&
    123      Services.sysinfo.getProperty("hasWinPackageId")) ||
    124    AppConstants.platform === "macosx",
    125 };
    126 add_task(condition, async function testDeletedFile() {
    127  // Set up the test by clearing the cache and writing a valid file.
    128  await AttributionCode.writeAttributionFile(validAttrCodes[0].code);
    129  let result = await AttributionCode.getAttrDataAsync();
    130  Assert.deepEqual(
    131    result,
    132    validAttrCodes[0].parsed,
    133    "The code should be readable directly from the file"
    134  );
    135 
    136  // Delete the file and make sure we can still read the value back from cache.
    137  await AttributionCode.deleteFileAsync();
    138  result = await AttributionCode.getAttrDataAsync();
    139  Assert.deepEqual(
    140    result,
    141    validAttrCodes[0].parsed,
    142    "The code should be readable from the cache"
    143  );
    144 
    145  // Clear the cache and check we can't read anything.
    146  AttributionCode._clearCache();
    147  result = await AttributionCode.getAttrDataAsync();
    148  Assert.deepEqual(
    149    result,
    150    {},
    151    "Shouldn't be able to get a code after file is deleted and cache is cleared"
    152  );
    153 });