Bug 1134778 - Consolidate usages of view sourcing in tools with a source-utils module. r=vp,jryans

This commit is contained in:
Jordan Santell 2015-04-24 14:16:34 -07:00
Родитель ee2bb39767
Коммит 2513d09a8a
31 изменённых файлов: 478 добавлений и 271 удалений

Просмотреть файл

@ -384,7 +384,7 @@ let CallsListView = Heritage.extend(WidgetMethods, {
// If clicking on the location, jump to the Debugger.
if (e.target.classList.contains("call-item-location")) {
let { file, line } = callItem.attachment.actor;
viewSourceInDebugger(file, line);
this._viewSourceInDebugger(file, line);
return;
}
// Otherwise hide the call stack.
@ -456,7 +456,7 @@ let CallsListView = Heritage.extend(WidgetMethods, {
* The line of the respective function.
*/
_onStackFileClick: function(e, { file, line }) {
viewSourceInDebugger(file, line);
this._viewSourceInDebugger(file, line);
},
/**
@ -501,7 +501,7 @@ let CallsListView = Heritage.extend(WidgetMethods, {
}
let callItem = this.selectedItem;
let { file, line } = callItem.attachment.actor;
viewSourceInDebugger(file, line);
this._viewSourceInDebugger(file, line);
},
/**
@ -509,5 +509,18 @@ let CallsListView = Heritage.extend(WidgetMethods, {
*/
_onStepOut: function() {
this.selectedIndex = this.itemCount - 1;
},
/**
* Opens the specified file and line in the debugger. Falls back to Firefox's View Source.
*/
_viewSourceInDebugger: function (file, line) {
gToolbox.viewSourceInDebugger(file, line).then(success => {
if (success) {
window.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
} else {
window.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER);
}
});
}
});

Просмотреть файл

@ -12,11 +12,13 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/devtools/Console.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
const { require } = devtools;
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/toolkit/event-emitter");
const { CallWatcherFront } = require("devtools/server/actors/call-watcher");
const { CanvasFront } = require("devtools/server/actors/canvas");
const Telemetry = require("devtools/shared/telemetry");
const telemetry = new Telemetry();
@ -354,32 +356,3 @@ function getThumbnailForCall(thumbnails, index) {
}
return CanvasFront.INVALID_SNAPSHOT_IMAGE;
}
/**
* Opens/selects the debugger in this toolbox and jumps to the specified
* file name and line number.
*/
function viewSourceInDebugger(url, line) {
let showSource = ({ DebuggerView }) => {
let item = DebuggerView.Sources.getItemForAttachment(a => a.source.url === url);
if (item) {
DebuggerView.setEditorLocation(item.attachment.source.actor, line, { noDebug: true }).then(() => {
window.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
}, () => {
window.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER);
});
}
}
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = gToolbox.getPanel("jsdebugger");
gToolbox.selectTool("jsdebugger").then(({ panelWin: dbg }) => {
if (debuggerAlreadyOpen) {
showSource(dbg);
} else {
dbg.once(dbg.EVENTS.SOURCES_ADDED, () => showSource(dbg));
}
});
}

Просмотреть файл

@ -6,9 +6,11 @@ support-files =
browser_toolbox_options_disable_js_iframe.html
browser_toolbox_options_disable_cache.sjs
browser_toolbox_sidebar_tool.xul
code_math.js
head.js
helper_disable_cache.js
doc_theme.css
doc_viewsource.html
browser_toolbox_options_enable_serviceworkers_testing.html
serviceworker.js
@ -48,6 +50,10 @@ skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
[browser_toolbox_tool_ready.js]
[browser_toolbox_tool_remote_reopen.js]
[browser_toolbox_transport_events.js]
[browser_toolbox_view_source_01.js]
[browser_toolbox_view_source_02.js]
[browser_toolbox_view_source_03.js]
[browser_toolbox_view_source_04.js]
[browser_toolbox_window_reload_target.js]
[browser_toolbox_window_shortcuts.js]
skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5.1" # Bug 851129 - Re-enable browser_toolbox_window_shortcuts.js test after leaks are fixed
@ -56,7 +62,7 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
[browser_toolbox_custom_host.js]
[browser_toolbox_theme_registration.js]
[browser_toolbox_options_enable_serviceworkers_testing.js]
skip-if = e10s # Bug 1030318
skip-if = true # Bug 1153407 - this test breaks subsequent tests and is not e10s compatible
# We want this test to run for mochitest-dt as well, so we include it here:
[../../../base/content/test/general/browser_parsable_css.js]

