summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/view-source.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/view-source.js')
-rw-r--r--devtools/client/shared/view-source.js197
1 files changed, 197 insertions, 0 deletions
diff --git a/devtools/client/shared/view-source.js b/devtools/client/shared/view-source.js
new file mode 100644
index 0000000000..d551a37aa8
--- /dev/null
+++ b/devtools/client/shared/view-source.js
@@ -0,0 +1,197 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/**
+ * Tries to open a Stylesheet file in the Style Editor. If the file is not
+ * found, it is opened in source view instead.
+ * Returns a promise resolving to a boolean indicating whether or not
+ * the source was able to be displayed in the StyleEditor, as the built-in
+ * Firefox View Source is the fallback.
+ *
+ * @param {Toolbox} toolbox
+ * @param {string|Object} stylesheetResourceOrGeneratedURL
+ * @param {number} generatedLine
+ * @param {number} generatedColumn
+ *
+ * @return {Promise<boolean>}
+ */
+exports.viewSourceInStyleEditor = async function (
+ toolbox,
+ stylesheetResourceOrGeneratedURL,
+ generatedLine,
+ generatedColumn
+) {
+ const originalPanelId = toolbox.currentToolId;
+
+ try {
+ const panel = await toolbox.selectTool("styleeditor", "view-source", {
+ // This will be only used in case the styleeditor wasn't loaded yet, to make the
+ // initialization faster in case we already have a stylesheet resource. We still
+ // need the rest of this function to handle subsequent calls and sourcemapped stylesheets.
+ stylesheetToSelect: {
+ stylesheet: stylesheetResourceOrGeneratedURL,
+ line: generatedLine,
+ column: generatedColumn,
+ },
+ });
+
+ let stylesheetResource;
+ if (typeof stylesheetResourceOrGeneratedURL === "string") {
+ stylesheetResource = panel.getStylesheetResourceForGeneratedURL(
+ stylesheetResourceOrGeneratedURL
+ );
+ } else {
+ stylesheetResource = stylesheetResourceOrGeneratedURL;
+ }
+
+ const originalLocation = stylesheetResource
+ ? await getOriginalLocation(
+ toolbox,
+ stylesheetResource.resourceId,
+ generatedLine,
+ generatedColumn
+ )
+ : null;
+
+ if (originalLocation) {
+ await panel.selectOriginalSheet(
+ originalLocation.sourceId,
+ originalLocation.line,
+ originalLocation.column
+ );
+ return true;
+ }
+
+ if (stylesheetResource) {
+ await panel.selectStyleSheet(
+ stylesheetResource,
+ generatedLine,
+ generatedColumn
+ );
+ return true;
+ }
+ } catch (e) {
+ console.error("Failed to view source in style editor", e);
+ }
+
+ // If we weren't able to select the stylesheet in the style editor, display it in a
+ // view-source tab
+ exports.viewSource(
+ toolbox,
+ typeof stylesheetResourceOrGeneratedURL === "string"
+ ? stylesheetResourceOrGeneratedURL
+ : stylesheetResourceOrGeneratedURL.href ||
+ stylesheetResourceOrGeneratedURL.nodeHref,
+ generatedLine
+ );
+
+ // As we might have moved to the styleeditor, switch back to the original panel
+ await toolbox.selectTool(originalPanelId);
+
+ return false;
+};
+
+/**
+ * Tries to open a JavaScript file in the Debugger. If the file is not found,
+ * it is opened in source view instead. Either the source URL or source actor ID
+ * can be specified. If both are specified, the source actor ID is used.
+ *
+ * Returns a promise resolving to a boolean indicating whether or not
+ * the source was able to be displayed in the Debugger, as the built-in Firefox
+ * View Source is the fallback.
+ *
+ * @param {Toolbox} toolbox
+ * @param {string} sourceURL
+ * @param {number} sourceLine
+ * @param {number} sourceColumn
+ * @param {string} sourceID
+ * @param {(string|object)} [reason=unknown]
+ *
+ * @return {Promise<boolean>}
+ */
+exports.viewSourceInDebugger = async function (
+ toolbox,
+ generatedURL,
+ generatedLine,
+ generatedColumn,
+ sourceActorId,
+ reason = "unknown"
+) {
+ // Load the debugger in the background
+ const dbg = await toolbox.loadTool("jsdebugger");
+
+ const openedSourceInDebugger = await dbg.openSourceInDebugger({
+ generatedURL,
+ generatedLine,
+ generatedColumn,
+ sourceActorId,
+ reason,
+ });
+
+ if (openedSourceInDebugger) {
+ return true;
+ }
+
+ // Fallback to built-in firefox view-source:
+ exports.viewSource(toolbox, generatedURL, generatedLine, generatedColumn);
+ return false;
+};
+
+async function getOriginalLocation(
+ toolbox,
+ generatedID,
+ generatedLine,
+ generatedColumn
+) {
+ // If there is no line number, then there's no chance that we'll get back
+ // a useful original location.
+ if (typeof generatedLine !== "number") {
+ return null;
+ }
+
+ let originalLocation = null;
+ try {
+ originalLocation = await toolbox.sourceMapLoader.getOriginalLocation({
+ sourceId: generatedID,
+ line: generatedLine,
+ column: generatedColumn,
+ });
+ if (originalLocation && originalLocation.sourceId === generatedID) {
+ originalLocation = null;
+ }
+ } catch (err) {
+ console.error(
+ "Failed to resolve sourcemapped location for the given source location",
+ { generatedID, generatedLine, generatedColumn },
+ err
+ );
+ }
+ return originalLocation;
+}
+
+/**
+ * Open a link in Firefox's View Source.
+ *
+ * @param {Toolbox} toolbox
+ * @param {string} sourceURL
+ * @param {number} sourceLine
+ * @param {number} sourceColumn
+ *
+ * @return {Promise}
+ */
+exports.viewSource = async function (
+ toolbox,
+ sourceURL,
+ sourceLine,
+ sourceColumn
+) {
+ const utils = toolbox.gViewSourceUtils;
+ utils.viewSource({
+ URL: sourceURL,
+ lineNumber: sourceLine || -1,
+ columnNumber: sourceColumn || -1,
+ });
+};