Backed out 6 changesets (bug 663778) for browser_dbg_listtabs-02.js leaks on a CLOSED TREE.

Backed out changeset cbd200206f9b (bug 663778)
Backed out changeset b0b74401e614 (bug 663778)
Backed out changeset df5255cffbfa (bug 663778)
Backed out changeset e6d0dd124356 (bug 663778)
Backed out changeset 134f77474941 (bug 663778)
Backed out changeset 456609873c5f (bug 663778)
This commit is contained in:
Ryan VanderMeulen 2014-03-13 13:56:22 -04:00
parent 9a2f1aeeb4
commit 991e5c8bc3
72 changed files with 649 additions and 1132 deletions

View File

@ -4,7 +4,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace svg url("http://www.w3.org/2000/svg");
#main-window:not([chromehidden~="toolbar"]) {
%ifdef XP_MACOSX

View File

@ -6,15 +6,25 @@
pointer-events: none;
}
/*
* Box model highlighter
*/
svg|svg.box-model-root[hidden],
svg|line.box-model-guide-top[hidden],
svg|line.box-model-guide-right[hidden],
svg|line.box-model-guide-left[hidden],
svg|line.box-model-guide-bottom[hidden] {
display: none;
.highlighter-outline-container {
overflow: hidden;
position: relative;
}
.highlighter-outline {
position: absolute;
}
.highlighter-outline[hidden] {
opacity: 0;
pointer-events: none;
display: -moz-box;
}
.highlighter-outline:not([disable-transitions]) {
transition-property: opacity, top, left, width, height;
transition-duration: 0.1s;
transition-timing-function: linear;
}
/*
@ -35,6 +45,13 @@ svg|line.box-model-guide-bottom[hidden] {
display: -moz-box;
}
.highlighter-nodeinfobar-positioner:not([disable-transitions]),
.highlighter-nodeinfobar-positioner[disable-transitions][force-transitions] {
transition-property: transform, opacity, top, left;
transition-duration: 0.1s;
transition-timing-function: linear;
}
.highlighter-nodeinfobar-text {
overflow: hidden;
white-space: nowrap;

View File

@ -46,6 +46,6 @@ function test()
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,domplate_test.js";
content.location = "data:text/html,basic domplate tests";
}

View File

@ -19,11 +19,6 @@ const HOSTED_APP_MANIFEST = TEST_BASE + "hosted_app.manifest";
const PACKAGED_APP_DIR_PATH = getTestFilePath(".");
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function addTab(url, targetWindow = window) {
info("Adding tab: " + url);

View File

@ -10,11 +10,6 @@ let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
Services.scriptloader.loadSubScript(testDir + "/mockCommands.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {

View File

@ -207,5 +207,4 @@ registerCleanupFunction(function() {
gDebuggee = null;
gPanel = null;
gDebugger = null;
gVariables = null;
});

View File

@ -27,11 +27,6 @@ let Toolbox = devtools.Toolbox;
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
// All tests are asynchronous.
waitForExplicitFinish();

View File

@ -16,11 +16,6 @@ function test() {
let viewDoc;
let inspector;
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);

View File

@ -32,8 +32,6 @@ this.DevTools = function DevTools() {
this.destroy = this.destroy.bind(this);
this._teardown = this._teardown.bind(this);
this._testing = false;
EventEmitter.decorate(this);
Services.obs.addObserver(this._teardown, "devtools-unloaded", false);
@ -41,29 +39,6 @@ this.DevTools = function DevTools() {
}
DevTools.prototype = {
/**
* When the testing flag is set we take appropriate action to prevent race
* conditions in our testing environment. This means setting
* dom.send_after_paint_to_content to false to prevent infinite MozAfterPaint
* loops and not autohiding the highlighter.
*/
get testing() {
return this._testing;
},
set testing(state) {
this._testing = state;
if (state) {
// dom.send_after_paint_to_content is set to true (non-default) in
// testing/profiles/prefs_general.js so lets set it to the same as it is
// in a default browser profile for the duration of the test.
Services.prefs.setBoolPref("dom.send_after_paint_to_content", false);
} else {
Services.prefs.setBoolPref("dom.send_after_paint_to_content", true);
}
},
/**
* Register a new developer tool.
*

View File

@ -160,22 +160,20 @@ Selection.prototype = {
setNodeFront: function(value, reason="unknown") {
this.reason = reason;
// We used to return here if the node had not changed but we now need to
// set the node even if it is already set otherwise it is not possible to
// e.g. highlight the same node twice.
let rawValue = null;
if (value && value.isLocal_toBeDeprecated()) {
rawValue = value.rawNode();
if (value !== this._nodeFront) {
let rawValue = null;
if (value && value.isLocal_toBeDeprecated()) {
rawValue = value.rawNode();
}
this.emit("before-new-node", rawValue, reason);
this.emit("before-new-node-front", value, reason);
let previousNode = this._node;
let previousFront = this._nodeFront;
this._node = rawValue;
this._nodeFront = value;
this.emit("new-node", previousNode, this.reason);
this.emit("new-node-front", value, this.reason);
}
this.emit("before-new-node", rawValue, reason);
this.emit("before-new-node-front", value, reason);
let previousNode = this._node;
let previousFront = this._nodeFront;
this._node = rawValue;
this._nodeFront = value;
this.emit("new-node", previousNode, this.reason);
this.emit("new-node-front", value, this.reason);
},
get documentFront() {

View File

@ -13,11 +13,6 @@ let promise = tempScope.Promise;
let {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
/**
* Open a new tab at a URL and call a callback on load
*/

View File

@ -73,8 +73,6 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this)
this.destroy = this.destroy.bind(this);
this.highlighterUtils = new ToolboxHighlighterUtils(this);
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
this._target.on("close", this.destroy);
@ -1099,14 +1097,8 @@ Toolbox.prototype = {
this._inspector = InspectorFront(this._target.client, this._target.form);
this._walker = yield this._inspector.getWalker();
this._selection = new Selection(this._walker);
if (this.highlighterUtils.isRemoteHighlightable) {
let autohide = !gDevTools.testing;
this.walker.on("highlighter-ready", this._highlighterReady);
this.walker.on("highlighter-hide", this._highlighterHidden);
this._highlighter = yield this._inspector.getHighlighter(autohide);
this._highlighter = yield this._inspector.getHighlighter();
}
}.bind(this));
}
@ -1118,10 +1110,6 @@ Toolbox.prototype = {
* Returns a promise that resolves when the fronts are destroyed
*/
destroyInspector: function() {
if (this._destroying) {
return this._destroying;
}
if (!this._inspector) {
return promise.resolve();
}
@ -1137,11 +1125,6 @@ Toolbox.prototype = {
this._selection.destroy();
}
if (this.walker) {
this.walker.off("highlighter-ready", this._highlighterReady);
this.walker.off("highlighter-hide", this._highlighterHidden);
}
this._inspector = null;
this._highlighter = null;
this._selection = null;
@ -1152,9 +1135,7 @@ Toolbox.prototype = {
// Releasing the walker (if it has been created)
// This can fail, but in any case, we want to continue destroying the
// inspector/highlighter/selection
let walker = (this._destroying = this._walker) ?
this._walker.release() :
promise.resolve();
let walker = this._walker ? this._walker.release() : promise.resolve();
return walker.then(outstanding, outstanding);
},
@ -1243,15 +1224,7 @@ Toolbox.prototype = {
this._host = null;
this._toolPanels.clear();
}).then(null, console.error);
},
_highlighterReady: function() {
this.emit("highlighter-ready");
},
_highlighterHidden: function() {
this.emit("highlighter-hide");
},
}
};
/**
@ -1311,7 +1284,6 @@ ToolboxHighlighterUtils.prototype = {
let deferred = promise.defer();
let done = () => {
this._isPicking = true;
this.toolbox.emit("picker-started");
this.toolbox.on("select", this.stopPicker);
deferred.resolve();
@ -1321,20 +1293,20 @@ ToolboxHighlighterUtils.prototype = {
this.toolbox.initInspector(),
this.toolbox.selectTool("inspector")
]).then(() => {
this._isPicking = true;
this.toolbox._pickerButton.setAttribute("checked", "true");
if (this.isRemoteHighlightable) {
this.toolbox.highlighter.pick().then(done);
this.toolbox.walker.on("picker-node-hovered", this._onPickerNodeHovered);
this.toolbox.walker.on("picker-node-picked", this._onPickerNodePicked);
this.toolbox.highlighter.pick().then(done);
} else {
return this.toolbox.walker.pick().then(node => {
this.toolbox.selection.setNodeFront(node, "picker-node-picked").then(() => {
this.stopPicker();
done();
});
this.toolbox.walker.pick().then(node => {
this.toolbox.selection.setNodeFront(node, "picker-node-picked");
this.stopPicker();
});
done();
}
});
@ -1432,16 +1404,11 @@ ToolboxHighlighterUtils.prototype = {
* Hide the highlighter.
* @return a promise that resolves when the highlighter is hidden
*/
unhighlight: function(forceHide=false) {
unhighlight: function() {
if (this.isRemoteHighlightable) {
// If the remote highlighter exists on the target, use it
return this.toolbox.initInspector().then(() => {
let autohide = forceHide || !gDevTools.testing;
if (autohide) {
return this.toolbox.highlighter.hideBoxModel();
}
return promise.resolve();
return this.toolbox.highlighter.hideBoxModel();
});
} else {
// If not, no need to unhighlight as the older highlight method uses a

View File

@ -699,7 +699,7 @@ HTMLBreadcrumbs.prototype = {
this.selectionGuardEnd(err);
});
}
};
}
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);

View File