Просмотреть файл

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that Toolbox#viewSourceInDebugger works when debugger is not
* yet opened.
*/
let URL = `${URL_ROOT}doc_viewsource.html`;
let JS_URL = `${URL_ROOT}code_math.js`;
function *viewSource() {
let toolbox = yield loadToolbox(URL);
yield toolbox.viewSourceInDebugger(JS_URL, 2);
let debuggerPanel = toolbox.getPanel("jsdebugger");
ok(debuggerPanel, "The debugger panel was opened.");
is(toolbox.currentToolId, "jsdebugger", "The debugger panel was selected.");
let { DebuggerView } = debuggerPanel.panelWin;
let Sources = DebuggerView.Sources;
is(Sources.selectedValue, getSourceActor(Sources, JS_URL),
"The correct source is shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 2,
"The correct line is highlighted in the debugger's source editor.");
yield unloadToolbox(toolbox);
finish();
}
function test () {
Task.spawn(viewSource).then(finish, (aError) => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
});
}

Просмотреть файл

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that Toolbox#viewSourceInDebugger works when debugger is already loaded.
*/
let URL = `${URL_ROOT}doc_viewsource.html`;
let JS_URL = `${URL_ROOT}code_math.js`;
function *viewSource() {
let toolbox = yield loadToolbox(URL);
let { panelWin: debuggerWin } = yield toolbox.selectTool("jsdebugger");
let debuggerEvents = debuggerWin.EVENTS;
let { DebuggerView } = debuggerWin;
let Sources = DebuggerView.Sources;
yield debuggerWin.once(debuggerEvents.SOURCE_SHOWN);
ok("A source was shown in the debugger.");
is(Sources.selectedValue, getSourceActor(Sources, JS_URL),
"The correct source is initially shown in the debugger.");
is(DebuggerView.editor.getCursor().line, 0,
"The correct line is initially highlighted in the debugger's source editor.");
yield toolbox.viewSourceInDebugger(JS_URL, 2);
let debuggerPanel = toolbox.getPanel("jsdebugger");
ok(debuggerPanel, "The debugger panel was opened.");
is(toolbox.currentToolId, "jsdebugger", "The debugger panel was selected.");
is(Sources.selectedValue, getSourceActor(Sources, JS_URL),
"The correct source is shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 2,
"The correct line is highlighted in the debugger's source editor.");
yield unloadToolbox(toolbox);
finish();
}
function test () {
Task.spawn(viewSource).then(finish, (aError) => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
});
}

Просмотреть файл

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that Toolbox#viewSourceInStyleEditor works when style editor is not
* yet opened.
*/
let URL = `${URL_ROOT}doc_viewsource.html`;
let CSS_URL = `${URL_ROOT}doc_theme.css`;
function *viewSource() {
let toolbox = yield loadToolbox(URL);
let fileFound = yield toolbox.viewSourceInStyleEditor(CSS_URL, 2);
ok(fileFound, "viewSourceInStyleEditor should resolve to true if source found.");
let stylePanel = toolbox.getPanel("styleeditor");
ok(stylePanel, "The style editor panel was opened.");
is(toolbox.currentToolId, "styleeditor", "The style editor panel was selected.");
let { UI } = stylePanel;
is(UI.selectedEditor.styleSheet.href, CSS_URL,
"The correct source is shown in the style editor.");
is(UI.selectedEditor.sourceEditor.getCursor().line + 1, 2,
"The correct line is highlighted in the style editor's source editor.");
yield unloadToolbox(toolbox);
finish();
}
function test () {
Task.spawn(viewSource).then(finish, (aError) => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
});
}

