tor-browser

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

devtools-experimental-prefs.js (6781B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 loader.lazyRequireGetter(
      8  this,
      9  "HTMLTooltip",
     10  "resource://devtools/client/shared/widgets/tooltip/HTMLTooltip.js",
     11  true
     12 );
     13 
     14 const PREFERENCES = [
     15  [
     16    "fission.autostart",
     17    "Enable fission in Firefox. When navigating between two domains, you " +
     18      "will switch between two distinct processes. And if an iframe is " +
     19      "hosted from another domain, it will run in another process",
     20  ],
     21  [
     22    "fission.bfcacheInParent",
     23    "Enable bfcache navigation in parent process (requires Fission and involve " +
     24      "more top level target switching",
     25  ],
     26  [
     27    "devtools.debugger.features.javascript-tracing",
     28    "Enable the JavaScript tracer. (You need to restart Firefox / the Browser Toolbox to apply this setting)",
     29  ],
     30 ];
     31 
     32 /**
     33 * Show a Tooltip with the currently enabled preferences relevant for DevTools
     34 * ongoing experiments (new features, refactors, migrations).
     35 */
     36 function showTooltip(toolbox) {
     37  if (!toolbox._experimentalPrefsTooltip) {
     38    toolbox._experimentalPrefsTooltip = new HTMLTooltip(toolbox.doc, {
     39      type: "doorhanger",
     40      useXulWrapper: true,
     41    });
     42    toolbox.once("destroy", () => toolbox._experimentalPrefsTooltip.destroy());
     43  }
     44 
     45  // Terrible hack to allow to toggle using the command button.
     46  if (toolbox._experimentalPrefsTooltip.preventShow) {
     47    return;
     48  }
     49 
     50  updateTooltipContent(toolbox);
     51 
     52  const commandId = "command-button-experimental-prefs";
     53  toolbox._experimentalPrefsTooltip.show(toolbox.doc.getElementById(commandId));
     54 
     55  // Follows a hack to be able to close the tooltip when clicking on the
     56  // command button. Otherwise it will flicker and reopen.
     57  toolbox._experimentalPrefsTooltip.preventShow = true;
     58  toolbox._experimentalPrefsTooltip.once("hidden", () => {
     59    toolbox.win.setTimeout(
     60      () => (toolbox._experimentalPrefsTooltip.preventShow = false),
     61      250
     62    );
     63  });
     64 }
     65 exports.showTooltip = showTooltip;
     66 function updateTooltipContent(toolbox) {
     67  const container = toolbox.doc.createElement("div");
     68 
     69  /*
     70   *  This is the grid we want to have:
     71   *  +--------------------------------------------+---------------+
     72   *  | Header text                                | Reset button  |
     73   *  +------+-----------------------------+-------+---------------+
     74   *  | Icon | Preference name             | Value | Toggle button |
     75   *  +------+-----------------------------+-------+---------------+
     76   *  | Icon | Preference name             | Value | Toggle button |
     77   *  +------+-----------------------------+-------+---------------+
     78   */
     79 
     80  Object.assign(container.style, {
     81    display: "grid",
     82    gridTemplateColumns:
     83      "max-content minmax(300px, auto) max-content max-content",
     84    gridColumnGap: "8px",
     85    gridTemplateRows: `repeat(${PREFERENCES.length + 1}, auto)`,
     86    gridRowGap: "8px",
     87    padding: "12px",
     88    fontSize: "11px",
     89  });
     90 
     91  container.classList.add("theme-body");
     92 
     93  const headerContainer = toolbox.doc.createElement("header");
     94  /**
     95   * The grid layout of the header container is as follows:
     96   *
     97   *  +-------------------------+--------------+
     98   *  | Header text             | Reset button |
     99   *  +-------------------------+--------------+
    100   */
    101 
    102  Object.assign(headerContainer.style, {
    103    display: "grid",
    104    gridTemplateColumns: "subgrid",
    105    gridColumn: "1 / -1",
    106  });
    107 
    108  const header = toolbox.doc.createElement("h1");
    109 
    110  Object.assign(header.style, {
    111    gridColumn: "1 / -2",
    112    fontSize: "11px",
    113    margin: "0",
    114    padding: "0",
    115  });
    116 
    117  header.textContent = "DevTools Experimental preferences";
    118 
    119  const resetButton = toolbox.doc.createElement("button");
    120  resetButton.addEventListener("click", () => {
    121    for (const [name] of PREFERENCES) {
    122      Services.prefs.clearUserPref(name);
    123    }
    124    updateTooltipContent(toolbox);
    125  });
    126  resetButton.textContent = "reset all";
    127 
    128  headerContainer.append(header, resetButton);
    129 
    130  const prefList = toolbox.doc.createElement("ul");
    131  Object.assign(prefList.style, {
    132    display: "grid",
    133    gridTemplateColumns: "subgrid",
    134    gridTemplateRows: "subgrid",
    135    // Subgrid should span all grid columns
    136    gridColumn: "1 / -1",
    137    gridRow: "2 / -1",
    138    listStyle: "none",
    139    margin: "0",
    140    padding: "0",
    141  });
    142 
    143  for (const [name, desc] of PREFERENCES) {
    144    const prefEl = createPreferenceListItem(toolbox, name, desc);
    145    prefList.appendChild(prefEl);
    146  }
    147 
    148  container.append(headerContainer, prefList);
    149 
    150  toolbox._experimentalPrefsTooltip.panel.innerHTML = "";
    151  // There is a hardcoded 320px max width for doorhanger tooltips,
    152  // see Bug 1654020.
    153  toolbox._experimentalPrefsTooltip.panel.style.maxWidth = "unset";
    154  toolbox._experimentalPrefsTooltip.panel.appendChild(container);
    155 }
    156 
    157 function createPreferenceListItem(toolbox, name, desc) {
    158  const isPrefEnabled = Services.prefs.getBoolPref(name, false);
    159 
    160  const prefEl = toolbox.doc.createElement("li");
    161 
    162  /**
    163   * The grid layout of a preference line is as follows:
    164   *
    165   *  +------+-----------------------------+-------+---------------+
    166   *  | Icon | Preference name             | Value | Toggle button |
    167   *  +------+-----------------------------+-------+---------------+
    168   */
    169 
    170  Object.assign(prefEl.style, {
    171    margin: "0",
    172    lineHeight: "12px",
    173    display: "grid",
    174    alignItems: "center",
    175    gridTemplateColumns: "subgrid",
    176    gridColumn: "1 / -1",
    177  });
    178 
    179  prefEl.classList.toggle("theme-comment", !isPrefEnabled);
    180 
    181  // Icon
    182  const prefInfo = toolbox.doc.createElement("div");
    183  prefInfo.title = desc;
    184 
    185  Object.assign(prefInfo.style, {
    186    width: "12px",
    187    height: "12px",
    188  });
    189 
    190  prefInfo.classList.add("experimental-pref-icon");
    191 
    192  // Preference name
    193  const prefTitle = toolbox.doc.createElement("span");
    194 
    195  Object.assign(prefTitle.style, {
    196    userSelect: "text",
    197    fontWeight: isPrefEnabled ? "bold" : "normal",
    198  });
    199 
    200  prefTitle.textContent = name;
    201 
    202  // Value
    203  const prefValue = toolbox.doc.createElement("span");
    204  prefValue.textContent = isPrefEnabled;
    205 
    206  // Toggle Button
    207  const toggleButton = toolbox.doc.createElement("button");
    208  toggleButton.addEventListener("click", () => {
    209    Services.prefs.setBoolPref(name, !isPrefEnabled);
    210    updateTooltipContent(toolbox);
    211  });
    212  toggleButton.textContent = "toggle";
    213 
    214  prefEl.append(prefInfo, prefTitle, prefValue, toggleButton);
    215  return prefEl;
    216 }
    217 
    218 function isAnyPreferenceEnabled() {
    219  for (const [name] of PREFERENCES) {
    220    const isPrefEnabled = Services.prefs.getBoolPref(name, false);
    221    if (isPrefEnabled) {
    222      return true;
    223    }
    224  }
    225  return false;
    226 }
    227 exports.isAnyPreferenceEnabled = isAnyPreferenceEnabled;