michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Cu = Components.utils; michael@0: const Ci = Components.interfaces; michael@0: const Cc = Components.classes; michael@0: michael@0: // Services.prefs.setBoolPref("devtools.debugger.log", true); michael@0: // SimpleTest.registerCleanupFunction(() => { michael@0: // Services.prefs.clearUserPref("devtools.debugger.log"); michael@0: // }); michael@0: michael@0: //Services.prefs.setBoolPref("devtools.dump.emit", true); michael@0: michael@0: let tempScope = {}; michael@0: Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope); michael@0: let LayoutHelpers = tempScope.LayoutHelpers; michael@0: michael@0: let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope); michael@0: let TargetFactory = devtools.TargetFactory; michael@0: michael@0: Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope); michael@0: let console = tempScope.console; michael@0: michael@0: // Import the GCLI test helper michael@0: let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/")); michael@0: Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this); michael@0: michael@0: gDevTools.testing = true; michael@0: SimpleTest.registerCleanupFunction(() => { michael@0: gDevTools.testing = false; michael@0: }); michael@0: michael@0: SimpleTest.registerCleanupFunction(() => { michael@0: console.error("Here we are\n"); michael@0: let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {}); michael@0: console.error("DebuggerServer open connections: " + Object.getOwnPropertyNames(DebuggerServer._connections).length); michael@0: michael@0: Services.prefs.clearUserPref("devtools.dump.emit"); michael@0: Services.prefs.clearUserPref("devtools.inspector.activeSidebar"); michael@0: }); michael@0: michael@0: /** michael@0: * Simple DOM node accesor function that takes either a node or a string css michael@0: * selector as argument and returns the corresponding node michael@0: * @param {String|DOMNode} nodeOrSelector michael@0: * @return {DOMNode} michael@0: */ michael@0: function getNode(nodeOrSelector) { michael@0: return typeof nodeOrSelector === "string" ? michael@0: content.document.querySelector(nodeOrSelector) : michael@0: nodeOrSelector; michael@0: } michael@0: michael@0: /** michael@0: * Set the inspector's current selection to a node or to the first match of the michael@0: * given css selector michael@0: * @param {InspectorPanel} inspector The instance of InspectorPanel currently michael@0: * loaded in the toolbox michael@0: * @param {String} reason Defaults to "test" which instructs the inspector not michael@0: * to highlight the node upon selection michael@0: * @param {String} reason Defaults to "test" which instructs the inspector not to highlight the node upon selection michael@0: * @return a promise that resolves when the inspector is updated with the new michael@0: * node michael@0: */ michael@0: function selectNode(nodeOrSelector, inspector, reason="test") { michael@0: info("Selecting the node " + nodeOrSelector); michael@0: let node = getNode(nodeOrSelector); michael@0: let updated = inspector.once("inspector-updated"); michael@0: inspector.selection.setNode(node, reason); michael@0: return updated; michael@0: } michael@0: michael@0: /** michael@0: * Open the toolbox, with the inspector tool visible. michael@0: * @param {Function} cb Optional callback, if you don't want to use the returned michael@0: * promise michael@0: * @return a promise that resolves when the inspector is ready michael@0: */ michael@0: let openInspector = Task.async(function*(cb) { michael@0: info("Opening the inspector"); michael@0: let target = TargetFactory.forTab(gBrowser.selectedTab); michael@0: michael@0: let inspector, toolbox; michael@0: michael@0: // Checking if the toolbox and the inspector are already loaded michael@0: // The inspector-updated event should only be waited for if the inspector michael@0: // isn't loaded yet michael@0: toolbox = gDevTools.getToolbox(target); michael@0: if (toolbox) { michael@0: inspector = toolbox.getPanel("inspector"); michael@0: if (inspector) { michael@0: info("Toolbox and inspector already open"); michael@0: if (cb) { michael@0: return cb(inspector, toolbox); michael@0: } else { michael@0: return { michael@0: toolbox: toolbox, michael@0: inspector: inspector michael@0: }; michael@0: } michael@0: } michael@0: } michael@0: michael@0: info("Opening the toolbox"); michael@0: toolbox = yield gDevTools.showToolbox(target, "inspector"); michael@0: yield waitForToolboxFrameFocus(toolbox); michael@0: inspector = toolbox.getPanel("inspector"); michael@0: michael@0: info("Waiting for the inspector to update"); michael@0: yield inspector.once("inspector-updated"); michael@0: michael@0: if (cb) { michael@0: return cb(inspector, toolbox); michael@0: } else { michael@0: return { michael@0: toolbox: toolbox, michael@0: inspector: inspector michael@0: }; michael@0: } michael@0: }); michael@0: michael@0: /** michael@0: * Wait for the toolbox frame to receive focus after it loads michael@0: * @param {Toolbox} toolbox michael@0: * @return a promise that resolves when focus has been received michael@0: */ michael@0: function waitForToolboxFrameFocus(toolbox) { michael@0: info("Making sure that the toolbox's frame is focused"); michael@0: let def = promise.defer(); michael@0: let win = toolbox.frame.contentWindow; michael@0: waitForFocus(def.resolve, win); michael@0: return def.promise; michael@0: } michael@0: michael@0: /** michael@0: * Open the toolbox, with the inspector tool visible, and the sidebar that michael@0: * corresponds to the given id selected michael@0: * @return a promise that resolves when the inspector is ready and the sidebar michael@0: * view is visible and ready michael@0: */ michael@0: let openInspectorSideBar = Task.async(function*(id) { michael@0: let {toolbox, inspector} = yield openInspector(); michael@0: michael@0: if (!hasSideBarTab(inspector, id)) { michael@0: info("Waiting for the " + id + " sidebar to be ready"); michael@0: yield inspector.sidebar.once(id + "-ready"); michael@0: } michael@0: michael@0: info("Selecting the " + id + " sidebar"); michael@0: inspector.sidebar.select(id); michael@0: michael@0: return { michael@0: toolbox: toolbox, michael@0: inspector: inspector, michael@0: view: inspector.sidebar.getWindowForTab(id)[id].view michael@0: }; michael@0: }); michael@0: michael@0: /** michael@0: * Open the toolbox, with the inspector tool visible, and the computed-view michael@0: * sidebar tab selected. michael@0: * @return a promise that resolves when the inspector is ready and the computed michael@0: * view is visible and ready michael@0: */ michael@0: function openComputedView() { michael@0: return openInspectorSideBar("computedview"); michael@0: } michael@0: michael@0: /** michael@0: * Open the toolbox, with the inspector tool visible, and the rule-view michael@0: * sidebar tab selected. michael@0: * @return a promise that resolves when the inspector is ready and the rule michael@0: * view is visible and ready michael@0: */ michael@0: function openRuleView() { michael@0: return openInspectorSideBar("ruleview"); michael@0: } michael@0: michael@0: /** michael@0: * Checks whether the inspector's sidebar corresponding to the given id already michael@0: * exists michael@0: * @param {InspectorPanel} michael@0: * @param {String} michael@0: * @return {Boolean} michael@0: */ michael@0: function hasSideBarTab(inspector, id) { michael@0: return !!inspector.sidebar.getWindowForTab(id); michael@0: } michael@0: michael@0: function getActiveInspector() michael@0: { michael@0: let target = TargetFactory.forTab(gBrowser.selectedTab); michael@0: return gDevTools.getToolbox(target).getPanel("inspector"); michael@0: } michael@0: michael@0: function getNodeFront(node) michael@0: { michael@0: let inspector = getActiveInspector(); michael@0: return inspector.walker.frontForRawNode(node); michael@0: } michael@0: michael@0: function getHighlighter() michael@0: { michael@0: return gBrowser.selectedBrowser.parentNode.querySelector(".highlighter-container"); michael@0: } michael@0: michael@0: function getSimpleBorderRect() { michael@0: let {p1, p2, p3, p4} = getBoxModelStatus().border.points; michael@0: michael@0: return { michael@0: top: p1.y, michael@0: left: p1.x, michael@0: width: p2.x - p1.x, michael@0: height: p4.y - p1.y michael@0: }; michael@0: } michael@0: michael@0: function getBoxModelRoot() { michael@0: let highlighter = getHighlighter(); michael@0: return highlighter.querySelector(".box-model-root"); michael@0: } michael@0: michael@0: function getBoxModelStatus() { michael@0: let root = getBoxModelRoot(); michael@0: let inspector = getActiveInspector(); michael@0: michael@0: return { michael@0: visible: !root.hasAttribute("hidden"), michael@0: currentNode: inspector.walker.currentNode, michael@0: margin: { michael@0: points: getPointsForRegion("margin"), michael@0: visible: isRegionHidden("margin") michael@0: }, michael@0: border: { michael@0: points: getPointsForRegion("border"), michael@0: visible: isRegionHidden("border") michael@0: }, michael@0: padding: { michael@0: points: getPointsForRegion("padding"), michael@0: visible: isRegionHidden("padding") michael@0: }, michael@0: content: { michael@0: points: getPointsForRegion("content"), michael@0: visible: isRegionHidden("content") michael@0: }, michael@0: guides: { michael@0: top: getGuideStatus("top"), michael@0: right: getGuideStatus("right"), michael@0: bottom: getGuideStatus("bottom"), michael@0: left: getGuideStatus("left") michael@0: } michael@0: }; michael@0: } michael@0: michael@0: function getGuideStatus(location) { michael@0: let root = getBoxModelRoot(); michael@0: let guide = root.querySelector(".box-model-guide-" + location); michael@0: michael@0: return { michael@0: visible: !guide.hasAttribute("hidden"), michael@0: x1: guide.getAttribute("x1"), michael@0: y1: guide.getAttribute("y1"), michael@0: x2: guide.getAttribute("x2"), michael@0: y2: guide.getAttribute("y2") michael@0: }; michael@0: } michael@0: michael@0: function getPointsForRegion(region) { michael@0: let root = getBoxModelRoot(); michael@0: let box = root.querySelector(".box-model-" + region); michael@0: let points = box.getAttribute("points").split(/[, ]/); michael@0: michael@0: // We multiply each value by 1 to cast it into a number michael@0: return { michael@0: p1: { michael@0: x: parseFloat(points[0]), michael@0: y: parseFloat(points[1]) michael@0: }, michael@0: p2: { michael@0: x: parseFloat(points[2]), michael@0: y: parseFloat(points[3]) michael@0: }, michael@0: p3: { michael@0: x: parseFloat(points[4]), michael@0: y: parseFloat(points[5]) michael@0: }, michael@0: p4: { michael@0: x: parseFloat(points[6]), michael@0: y: parseFloat(points[7]) michael@0: } michael@0: }; michael@0: } michael@0: michael@0: function isRegionHidden(region) { michael@0: let root = getBoxModelRoot(); michael@0: let box = root.querySelector(".box-model-" + region); michael@0: michael@0: return !box.hasAttribute("hidden"); michael@0: } michael@0: michael@0: function isHighlighting() michael@0: { michael@0: let root = getBoxModelRoot(); michael@0: return !root.hasAttribute("hidden"); michael@0: } michael@0: michael@0: function getHighlitNode() michael@0: { michael@0: if (isHighlighting()) { michael@0: let helper = new LayoutHelpers(window.content); michael@0: let points = getBoxModelStatus().content.points; michael@0: let x = (points.p1.x + points.p2.x + points.p3.x + points.p4.x) / 4; michael@0: let y = (points.p1.y + points.p2.y + points.p3.y + points.p4.y) / 4; michael@0: michael@0: return helper.getElementFromPoint(window.content.document, x, y); michael@0: } michael@0: } michael@0: michael@0: function computedView() michael@0: { michael@0: let sidebar = getActiveInspector().sidebar; michael@0: let iframe = sidebar.tabbox.querySelector(".iframe-computedview"); michael@0: return iframe.contentWindow.computedView; michael@0: } michael@0: michael@0: function computedViewTree() michael@0: { michael@0: return computedView().view; michael@0: } michael@0: michael@0: function ruleView() michael@0: { michael@0: let sidebar = getActiveInspector().sidebar; michael@0: let iframe = sidebar.tabbox.querySelector(".iframe-ruleview"); michael@0: return iframe.contentWindow.ruleView; michael@0: } michael@0: michael@0: function getComputedView() { michael@0: let inspector = getActiveInspector(); michael@0: return inspector.sidebar.getWindowForTab("computedview").computedview.view; michael@0: } michael@0: michael@0: function waitForView(aName, aCallback) { michael@0: let inspector = getActiveInspector(); michael@0: if (inspector.sidebar.getTab(aName)) { michael@0: aCallback(); michael@0: } else { michael@0: inspector.sidebar.once(aName + "-ready", aCallback); michael@0: } michael@0: } michael@0: michael@0: function synthesizeKeyFromKeyTag(aKeyId) { michael@0: let key = document.getElementById(aKeyId); michael@0: isnot(key, null, "Successfully retrieved the node"); michael@0: michael@0: let modifiersAttr = key.getAttribute("modifiers"); michael@0: michael@0: let name = null; michael@0: michael@0: if (key.getAttribute("keycode")) michael@0: name = key.getAttribute("keycode"); michael@0: else if (key.getAttribute("key")) michael@0: name = key.getAttribute("key"); michael@0: michael@0: isnot(name, null, "Successfully retrieved keycode/key"); michael@0: michael@0: let modifiers = { michael@0: shiftKey: modifiersAttr.match("shift"), michael@0: ctrlKey: modifiersAttr.match("ctrl"), michael@0: altKey: modifiersAttr.match("alt"), michael@0: metaKey: modifiersAttr.match("meta"), michael@0: accelKey: modifiersAttr.match("accel") michael@0: } michael@0: michael@0: EventUtils.synthesizeKey(name, modifiers); michael@0: } michael@0: michael@0: function focusSearchBoxUsingShortcut(panelWin, callback) { michael@0: panelWin.focus(); michael@0: let key = panelWin.document.getElementById("nodeSearchKey"); michael@0: isnot(key, null, "Successfully retrieved the node"); michael@0: michael@0: let modifiersAttr = key.getAttribute("modifiers"); michael@0: michael@0: let name = null; michael@0: michael@0: if (key.getAttribute("keycode")) { michael@0: name = key.getAttribute("keycode"); michael@0: } else if (key.getAttribute("key")) { michael@0: name = key.getAttribute("key"); michael@0: } michael@0: michael@0: isnot(name, null, "Successfully retrieved keycode/key"); michael@0: michael@0: let modifiers = { michael@0: shiftKey: modifiersAttr.match("shift"), michael@0: ctrlKey: modifiersAttr.match("ctrl"), michael@0: altKey: modifiersAttr.match("alt"), michael@0: metaKey: modifiersAttr.match("meta"), michael@0: accelKey: modifiersAttr.match("accel") michael@0: } michael@0: michael@0: let searchBox = panelWin.document.getElementById("inspector-searchbox"); michael@0: searchBox.addEventListener("focus", function onFocus() { michael@0: searchBox.removeEventListener("focus", onFocus, false); michael@0: callback && callback(); michael@0: }, false); michael@0: EventUtils.synthesizeKey(name, modifiers); michael@0: } michael@0: michael@0: function getComputedPropertyValue(aName) michael@0: { michael@0: let computedview = getComputedView(); michael@0: let props = computedview.styleDocument.querySelectorAll(".property-view"); michael@0: michael@0: for (let prop of props) { michael@0: let name = prop.querySelector(".property-name"); michael@0: michael@0: if (name.textContent === aName) { michael@0: let value = prop.querySelector(".property-value"); michael@0: return value.textContent; michael@0: } michael@0: } michael@0: } michael@0: michael@0: function getContainerForRawNode(markupView, rawNode) michael@0: { michael@0: let front = markupView.walker.frontForRawNode(rawNode); michael@0: let container = markupView.getContainer(front); michael@0: return container; michael@0: } michael@0: michael@0: SimpleTest.registerCleanupFunction(function () { michael@0: let target = TargetFactory.forTab(gBrowser.selectedTab); michael@0: gDevTools.closeToolbox(target); michael@0: });