Просмотреть файл

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that Toolbox#viewSourceInScratchpad works.
*/
let URL = `${URL_ROOT}doc_viewsource.html`;
function *viewSource() {
let toolbox = yield loadToolbox(URL);
let win = yield openScratchpadWindow();
let { Scratchpad: scratchpad } = win;
// Brahm's Cello Sonata No.1, Op.38 now in the scratchpad
scratchpad.setText("E G B C B\nA B A G A B\nG E");
let scratchpadURL = scratchpad.uniqueName;
// Now select another tool for focus
yield toolbox.selectTool("webconsole");
yield toolbox.viewSourceInScratchpad(scratchpadURL, 2);
is(scratchpad.editor.getCursor().line, 2,
"The correct line is highlighted in scratchpad's editor.");
win.close();
yield unloadToolbox(toolbox);
finish();
}
function test () {
Task.spawn(viewSource).then(finish, (aError) => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
});
}

Просмотреть файл

@ -0,0 +1,4 @@
function add(a, b, k) {
var result = a + b;
return k(result);
}

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Toolbox test for View Source methods</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<link charset="UTF-8" rel="stylesheet" href="doc_theme.css" />
<script src="code_math.js"></script>
</head>
<body>
</body>
</html>

Просмотреть файл

@ -7,6 +7,7 @@ let TargetFactory = gDevTools.TargetFactory;
const { console } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const { ScratchpadManager } = Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", {});
const URL_ROOT = "http://example.com/browser/browser/devtools/framework/test/";
const CHROME_URL_ROOT = "chrome://mochitests/content/browser/browser/devtools/framework/test/";
@ -175,3 +176,49 @@ function getChromeActors(callback)
DebuggerServer.destroy();
});
}
function loadToolbox (url) {
let { promise: p, resolve } = promise.defer();
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
gDevTools.showToolbox(target).then(resolve);
}, true);
content.location = url;
return p;
}
function unloadToolbox (toolbox) {
return toolbox.destroy().then(function() {
gBrowser.removeCurrentTab();
});
}
function getSourceActor(aSources, aURL) {
let item = aSources.getItemForAttachment(a => a.source.url === aURL);
return item && item.value;
}
/**
* Open a Scratchpad window.
*
* @return nsIDOMWindow
* The new window object that holds Scratchpad.
*/
function *openScratchpadWindow () {
let { promise: p, resolve } = promise.defer();
let win = ScratchpadManager.openScratchpad();
yield once(win, "load");
win.Scratchpad.addObserver({
onReady: function () {
win.Scratchpad.removeObserver(this);
resolve(win);
}
});
return p;
}

Просмотреть файл