@ -18,21 +18,24 @@ function test() {
waitForFocus(setupTest, content);
}, true);
content.location = "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>";
content.location = "data:text/html,<h1>foo</h1><h2>bar</h2>";
function setupTest() {
openInspector((aInspector, aToolbox) => {
toolbox = aToolbox;
inspector = aInspector;
inspector.selection.setNode(doc.querySelector("span"), "test");
inspector.toolbox.once("highlighter-ready", runTests);
inspector.selection.setNode(doc.querySelector("h2"), null);
inspector.once("inspector-updated", runTests);
});
}
function runTests() {
function runTests(aInspector) {
getHighlighterOutline().setAttribute("disable-transitions", "true");
Task.spawn(function() {
yield hoverH1InMarkupView();
yield assertH1Highlighted();
yield mouseLeaveMarkupView();
yield assertNoNodeHighlighted();
finishUp();
}).then(null, Cu.reportError);
@ -40,11 +43,11 @@ function test() {
function hoverH1InMarkupView() {
let deferred = promise.defer();
let container = getContainerForRawNode(inspector.markup, doc.querySelector("h1"));
inspector.toolbox.once("highlighter-ready", deferred.resolve);
EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
inspector.markup.doc.defaultView);
let container = getContainerForRawNode(inspector.markup, doc.querySelector("h1"));
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
inspector.markup.doc.defaultView);
inspector.toolbox.once("node-highlight", deferred.resolve);
return deferred.promise;
}
@ -52,6 +55,25 @@ function test() {
function assertH1Highlighted() {
ok(isHighlighting(), "The highlighter is shown on a markup container hover");
is(getHighlitNode(), doc.querySelector("h1"), "The highlighter highlights the right node");
return promise.resolve();
}
function mouseLeaveMarkupView() {
let deferred = promise.defer();
// Find another element to mouseover over in order to leave the markup-view
let btn = toolbox.doc.querySelector(".toolbox-dock-button");
EventUtils.synthesizeMouse(btn, 2, 2, {type: "mousemove"},
toolbox.doc.defaultView);
executeSoon(deferred.resolve);
return deferred.promise;
}
function assertNoNodeHighlighted() {
ok(!isHighlighting(), "After the mouse left the markup view, the highlighter is hidden");
return promise.resolve();
}
function finishUp() {

View File

@ -91,7 +91,7 @@ function test()
}
function finishUp() {
doc = nodes = inspector = null;
doc = nodes = null;
gBrowser.removeCurrentTab();
finish();
}

View File

@ -52,8 +52,7 @@ function test()
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/" +
"inspector/test/browser_inspector_bug_650804_search.html";
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_650804_search.html";
function $(id) {
if (id == null) return null;

View File

@ -50,6 +50,7 @@ function test()
inspector = aInspector;
// Make sure the highlighter is shown so we can disable transitions
inspector.toolbox.highlighter.showBoxModel(getNodeFront(doc.body)).then(() => {
getHighlighterOutline().setAttribute("disable-transitions", "true");
runTests();
});
});
@ -64,17 +65,12 @@ function test()
function isTheIframeHighlighted()
{
let {p1, p2, p3, p4} = getBoxModelStatus().border.points;
let {top, right, bottom, left} = iframeNode.getBoundingClientRect();
is(top, p1.y, "iframeRect.top === boxModelStatus.p1.y");
is(top, p2.y, "iframeRect.top === boxModelStatus.p2.y");
is(right, p2.x, "iframeRect.right === boxModelStatus.p2.x");
is(right, p3.x, "iframeRect.right === boxModelStatus.p3.x");
is(bottom, p3.y, "iframeRect.bottom === boxModelStatus.p3.y");
is(bottom, p4.y, "iframeRect.bottom === boxModelStatus.p4.y");
is(left, p1.x, "iframeRect.left === boxModelStatus.p1.x");
is(left, p4.x, "iframeRect.left === boxModelStatus.p4.x");
let outlineRect = getHighlighterOutlineRect();
let iframeRect = iframeNode.getBoundingClientRect();
for (let dim of ["width", "height", "top", "left"]) {
is(Math.floor(outlineRect[dim]), Math.floor(iframeRect[dim]),
"Outline dimension is correct " + outlineRect[dim]);
}
iframeNode.style.marginBottom = doc.defaultView.innerHeight + "px";
doc.defaultView.scrollBy(0, 40);
@ -86,8 +82,9 @@ function test()
{
is(getHighlitNode(), iframeBodyNode, "highlighter shows the right node");
let outlineRect = getSimpleBorderRect();
is(outlineRect.height, 200, "highlighter height");
// 184 == 200 + 11(border) + 13(padding) - 40(scroll)
let outlineRect = getHighlighterOutlineRect();
is(outlineRect.height, 184, "highlighter height");
inspector.toolbox.highlighterUtils.stopPicker().then(() => {
let target = TargetFactory.forTab(gBrowser.selectedTab);

View File

@ -18,7 +18,12 @@ function test() {
inspector.toolbox.highlighterUtils.startPicker().then(() => {
EventUtils.synthesizeMouse(content.document.body, 1, 1,
{type: "mousemove"}, content);
inspector.toolbox.once("highlighter-ready", cb);
inspector.toolbox.once("picker-node-hovered", () => {
executeSoon(() => {
getHighlighterOutline().setAttribute("disable-transitions", "true");
cb();
});
});
});
}
@ -30,7 +35,8 @@ function test() {
ok(isHighlighting(), "Inspector is highlighting");
iframe.addEventListener("load", onIframeLoad, false);
executeSoon(() => {
executeSoon(function() {
iframe.contentWindow.location = "javascript:location.reload()";
});
});
@ -45,7 +51,6 @@ function test() {
}
iframe.removeEventListener("load", onIframeLoad, false);
info("Finished reloading iframe and inspector updated");
ok(isHighlighting(), "Inspector is highlighting after iframe nav");
@ -73,7 +78,6 @@ function test() {
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html;charset=utf-8," +
"<p>bug 699308 - test iframe navigation</p>" +
"<iframe src='data:text/html;charset=utf-8,hello world'></iframe>";
content.location = "data:text/html,<p>bug 699308 - test iframe navigation" +
"<iframe src='data:text/html,hello world'></iframe>";
}

View File

@ -77,6 +77,7 @@ function prepareHighlighter() {
let deferred = promise.defer();
inspector.selection.setNode(doc.querySelector("p"), null);
inspector.once("inspector-updated", () => {
getHighlighterOutline().setAttribute("disable-transitions", "true");
deferred.resolve();
});
return deferred.promise;

View File

@ -150,5 +150,5 @@ function test() {
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -51,29 +51,30 @@ function createDocument() {
inspector = aInspector;
inspector.selection.setNode(div, null);
inspector.once("inspector-updated", () => {
getHighlighterOutline().setAttribute("disable-transitions", "true");
inspector.toolbox.highlighterUtils.startPicker().then(testMouseOverH1Highlights);
});
});
}
function testMouseOverH1Highlights() {
inspector.toolbox.once("highlighter-ready", () => {
inspector.toolbox.once("picker-node-hovered", () => {
ok(isHighlighting(), "Highlighter is shown");
is(getHighlitNode(), h1, "Highlighter's outline correspond to the selected node");
testBoxModelDimensions();
testOutlineDimensions();
});
EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
}
function testBoxModelDimensions() {
function testOutlineDimensions() {
let h1Dims = h1.getBoundingClientRect();
let h1Width = Math.ceil(h1Dims.width);
let h1Height = Math.ceil(h1Dims.height);
let h1Width = h1Dims.width;
let h1Height = h1Dims.height;
let outlineDims = getSimpleBorderRect();
let outlineWidth = Math.ceil(outlineDims.width);
let outlineHeight = Math.ceil(outlineDims.height);
let outlineDims = getHighlighterOutlineRect();
let outlineWidth = outlineDims.width;
let outlineHeight = outlineDims.height;
// Disabled due to bug 716245
is(outlineWidth, h1Width, "outline width matches dimensions of element (no zoom)");
@ -84,22 +85,27 @@ function testBoxModelDimensions() {
.QueryInterface(Ci.nsIMarkupDocumentViewer);
contentViewer.fullZoom = 2;
// simulate the zoomed dimensions of the div element
let h1Dims = h1.getBoundingClientRect();
// There seems to be some very minor differences in the floats, so let's
// floor the values
let h1Width = Math.floor(h1Dims.width * contentViewer.fullZoom);
let h1Height = Math.floor(h1Dims.height * contentViewer.fullZoom);
// We wait at least 500ms to make sure the highlighter is not "mutting" the
// resize event
let outlineDims = getSimpleBorderRect();
let outlineWidth = Math.floor(outlineDims.width);
let outlineHeight = Math.floor(outlineDims.height);
window.setTimeout(function() {
// simulate the zoomed dimensions of the div element
let h1Dims = h1.getBoundingClientRect();
// There seems to be some very minor differences in the floats, so let's
// floor the values
let h1Width = Math.floor(h1Dims.width * contentViewer.fullZoom);
let h1Height = Math.floor(h1Dims.height * contentViewer.fullZoom);
is(outlineWidth, h1Width, "outline width matches dimensions of element (zoomed)");
let outlineDims = getHighlighterOutlineRect();
let outlineWidth = Math.floor(outlineDims.width);
let outlineHeight = Math.floor(outlineDims.height);
is(outlineHeight, h1Height, "outline height matches dimensions of element (zoomed)");
// Disabled due to bug 716245
is(outlineWidth, h1Width, "outline width matches dimensions of element (zoomed)");
is(outlineHeight, h1Height, "outline height matches dimensions of element (zoomed)");
executeSoon(finishUp);
executeSoon(finishUp);
}, 500);
}
function finishUp() {
@ -121,5 +127,5 @@ function test() {
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_highlighter.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -31,13 +31,10 @@ function createDocument() {
div2 = iframe2.contentDocument.createElement('div');
div2.textContent = 'nested div';
iframe2.contentDocument.body.appendChild(div2);
// Open the inspector, start the picker mode, and start the tests
openInspector(aInspector => {
inspector = aInspector;
inspector.once("inspector-updated", () => {
inspector.toolbox.highlighterUtils.startPicker().then(runTests);
});
inspector.toolbox.highlighterUtils.startPicker().then(runTests);
});
}, false);
@ -50,7 +47,9 @@ function createDocument() {
}
function moveMouseOver(aElement, cb) {
inspector.toolbox.once("picker-node-hovered", cb);
inspector.toolbox.once("picker-node-hovered", () => {
executeSoon(cb);
});
EventUtils.synthesizeMouseAtCenter(aElement, {type: "mousemove"},
aElement.ownerDocument.defaultView);
}
@ -61,14 +60,15 @@ function runTests() {
function testDiv1Highlighter() {
moveMouseOver(div1, () => {
is(getHighlitNode(), div1, "highlighter matches selection of div1");
getHighlighterOutline().setAttribute("disable-transitions", "true");
is(getHighlitNode(), div1, "highlighter matches selection");
testDiv2Highlighter();
});
}
function testDiv2Highlighter() {
moveMouseOver(div2, () => {
is(getHighlitNode(), div2, "highlighter matches selection of div2");
is(getHighlitNode(), div2, "highlighter matches selection");
selectRoot();
});
}

View File

@ -137,5 +137,5 @@ function test()
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_initialization.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -13,24 +13,24 @@ function test() {
openInspector(aInspector => {
inspector = aInspector;
inspector.once("inspector-updated", () => {
inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
});
inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
});
}
function runTest() {
let rect = getSimpleBorderRect();
is(rect.width, 100, "outline has the right width");
let outline = getHighlighterOutline();
is(outline.style.width, "100px", "outline has the right width");
div.style.width = "200px";
inspector.toolbox.once("highlighter-ready", testRectWidth);
}
function testRectWidth() {
let rect = getSimpleBorderRect();
is(rect.width, 200, "outline updated");
finishUp();
function pollTest() {
if (outline.style.width == "100px") {
setTimeout(pollTest, 10);
return;
}
is(outline.style.width, "200px", "outline updated");
finishUp();
}
setTimeout(pollTest, 10);
}
function finishUp() {
@ -49,5 +49,5 @@ function test() {
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_invalidate.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -33,34 +33,34 @@ function inspectNode(aInspector)
{
inspector = aInspector;
let highlighter = inspector.toolbox.highlighter;
highlighter.showBoxModel(getNodeFront(div)).then(performScrollingTest);
inspector.once("inspector-updated", performScrollingTest);
executeSoon(function() {
inspector.selection.setNode(div, "");
});
}
function performScrollingTest()
{
executeSoon(function() {
// FIXME: this will fail on retina displays. EventUtils will only scroll
// 25px down instead of 50.
EventUtils.synthesizeWheel(div, 10, 10,
{ deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
iframe.contentWindow);
});
gBrowser.selectedBrowser.addEventListener("scroll", function() {
gBrowser.selectedBrowser.removeEventListener("scroll", arguments.callee,
false);
let isRetina = devicePixelRatio === 2;
is(iframe.contentDocument.body.scrollTop,
isRetina ? 25 : 50, "inspected iframe scrolled");
finishUp();
is(iframe.contentDocument.body.scrollTop, 50, "inspected iframe scrolled");
inspector = div = iframe = doc = null;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
gBrowser.removeCurrentTab();
finish();
}, false);
EventUtils.synthesizeWheel(div, 10, 10,
{ deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
iframe.contentWindow);
}
function finishUp()
{
inspector = div = iframe = doc = null;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
gBrowser.removeCurrentTab();
finish();
}
function test()

View File

@ -25,19 +25,18 @@ function inspectorRuleViewOpened()
gDevTools.once("toolbox-destroyed", inspectorClosed);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
gDevTools.getToolbox(target).destroy();
}
function inspectorClosed()
{
openInspector(function(panel) {
inspector = panel;
if (inspector.sidebar.getCurrentTabID()) {
info("Default sidebar already selected.")
// Default sidebar already selected.
testNewDefaultTab();
} else {
info("Default sidebar still to be selected, adding select listener.");
// Default sidebar still to be selected.
inspector.sidebar.once("select", testNewDefaultTab);
}
});
@ -68,5 +67,5 @@ function test()
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_sidebarstate.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -106,6 +106,6 @@ function test()
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_tree_height.js";
content.location = "data:text/html,basic tests for inspector";
}

View File

@ -27,18 +27,12 @@ let console = tempScope.console;
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
SimpleTest.registerCleanupFunction(() => {
console.error("Here we are\n");
console.error("Here we are\n")
let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
console.error("DebuggerServer open connections: " + Object.getOwnPropertyNames(DebuggerServer._connections).length);
Services.prefs.clearUserPref("devtools.dump.emit");
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
});
function openInspector(callback)
@ -66,118 +60,63 @@ function getHighlighter()
return gBrowser.selectedBrowser.parentNode.querySelector(".highlighter-container");
}
function getSimpleBorderRect() {
let {p1, p2, p3, p4} = getBoxModelStatus().border.points;
return {
top: p1.y,
left: p1.x,
width: p2.x - p1.x,
height: p4.y - p1.y
};
function getHighlighterOutline()
{
let h = getHighlighter();
if (h) {
return h.querySelector(".highlighter-outline");
}
}
function getBoxModelRoot() {
let highlighter = getHighlighter();
return highlighter.querySelector(".box-model-root");
}
function getHighlighterOutlineRect() {
let helper = new LayoutHelpers(window.content);
let outline = getHighlighterOutline();
function getBoxModelStatus() {
let root = getBoxModelRoot();
let inspector = getActiveInspector();
if (outline) {
let browserOffsetRect = helper.getDirtyRect(gBrowser.selectedBrowser);
let outlineRect = helper.getDirtyRect(outline);
outlineRect.top -= browserOffsetRect.top;
outlineRect.left -= browserOffsetRect.left;
return {
visible: !root.hasAttribute("hidden"),
currentNode: inspector.walker.currentNode,
margin: {
points: getPointsForRegion("margin"),
visible: isRegionHidden("margin")
},
border: {
points: getPointsForRegion("border"),
visible: isRegionHidden("border")
},
padding: {
points: getPointsForRegion("padding"),
visible: isRegionHidden("padding")
},
content: {
points: getPointsForRegion("content"),
visible: isRegionHidden("content")
},
guides: {
top: getGuideStatus("top"),
right: getGuideStatus("right"),
bottom: getGuideStatus("bottom"),
left: getGuideStatus("left")
}
};
}
function getGuideStatus(location) {
let root = getBoxModelRoot();
let guide = root.querySelector(".box-model-guide-" + location);
return {
visible: !guide.hasAttribute("hidden"),
x1: guide.getAttribute("x1"),
y1: guide.getAttribute("y1"),
x2: guide.getAttribute("x2"),
y2: guide.getAttribute("y2")
};
}
function getPointsForRegion(region) {
let root = getBoxModelRoot();
let box = root.querySelector(".box-model-" + region);
let points = box.getAttribute("points").split(/[, ]/);
// We multiply each value by 1 to cast it into a number
return {
p1: {
x: parseFloat(points[0]),
y: parseFloat(points[1])
},
p2: {
x: parseFloat(points[2]),
y: parseFloat(points[3])
},
p3: {
x: parseFloat(points[4]),
y: parseFloat(points[5])
},
p4: {
x: parseFloat(points[6]),
y: parseFloat(points[7])
}
};
}
function isRegionHidden(region) {
let root = getBoxModelRoot();
let box = root.querySelector(".box-model-" + region);
return !box.hasAttribute("hidden");
return outlineRect;
}
}
function isHighlighting()
{
let root = getBoxModelRoot();
return !root.hasAttribute("hidden");
let outline = getHighlighterOutline();
return outline && !outline.hasAttribute("hidden");
}
function getHighlitNode()
{
if (isHighlighting()) {
let helper = new LayoutHelpers(window.content);
let points = getBoxModelStatus().content.points;
let x = (points.p1.x + points.p2.x + points.p3.x + points.p4.x) / 4;
let y = (points.p1.y + points.p2.y + points.p3.y + points.p4.y) / 4;
let outlineRect = getHighlighterOutlineRect();
let a = {
x: outlineRect.left,
y: outlineRect.top
};
let b = {
x: a.x + outlineRect.width,
y: a.y + outlineRect.height
};
let {x, y} = getMidPoint(a, b);
return helper.getElementFromPoint(window.content.document, x, y);
}
}
function getMidPoint(aPointA, aPointB)
{
let pointC = {};
pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
return pointC;
}
function computedView()
{
let sidebar = getActiveInspector().sidebar;

View File

@ -7,11 +7,6 @@ let TargetFactory = devtools.TargetFactory;
function test() {
waitForExplicitFinish();
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", true);
let doc;

View File

@ -54,23 +54,23 @@ body {
}
}
#content,
#borders {
border-width: 1px;
#margins {
padding: 28px;
}
#content {
height: 25px;
height: 20px;
border-width: 1px;
}
#margins,
#padding {
border-style: solid;
border-width: 25px;
}
#borders {
padding: 25px;
border-width: 2px;
box-shadow: 0 0 16px black;
}
#main > p {
@ -89,44 +89,55 @@ body {
cursor: default;
}
.top,
.bottom {
.border.top {
left: 0; top: 23px;
width: 98px;
}
.border.bottom {
right: 0; bottom: 22px;
width: 98px;
top: auto;
}
.border.left {
top: 42px; left: 0;
width: 56px;
}
.border.right{
bottom: 42px; right: 0;
width: 56px;
top: auto;
}
.top, .bottom {
width: calc(100% - 2px);
text-align: center;
}
.padding.top {
top: 55px;
}
.padding.bottom {
bottom: 57px;
}
.border.top {
top: 30px;
}
.border.bottom {
bottom: 31px;
}
.margin.top {
top: 5px;
top: 8px;
}
.margin.bottom {
bottom: 6px;
}
.padding.top {
top: 35px;
}
.padding.bottom {
bottom: 35px;
}
.size,
.margin.left,
.margin.right,
.border.left,
.border.right,
.padding.left,
.padding.right {
top: 22px;
top: 0;
line-height: 132px;
}
@ -135,30 +146,15 @@ body {
}
.margin.right,
.margin.left,
.border.left,
.border.right,
.margin.left {
width: 28px;
}
.padding.right,
.padding.left {
width: 25px;
}
.padding.left {
left: 52px;
}
.padding.right {
right: 51px;
}
.border.left {
left: 26px;
}
.border.right {
right: 26px;
}
.margin.right {
right: 0;
}
@ -167,6 +163,14 @@ body {
left: 0;
}
.padding.left {
left: 30px;
}
.padding.right {
right: 30px;
}
.tooltip {
position: absolute;
bottom: 0;

View File

@ -239,41 +239,12 @@ LayoutView.prototype = {
this._lastRequest = lastRequest;
return this._lastRequest;
},
showBoxModel: function(options={}) {
let toolbox = this.inspector.toolbox;
let nodeFront = this.inspector.selection.nodeFront;
toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
},
hideBoxModel: function() {
let toolbox = this.inspector.toolbox;
toolbox.highlighterUtils.unhighlight();
},
};
}
}
let elts;
let tooltip;
let onmouseover = function(e) {
let region = e.target.getAttribute("data-box");
tooltip.textContent = e.target.getAttribute("tooltip");
this.layoutview.showBoxModel({region: region});
return false;
}.bind(window);
let onmouseout = function(e) {
tooltip.textContent = "";
this.layoutview.hideBoxModel();
return false;
}.bind(window);
window.setPanel = function(panel) {
this.layoutview = new LayoutView(panel, window);
@ -305,3 +276,11 @@ window.onunload = function() {
}
}
};
function onmouseover(e) {
tooltip.textContent = e.target.getAttribute("tooltip");
}
function onmouseout(e) {
tooltip.textContent = "";
}

View File

@ -30,31 +30,31 @@
<div id="main">
<div id="margins" data-box="margin" tooltip="&margins.tooltip;">
<div id="borders" data-box="border" tooltip="&borders.tooltip;">
<div id="padding" data-box="padding" tooltip="&padding.tooltip;">
<div id="content" data-box="content" tooltip="&content.tooltip;">
<div id="margins" tooltip="&margins.tooltip;">
<div id="borders" tooltip="&borders.tooltip;">
<div id="padding" tooltip="&padding.tooltip;">
<div id="content" tooltip="&content.tooltip;">
</div>
</div>
</div>
</div>
<p class="border top"><span data-box="border" tooltip="border-top"></span></p>
<p class="border right"><span data-box="border" tooltip="border-right"></span></p>
<p class="border bottom"><span data-box="border" tooltip="border-bottom"></span></p>
<p class="border left"><span data-box="border" tooltip="border-left"></span></p>
<p class="border top"><span tooltip="border-top"></span></p>
<p class="border right"><span tooltip="border-right"></span></p>
<p class="border bottom"><span tooltip="border-bottom"></span></p>
<p class="border left"><span tooltip="border-left"></span></p>
<p class="margin top"><span data-box="margin" tooltip="margin-top"></span></p>
<p class="margin right"><span data-box="margin" tooltip="margin-right"></span></p>
<p class="margin bottom"><span data-box="margin" tooltip="margin-bottom"></span></p>
<p class="margin left"><span data-box="margin" tooltip="margin-left"></span></p>
<p class="margin top"><span tooltip="margin-top"></span></p>
<p class="margin right"><span tooltip="margin-right"></span></p>
<p class="margin bottom"><span tooltip="margin-bottom"></span></p>
<p class="margin left"><span tooltip="margin-left"></span></p>
<p class="padding top"><span data-box="padding" tooltip="padding-top"></span></p>
<p class="padding right"><span data-box="padding" tooltip="padding-right"></span></p>
<p class="padding bottom"><span data-box="padding" tooltip="padding-bottom"></span></p>
<p class="padding left"><span data-box="padding" tooltip="padding-left"></span></p>
<p class="padding top"><span tooltip="padding-top"></span></p>
<p class="padding right"><span tooltip="padding-right"></span></p>
<p class="padding bottom"><span tooltip="padding-bottom"></span></p>
<p class="padding left"><span tooltip="padding-left"></span></p>
<p class="size"><span data-box="content" tooltip="&content.tooltip;"></span></p>
<p class="size"><span tooltip="&content.tooltip;"></span></p>
<span class="tooltip"></span>

View File

@ -165,7 +165,7 @@ MarkupView.prototype = {
},
_onMouseLeave: function() {
this._hideBoxModel(true);
this._hideBoxModel();
if (this._hoveredNode) {
this._containers.get(this._hoveredNode).hovered = false;
}
@ -176,8 +176,8 @@ MarkupView.prototype = {
this._inspector.toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
},
_hideBoxModel: function(forceHide) {
this._inspector.toolbox.highlighterUtils.unhighlight(forceHide);
_hideBoxModel: function() {
this._inspector.toolbox.highlighterUtils.unhighlight();
},
_briefBoxModelTimer: null,
@ -1545,6 +1545,8 @@ MarkupContainer.prototype = {
// Remove event listeners
this.elt.removeEventListener("dblclick", this._onToggle, false);
this.elt.removeEventListener("mouseover", this._onMouseOver, false);
this.elt.removeEventListener("mouseout", this._onMouseOut, false);
this.elt.removeEventListener("mousedown", this._onMouseDown, false);
this.expander.removeEventListener("click", this._onToggle, false);

View File

@ -15,7 +15,7 @@ function test() {
waitForFocus(startTests, content);
}, true);
content.location = "data:text/html;charset=utf-8,<p>Select me!</p>";
content.location = "data:text/html,<p>Select me!</p>";
}
function startTests(aInspector, aToolbox) {

View File

@ -15,7 +15,7 @@ function test() {
waitForFocus(startTests, content);
}, true);
content.location = "data:text/html;charset=utf-8,<p>It's going to be legen....</p>";
content.location = "data:text/html,<p>It's going to be legen....</p>";
}
function startTests(aInspector, aToolbox) {

View File

@ -125,7 +125,7 @@ function test() {
break;
}
inspector.markup._waitForChildren().then(() => executeSoon(() => {
inspector.markup._waitForChildren().then(() => executeSoon(function BIMNT_newNode() {
let node = inspector.selection.node;
if (className == "*comment*") {

View File

@ -12,11 +12,6 @@ let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared
//Services.prefs.setBoolPref("devtools.dump.emit", true);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
// Clear preferences that may be set during the course of tests.
function clearUserPrefs() {
Services.prefs.clearUserPref("devtools.inspector.htmlPanelOpen");
@ -125,7 +120,7 @@ function hoverContainer(nodeOrSelector, inspector) {
info("Hovering over the markup-container for node " + nodeOrSelector);
let highlit = inspector.toolbox.once("node-highlight");
let container = getContainerForRawNode(inspector.markup, getNode(nodeOrSelector));
EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
inspector.markup.doc.defaultView);
return highlit;
}
@ -153,9 +148,8 @@ function clickContainer(nodeOrSelector, inspector) {
* @return {Boolean}
*/
function isHighlighterVisible() {
let highlighter = gBrowser.selectedBrowser.parentNode
.querySelector(".highlighter-container .box-model-root");
return highlighter && !highlighter.hasAttribute("hidden");
let outline = gBrowser.selectedBrowser.parentNode.querySelector(".highlighter-container .highlighter-outline");
return outline && !outline.hasAttribute("hidden");
}
/**
@ -170,7 +164,7 @@ function mouseLeaveMarkupView(inspector) {
// Find another element to mouseover over in order to leave the markup-view
let btn = inspector.toolbox.doc.querySelector(".toolbox-dock-button");
EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"},
EventUtils.synthesizeMouse(btn, 2, 2, {type: "mousemove"},
inspector.toolbox.doc.defaultView);
executeSoon(def.resolve);

View File

@ -43,11 +43,6 @@ const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs";
const TEST_IMAGE = EXAMPLE_URL + "test-image.png";
const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==";
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
// All tests are asynchronous.
waitForExplicitFinish();
@ -60,7 +55,6 @@ const gDefaultFilters = Services.prefs.getCharPref("devtools.netmonitor.filters"
registerCleanupFunction(() => {
info("finish() was called, cleaning up...");
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
Services.prefs.setCharPref("devtools.netmonitor.filters", gDefaultFilters);
});

View File

@ -23,11 +23,6 @@ let DebuggerServer = temp.DebuggerServer;
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
registerCleanupFunction(function () {
helpers = null;
Services.prefs.clearUserPref(PROFILER_ENABLED);

View File

@ -10,11 +10,6 @@ let TargetFactory = devtools.TargetFactory;
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function openInspector(callback)
{
let target = TargetFactory.forTab(gBrowser.selectedTab);

View File

@ -90,7 +90,8 @@ function testAfterSecondRevert() {
ok(menu.hasAttribute("disabled"),
"Revert menu entry is disabled after reverting to changed saved state.");
gFile.remove(false);
gFile = gScratchpad = menu = null;
gFile = null;
gScratchpad = null;
finish();
}

View File

@ -10,11 +10,6 @@ const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let gScratchpadWindow; // Reference to the Scratchpad chrome window object
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
/**
* Open a Scratchpad window.
*

View File

@ -6,11 +6,6 @@ let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
/**
* Open a new tab at a URL and call a callback on load
*/

View File

@ -32,7 +32,8 @@ const CM_STYLES = [
"chrome://browser/skin/devtools/common.css",
"chrome://browser/content/devtools/codemirror/codemirror.css",
"chrome://browser/content/devtools/codemirror/dialog.css",
"chrome://browser/content/devtools/codemirror/mozilla.css"
"chrome://browser/content/devtools/codemirror/mozilla.css",
"chrome://browser/content/devtools/codemirror/foldgutter.css"
];
const CM_SCRIPTS = [

View File

@ -8,11 +8,6 @@ const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {})
const { require } = devtools;
const Editor = require("devtools/sourceeditor/editor");
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function setup(cb) {
const opt = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
const url = "data:text/xml;charset=UTF-8,<?xml version='1.0'?>" +

View File

@ -23,11 +23,6 @@ let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function cleanup()
{
gPanelWindow = null;

View File

@ -135,7 +135,7 @@ RuleViewTool.prototype = {
delete this.doc;
delete this.inspector;
}
};
}
function ComputedViewTool(aInspector, aWindow, aIFrame)
{

View File

@ -112,5 +112,5 @@ function test()
waitForFocus(() => openRuleView(simpleInherit), content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
content.location = "data:text/html,basic style inspector tests";
}

View File

@ -83,5 +83,5 @@ function test()
waitForFocus(() => openRuleView(simpleOverride), content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_ruleview_manipulation.js";
content.location = "data:text/html,basic style inspector tests";
}

View File

@ -178,5 +178,5 @@ function test()
waitForFocus(() => openRuleView(simpleOverride), content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_ruleview_override.js";
content.location = "data:text/html,basic style inspector tests";
}

View File

@ -248,5 +248,5 @@ function test()
waitForFocus(() => openRuleView(startTest), content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_ruleview_ui.js";
content.location = "data:text/html,basic style inspector tests";
}

View File

@ -189,5 +189,5 @@ function test()
waitForFocus(() => openRuleView(startTest), content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_ruleview_update.js";
content.location = "data:text/html,basic style inspector tests";
}

View File

@ -9,6 +9,11 @@ const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/styleinspe
//Services.prefs.setBoolPref("devtools.dump.emit", true);
Services.prefs.setBoolPref("devtools.debugger.log", true);
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.debugger.log");
Services.prefs.clearUserPref("devtools.dump.emit");
});
let tempScope = {};
Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
@ -25,16 +30,6 @@ let {CssLogic, CssSelector} = devtools.require("devtools/styleinspector/css-logi
let promise = devtools.require("sdk/core/promise");
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.debugger.log");
Services.prefs.clearUserPref("devtools.dump.emit");
});
let {
editableField,
getInplaceEditorForSpan: inplaceEditor

View File

@ -56,10 +56,6 @@ const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED;
const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function isTiltEnabled() {
info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled.");

View File

@ -66,7 +66,7 @@ function onNodeListVviewFetched(aEvent, aVar)
// variable's highlightDomNode and see if it has the desired effect
prop.highlightDomNode();
} else {
finishUp();
finishTest();
}
}
@ -89,9 +89,3 @@ function onNodeListVviewFetched(aEvent, aVar)
hoverOverDomNodeVariableAndAssertHighlighter(0);
}
function finishUp() {
gWebConsole = gJSTerm = gVariablesView = gToolbox = null;
finishTest();
}

View File

@ -214,7 +214,7 @@ function testCompletion(hud) {
is(newItems.length, 0, "no items for foo2Obj[0]");
testDriver = null;
executeSoon(finishUp);
executeSoon(finishTest);
yield undefined;
}
@ -237,8 +237,3 @@ function onFramesAdded()
info("onFramesAdded, openConsole() now");
executeSoon(() => openConsole(null, testNext));
}
function finishUp() {
testDriver = gStackframes = null;
finishTest();
}

View File

@ -332,10 +332,5 @@ function popupHideAfterCompletionInText()
is(inputNode.selectionStart, inputNode.selectionEnd, "cursor location (confirmed)");
ok(!completeNode.value, "completeNode is empty");
finishUp();
}
function finishUp() {
HUD = popup = jsterm = inputNode = completeNode = null;
finishTest();
}

View File

@ -84,10 +84,5 @@ function onVariablesViewReady(aEvent, aView)
{
findVariableViewProperties(aView, [
{ name: "body", value: "<body>" },
], { webconsole: gHUD }).then(finishUp);
}
function finishUp() {
gHUD = null;
finishTest();
], { webconsole: gHUD }).then(finishTest);
}

View File

@ -89,10 +89,5 @@ function test() {
let {tab} = yield loadTab(TEST_URI);
let hud = yield openConsole(tab);
return checkOutputForInputs(hud, inputTests);
}).then(finishUp);
}
function finishUp() {
inputTests = null;
finishTest();
}).then(finishTest);
}

View File

@ -153,17 +153,12 @@ let inputTests = [
];
function test() {
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole().then((hud) => {
return checkOutputForInputs(hud, inputTests);
}).then(finishUp);
}).then(finishTest);
}, true);
}
function finishUp() {
inputTests = null;
finishTest();
}

View File

@ -28,7 +28,7 @@ function testViewSource(hud) {
EventUtils.sendMouseEvent({ type: "click" }, button, content);
openDebugger().then(({panelWin: { DebuggerView }}) => {
info("debugger opened");
info("debugger openeed");
Sources = DebuggerView.Sources;
openConsole(null, (hud) => {
info("console opened again");
@ -71,11 +71,14 @@ let observer = {
ok(true, "the view source window was opened in response to clicking " +
"the location node");
aSubject.close();
ok(containsValueInvoked, "custom containsValue() was invoked");
Sources.containsValue = containsValue;
Sources = containsValue = null;
finishTest();
// executeSoon() is necessary to avoid crashing Firefox. See bug 611543.
executeSoon(function() {
aSubject.close();
ok(containsValueInvoked, "custom containsValue() was invoked");
Sources.containsValue = containsValue;
Sources = containsValue = null;
finishTest();
});
}
};

View File

@ -40,11 +40,6 @@ const GROUP_INDENT_DEFAULT = 6;
const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
gDevTools.testing = true;
SimpleTest.registerCleanupFunction(() => {
gDevTools.testing = false;
});
function log(aMsg)
{
dump("*** WebConsoleTest: " + aMsg + "\n");
@ -303,7 +298,7 @@ function dumpMessageElement(aMessage)
function finishTest()
{
browser = hudId = hud = filterBox = outputNode = cs = hudBox = null;
browser = hudId = hud = filterBox = outputNode = cs = null;
dumpConsoles();

View File

@ -8,7 +8,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace svg url("http://www.w3.org/2000/svg");
%include ../shared/browser.inc
%include linuxShared.inc

View File

@ -11,40 +11,36 @@
}
.theme-body {
color: hsl(210,53%,45%) !important;
color: hsl(210,100%,85%) !important;
box-sizing: border-box;
}
#main {
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
}
#content {
background-color: #80d4ff;
border-color: hsl(210,100%,85%);
border-style: dotted;
#main > .border {
color: hsl(210,53%,45%);
}
#padding,
#margins {
border-color: hsla(210,100%,85%,0.2);
outline: dotted 1px hsl(210,100%,85%);
.border > span {
background-color: hsl(210,100%,85%);
border-radius: 2px;
padding: 0 4px;
}
#content {
border-color: hsla(210,100%,85%,0.7);
border-style: dotted
}
#padding {
background-color: #66cc52;
border-color: hsla(210,100%,85%,0.2);
border-style: solid;
}
#borders {
background-color: #ffe431;
border-style: dotted;
border-style: solid;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {
background-color: #d89b28;
opacity: 0.6;
}

View File

@ -14,7 +14,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace svg url("http://www.w3.org/2000/svg");
#urlbar:-moz-lwtheme:not([focused="true"]),
.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {

View File

@ -11,40 +11,36 @@
}
.theme-body {
color: hsl(210,53%,45%) !important;
color: hsl(210,100%,85%) !important;
box-sizing: border-box;
}
#main {
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
}
#content {
background-color: #80d4ff;
border-color: hsl(210,100%,85%);
border-style: dotted;
#main > .border {
color: hsl(210,53%,45%);
}
#padding,
#margins {
border-color: hsla(210,100%,85%,0.2);
outline: dotted 1px hsl(210,100%,85%);
.border > span {
background-color: hsl(210,100%,85%);
border-radius: 2px;
padding: 0 4px;
}
#content {
border-color: hsla(210,100%,85%,0.7);
border-style: dotted
}
#padding {
background-color: #66cc52;
border-color: hsla(210,100%,85%,0.2);
border-style: solid;
}
#borders {
background-color: #ffe431;
border-style: dotted;
border-style: solid;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {
background-color: #d89b28;
opacity: 0.6;
}

View File

@ -4,40 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%endif
/* Box model highlighter */
svg|g.box-model-container {
opacity: 0.4;
}
/* Highlighter */
svg|polygon.box-model-content {
fill: #80d4ff;
}
svg|polygon.box-model-padding {
fill: #66cc52;
}
svg|polygon.box-model-border {
fill: #ffe431;
}
svg|polygon.box-model-margin {
fill: #d89b28;
}
svg|polygon.box-model-content,
svg|polygon.box-model-padding,
svg|polygon.box-model-border,
svg|polygon.box-model-margin {
stroke: none;
}
svg|line.box-model-guide-top,
svg|line.box-model-guide-right,
svg|line.box-model-guide-bottom,
svg|line.box-model-guide-left {
stroke: #08C;
stroke-dasharray: 5 3;
.highlighter-outline {
box-shadow: 0 0 0 1px black;
outline: 1px dashed white;
outline-offset: -1px;
}
/* Highlighter - Node Infobar */

View File

@ -6,7 +6,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace svg url("http://www.w3.org/2000/svg");
%include ../shared/browser.inc
%include windowsShared.inc

View File

@ -11,40 +11,36 @@
}
.theme-body {
color: hsl(210,53%,45%) !important;
color: hsl(210,100%,85%) !important;
box-sizing: border-box;
}
#main {
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
}
#content {
background-color: #80d4ff;
border-color: hsl(210,100%,85%);
border-style: dotted;
#main > .border {
color: hsl(210,53%,45%);
}
#padding,
#margins {
border-color: hsla(210,100%,85%,0.2);
outline: dotted 1px hsl(210,100%,85%);
.border > span {
background-color: hsl(210,100%,85%);
border-radius: 2px;
padding: 0 4px;
}
#content {
border-color: hsla(210,100%,85%,0.7);
border-style: dotted
}
#padding {
background-color: #66cc52;
border-color: hsla(210,100%,85%,0.2);
border-style: solid;
}
#borders {
background-color: #ffe431;
border-style: dotted;
border-style: solid;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {
background-color: #d89b28;
opacity: 0.6;
}

