tor-browser

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

blackbox.js (6849B)


      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 /**
      6 * Redux actions for the sources state
      7 *
      8 * @module actions/sources
      9 */
     10 
     11 import { recordEvent } from "../../utils/telemetry";
     12 import { toggleBreakpoints } from "../breakpoints/index";
     13 import {
     14  getSourceActorsForSource,
     15  isSourceBlackBoxed,
     16  getBlackBoxRanges,
     17  getBreakpointsForSource,
     18 } from "../../selectors/index";
     19 
     20 export async function blackboxSourceActorsForSource(
     21  thunkArgs,
     22  source,
     23  shouldBlackBox,
     24  ranges = []
     25 ) {
     26  const { getState, client, sourceMapLoader } = thunkArgs;
     27  let sourceId = source.id;
     28  // If the source is the original, then get the source id of its generated file
     29  // and the range for where the original is represented in the generated file
     30  // (which might be a bundle including other files).
     31  if (source.isOriginal) {
     32    sourceId = source.generatedSource.id;
     33    const range = await sourceMapLoader.getFileGeneratedRange(source.id);
     34    ranges = [];
     35    if (range) {
     36      ranges.push(range);
     37      // TODO bug 1752108: Investigate blackboxing lines in original files,
     38      // there is likely to be issues as the whole genrated file
     39      // representing the original file will always be blackboxed.
     40      console.warn(
     41        "The might be unxpected issues when ignoring lines in an original file. " +
     42          "The whole original source is being blackboxed."
     43      );
     44    } else {
     45      throw new Error(
     46        `Unable to retrieve generated ranges for original source ${source.url}`
     47      );
     48    }
     49  }
     50 
     51  for (const actor of getSourceActorsForSource(getState(), sourceId)) {
     52    await client.blackBox(actor, shouldBlackBox, ranges);
     53  }
     54 }
     55 
     56 /**
     57 * Toggle blackboxing for the whole source or for specific lines in a source
     58 *
     59 * @param {object} source - The source to be blackboxed/unblackboxed.
     60 * @param {boolean} [shouldBlackBox] - Specifies if the source should be blackboxed (true
     61 *                                     or unblackboxed (false). When this is not provided
     62 *                                     option is decided based on the blackboxed state
     63 *                                     of the source.
     64 * @param {Array} [ranges] - List of line/column offsets to blackbox, these
     65 *                           are provided only when blackboxing lines.
     66 *                           The range structure:
     67 *                           const range = {
     68 *                            start: { line: 1, column: 5 },
     69 *                            end: { line: 3, column: 4 },
     70 *                           }
     71 */
     72 export function toggleBlackBox(source, shouldBlackBox, ranges = []) {
     73  return async thunkArgs => {
     74    const { dispatch, getState } = thunkArgs;
     75 
     76    shouldBlackBox =
     77      typeof shouldBlackBox == "boolean"
     78        ? shouldBlackBox
     79        : !isSourceBlackBoxed(getState(), source);
     80 
     81    await blackboxSourceActorsForSource(
     82      thunkArgs,
     83      source,
     84      shouldBlackBox,
     85      ranges
     86    );
     87 
     88    if (shouldBlackBox) {
     89      recordEvent("blackbox");
     90      // If ranges is an empty array, it would mean we are blackboxing the whole
     91      // source. To do that lets reset the content to an empty array.
     92      if (!ranges.length) {
     93        dispatch({ type: "BLACKBOX_WHOLE_SOURCES", sources: [source] });
     94        await toggleBreakpointsInBlackboxedSources({
     95          thunkArgs,
     96          shouldDisable: true,
     97          sources: [source],
     98        });
     99      } else {
    100        const currentRanges = getBlackBoxRanges(getState())[source.url] || [];
    101        ranges = ranges.filter(newRange => {
    102          // To avoid adding duplicate ranges make sure
    103          // no range already exists with same start and end lines.
    104          const duplicate = currentRanges.findIndex(
    105            r =>
    106              r.start.line == newRange.start.line &&
    107              r.end.line == newRange.end.line
    108          );
    109          return duplicate == -1;
    110        });
    111        dispatch({ type: "BLACKBOX_SOURCE_RANGES", source, ranges });
    112        await toggleBreakpointsInRangesForBlackboxedSource({
    113          thunkArgs,
    114          shouldDisable: true,
    115          source,
    116          ranges,
    117        });
    118      }
    119    } else {
    120      // if there are no ranges to blackbox, then we are unblackboxing
    121      // the whole source
    122      // eslint-disable-next-line no-lonely-if
    123      if (!ranges.length) {
    124        dispatch({ type: "UNBLACKBOX_WHOLE_SOURCES", sources: [source] });
    125        toggleBreakpointsInBlackboxedSources({
    126          thunkArgs,
    127          shouldDisable: false,
    128          sources: [source],
    129        });
    130      } else {
    131        dispatch({ type: "UNBLACKBOX_SOURCE_RANGES", source, ranges });
    132        const blackboxRanges = getBlackBoxRanges(getState());
    133        if (!blackboxRanges[source.url].length) {
    134          dispatch({ type: "UNBLACKBOX_WHOLE_SOURCES", sources: [source] });
    135        }
    136        await toggleBreakpointsInRangesForBlackboxedSource({
    137          thunkArgs,
    138          shouldDisable: false,
    139          source,
    140          ranges,
    141        });
    142      }
    143    }
    144  };
    145 }
    146 
    147 async function toggleBreakpointsInRangesForBlackboxedSource({
    148  thunkArgs,
    149  shouldDisable,
    150  source,
    151  ranges,
    152 }) {
    153  const { dispatch, getState } = thunkArgs;
    154  for (const range of ranges) {
    155    const breakpoints = getBreakpointsForSource(getState(), source, range);
    156    await dispatch(toggleBreakpoints(shouldDisable, breakpoints));
    157  }
    158 }
    159 
    160 async function toggleBreakpointsInBlackboxedSources({
    161  thunkArgs,
    162  shouldDisable,
    163  sources,
    164 }) {
    165  const { dispatch, getState } = thunkArgs;
    166  for (const source of sources) {
    167    const breakpoints = getBreakpointsForSource(getState(), source);
    168    await dispatch(toggleBreakpoints(shouldDisable, breakpoints));
    169  }
    170 }
    171 
    172 /**
    173 * Blackboxes a group of sources together
    174 *
    175 * @param {Array} sourcesToBlackBox - The list of sources to blackbox
    176 * @param {boolean} shouldBlackbox - Specifies if the sources should blackboxed (true)
    177 *                                   or unblackboxed (false).
    178 */
    179 export function blackBoxSources(sourcesToBlackBox, shouldBlackBox) {
    180  return async thunkArgs => {
    181    const { dispatch, getState } = thunkArgs;
    182 
    183    const sources = sourcesToBlackBox.filter(
    184      source => isSourceBlackBoxed(getState(), source) !== shouldBlackBox
    185    );
    186 
    187    if (!sources.length) {
    188      return;
    189    }
    190 
    191    for (const source of sources) {
    192      await blackboxSourceActorsForSource(thunkArgs, source, shouldBlackBox);
    193    }
    194 
    195    if (shouldBlackBox) {
    196      recordEvent("blackbox");
    197    }
    198 
    199    dispatch({
    200      type: shouldBlackBox
    201        ? "BLACKBOX_WHOLE_SOURCES"
    202        : "UNBLACKBOX_WHOLE_SOURCES",
    203      sources,
    204    });
    205    await toggleBreakpointsInBlackboxedSources({
    206      thunkArgs,
    207      shouldDisable: shouldBlackBox,
    208      sources,
    209    });
    210  };
    211 }