@ -21,6 +21,7 @@ let Telemetry = require("devtools/shared/telemetry");
let {getHighlighterUtils} = require("devtools/framework/toolbox-highlighter-utils");
let HUDService = require("devtools/webconsole/hudservice");
let {showDoorhanger} = require("devtools/shared/doorhanger");
let sourceUtils = require("devtools/shared/source-utils");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -1711,6 +1712,7 @@ Toolbox.prototype = {
gDevTools.off("pref-changed", this._prefChanged);
this._lastFocusedElement = null;
if (this.webconsolePanel) {
this._saveSplitConsoleHeight();
this.webconsolePanel.removeEventListener("resize",
@ -1880,4 +1882,48 @@ Toolbox.prototype = {
yield this._performanceConnection.destroy();
this._performanceConnection = null;
}),
/**
* Returns gViewSourceUtils for viewing source.
*/
get gViewSourceUtils() {
return this.frame.contentWindow.gViewSourceUtils;
},
/**
* Opens source in style editor. Falls back to plain "view-source:".
* @see browser/devtools/shared/source-utils.js
*/
viewSourceInStyleEditor: function (sourceURL, sourceLine) {
return sourceUtils.viewSourceInStyleEditor(this, sourceURL, sourceLine);
},
/**
* Opens source in debugger. Falls back to plain "view-source:".
* @see browser/devtools/shared/source-utils.js
*/
viewSourceInDebugger: function (sourceURL, sourceLine) {
return sourceUtils.viewSourceInDebugger(this, sourceURL, sourceLine);
},
/**
* Opens source in scratchpad. Falls back to plain "view-source:".
* TODO The `sourceURL` for scratchpad instances are like `Scratchpad/1`.
* If instances are scoped one-per-browser-window, then we should be able
* to infer the URL from this toolbox, or use the built in scratchpad IN
* the toolbox.
*
* @see browser/devtools/shared/source-utils.js
*/
viewSourceInScratchpad: function (sourceURL, sourceLine) {
return sourceUtils.viewSourceInScratchpad(sourceURL, sourceLine);
},
/**
* Opens source in plain "view-source:".
* @see browser/devtools/shared/source-utils.js
*/
viewSource: function (sourceURL, sourceLine) {
return sourceUtils.viewSource(this, sourceURL, sourceLine);
},
};

Просмотреть файл

@ -18,6 +18,9 @@
<script type="application/javascript;version=1.8"
src="chrome://browser/content/devtools/theme-switching.js"/>
<script type="application/javascript"
src="chrome://global/content/viewSourceUtils.js"/>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<commandset id="editMenuCommands"/>

Просмотреть файл

@ -283,13 +283,6 @@ InspectorPanel.prototype = {
this._target = value;
},
/**
* Expose gViewSourceUtils so that other tools can make use of them.
*/
get viewSourceUtils() {
return this.panelWin.gViewSourceUtils;
},
/**
* Indicate that a tool has modified the state of the page. Used to
* decide whether to show the "are you sure you want to navigate"

Просмотреть файл

@ -18,9 +18,6 @@
<script type="application/javascript;version=1.8"
src="chrome://browser/content/devtools/theme-switching.js"/>
<script type="application/javascript"
src="chrome://global/content/viewSourceUtils.js"/>
<commandset>
<command id="nodeSearchCommand"
oncommand="inspector.searchBox.focus()"/>

Просмотреть файл

@ -58,8 +58,6 @@ support-files =
[browser_perf-jit-view-02.js]
[browser_perf-jit-model-01.js]
[browser_perf-jit-model-02.js]
[browser_perf-jump-to-debugger-01.js]
[browser_perf-jump-to-debugger-02.js]
[browser_perf-options-01.js]
[browser_perf-options-02.js]
[browser_perf-options-invert-call-tree-01.js]

Просмотреть файл

@ -1,27 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the performance tool can jump to the debugger.
*/
function spawnTest () {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { viewSourceInDebugger } = panel.panelWin;
yield viewSourceInDebugger(SIMPLE_URL, 14);
let debuggerPanel = toolbox.getPanel("jsdebugger");
ok(debuggerPanel, "The debugger panel was opened.");
let { DebuggerView } = debuggerPanel.panelWin;
let Sources = DebuggerView.Sources;
is(Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 14,
"The correct line is highlighted in the debugger's source editor.");
yield teardown(panel);
finish();
}

Просмотреть файл

@ -1,41 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the performance tool can jump to the debugger, when the source was
* already loaded in that tool.
*/
function spawnTest() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL, "jsdebugger");
let debuggerWin = panel.panelWin;
let debuggerEvents = debuggerWin.EVENTS;
let { DebuggerView } = debuggerWin;
let Sources = DebuggerView.Sources;
yield debuggerWin.once(debuggerEvents.SOURCE_SHOWN);
ok("A source was shown in the debugger.");
is(Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is initially shown in the debugger.");
is(DebuggerView.editor.getCursor().line, 0,
"The correct line is initially highlighted in the debugger's source editor.");
yield toolbox.selectTool("performance");
let perfPanel = toolbox.getCurrentPanel();
let perfWin = perfPanel.panelWin;
let { viewSourceInDebugger } = perfWin;
yield viewSourceInDebugger(SIMPLE_URL, 14);
panel = toolbox.getPanel("jsdebugger");
ok(panel, "The debugger panel was reselected.");
is(DebuggerView.Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is still shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 14,
"The correct line is now highlighted in the debugger's source editor.");
yield teardown(perfPanel);
finish();
}

