tor-browser

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

view-source.js (5503B)


      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 /**
      8 * Tries to open a Stylesheet file in the Style Editor. If the file is not
      9 * found, it is opened in source view instead.
     10 * Returns a promise resolving to a boolean indicating whether or not
     11 * the source was able to be displayed in the StyleEditor, as the built-in
     12 * Firefox View Source is the fallback.
     13 *
     14 * @param {Toolbox} toolbox
     15 * @param {string | object} stylesheetResourceOrGeneratedURL
     16 * @param {number} generatedLine
     17 * @param {number} generatedColumn
     18 *
     19 * @return {Promise<boolean>}
     20 */
     21 exports.viewSourceInStyleEditor = async function (
     22  toolbox,
     23  stylesheetResourceOrGeneratedURL,
     24  generatedLine,
     25  generatedColumn
     26 ) {
     27  const originalPanelId = toolbox.currentToolId;
     28 
     29  try {
     30    const panel = await toolbox.selectTool("styleeditor", "view-source", {
     31      // This will be only used in case the styleeditor wasn't loaded yet, to make the
     32      // initialization faster in case we already have a stylesheet resource. We still
     33      // need the rest of this function to handle subsequent calls and sourcemapped stylesheets.
     34      stylesheetToSelect: {
     35        stylesheet: stylesheetResourceOrGeneratedURL,
     36        line: generatedLine,
     37        column: generatedColumn,
     38      },
     39    });
     40 
     41    let stylesheetResource;
     42    if (typeof stylesheetResourceOrGeneratedURL === "string") {
     43      stylesheetResource = panel.getStylesheetResourceForGeneratedURL(
     44        stylesheetResourceOrGeneratedURL
     45      );
     46    } else {
     47      stylesheetResource = stylesheetResourceOrGeneratedURL;
     48    }
     49 
     50    const originalLocation = stylesheetResource
     51      ? await getOriginalLocation(
     52          toolbox,
     53          stylesheetResource.resourceId,
     54          generatedLine,
     55          generatedColumn
     56        )
     57      : null;
     58 
     59    if (originalLocation) {
     60      await panel.selectOriginalSheet(
     61        originalLocation.sourceId,
     62        originalLocation.line,
     63        originalLocation.column
     64      );
     65      return true;
     66    }
     67 
     68    if (stylesheetResource) {
     69      await panel.selectStyleSheet(
     70        stylesheetResource,
     71        generatedLine,
     72        generatedColumn
     73      );
     74      return true;
     75    }
     76  } catch (e) {
     77    console.error("Failed to view source in style editor", e);
     78  }
     79 
     80  // If we weren't able to select the stylesheet in the style editor, display it in a
     81  // view-source tab
     82  exports.viewSource(
     83    toolbox,
     84    typeof stylesheetResourceOrGeneratedURL === "string"
     85      ? stylesheetResourceOrGeneratedURL
     86      : stylesheetResourceOrGeneratedURL.href ||
     87          stylesheetResourceOrGeneratedURL.nodeHref,
     88    generatedLine
     89  );
     90 
     91  // As we might have moved to the styleeditor, switch back to the original panel
     92  await toolbox.selectTool(originalPanelId);
     93 
     94  return false;
     95 };
     96 
     97 /**
     98 * Tries to open a JavaScript file in the Debugger. If the file is not found,
     99 * it is opened in source view instead. Either the source URL or source actor ID
    100 * can be specified. If both are specified, the source actor ID is used.
    101 *
    102 * Returns a promise resolving to a boolean indicating whether or not
    103 * the source was able to be displayed in the Debugger, as the built-in Firefox
    104 * View Source is the fallback.
    105 *
    106 * @param {Toolbox} toolbox
    107 * @param {string} sourceURL
    108 * @param {number} sourceLine
    109 * @param {number} sourceColumn
    110 * @param {string} sourceID
    111 * @param {(string|object)} [reason=unknown]
    112 *
    113 * @return {Promise<boolean>}
    114 */
    115 exports.viewSourceInDebugger = async function (
    116  toolbox,
    117  generatedURL,
    118  generatedLine,
    119  generatedColumn,
    120  sourceActorId,
    121  reason = "unknown"
    122 ) {
    123  // Load the debugger in the background
    124  const dbg = await toolbox.loadTool("jsdebugger");
    125 
    126  const openedSourceInDebugger = await dbg.openSourceInDebugger({
    127    generatedURL,
    128    generatedLine,
    129    generatedColumn,
    130    sourceActorId,
    131    reason,
    132  });
    133 
    134  if (openedSourceInDebugger) {
    135    toolbox.emitForTests("source-opened-in-debugger");
    136    return true;
    137  }
    138 
    139  // Fallback to built-in firefox view-source:
    140  exports.viewSource(toolbox, generatedURL, generatedLine, generatedColumn);
    141  return false;
    142 };
    143 
    144 async function getOriginalLocation(
    145  toolbox,
    146  generatedID,
    147  generatedLine,
    148  generatedColumn
    149 ) {
    150  // If there is no line number, then there's no chance that we'll get back
    151  // a useful original location.
    152  if (typeof generatedLine !== "number") {
    153    return null;
    154  }
    155 
    156  let originalLocation = null;
    157  try {
    158    originalLocation = await toolbox.sourceMapLoader.getOriginalLocation({
    159      sourceId: generatedID,
    160      line: generatedLine,
    161      column: generatedColumn,
    162    });
    163    if (originalLocation && originalLocation.sourceId === generatedID) {
    164      originalLocation = null;
    165    }
    166  } catch (err) {
    167    console.error(
    168      "Failed to resolve sourcemapped location for the given source location",
    169      { generatedID, generatedLine, generatedColumn },
    170      err
    171    );
    172  }
    173  return originalLocation;
    174 }
    175 
    176 /**
    177 * Open a link in Firefox's View Source.
    178 *
    179 * @param {Toolbox} toolbox
    180 * @param {string} sourceURL
    181 * @param {number} sourceLine
    182 * @param {number} sourceColumn
    183 *
    184 * @return {Promise}
    185 */
    186 exports.viewSource = async function (
    187  toolbox,
    188  sourceURL,
    189  sourceLine,
    190  sourceColumn
    191 ) {
    192  const utils = toolbox.gViewSourceUtils;
    193  utils.viewSource({
    194    URL: sourceURL,
    195    lineNumber: sourceLine || -1,
    196    columnNumber: sourceColumn || -1,
    197  });
    198 };