tor-browser

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

dom-mutation-breakpoints.js (4619B)


      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 "use strict";
      5 
      6 const { assert } = require("resource://devtools/shared/DevToolsUtils.js");
      7 const {
      8  getDOMMutationBreakpoint,
      9  getDOMMutationBreakpoints,
     10 } = require("resource://devtools/client/framework/reducers/dom-mutation-breakpoints.js");
     11 
     12 exports.registerWalkerListeners = registerWalkerListeners;
     13 function registerWalkerListeners(store, walker) {
     14  walker.on("mutations", mutations => handleWalkerMutations(mutations, store));
     15 }
     16 
     17 /**
     18 * Called when a target is destroyed. This will allow the reducer to remove breakpoints on
     19 * nodeFront associated with the passed target
     20 *
     21 * @param {ToolboxStore} store: The toolbox redux store
     22 * @param {TargetFront} targetFront
     23 */
     24 function removeTarget(store, targetFront) {
     25  store.dispatch({
     26    type: "REMOVE_TARGET",
     27    targetFront,
     28  });
     29 }
     30 exports.removeTarget = removeTarget;
     31 
     32 function handleWalkerMutations(mutations, store) {
     33  // If we got BP updates for detach/unload, we want to drop those nodes from
     34  // the list of active DOM mutation breakpoints. We explicitly check these
     35  // cases because BP updates could also happen due to explicitly API
     36  // operations to add/remove bps.
     37  const mutationItems = mutations.filter(
     38    mutation => mutation.type === "mutationBreakpoint"
     39  );
     40  if (mutationItems.length) {
     41    store.dispatch(updateBreakpointsForMutations(mutationItems));
     42  }
     43 }
     44 
     45 exports.createDOMMutationBreakpoint = createDOMMutationBreakpoint;
     46 function createDOMMutationBreakpoint(nodeFront, mutationType) {
     47  assert(typeof nodeFront === "object" && nodeFront);
     48  assert(typeof mutationType === "string");
     49 
     50  return async function ({ dispatch }) {
     51    const walker = nodeFront.walkerFront;
     52 
     53    dispatch({
     54      type: "ADD_DOM_MUTATION_BREAKPOINT",
     55      nodeFront,
     56      mutationType,
     57    });
     58 
     59    await walker.setMutationBreakpoints(nodeFront, {
     60      [mutationType]: true,
     61    });
     62  };
     63 }
     64 
     65 exports.deleteDOMMutationBreakpoint = deleteDOMMutationBreakpoint;
     66 function deleteDOMMutationBreakpoint(nodeFront, mutationType) {
     67  assert(typeof nodeFront === "object" && nodeFront);
     68  assert(typeof mutationType === "string");
     69 
     70  return async function ({ dispatch }) {
     71    const walker = nodeFront.walkerFront;
     72    await walker.setMutationBreakpoints(nodeFront, {
     73      [mutationType]: false,
     74    });
     75 
     76    dispatch({
     77      type: "REMOVE_DOM_MUTATION_BREAKPOINT",
     78      nodeFront,
     79      mutationType,
     80    });
     81  };
     82 }
     83 
     84 function updateBreakpointsForMutations(mutationItems) {
     85  return async function ({ dispatch, getState }) {
     86    const removedNodeFronts = [];
     87    const changedNodeFronts = new Set();
     88 
     89    for (const { target: nodeFront, mutationReason } of mutationItems) {
     90      switch (mutationReason) {
     91        case "api":
     92          changedNodeFronts.add(nodeFront);
     93          break;
     94        default:
     95          console.error(
     96            "Unexpected mutation reason",
     97            mutationReason,
     98            ", removing"
     99          );
    100        // Fall Through
    101        case "detach":
    102        case "unload":
    103          removedNodeFronts.push(nodeFront);
    104          break;
    105      }
    106    }
    107 
    108    if (removedNodeFronts.length) {
    109      dispatch({
    110        type: "REMOVE_DOM_MUTATION_BREAKPOINTS_FOR_FRONTS",
    111        nodeFronts: removedNodeFronts,
    112      });
    113    }
    114    if (changedNodeFronts.size > 0) {
    115      const enabledStates = [];
    116      for (const {
    117        id,
    118        nodeFront,
    119        mutationType,
    120        enabled,
    121      } of getDOMMutationBreakpoints(getState())) {
    122        if (changedNodeFronts.has(nodeFront)) {
    123          const bpEnabledOnFront = nodeFront.mutationBreakpoints[mutationType];
    124          if (bpEnabledOnFront !== enabled) {
    125            // Sync the bp state from the front into the store.
    126            enabledStates.push([id, bpEnabledOnFront]);
    127          }
    128        }
    129      }
    130 
    131      dispatch({
    132        type: "SET_DOM_MUTATION_BREAKPOINTS_ENABLED_STATE",
    133        enabledStates,
    134      });
    135    }
    136  };
    137 }
    138 
    139 exports.toggleDOMMutationBreakpointState = toggleDOMMutationBreakpointState;
    140 function toggleDOMMutationBreakpointState(id, enabled) {
    141  assert(typeof id === "string");
    142  assert(typeof enabled === "boolean");
    143 
    144  return async function ({ getState }) {
    145    const bp = getDOMMutationBreakpoint(getState(), id);
    146    if (!bp) {
    147      throw new Error(`No DOM mutation BP with ID ${id}`);
    148    }
    149 
    150    const walker = bp.nodeFront.getParent();
    151    await walker.setMutationBreakpoints(bp.nodeFront, {
    152      [bp.mutationType]: enabled,
    153    });
    154  };
    155 }