Просмотреть файл

@ -473,11 +473,6 @@ function dropSelection(graph) {
graph.emit("selecting");
}
function getSourceActor(aSources, aURL) {
let item = aSources.getItemForAttachment(a => a.source.url === aURL);
return item && item.value;
}
/**
* Fires a key event, like "VK_UP", "VK_DOWN", etc.
*/

Просмотреть файл

@ -61,9 +61,13 @@ let JsCallTreeView = Heritage.extend(DetailsSubview, {
*/
_onLink: function (_, treeItem) {
let { url, line } = treeItem.frame.getInfo();
viewSourceInDebugger(url, line).then(
() => this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER),
() => this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER));
gToolbox.viewSourceInDebugger(url, line).then(success => {
if (success) {
this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
} else {
this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER);
}
});
},
/**
@ -121,31 +125,3 @@ let JsCallTreeView = Heritage.extend(DetailsSubview, {
toString: () => "[object JsCallTreeView]"
});
/**
* Opens/selects the debugger in this toolbox and jumps to the specified
* file name and line number.
* @param string url
* @param number line
*/
let viewSourceInDebugger = Task.async(function *(url, line) {
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = gToolbox.getPanel("jsdebugger");
let { panelWin: dbg } = yield gToolbox.selectTool("jsdebugger");
if (!debuggerAlreadyOpen) {
yield dbg.once(dbg.EVENTS.SOURCES_ADDED);
}
let { DebuggerView } = dbg;
let { Sources } = DebuggerView;
let item = Sources.getItemForAttachment(a => a.source.url === url);
if (item) {
return DebuggerView.setEditorLocation(item.attachment.source.actor, line, { noDebug: true });
}
return Promise.reject("Couldn't find the specified source in the debugger.");
});

Просмотреть файл

@ -51,9 +51,13 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
*/
_onLink: function (_, treeItem) {
let { url, line } = treeItem.frame.getInfo();
viewSourceInDebugger(url, line).then(
() => this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER),
() => this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER));
gToolbox.viewSourceInDebugger(url, line).then(success => {
if (success) {
this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
} else {
this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER);
}
});
},
/**

Просмотреть файл

@ -29,10 +29,12 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
this._onMarkerSelected = this._onMarkerSelected.bind(this);
this._onResize = this._onResize.bind(this);
this._onViewSource = this._onViewSource.bind(this);
this.waterfall.on("selected", this._onMarkerSelected);
this.waterfall.on("unselected", this._onMarkerSelected);
this.details.on("resize", this._onResize);
this.details.on("view-source", this._onViewSource);
let blueprint = PerformanceController.getTimelineBlueprint();
this.waterfall.setBlueprint(blueprint);
@ -48,6 +50,7 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
this.waterfall.off("selected", this._onMarkerSelected);
this.waterfall.off("unselected", this._onMarkerSelected);
this.details.off("resize", this._onResize);
this.details.off("view-source", this._onViewSource);
},
/**
@ -97,5 +100,12 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
this.waterfall.setBlueprint(blueprint);
},
/**
* Called when MarkerDetails view emits an event to view source.
*/
_onViewSource: function (_, file, line) {
gToolbox.viewSourceInDebugger(file, line);
},
toString: () => "[object WaterfallView]"
});

Просмотреть файл

@ -350,7 +350,7 @@ let JITOptimizationsView = {
fileName = url.slice(url.lastIndexOf("/") + 1);
node.classList.add("debugger-link");
node.setAttribute("tooltiptext", URL_LABEL_TOOLTIP + " → " + url);
node.addEventListener("click", () => viewSourceInDebugger(url, line));
node.addEventListener("click", () => gToolbox.viewSourceInDebugger(url, line));
}
fileName = fileName || url || "";
node.textContent = fileName ? `@${fileName}` : "";

Просмотреть файл

