tor-browser

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

head.js (5476B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 /* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
      4 
      5 "use strict";
      6 
      7 // shared-head.js handles imports, constants, and utility functions
      8 Services.scriptloader.loadSubScript(
      9  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
     10  this
     11 );
     12 
     13 // DOM panel actions.
     14 const constants = require("resource://devtools/client/dom/content/constants.js");
     15 
     16 // Uncomment this pref to dump all devtools emitted events to the console.
     17 // Services.prefs.setBoolPref("devtools.dump.emit", true);
     18 
     19 /**
     20 * Add a new test tab in the browser and load the given url.
     21 *
     22 * @param {string} url
     23 *        The url to be loaded in the new tab
     24 * @return a promise that resolves to the tab object when
     25 *        the url is loaded
     26 */
     27 async function addTestTab(url) {
     28  info("Adding a new test tab with URL: '" + url + "'");
     29 
     30  const tab = await addTab(url);
     31 
     32  // Select the DOM panel and wait till it's initialized.
     33  const panel = await initDOMPanel(tab);
     34 
     35  // FETCH_PROPERTIES should be fired during the call to initDOMPanel
     36  // But note that this behavior changed during a change in webconsole
     37  // initialization. So this might be racy.
     38  const doc = panel.panelWin.document;
     39  const nodes = [...doc.querySelectorAll(".treeLabel")];
     40  ok(!!nodes.length, "The DOM panel is already populated");
     41 
     42  return {
     43    tab,
     44    browser: tab.linkedBrowser,
     45    panel,
     46  };
     47 }
     48 
     49 /**
     50 * Open the DOM panel for the given tab.
     51 *
     52 * @param {Element} tab
     53 *        Optional tab element for which you want open the DOM panel.
     54 *        The default tab is taken from the global variable |tab|.
     55 * @return a promise that is resolved once the web console is open.
     56 */
     57 async function initDOMPanel(tab) {
     58  tab = tab || gBrowser.selectedTab;
     59  const toolbox = await gDevTools.showToolboxForTab(tab, { toolId: "dom" });
     60  const panel = toolbox.getCurrentPanel();
     61  return panel;
     62 }
     63 
     64 /**
     65 * Synthesize asynchronous click event (with clean stack trace).
     66 */
     67 function synthesizeMouseClickSoon(panel, element) {
     68  return new Promise(resolve => {
     69    executeSoon(() => {
     70      EventUtils.synthesizeMouse(element, 2, 2, {}, panel.panelWin);
     71      resolve();
     72    });
     73  });
     74 }
     75 
     76 /**
     77 * Returns tree row with specified label.
     78 */
     79 function getRowByLabel(panel, text) {
     80  const doc = panel.panelWin.document;
     81  const labels = [...doc.querySelectorAll(".treeLabel")];
     82  const label = labels.find(node => node.textContent == text);
     83  return label ? label.closest(".treeRow") : null;
     84 }
     85 
     86 /**
     87 * Returns tree row with specified index.
     88 */
     89 function getRowByIndex(panel, id) {
     90  const doc = panel.panelWin.document;
     91  const labels = [...doc.querySelectorAll(".treeLabel")];
     92  const label = labels.find((node, i) => i == id);
     93  return label ? label.closest(".treeRow") : null;
     94 }
     95 
     96 /**
     97 * Returns the children (tree row text) of the specified object name as an
     98 * array.
     99 */
    100 function getAllRowsForLabel(panel, text) {
    101  let rootObjectLevel;
    102  let node;
    103  const result = [];
    104  const doc = panel.panelWin.document;
    105  const nodes = [...doc.querySelectorAll(".treeLabel")];
    106 
    107  // Find the label (object name) for which we want the children. We remove
    108  // nodes from the start of the array until we reach the property. The children
    109  // are then at the start of the array.
    110  while (true) {
    111    node = nodes.shift();
    112 
    113    if (!node || node.textContent === text) {
    114      rootObjectLevel = node.getAttribute("data-level");
    115      break;
    116    }
    117  }
    118 
    119  // Return an empty array if the node is not found.
    120  if (!node) {
    121    return result;
    122  }
    123 
    124  // Now get the children.
    125  for (node of nodes) {
    126    const level = node.getAttribute("data-level");
    127 
    128    if (level > rootObjectLevel) {
    129      result.push({
    130        name: normalizeTreeValue(node.textContent),
    131        value: normalizeTreeValue(
    132          node.parentNode.nextElementSibling.textContent
    133        ),
    134      });
    135    } else {
    136      break;
    137    }
    138  }
    139 
    140  return result;
    141 }
    142 
    143 /**
    144 * Strings in the tree are in the form ""a"" and numbers in the form "1". We
    145 * normalize these values by converting ""a"" to "a" and "1" to 1.
    146 *
    147 * @param  {string} value
    148 *         The value to normalize.
    149 * @return {string | number}
    150 *         The normalized value.
    151 */
    152 function normalizeTreeValue(value) {
    153  if (value === `""`) {
    154    return "";
    155  }
    156  if (value.startsWith(`"`) && value.endsWith(`"`)) {
    157    return value.substr(1, value.length - 2);
    158  }
    159  if (isFinite(value) && parseInt(value, 10) == value) {
    160    return parseInt(value, 10);
    161  }
    162 
    163  return value;
    164 }
    165 
    166 /**
    167 * Expands elements with given label and waits till
    168 * children are received from the backend.
    169 */
    170 function expandRow(panel, labelText) {
    171  const row = getRowByLabel(panel, labelText);
    172  return synthesizeMouseClickSoon(panel, row).then(() => {
    173    // Wait till children (properties) are fetched
    174    // from the backend.
    175    const store = getReduxStoreFromPanel(panel);
    176    return waitForDispatch(store, "FETCH_PROPERTIES");
    177  });
    178 }
    179 
    180 function refreshPanel(panel) {
    181  const doc = panel.panelWin.document;
    182  const button = doc.querySelector("#dom-refresh-button");
    183  return synthesizeMouseClickSoon(panel, button).then(() => {
    184    // Wait till children (properties) are fetched
    185    // from the backend.
    186    const store = getReduxStoreFromPanel(panel);
    187    return waitForDispatch(store, "FETCH_PROPERTIES");
    188  });
    189 }
    190 
    191 function getReduxStoreFromPanel(panel) {
    192  return panel.panelWin.view.mainFrame.store;
    193 }