tor-browser

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

test_FirefoxBridgeExtensionUtilsNativeManifest.js (9933B)


      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 const { FileUtils } = ChromeUtils.importESModule(
     10  "resource://gre/modules/FileUtils.sys.mjs"
     11 );
     12 const { FirefoxBridgeExtensionUtils } = ChromeUtils.importESModule(
     13  "resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs"
     14 );
     15 
     16 const DUAL_BROWSER_EXTENSION_ORIGIN = ["chrome-extension://fake-origin/"];
     17 const NATIVE_MESSAGING_HOST_ID = "org.mozilla.firefox_bridge_test";
     18 
     19 if (AppConstants.platform == "win") {
     20  var { MockRegistry } = ChromeUtils.importESModule(
     21    "resource://testing-common/MockRegistry.sys.mjs"
     22  );
     23 }
     24 
     25 let registry = null;
     26 add_setup(() => {
     27  if (AppConstants.platform == "win") {
     28    registry = new MockRegistry();
     29    registerCleanupFunction(() => {
     30      registry.shutdown();
     31    });
     32  }
     33 });
     34 
     35 function resetMockRegistry() {
     36  if (AppConstants.platform != "win") {
     37    return;
     38  }
     39  registry.shutdown();
     40  registry = new MockRegistry();
     41 }
     42 
     43 let dir = FileUtils.getDir("TmpD", ["NativeMessagingHostsTest"]);
     44 dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
     45 
     46 let userDir = dir.clone();
     47 userDir.append("user");
     48 userDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
     49 
     50 let appDir = dir.clone();
     51 appDir.append("app");
     52 appDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
     53 
     54 let dirProvider = {
     55  getFile(property) {
     56    if (property == "Home") {
     57      return userDir.clone();
     58    } else if (property == "AppData") {
     59      return appDir.clone();
     60    }
     61    return null;
     62  },
     63 };
     64 
     65 try {
     66  Services.dirsvc.undefine("Home");
     67 } catch (e) {}
     68 try {
     69  Services.dirsvc.undefine("AppData");
     70 } catch (e) {}
     71 Services.dirsvc.registerProvider(dirProvider);
     72 
     73 registerCleanupFunction(() => {
     74  Services.dirsvc.unregisterProvider(dirProvider);
     75  dir.remove(true);
     76 });
     77 
     78 const USER_TEST_PATH = PathUtils.join(userDir.path, "manifestDir");
     79 
     80 let binFile = null;
     81 add_setup(async function () {
     82  binFile = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent.clone();
     83  if (AppConstants.platform == "win") {
     84    binFile.append("nmhproxy.exe");
     85  } else if (AppConstants.platform == "macosx") {
     86    binFile.append("nmhproxy");
     87  } else {
     88    throw new Error("Unsupported platform");
     89  }
     90 });
     91 
     92 function getExpectedOutput() {
     93  return {
     94    name: NATIVE_MESSAGING_HOST_ID,
     95    description: "Firefox Native Messaging Host",
     96    path: binFile.path,
     97    type: "stdio",
     98    allowed_origins: DUAL_BROWSER_EXTENSION_ORIGIN,
     99  };
    100 }
    101 
    102 function DumpWindowsRegistry() {
    103  let key = "";
    104  let pathBuffer = [];
    105 
    106  if (AppConstants.platform == "win") {
    107    function bufferPrint(line) {
    108      let regPath = line.trimStart();
    109      if (regPath.includes(":")) {
    110        // After trimming white space, keys are formatted as
    111        // ": <key> (<value_type>)". We can assume it's only ever
    112        // going to be of type REG_SZ for this test.
    113        key = regPath.slice(2, regPath.length - " (REG_SZ)".length);
    114      } else {
    115        pathBuffer.push(regPath);
    116      }
    117    }
    118 
    119    MockRegistry.dump(
    120      MockRegistry.getRoot(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER),
    121      "",
    122      bufferPrint
    123    );
    124  } else {
    125    Assert.ok(false, "Only windows has a registry!");
    126  }
    127 
    128  return [pathBuffer, key];
    129 }
    130 
    131 add_task(async function test_maybeWriteManifestFiles() {
    132  await FirefoxBridgeExtensionUtils.maybeWriteManifestFiles(
    133    USER_TEST_PATH,
    134    NATIVE_MESSAGING_HOST_ID,
    135    DUAL_BROWSER_EXTENSION_ORIGIN
    136  );
    137  let expectedOutput = JSON.stringify(getExpectedOutput());
    138  let nmhManifestFilePath = PathUtils.join(
    139    USER_TEST_PATH,
    140    `${NATIVE_MESSAGING_HOST_ID}.json`
    141  );
    142  let nmhManifestFileContent = await IOUtils.readUTF8(nmhManifestFilePath);
    143  await IOUtils.remove(nmhManifestFilePath);
    144  Assert.equal(nmhManifestFileContent, expectedOutput);
    145 });
    146 
    147 add_task(async function test_maybeWriteManifestFilesIncorrect() {
    148  let nmhManifestFile = await IOUtils.getFile(
    149    USER_TEST_PATH,
    150    `${NATIVE_MESSAGING_HOST_ID}.json`
    151  );
    152 
    153  let incorrectInput = {
    154    name: NATIVE_MESSAGING_HOST_ID,
    155    description: "Manifest with unexpected description",
    156    path: binFile.path,
    157    type: "stdio",
    158    allowed_origins: DUAL_BROWSER_EXTENSION_ORIGIN,
    159  };
    160  await IOUtils.writeJSON(nmhManifestFile.path, incorrectInput);
    161 
    162  // Write correct JSON to the file and check to make sure it matches
    163  // the expected output
    164  await FirefoxBridgeExtensionUtils.maybeWriteManifestFiles(
    165    USER_TEST_PATH,
    166    NATIVE_MESSAGING_HOST_ID,
    167    DUAL_BROWSER_EXTENSION_ORIGIN
    168  );
    169  let expectedOutput = JSON.stringify(getExpectedOutput());
    170 
    171  let nmhManifestFilePath = PathUtils.join(
    172    USER_TEST_PATH,
    173    `${NATIVE_MESSAGING_HOST_ID}.json`
    174  );
    175  let nmhManifestFileContent = await IOUtils.readUTF8(nmhManifestFilePath);
    176  await IOUtils.remove(nmhManifestFilePath);
    177  Assert.equal(nmhManifestFileContent, expectedOutput);
    178 });
    179 
    180 add_task(async function test_maybeWriteManifestFilesAlreadyExists() {
    181  // Write file and confirm it exists
    182  await FirefoxBridgeExtensionUtils.maybeWriteManifestFiles(
    183    USER_TEST_PATH,
    184    NATIVE_MESSAGING_HOST_ID,
    185    DUAL_BROWSER_EXTENSION_ORIGIN
    186  );
    187  let nmhManifestFile = await IOUtils.getFile(
    188    USER_TEST_PATH,
    189    `${NATIVE_MESSAGING_HOST_ID}.json`
    190  );
    191 
    192  // Modify file modificatiomn time to be older than the write time
    193  let oldModificationTime = Date.now() - 1000000;
    194  let setModificationTime = await IOUtils.setModificationTime(
    195    nmhManifestFile.path,
    196    oldModificationTime
    197  );
    198  Assert.equal(oldModificationTime, setModificationTime);
    199 
    200  // Call function which writes correct JSON to the file and make sure
    201  // the modification time is the same, meaning we haven't written anything
    202  await FirefoxBridgeExtensionUtils.maybeWriteManifestFiles(
    203    USER_TEST_PATH,
    204    NATIVE_MESSAGING_HOST_ID,
    205    DUAL_BROWSER_EXTENSION_ORIGIN
    206  );
    207  let stat = await IOUtils.stat(nmhManifestFile.path);
    208  await IOUtils.remove(nmhManifestFile.path);
    209  Assert.equal(stat.lastModified, oldModificationTime);
    210 });
    211 
    212 add_task(async function test_maybeWriteManifestFilesDirDoesNotExist() {
    213  let testDir = dir.clone();
    214  // This folder does not exist, so we want to make sure it's created
    215  testDir.append("dirDoesNotExist");
    216  await FirefoxBridgeExtensionUtils.maybeWriteManifestFiles(
    217    testDir.path,
    218    NATIVE_MESSAGING_HOST_ID,
    219    DUAL_BROWSER_EXTENSION_ORIGIN
    220  );
    221 
    222  ok(await IOUtils.exists(testDir.path));
    223  ok(
    224    await IOUtils.exists(
    225      PathUtils.join(testDir.path, `${NATIVE_MESSAGING_HOST_ID}.json`)
    226    )
    227  );
    228  await IOUtils.remove(testDir.path, { recursive: true });
    229 });
    230 
    231 add_task(async function test_ensureRegistered() {
    232  let expectedJSONDirPath = null;
    233  let nativeHostId = "org.mozilla.firefox_bridge_nmh";
    234  if (AppConstants.NIGHTLY_BUILD) {
    235    nativeHostId = "org.mozilla.firefox_bridge_nmh_nightly";
    236  } else if (AppConstants.MOZ_DEV_EDITION) {
    237    nativeHostId = "org.mozilla.firefox_bridge_nmh_dev";
    238  } else if (AppConstants.IS_ESR) {
    239    nativeHostId = "org.mozilla.firefox_bridge_nmh_esr";
    240  }
    241 
    242  if (AppConstants.platform == "macosx") {
    243    expectedJSONDirPath = PathUtils.joinRelative(
    244      userDir.path,
    245      "Library/Application Support/Google/Chrome/NativeMessagingHosts/"
    246    );
    247  } else if (AppConstants.platform == "win") {
    248    expectedJSONDirPath = PathUtils.joinRelative(
    249      appDir.path,
    250      "Mozilla\\Firefox"
    251    );
    252    resetMockRegistry();
    253  } else {
    254    throw new Error("Unsupported platform");
    255  }
    256 
    257  ok(!(await IOUtils.exists(expectedJSONDirPath)));
    258  let expectedJSONPath = PathUtils.join(
    259    expectedJSONDirPath,
    260    `${nativeHostId}.json`
    261  );
    262 
    263  await FirefoxBridgeExtensionUtils.ensureRegistered();
    264  let realOutput = {
    265    name: nativeHostId,
    266    description: "Firefox Native Messaging Host",
    267    path: binFile.path,
    268    type: "stdio",
    269    allowed_origins: FirefoxBridgeExtensionUtils.getExtensionOrigins(),
    270  };
    271 
    272  let expectedOutput = JSON.stringify(realOutput);
    273  let JSONContent = await IOUtils.readUTF8(expectedJSONPath);
    274  await IOUtils.remove(expectedJSONPath);
    275  Assert.equal(JSONContent, expectedOutput);
    276 
    277  //  Test that the registry key is written for Windows only
    278  if (AppConstants.platform == "win") {
    279    let [pathBuffer, key] = DumpWindowsRegistry();
    280    Assert.equal(
    281      pathBuffer.toString(),
    282      [
    283        "Software",
    284        "Google",
    285        "Chrome",
    286        "NativeMessagingHosts",
    287        nativeHostId,
    288      ].toString()
    289    );
    290    Assert.equal(key, expectedJSONPath);
    291  }
    292 });
    293 
    294 add_task(async function test_maybeWriteNativeMessagingRegKeys() {
    295  if (AppConstants.platform != "win") {
    296    return;
    297  }
    298  resetMockRegistry();
    299  FirefoxBridgeExtensionUtils.maybeWriteNativeMessagingRegKeys(
    300    "Test\\Path\\For\\Reg\\Key",
    301    binFile.parent.path,
    302    NATIVE_MESSAGING_HOST_ID
    303  );
    304  let [pathBuffer, key] = DumpWindowsRegistry();
    305  registry.shutdown();
    306  Assert.equal(
    307    pathBuffer.toString(),
    308    ["Test", "Path", "For", "Reg", "Key", NATIVE_MESSAGING_HOST_ID].toString()
    309  );
    310  console.log("The key is: " + key);
    311  Assert.equal(key, `${binFile.parent.path}\\${NATIVE_MESSAGING_HOST_ID}.json`);
    312 });
    313 
    314 add_task(async function test_maybeWriteNativeMessagingRegKeysIncorrectValue() {
    315  if (AppConstants.platform != "win") {
    316    return;
    317  }
    318  resetMockRegistry();
    319  registry.setValue(
    320    Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
    321    `Test\\Path\\For\\Reg\\Key\\${NATIVE_MESSAGING_HOST_ID}`,
    322    "",
    323    "IncorrectValue"
    324  );
    325  FirefoxBridgeExtensionUtils.maybeWriteNativeMessagingRegKeys(
    326    "Test\\Path\\For\\Reg\\Key",
    327    binFile.parent.path,
    328    NATIVE_MESSAGING_HOST_ID
    329  );
    330  let [pathBuffer, key] = DumpWindowsRegistry();
    331  registry.shutdown();
    332  Assert.equal(
    333    pathBuffer.toString(),
    334    ["Test", "Path", "For", "Reg", "Key", NATIVE_MESSAGING_HOST_ID].toString()
    335  );
    336  Assert.equal(key, `${binFile.parent.path}\\${NATIVE_MESSAGING_HOST_ID}.json`);
    337 });