@ -54,6 +54,7 @@ EXTRA_JS_MODULES.devtools.shared += [
'inplace-editor.js',
'observable-object.js',
'options-view.js',
'source-utils.js',
'telemetry.js',
'theme-switching.js',
'theme.js',

Просмотреть файл

@ -0,0 +1,128 @@
/* 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";
loader.lazyRequireGetter(this, "Services");
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
/**
* 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} sourceURL
* @param {number} sourceLine
*
* @return {Promise<boolean>}
*/
exports.viewSourceInStyleEditor = Task.async(function *(toolbox, sourceURL, sourceLine) {
let panel = yield toolbox.loadTool("styleeditor");
try {
let selected = panel.UI.once("editor-selected");
yield panel.selectStyleSheet(sourceURL, sourceLine);
yield toolbox.selectTool("styleeditor");
yield selected;
return true;
} catch (e) {
exports.viewSource(toolbox, sourceURL, sourceLine);
return false;
}
});
/**
* Tries to open a JavaScript file in the Debugger. 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 Debugger, as the built-in Firefox
* View Source is the fallback.
*
* @param {Toolbox} toolbox
* @param {string} sourceURL
* @param {number} sourceLine
*
* @return {Promise<boolean>}
*/
exports.viewSourceInDebugger = Task.async(function *(toolbox, sourceURL, sourceLine) {
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = toolbox.getPanel("jsdebugger");
let { panelWin: dbg } = yield toolbox.loadTool("jsdebugger");
if (!debuggerAlreadyOpen) {
yield dbg.once(dbg.EVENTS.SOURCES_ADDED);
}
let { DebuggerView } = dbg;
let { Sources } = DebuggerView;
let item = Sources.getItemForAttachment(a => a.source.url === sourceURL);
if (item) {
yield toolbox.selectTool("jsdebugger");
yield DebuggerView.setEditorLocation(item.attachment.source.actor, sourceLine, { noDebug: true });
return true;
}
// If not found, still attempt to open in View Source
exports.viewSource(toolbox, sourceURL, sourceLine);
return false;
});
/**
* Tries to open a JavaScript file in the corresponding Scratchpad.
*
* @param {string} sourceURL
* @param {number} sourceLine
*
* @return {Promise}
*/
exports.viewSourceInScratchpad = Task.async(function *(sourceURL, sourceLine) {
// Check for matching top level scratchpad window.
let wins = Services.wm.getEnumerator("devtools:scratchpad");
while (wins.hasMoreElements()) {
let win = wins.getNext();
if (!win.closed && win.Scratchpad.uniqueName === sourceURL) {
win.focus();
win.Scratchpad.editor.setCursor({ line: sourceLine, ch: 0 });
return;
}
}
// For scratchpads within toolbox
for (let [, toolbox] of gDevTools) {
let scratchpadPanel = toolbox.getPanel("scratchpad");
if (scratchpadPanel) {
let { scratchpad } = scratchpadPanel;
if (scratchpad.uniqueName === sourceURL) {
toolbox.selectTool("scratchpad");
toolbox.raise();
scratchpad.editor.focus();
scratchpad.editor.setCursor({ line: sourceLine, ch: 0 });
return;
}
}
}
});
/**
* Open a link in Firefox's View Source.
*
* @param {Toolbox} toolbox
* @param {string} sourceURL
* @param {number} sourceLine
*
* @return {Promise}
*/
exports.viewSource = Task.async(function *(toolbox, sourceURL, sourceLine) {
let utils = toolbox.gViewSourceUtils;
utils.viewSource(sourceURL, null, toolbox.doc, sourceLine || 0);
});

Просмотреть файл

@ -222,7 +222,7 @@ MarkerDetails.prototype = {
aNode.addEventListener("click", (event) => {
event.preventDefault();
viewSourceInDebugger(toolbox, url, line);
this.emit("view-source", url, line);
});
}
@ -304,34 +304,4 @@ MarkerDetails.prototype = {
};
/**
* Opens/selects the debugger in this toolbox and jumps to the specified
* file name and line number.
* @param object toolbox
* The toolbox.
* @param string url
* @param number line
*/
let viewSourceInDebugger = Task.async(function *(toolbox, url, line) {
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = toolbox.getPanel("jsdebugger");
let { panelWin: dbg } = yield toolbox.selectTool("jsdebugger");
if (!debuggerAlreadyOpen) {
yield dbg.once(dbg.EVENTS.SOURCES_ADDED);
}
let { DebuggerView } = dbg;
let { Sources } = DebuggerView;
let item = Sources.getItemForAttachment(a => a.source.url === url);
if (item) {
return DebuggerView.setEditorLocation(item.attachment.source.actor, line, { noDebug: true });
}
return Promise.reject("Couldn't find the specified source in the debugger.");
});
exports.MarkerDetails = MarkerDetails;

Просмотреть файл

@ -1561,8 +1561,8 @@ SelectorView.prototype = {
contentDoc = rawNode.ownerDocument;
}
}
let viewSourceUtils = inspector.viewSourceUtils;
viewSourceUtils.viewSource(rule.href, null, contentDoc, rule.line);
let toolbox = gDevTools.getToolbox(inspector.target);
toolbox.viewSource(rule.href, rule.line);
return;
}