View File

@ -24,73 +24,77 @@ this.LayoutHelpers = LayoutHelpers = function(aTopLevelWindow) {
LayoutHelpers.prototype = {
/**
* Get box quads adjusted for iframes and zoom level.
* Compute the position and the dimensions for the visible portion
* of a node, relativalely to the root window.
*
* @param {DOMNode} node
* The node for which we are to get the box model region quads
* @param {String} region
* The box model region to return:
* "content", "padding", "border" or "margin"
* @param nsIDOMNode aNode
* a DOM element to be highlighted
*/
getAdjustedQuads: function(node, region) {
if (!node) {
return;
}
getDirtyRect: function LH_getDirectyRect(aNode) {
let frameWin = aNode.ownerDocument.defaultView;
let clientRect = aNode.getBoundingClientRect();
let [quads] = node.getBoxQuads({
box: region
});
// Go up in the tree of frames to determine the correct rectangle.
// clientRect is read-only, we need to be able to change properties.
rect = {top: clientRect.top,
left: clientRect.left,
width: clientRect.width,
height: clientRect.height};
if (!quads) {
return;
}
// We iterate through all the parent windows.
while (true) {
let [xOffset, yOffset] = this._getNodeOffsets(node);
let scale = this.calculateScale(node);
return {
p1: {
w: quads.p1.w * scale,
x: quads.p1.x * scale + xOffset,
y: quads.p1.y * scale + yOffset,
z: quads.p1.z * scale
},
p2: {
w: quads.p2.w * scale,
x: quads.p2.x * scale + xOffset,
y: quads.p2.y * scale + yOffset,
z: quads.p2.z * scale
},
p3: {
w: quads.p3.w * scale,
x: quads.p3.x * scale + xOffset,
y: quads.p3.y * scale + yOffset,
z: quads.p3.z * scale
},
p4: {
w: quads.p4.w * scale,
x: quads.p4.x * scale + xOffset,
y: quads.p4.y * scale + yOffset,
z: quads.p4.z * scale
},
bounds: {
bottom: quads.bounds.bottom * scale + yOffset,
height: quads.bounds.height * scale,
left: quads.bounds.left * scale + xOffset,
right: quads.bounds.right * scale + xOffset,
top: quads.bounds.top * scale + yOffset,
width: quads.bounds.width * scale,
x: quads.bounds.x * scale + xOffset,
y: quads.bounds.y * scale + yOffset
// Does the selection overflow on the right of its window?
let diffx = frameWin.innerWidth - (rect.left + rect.width);
if (diffx < 0) {
rect.width += diffx;
}
};
},
calculateScale: function(node) {
let win = node.ownerDocument.defaultView;
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
return winUtils.fullZoom;
// Does the selection overflow on the bottom of its window?
let diffy = frameWin.innerHeight - (rect.top + rect.height);
if (diffy < 0) {
rect.height += diffy;
}
// Does the selection overflow on the left of its window?
if (rect.left < 0) {
rect.width += rect.left;
rect.left = 0;
}
// Does the selection overflow on the top of its window?
if (rect.top < 0) {
rect.height += rect.top;
rect.top = 0;
}
// Selection has been clipped to fit in its own window.
// Are we in the top-level window?
if (this.isTopLevelWindow(frameWin)) {
break;
}
let frameElement = this.getFrameElement(frameWin);
if (!frameElement) {
break;
}
// We are in an iframe.
// We take into account the parent iframe position and its
// offset (borders and padding).
let frameRect = frameElement.getBoundingClientRect();
let [offsetTop, offsetLeft] =
this.getIframeContentOffset(frameElement);
rect.top += frameRect.top + offsetTop;
rect.left += frameRect.left + offsetLeft;
frameWin = this.getParentWindow(frameWin);
}
return rect;
},
/**
@ -108,7 +112,7 @@ LayoutHelpers.prototype = {
// Go up in the tree of frames to determine the correct rectangle.
// clientRect is read-only, we need to be able to change properties.
let rect = {top: clientRect.top + aContentWindow.pageYOffset,
rect = {top: clientRect.top + aContentWindow.pageYOffset,
left: clientRect.left + aContentWindow.pageXOffset,
width: clientRect.width,
height: clientRect.height};
@ -174,6 +178,26 @@ LayoutHelpers.prototype = {
return [borderTop + paddingTop, borderLeft + paddingLeft];
},
/**
* Apply the page zoom factor.
*/
getZoomedRect: function LH_getZoomedRect(aWin, aRect) {
// get page zoom factor, if any
let zoom =
aWin.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.fullZoom;
// adjust rect for zoom scaling
let aRectScaled = {};
for (let prop in aRect) {
aRectScaled[prop] = aRect[prop] * zoom;
}
return aRectScaled;
},
/**
* Find an element from the given coordinates. This method descends through
* frames to find the element the user clicked inside frames.
@ -219,7 +243,8 @@ LayoutHelpers.prototype = {
* appear on the top of the viewport. It is true by default, and that is
* usually what you want.
*/
scrollIntoViewIfNeeded: function(elem, centered) {
scrollIntoViewIfNeeded:
function LH_scrollIntoViewIfNeeded(elem, centered) {
// We want to default to centering the element in the page,
// so as to keep the context of the element.
centered = centered === undefined? true: !!centered;
@ -372,138 +397,4 @@ LayoutHelpers.prototype = {
return winUtils.containerElement;
},
/**
* Get the x and y offsets for a node taking iframes into account.
*
* @param {DOMNode} node
* The node for which we are to get the offset
*/
_getNodeOffsets: function(node) {
let xOffset = 0;
let yOffset = 0;
let frameWin = node.ownerDocument.defaultView;
let scale = this.calculateScale(node);
while (true) {
// Are we in the top-level window?
if (this.isTopLevelWindow(frameWin)) {
break;
}
let frameElement = this.getFrameElement(frameWin);
if (!frameElement) {
break;
}
// We are in an iframe.
// We take into account the parent iframe position and its
// offset (borders and padding).
let frameRect = frameElement.getBoundingClientRect();
let [offsetTop, offsetLeft] =
this.getIframeContentOffset(frameElement);
xOffset += frameRect.left + offsetLeft;
yOffset += frameRect.top + offsetTop;
frameWin = this.getParentWindow(frameWin);
}
return [xOffset * scale, yOffset * scale];
},
/********************************************************************
* GetBoxQuads POLYFILL START TODO: Remove this when bug 917755 is fixed.
********************************************************************/
_getBoxQuadsFromRect: function(rect, node) {
let scale = this.calculateScale(node);
let [xOffset, yOffset] = this._getNodeOffsets(node);
let out = {
p1: {
x: rect.left * scale + xOffset,
y: rect.top * scale + yOffset
},
p2: {
x: (rect.left + rect.width) * scale + xOffset,
y: rect.top * scale + yOffset
},
p3: {
x: (rect.left + rect.width) * scale + xOffset,
y: (rect.top + rect.height) * scale + yOffset
},
p4: {
x: rect.left * scale + xOffset,
y: (rect.top + rect.height) * scale + yOffset
}
};
out.bounds = {
bottom: out.p4.y,
height: out.p4.y - out.p1.y,
left: out.p1.x,
right: out.p2.x,
top: out.p1.y,
width: out.p2.x - out.p1.x,
x: out.p1.x,
y: out.p1.y
};
return out;
},
_parseNb: function(distance) {
let nb = parseFloat(distance, 10);
return isNaN(nb) ? 0 : nb;
},
getAdjustedQuadsPolyfill: function(node, region) {
// Get the border-box rect
// Note that this is relative to the node's viewport, so before we can use
// it, will need to go back up the frames like getRect
let borderRect = node.getBoundingClientRect();
// If the boxType is border, no need to go any further, we're done
if (region === "border") {
return this._getBoxQuadsFromRect(borderRect, node);
}
// Else, need to get margin/padding/border distances
let style = node.ownerDocument.defaultView.getComputedStyle(node);
let camel = s => s.substring(0, 1).toUpperCase() + s.substring(1);
let distances = {border:{}, padding:{}, margin: {}};
for (let side of ["top", "right", "bottom", "left"]) {
distances.border[side] = this._parseNb(style["border" + camel(side) + "Width"]);
distances.padding[side] = this._parseNb(style["padding" + camel(side)]);
distances.margin[side] = this._parseNb(style["margin" + camel(side)]);
}
// From the border-box rect, calculate the content-box, padding-box and
// margin-box rects
function offsetRect(rect, offsetType, dir=1) {
return {
top: rect.top + (dir * distances[offsetType].top),
left: rect.left + (dir * distances[offsetType].left),
width: rect.width - (dir * (distances[offsetType].left + distances[offsetType].right)),
height: rect.height - (dir * (distances[offsetType].top + distances[offsetType].bottom))
};
}
if (region === "margin") {
return this._getBoxQuadsFromRect(offsetRect(borderRect, "margin", -1), node);
} else if (region === "padding") {
return this._getBoxQuadsFromRect(offsetRect(borderRect, "border"), node);
} else if (region === "content") {
let paddingRect = offsetRect(borderRect, "border");
return this._getBoxQuadsFromRect(offsetRect(paddingRect, "padding"), node);
}
},
/********************************************************************
* GetBoxQuads POLYFILL END
********************************************************************/
};

View File

@ -8,9 +8,6 @@ const {Cu, Cc, Ci} = require("chrome");
const protocol = require("devtools/server/protocol");
const {Arg, Option, method} = protocol;
const events = require("sdk/event/core");
const EventEmitter = require("devtools/toolkit/event-emitter");
const GUIDE_STROKE_WIDTH = 1;
// Make sure the domnode type is known here
require("devtools/server/actors/inspector");
@ -24,9 +21,7 @@ const HIGHLIGHTED_PSEUDO_CLASS = ":-moz-devtools-highlighted";
let HELPER_SHEET = ".__fx-devtools-hide-shortcut__ { visibility: hidden !important } ";
HELPER_SHEET += ":-moz-devtools-highlighted { outline: 2px dashed #F06!important; outline-offset: -2px!important } ";
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const SVG_NS = "http://www.w3.org/2000/svg";
const HIGHLIGHTER_PICKED_TIMER = 1000;
const INFO_BAR_OFFSET = 5;
/**
* The HighlighterActor is the server-side entry points for any tool that wishes
@ -41,23 +36,15 @@ const INFO_BAR_OFFSET = 5;
let HighlighterActor = protocol.ActorClass({
typeName: "highlighter",
initialize: function(inspector, autohide) {
initialize: function(inspector) {
protocol.Actor.prototype.initialize.call(this, null);
this._autohide = autohide;
this._inspector = inspector;
this._walker = this._inspector.walker;
this._tabActor = this._inspector.tabActor;
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
if (this._supportsBoxModelHighlighter()) {
this._boxModelHighlighter =
new BoxModelHighlighter(this._tabActor, this._inspector);
this._boxModelHighlighter.on("ready", this._highlighterReady);
this._boxModelHighlighter.on("hide", this._highlighterHidden);
this._boxModelHighlighter = new BoxModelHighlighter(this._tabActor);
} else {
this._boxModelHighlighter = new SimpleOutlineHighlighter(this._tabActor);
}
@ -76,12 +63,9 @@ let HighlighterActor = protocol.ActorClass({
destroy: function() {
protocol.Actor.prototype.destroy.call(this);
if (this._boxModelHighlighter) {
this._boxModelHighlighter.off("ready", this._highlighterReady);
this._boxModelHighlighter.off("hide", this._highlighterHidden);
this._boxModelHighlighter.destroy();
this._boxModelHighlighter = null;
}
this._autohide = null;
this._inspector = null;
this._walker = null;
this._tabActor = null;
@ -95,7 +79,8 @@ let HighlighterActor = protocol.ActorClass({
*
* @param NodeActor The node to be highlighted
* @param Options See the request part for existing options. Note that not
* all options may be supported by all types of highlighters.
* all options may be supported by all types of highlighters. The simple
* outline highlighter for instance does not scrollIntoView
*/
showBoxModel: method(function(node, options={}) {
if (node && this._isNodeValidForHighlighting(node.rawNode)) {
@ -106,8 +91,7 @@ let HighlighterActor = protocol.ActorClass({
}, {
request: {
node: Arg(0, "domnode"),
scrollIntoView: Option(1),
region: Option(1)
scrollIntoView: Option(1)
}
}),
@ -151,7 +135,6 @@ let HighlighterActor = protocol.ActorClass({
*/
_isPicking: false,
_hoveredNode: null,
pick: method(function() {
if (this._isPicking) {
return null;
@ -167,11 +150,9 @@ let HighlighterActor = protocol.ActorClass({
this._preventContentEvent(event);
this._stopPickerListeners();
this._isPicking = false;
if (this._autohide) {
this._tabActor.window.setTimeout(() => {
this._boxModelHighlighter.hide();
}, HIGHLIGHTER_PICKED_TIMER);
}
this._tabActor.window.setTimeout(() => {
this._boxModelHighlighter.hide();
}, HIGHLIGHTER_PICKED_TIMER);
events.emit(this._walker, "picker-node-picked", this._findAndAttachElement(event));
};
@ -236,14 +217,6 @@ let HighlighterActor = protocol.ActorClass({
target.removeEventListener("dblclick", this._preventContentEvent, true);
},
_highlighterReady: function() {
events.emit(this._inspector.walker, "highlighter-ready");
},
_highlighterHidden: function() {
events.emit(this._inspector.walker, "highlighter-hide");
},
cancelPick: method(function() {
if (this._isPicking) {
this._boxModelHighlighter.hide();
@ -274,41 +247,26 @@ let HighlighterFront = protocol.FrontClass(HighlighterActor, {});
* h.destroy();
*
* Structure:
* <stack class="highlighter-container">
* <svg class="box-model-root" hidden="true">
* <g class="box-model-container">
* <polygon class="box-model-margin" points="317,122 747,36 747,181 317,267" />
* <polygon class="box-model-border" points="317,128 747,42 747,161 317,247" />
* <polygon class="box-model-padding" points="323,127 747,42 747,161 323,246" />
* <polygon class="box-model-content" points="335,137 735,57 735,152 335,232" />
* </g>
* <line class="box-model-guide-top" x1="0" y1="592" x2="99999" y2="592" />
* <line class="box-model-guide-right" x1="735" y1="0" x2="735" y2="99999" />
* <line class="box-model-guide-bottom" x1="0" y1="612" x2="99999" y2="612" />
* <line class="box-model-guide-left" x1="334" y1="0" x2="334" y2="99999" />
* </svg>
* <box class="highlighter-nodeinfobar-container">
* <box class="highlighter-nodeinfobar-positioner" position="top" />
* <box class="highlighter-nodeinfobar-arrow highlighter-nodeinfobar-arrow-top" />
* <hbox class="highlighter-nodeinfobar">
* <hbox class="highlighter-nodeinfobar-text" align="center" flex="1">
* <span class="highlighter-nodeinfobar-tagname">Node name</span>
* <span class="highlighter-nodeinfobar-id">Node id</span>
* <span class="highlighter-nodeinfobar-classes">.someClass</span>
* <span class="highlighter-nodeinfobar-pseudo-classes">:hover</span>
* </hbox>
* </hbox>
* <box class="highlighter-nodeinfobar-arrow highlighter-nodeinfobar-arrow-bottom"/>
* </box>
* </box>
* </stack>
* <stack class="highlighter-container">
* <box class="highlighter-outline-container">
* <box class="highlighter-outline" />
* </box>
* <box class="highlighter-nodeinfobar-container">
* <box class="highlighter-nodeinfobar-positioner" position="top/bottom">
* <box class="highlighter-nodeinfobar-arrow highlighter-nodeinfobar-arrow-top"/>
* <hbox class="highlighter-nodeinfobar">
* <hbox class="highlighter-nodeinfobar-text">tagname#id.class1.class2</hbox>
* </hbox>
* <box class="highlighter-nodeinfobar-arrow highlighter-nodeinfobar-arrow-bottom"/>
* </box>
* </box>
* </stack>
*/
function BoxModelHighlighter(tabActor, inspector) {
function BoxModelHighlighter(tabActor) {
this.browser = tabActor.browser;
this.win = tabActor.window;
this.chromeDoc = this.browser.ownerDocument;
this.chromeWin = this.chromeDoc.defaultView;
this._inspector = inspector;
this.layoutHelpers = new LayoutHelpers(this.win);
this.chromeLayoutHelper = new LayoutHelpers(this.chromeWin);
@ -316,56 +274,32 @@ function BoxModelHighlighter(tabActor, inspector) {
this.transitionDisabler = null;
this.pageEventsMuter = null;
this._update = this._update.bind(this);
this.handleEvent = this.handleEvent.bind(this);
this.currentNode = null;
EventEmitter.decorate(this);
this._initMarkup();
}
BoxModelHighlighter.prototype = {
get zoom() {
return this.win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).fullZoom;
},
_initMarkup: function() {
let stack = this.browser.parentNode;
this._highlighterContainer = this.chromeDoc.createElement("stack");
this._highlighterContainer.className = "highlighter-container";
this.highlighterContainer = this.chromeDoc.createElement("stack");
this.highlighterContainer.className = "highlighter-container";
this._svgRoot = this._createSVGNode("root", "svg", this._highlighterContainer);
this.outline = this.chromeDoc.createElement("box");
this.outline.className = "highlighter-outline";
this._boxModelContainer = this._createSVGNode("container", "g", this._svgRoot);
this._boxModelNodes = {
margin: this._createSVGNode("margin", "polygon", this._boxModelContainer),
border: this._createSVGNode("border", "polygon", this._boxModelContainer),
padding: this._createSVGNode("padding", "polygon", this._boxModelContainer),
content: this._createSVGNode("content", "polygon", this._boxModelContainer)
};
this._guideNodes = {
top: this._createSVGNode("guide-top", "line", this._svgRoot),
right: this._createSVGNode("guide-right", "line", this._svgRoot),
bottom: this._createSVGNode("guide-bottom", "line", this._svgRoot),
left: this._createSVGNode("guide-left", "line", this._svgRoot)
};
this._guideNodes.top.setAttribute("stroke-width", GUIDE_STROKE_WIDTH);
this._guideNodes.right.setAttribute("stroke-width", GUIDE_STROKE_WIDTH);
this._guideNodes.bottom.setAttribute("stroke-width", GUIDE_STROKE_WIDTH);
this._guideNodes.left.setAttribute("stroke-width", GUIDE_STROKE_WIDTH);
this._highlighterContainer.appendChild(this._svgRoot);
let outlineContainer = this.chromeDoc.createElement("box");
outlineContainer.appendChild(this.outline);
outlineContainer.className = "highlighter-outline-container";
this.highlighterContainer.appendChild(outlineContainer);
let infobarContainer = this.chromeDoc.createElement("box");
infobarContainer.className = "highlighter-nodeinfobar-container";
this._highlighterContainer.appendChild(infobarContainer);
this.highlighterContainer.appendChild(infobarContainer);
// Insert the highlighter right after the browser
stack.insertBefore(this._highlighterContainer, stack.childNodes[1]);
stack.insertBefore(this.highlighterContainer, stack.childNodes[1]);
// Building the infobar
let infobarPositioner = this.chromeDoc.createElement("box");
@ -428,15 +362,6 @@ BoxModelHighlighter.prototype = {
};
},
_createSVGNode: function(classPostfix, nodeType, parent) {
let node = this.chromeDoc.createElementNS(SVG_NS, nodeType);
node.setAttribute("class", "box-model-" + classPostfix);
parent.appendChild(node);
return node;
},
/**
* Destroy the nodes. Remove listeners.
*/
@ -446,13 +371,15 @@ BoxModelHighlighter.prototype = {
this.chromeWin.clearTimeout(this.transitionDisabler);
this.chromeWin.clearTimeout(this.pageEventsMuter);
this._contentRect = null;
this._highlightRect = null;
this.outline = null;
this.nodeInfo = null;
this._highlighterContainer.remove();
this._highlighterContainer = null;
this.highlighterContainer.remove();
this.highlighterContainer = null;
this.rect = null;
this.win = null;
this.win = null
this.browser = null;
this.chromeDoc = null;
this.chromeWin = null;
@ -463,29 +390,28 @@ BoxModelHighlighter.prototype = {
* Show the highlighter on a given node
*
* @param {DOMNode} node
* @param {Object} options
* Object used for passing options
*/
show: function(node, options={}) {
this.currentNode = node;
if (!this.currentNode || node !== this.currentNode) {
this.currentNode = node;
this._showInfobar();
this._detachPageListeners();
this._attachPageListeners();
this._update();
this._trackMutations();
this._showInfobar();
this._computeZoomFactor();
this._detachPageListeners();
this._attachPageListeners();
this._update();
this._trackMutations();
if (options.scrollIntoView) {
this.chromeLayoutHelper.scrollIntoViewIfNeeded(node);
if (options.scrollIntoView) {
this.chromeLayoutHelper.scrollIntoViewIfNeeded(node);
}
}
},
_trackMutations: function() {
if (this.currentNode) {
let win = this.currentNode.ownerDocument.defaultView;
this.currentNodeObserver = new win.MutationObserver(() => {
this._update();
});
this.currentNodeObserver = new win.MutationObserver(this._update);
this.currentNodeObserver.observe(this.currentNode, {attributes: true});
}
},
@ -507,20 +433,21 @@ BoxModelHighlighter.prototype = {
* Update the highlighter on the current highlighted node (the one that was
* passed as an argument to show(node)).
* Should be called whenever node size or attributes change
* @param {Object} options
* Object used for passing options. Valid options are:
* - box: "content", "padding", "border" or "margin." This specifies
* the box that the guides should outline. Default is content.
* @param {Boolean} brieflyDisableTransitions
* In case _update is called during scrolling or repaint, set this
* to true to avoid transitions
*/
_update: function(options={}) {
_update: function(brieflyDisableTransitions) {
if (this.currentNode) {
if (this._highlightBoxModel(options)) {
this._showInfobar();
let rect = this.layoutHelpers.getDirtyRect(this.currentNode);
if (this._highlightRectangle(rect, brieflyDisableTransitions)) {
this._moveInfobar();
this._updateInfobar();
} else {
// Nothing to highlight (0px rectangle like a <script> tag for instance)
this.hide();
}
this.emit("ready");
}
},
@ -531,17 +458,17 @@ BoxModelHighlighter.prototype = {
if (this.currentNode) {
this._untrackMutations();
this.currentNode = null;
this._hideBoxModel();
this._hideOutline();
this._hideInfobar();
this._detachPageListeners();
}
this.emit("hide");
},
/**
* Hide the infobar
*/
_hideInfobar: function() {
this.nodeInfo.positioner.setAttribute("force-transitions", "true");
this.nodeInfo.positioner.setAttribute("hidden", "true");
},
@ -550,157 +477,84 @@ BoxModelHighlighter.prototype = {
*/
_showInfobar: function() {
this.nodeInfo.positioner.removeAttribute("hidden");
this._updateInfobar();
this._moveInfobar();
this.nodeInfo.positioner.removeAttribute("force-transitions");
},
/**
* Hide the box model
* Hide the outline
*/
_hideBoxModel: function() {
this._svgRoot.setAttribute("hidden", "true");
_hideOutline: function() {
this.outline.setAttribute("hidden", "true");
},
/**
* Show the box model
* Show the outline
*/
_showBoxModel: function() {
this._svgRoot.removeAttribute("hidden");
_showOutline: function() {
this.outline.removeAttribute("hidden");
},
/**
* Highlight the box model.
* Highlight a rectangular region.
*
* @param {Object} options
* Object used for passing options. Valid options are:
* - region: "content", "padding", "border" or "margin." This specifies
* the region that the guides should outline. Default is content.
* @param {object} aRect
* The rectangle region to highlight.
* @param {boolean} brieflyDisableTransitions
* Set to true to avoid transitions during the highlighting
* @return {boolean}
* True if the rectangle was highlighted, false otherwise.
*/
_highlightBoxModel: function(options) {
let isShown = false;
options.region = options.region || "content";
// TODO: Remove this polyfill
this.rect =
this.layoutHelpers.getAdjustedQuadsPolyfill(this.currentNode, "margin");
if (!this.rect) {
return null;
_highlightRectangle: function(aRect, brieflyDisableTransitions) {
if (!aRect) {
return false;
}
if (this.rect.bounds.width > 0 && this.rect.bounds.height > 0) {
for (let boxType in this._boxModelNodes) {
// TODO: Remove this polyfill
let {p1, p2, p3, p4} = boxType === "margin" ? this.rect :
this.layoutHelpers.getAdjustedQuadsPolyfill(this.currentNode, boxType);
let oldRect = this._contentRect;
let boxNode = this._boxModelNodes[boxType];
boxNode.setAttribute("points",
p1.x + "," + p1.y + " " +
p2.x + "," + p2.y + " " +
p3.x + "," + p3.y + " " +
p4.x + "," + p4.y);
if (oldRect && aRect.top == oldRect.top && aRect.left == oldRect.left &&
aRect.width == oldRect.width && aRect.height == oldRect.height) {
this._showOutline();
return true; // same rectangle
}
if (boxType === options.region) {
this._showGuides(p1, p2, p3, p4);
}
let aRectScaled = this.layoutHelpers.getZoomedRect(this.win, aRect);
let isShown = false;
if (aRectScaled.left >= 0 && aRectScaled.top >= 0 &&
aRectScaled.width > 0 && aRectScaled.height > 0) {
// The bottom div and the right div are flexibles (flex=1).
// We don't need to resize them.
let top = "top:" + aRectScaled.top + "px;";
let left = "left:" + aRectScaled.left + "px;";
let width = "width:" + aRectScaled.width + "px;";
let height = "height:" + aRectScaled.height + "px;";
if (brieflyDisableTransitions) {
this._brieflyDisableTransitions();
}
this.outline.setAttribute("style", top + left + width + height);
isShown = true;
this._showBoxModel();
this._showOutline();
} else {
// Only return false if the element really is invisible.
// A height of 0 and a non-0 width corresponds to a visible element that
// is below the fold for instance
if (this.rect.width > 0 || this.rect.height > 0) {
if (aRectScaled.width > 0 || aRectScaled.height > 0) {
isShown = true;
this._hideBoxModel();
this._hideOutline();
}
}
this._contentRect = aRect; // save orig (non-scaled) rect
this._highlightRect = aRectScaled; // and save the scaled rect.
return isShown;
},
/**
* We only want to show guides for horizontal and vertical edges as this helps
* to line them up. This method finds these edges and displays a guide there.
*
* @param {DOMPoint} p1
* Point 1
* @param {DOMPoint} p2
* Point 2
* @param {DOMPoint} p3 [description]
* Point 3
* @param {DOMPoint} p4 [description]
* Point 4
*/
_showGuides: function(p1, p2, p3, p4) {
let allX = [p1.x, p2.x, p3.x, p4.x].sort();
let allY = [p1.y, p2.y, p3.y, p4.y].sort();
let toShowX = [];
let toShowY = [];
for (let arr of [allX, allY]) {
for (let i = 0; i < arr.length; i++) {
let val = arr[i];
if (i !== arr.lastIndexOf(val)) {
if (arr === allX) {
toShowX.push(val);
} else {
toShowY.push(val);
}
arr.splice(arr.lastIndexOf(val), 1);
}
}
}
// Move guide into place or hide it if no valid co-ordinate was found.
this._updateGuide(this._guideNodes.top, toShowY[0]);
this._updateGuide(this._guideNodes.right, toShowX[1]);
this._updateGuide(this._guideNodes.bottom, toShowY[1]);
this._updateGuide(this._guideNodes.left, toShowX[0]);
},
/**
* Move a guide to the appropriate position and display it. If no point is
* passed then the guide is hidden.
*
* @param {SVGLine} guide
* The guide to update
* @param {Integer} point
* x or y co-ordinate. If this is undefined we hide the guide.
*/
_updateGuide: function(guide, point=-1) {
if (point > 0) {
let offset = GUIDE_STROKE_WIDTH / 2;
if (guide === this._guideNodes.top || guide === this._guideNodes.left) {
point -= offset;
} else {
point += offset;
}
if (guide === this._guideNodes.top || guide === this._guideNodes.bottom) {
guide.setAttribute("x1", 0);
guide.setAttribute("y1", point);
guide.setAttribute("x2", "100%");
guide.setAttribute("y2", point);
} else {
guide.setAttribute("x1", point);
guide.setAttribute("y1", 0);
guide.setAttribute("x2", point);
guide.setAttribute("y2", "100%");
}
guide.removeAttribute("hidden");
return true;
} else {
guide.setAttribute("hidden", "true");
return false;
}
},
/**
* Update node information (tagName#id.class)
*/
@ -725,8 +579,6 @@ BoxModelHighlighter.prototype = {
let pseudoBox = this.nodeInfo.pseudoClassesBox;
pseudoBox.textContent = pseudos.join("");
this._moveInfobar();
}
},
@ -734,33 +586,46 @@ BoxModelHighlighter.prototype = {
* Move the Infobar to the right place in the highlighter.
*/
_moveInfobar: function() {
if (this.rect) {
let bounds = this.rect.bounds;
if (this._highlightRect) {
let winHeight = this.win.innerHeight * this.zoom;
let winWidth = this.win.innerWidth * this.zoom;
let rect = {top: this._highlightRect.top,
left: this._highlightRect.left,
width: this._highlightRect.width,
height: this._highlightRect.height};
rect.top = Math.max(rect.top, 0);
rect.left = Math.max(rect.left, 0);
rect.width = Math.max(rect.width, 0);
rect.height = Math.max(rect.height, 0);
rect.top = Math.min(rect.top, winHeight);
rect.left = Math.min(rect.left, winWidth);
this.nodeInfo.positioner.removeAttribute("disabled");
// Can the bar be above the node?
if (bounds.top < this.nodeInfo.barHeight) {
if (rect.top < this.nodeInfo.barHeight) {
// No. Can we move the toolbar under the node?
if (bounds.bottom + this.nodeInfo.barHeight > winHeight) {
if (rect.top + rect.height +
this.nodeInfo.barHeight > winHeight) {
// No. Let's move it inside.
this.nodeInfo.positioner.style.top = bounds.top + "px";
this.nodeInfo.positioner.style.top = rect.top + "px";
this.nodeInfo.positioner.setAttribute("position", "overlap");
} else {
// Yes. Let's move it under the node.
this.nodeInfo.positioner.style.top = bounds.bottom - INFO_BAR_OFFSET + "px";
this.nodeInfo.positioner.style.top = rect.top + rect.height + "px";
this.nodeInfo.positioner.setAttribute("position", "bottom");
}
} else {
// Yes. Let's move it on top of the node.
this.nodeInfo.positioner.style.top =
bounds.top + INFO_BAR_OFFSET - this.nodeInfo.barHeight + "px";
rect.top - this.nodeInfo.barHeight + "px";
this.nodeInfo.positioner.setAttribute("position", "top");
}
let barWidth = this.nodeInfo.positioner.getBoundingClientRect().width;
let left = bounds.right - bounds.width / 2 - barWidth / 2;
let left = rect.left + rect.width / 2 - barWidth / 2;
// Make sure the whole infobar is visible
if (left < 0) {
@ -783,24 +648,26 @@ BoxModelHighlighter.prototype = {
}
},
_attachPageListeners: function() {
if (this.currentNode) {
let win = this.currentNode.ownerGlobal;
/**
* Store page zoom factor.
*/
_computeZoomFactor: function() {
this.zoom =
this.win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.fullZoom;
},
win.addEventListener("scroll", this, false);
win.addEventListener("resize", this, false);
win.addEventListener("MozAfterPaint", this, false);
}
_attachPageListeners: function() {
this.browser.addEventListener("resize", this, true);
this.browser.addEventListener("scroll", this, true);
this.browser.addEventListener("MozAfterPaint", this, true);
},
_detachPageListeners: function() {
if (this.currentNode) {
let win = this.currentNode.ownerGlobal;
win.removeEventListener("scroll", this, false);
win.removeEventListener("resize", this, false);
win.removeEventListener("MozAfterPaint", this, false);
}
this.browser.removeEventListener("resize", this, true);
this.browser.removeEventListener("scroll", this, true);
this.browser.removeEventListener("MozAfterPaint", this, true);
},
/**
@ -812,12 +679,33 @@ BoxModelHighlighter.prototype = {
handleEvent: function(event) {
switch (event.type) {
case "resize":
this._computeZoomFactor();
break;
case "MozAfterPaint":
case "scroll":
this._update();
this._update(true);
break;
}
},
/**
* Disable the CSS transitions for a short time to avoid laggy animations
* during scrolling or resizing.
*/
_brieflyDisableTransitions: function() {
if (this.transitionDisabler) {
this.chromeWin.clearTimeout(this.transitionDisabler);
} else {
this.outline.setAttribute("disable-transitions", "true");
this.nodeInfo.positioner.setAttribute("disable-transitions", "true");
}
this.transitionDisabler =
this.chromeWin.setTimeout(() => {
this.outline.removeAttribute("disable-transitions");
this.nodeInfo.positioner.removeAttribute("disable-transitions");
this.transitionDisabler = null;
}, 500);
}
};
/**

View File

@ -849,12 +849,6 @@ var WalkerActor = protocol.ActorClass({
"picker-node-hovered" : {
type: "pickerNodeHovered",
node: Arg(0, "disconnectedNode")
},
"highlighter-ready" : {
type: "highlighter-ready"
},
"highlighter-hide" : {
type: "highlighter-hide"
}
},
@ -1200,7 +1194,7 @@ var WalkerActor = protocol.ActorClass({
// make it easier.
let filteredWalker = (node) => {
return documentWalker(node, this.rootWin, options.whatToShow);
};
}
// Need to know the first and last child.
let rawNode = node.rawNode;
@ -1391,15 +1385,7 @@ var WalkerActor = protocol.ActorClass({
* @param string selector
*/
querySelectorAll: method(function(baseNode, selector) {
let nodeList = null;
try {
nodeList = baseNode.rawNode.querySelectorAll(selector);
} catch(e) {
// Bad selector. Do nothing as the selector can come from a searchbox.
}
return new NodeListActor(this, nodeList);
return new NodeListActor(this, baseNode.rawNode.querySelectorAll(selector));
}, {
request: {
node: Arg(0, "domnode"),
@ -2552,17 +2538,17 @@ var InspectorActor = protocol.ActorClass({
}
}),
getHighlighter: method(function (autohide) {
getHighlighter: method(function () {
if (this._highlighterPromise) {
return this._highlighterPromise;
}
this._highlighterPromise = this.getWalker().then(walker => {
return HighlighterActor(this, autohide);
return HighlighterActor(this);
});
return this._highlighterPromise;
}, {
request: { autohide: Arg(0, "boolean") },
request: {},
response: {
highligter: RetVal("highlighter")
}