tor-browser

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

browser_resources_css_changes.js (6009B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Test the ResourceCommand API around CSS_CHANGE.
      7 
      8 add_task(async function () {
      9  // Open a test tab
     10  const tab = await addTab(
     11    "data:text/html,<body style='color: lime;'>CSS Changes</body>"
     12  );
     13 
     14  const { client, resourceCommand, targetCommand } =
     15    await initResourceCommand(tab);
     16 
     17  // CSS_CHANGE watcher doesn't record modification made before watching,
     18  // so we have to start watching before doing any DOM mutation.
     19  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
     20    onAvailable: () => {},
     21  });
     22 
     23  const { walker } = await targetCommand.targetFront.getFront("inspector");
     24  const nodeList = await walker.querySelectorAll(walker.rootNode, "body");
     25  const body = (await nodeList.items())[0];
     26  const style = (
     27    await body.inspectorFront.pageStyle.getApplied(body, {
     28      skipPseudo: false,
     29    })
     30  )[0];
     31 
     32  info(
     33    "Check whether ResourceCommand catches CSS change that fired before starting to watch"
     34  );
     35  await setProperty(style.rule, 0, "color", "black");
     36 
     37  const availableResources = [];
     38  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
     39    onAvailable: resources => availableResources.push(...resources),
     40  });
     41 
     42  // There is no guarantee that the CSS change will be already available when calling watchResources,
     43  // so wait for it to be received.
     44  info("Wait for CSS change to be received");
     45  await waitFor(() => availableResources.length == 1);
     46 
     47  assertResource(
     48    availableResources[0],
     49    { index: 0, property: "color", value: "black" },
     50    { index: 0, property: "color", value: "lime" }
     51  );
     52 
     53  info(
     54    "Check whether ResourceCommand catches CSS changes after the property was renamed and updated"
     55  );
     56 
     57  // RuleRewriter:apply will not support a simultaneous rename + setProperty.
     58  // Doing so would send inconsistent arguments to StyleRuleActor:setRuleText,
     59  // the CSS text for the rule will not match the list of modifications, which
     60  // would desynchronize the Changes view. Thankfully this scenario should not
     61  // happen when using the UI to update the rules.
     62  await renameProperty(style.rule, 0, "color", "background-color");
     63  await waitUntil(() => availableResources.length === 2);
     64  assertResource(
     65    availableResources[1],
     66    { index: 0, property: "background-color", value: "black" },
     67    { index: 0, property: "color", value: "black" }
     68  );
     69 
     70  await setProperty(style.rule, 0, "background-color", "pink");
     71  await waitUntil(() => availableResources.length === 3);
     72  assertResource(
     73    availableResources[2],
     74    { index: 0, property: "background-color", value: "pink" },
     75    { index: 0, property: "background-color", value: "black" }
     76  );
     77 
     78  info("Check whether ResourceCommand catches CSS change of disabling");
     79  await setPropertyEnabled(style.rule, 0, "background-color", false);
     80  await waitUntil(() => availableResources.length === 4);
     81  assertResource(availableResources[3], null, {
     82    index: 0,
     83    property: "background-color",
     84    value: "pink",
     85  });
     86 
     87  info("Check whether ResourceCommand catches CSS change of new property");
     88  await createProperty(style.rule, 1, "font-size", "100px");
     89  await waitUntil(() => availableResources.length === 5);
     90  assertResource(
     91    availableResources[4],
     92    { index: 1, property: "font-size", value: "100px" },
     93    null
     94  );
     95 
     96  info("Check whether ResourceCommand sends all resources added in this test");
     97  const existingResources = [];
     98  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
     99    onAvailable: resources => existingResources.push(...resources),
    100  });
    101  await waitUntil(() => existingResources.length === 5);
    102  is(availableResources[0], existingResources[0], "1st resource is correct");
    103  is(availableResources[1], existingResources[1], "2nd resource is correct");
    104  is(availableResources[2], existingResources[2], "3rd resource is correct");
    105  is(availableResources[3], existingResources[3], "4th resource is correct");
    106  is(availableResources[4], existingResources[4], "4th resource is correct");
    107 
    108  targetCommand.destroy();
    109  await client.close();
    110 });
    111 
    112 function assertResource(resource, expectedAddedChange, expectedRemovedChange) {
    113  if (expectedAddedChange) {
    114    is(resource.add.length, 1, "The number of added changes is correct");
    115    assertChange(resource.add[0], expectedAddedChange);
    116  } else {
    117    is(resource.add, null, "There is no added changes");
    118  }
    119 
    120  if (expectedRemovedChange) {
    121    is(resource.remove.length, 1, "The number of removed changes is correct");
    122    assertChange(resource.remove[0], expectedRemovedChange);
    123  } else {
    124    is(resource.remove, null, "There is no removed changes");
    125  }
    126 }
    127 
    128 function assertChange(change, expected) {
    129  is(change.index, expected.index, "The index of change is correct");
    130  is(change.property, expected.property, "The property of change is correct");
    131  is(change.value, expected.value, "The value of change is correct");
    132 }
    133 
    134 async function setProperty(rule, index, property, value) {
    135  const modifications = rule.startModifyingProperties(window, {
    136    isKnown: true,
    137  });
    138  modifications.setProperty(index, property, value, "");
    139  await modifications.apply();
    140 }
    141 
    142 async function renameProperty(rule, index, oldName, newName) {
    143  const modifications = rule.startModifyingProperties(window, {
    144    isKnown: true,
    145  });
    146  modifications.renameProperty(index, oldName, newName);
    147  await modifications.apply();
    148 }
    149 
    150 async function createProperty(rule, index, property, value) {
    151  const modifications = rule.startModifyingProperties(window, {
    152    isKnown: true,
    153  });
    154  modifications.createProperty(index, property, value, "", true);
    155  await modifications.apply();
    156 }
    157 
    158 async function setPropertyEnabled(rule, index, property, isEnabled) {
    159  const modifications = rule.startModifyingProperties(window, {
    160    isKnown: true,
    161  });
    162  modifications.setPropertyEnabled(index, property, isEnabled);
    163  await modifications.apply();
    164 }