Просмотреть файл

@ -110,9 +110,9 @@ RuleViewTool.prototype = {
// these sheets in the view source window instead.
if (!sheet || sheet.isSystem) {
let contentDoc = this.inspector.selection.document;
let viewSourceUtils = this.inspector.viewSourceUtils;
let href = rule.nodeHref || rule.href;
viewSourceUtils.viewSource(href, null, contentDoc, rule.line || 0);
let toolbox = gDevTools.getToolbox(this.inspector.target);
toolbox.viewSource(href, rule.line);
return;
}

Просмотреть файл

@ -20,6 +20,7 @@ loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm");
loader.lazyImporter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm");
loader.lazyGetter(this, "showDoorhanger", () => require("devtools/shared/doorhanger").showDoorhanger);
loader.lazyRequireGetter(this, "sourceUtils", "devtools/shared/source-utils");
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
@ -432,10 +433,8 @@ WebConsole.prototype = {
* @param integer aSourceLine
* The line number which should be highlighted.
*/
viewSource: function WC_viewSource(aSourceURL, aSourceLine)
{
this.gViewSourceUtils.viewSource(aSourceURL, null,
this.iframeWindow.document, aSourceLine);
viewSource: function WC_viewSource(aSourceURL, aSourceLine) {
this.gViewSourceUtils.viewSource(aSourceURL, null, this.iframeWindow.document, aSourceLine || 0);
},
/**
@ -443,30 +442,20 @@ WebConsole.prototype = {
* instance in the Style Editor. If the file is not found, it is opened in
* source view instead.
*
* Manually handle the case where toolbox does not exist (Browser Console).
*
* @param string aSourceURL
* The URL of the file.
* @param integer aSourceLine
* The line number which you want to place the caret.
* TODO: This function breaks the client-server boundaries.
* To be fixed in bug 793259.
*/
viewSourceInStyleEditor:
function WC_viewSourceInStyleEditor(aSourceURL, aSourceLine)
{
viewSourceInStyleEditor: function WC_viewSourceInStyleEditor(aSourceURL, aSourceLine) {
let toolbox = gDevTools.getToolbox(this.target);
if (!toolbox) {
this.viewSource(aSourceURL, aSourceLine);
return;
}
gDevTools.showToolbox(this.target, "styleeditor").then(function(toolbox) {
try {
toolbox.getCurrentPanel().selectStyleSheet(aSourceURL, aSourceLine);
} catch(e) {
// Open view source if style editor fails.
this.viewSource(aSourceURL, aSourceLine);
}
});
toolbox.viewSourceInStyleEditor(aSourceURL, aSourceLine);
},
/**
@ -474,49 +463,24 @@ WebConsole.prototype = {
* instance in the Script Debugger. If the file is not found, it is opened in
* source view instead.
*
* Manually handle the case where toolbox does not exist (Browser Console).
*
* @param string aSourceURL
* The URL of the file.
* @param integer aSourceLine
* The line number which you want to place the caret.
*/
viewSourceInDebugger:
function WC_viewSourceInDebugger(aSourceURL, aSourceLine)
{
viewSourceInDebugger: function WC_viewSourceInDebugger(aSourceURL, aSourceLine) {
let toolbox = gDevTools.getToolbox(this.target);
if (!toolbox) {
this.viewSource(aSourceURL, aSourceLine);
return;
}
let showSource = ({ DebuggerView }) => {
let item = DebuggerView.Sources.getItemForAttachment(
a => a.source.url === aSourceURL
);
if (item) {
DebuggerView.setEditorLocation(item.attachment.source.actor, aSourceLine,
{ noDebug: true }).then(() => {
toolbox.viewSourceInDebugger(aSourceURL, aSourceLine).then(() => {
this.ui.emit("source-in-debugger-opened");
});
return;
}
toolbox.selectTool("webconsole")
.then(() => this.viewSource(aSourceURL, aSourceLine));
}
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = toolbox.getPanel("jsdebugger");
toolbox.selectTool("jsdebugger").then(({ panelWin: dbg }) => {
if (debuggerAlreadyOpen) {
showSource(dbg);
} else {
dbg.once(dbg.EVENTS.SOURCES_ADDED, () => showSource(dbg));
}
});
})
},
/**
* Tries to open a JavaScript file related to the web page for the web console
* instance in the corresponding Scratchpad.
@ -524,33 +488,8 @@ WebConsole.prototype = {
* @param string aSourceURL
* The URL of the file which corresponds to a Scratchpad id.
*/
viewSourceInScratchpad: function WC_viewSourceInScratchpad(aSourceURL)
{
// Check for matching top level Scratchpad window.
let wins = Services.wm.getEnumerator("devtools:scratchpad");
while (wins.hasMoreElements()) {
let win = wins.getNext();
if (!win.closed && win.Scratchpad.uniqueName === aSourceURL) {
win.focus();
return;
}
}
// Check for matching Scratchpad toolbox tab.
for (let [, toolbox] of gDevTools) {
let scratchpadPanel = toolbox.getPanel("scratchpad");
if (scratchpadPanel) {
let { scratchpad } = scratchpadPanel;
if (scratchpad.uniqueName === aSourceURL) {
toolbox.selectTool("scratchpad");
toolbox.raise();
scratchpad.editor.focus();
return;
}
}
}
viewSourceInScratchpad: function WC_viewSourceInScratchpad(aSourceURL, aSourceLine) {
sourceUtils.viewSourceInScratchpad(aSourceURL, aSourceLine);
},
/**

Просмотреть файл

@ -67,8 +67,8 @@ function test()
let viewSource = browserconsole.viewSource;
let URL = null;
let clickPromise = promise.defer();
browserconsole.viewSource = (aURL) => {
info("browserconsole.viewSource() was invoked: " + aURL);
browserconsole.viewSourceInDebugger = (aURL) => {
info("browserconsole.viewSourceInDebugger() was invoked: " + aURL);
URL = aURL;
clickPromise.resolve(null);
};
@ -85,6 +85,6 @@ function test()
isnot(URL.indexOf("toolbox.js"), -1, "we have the expected view source URL");
is(URL.indexOf("->"), -1, "no -> in the URL given to view-source");
browserconsole.viewSource = viewSource;
browserconsole.viewSourceInDebugger = viewSource;
}
}

Просмотреть файл

@ -52,7 +52,7 @@ function test()
{
let viewSource = hud.viewSource;
let viewSourceCalled = false;
hud.viewSource = () => viewSourceCalled = true;
hud.viewSourceInDebugger = () => viewSourceCalled = true;
for (let result of results) {
viewSourceCalled = false;
@ -67,7 +67,7 @@ function test()
ok(viewSourceCalled, "view source opened");
}
hud.viewSource = viewSource;
hud.viewSourceInDebugger = viewSource;
finishTest();
}
}

Просмотреть файл

@ -2720,7 +2720,7 @@ WebConsoleFrame.prototype = {
let onClick = () => {
let target = locationNode.target;
if (target == "scratchpad" || isScratchpad) {
this.owner.viewSourceInScratchpad(url);
this.owner.viewSourceInScratchpad(url, line);
return;
}