Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Web Inspector: Add CSS.setLayoutContextTypeChangedMode for getting …
…information about all layout contexts

https://bugs.webkit.org/show_bug.cgi?id=221449

Source/JavaScriptCore:

Reviewed by Devin Rousso.

Added `CSS.setLayoutContextTypeChangedMode` command and `CSS.LayoutContextTypeChangedMode` enum for controlling
if the frontend should be informed of all layout context type changes, or if only currently instrumented nodes
should be observed.

* inspector/protocol/CSS.json:

Source/WebCore:

Reviewed by Devin Rousso.

Test: inspector/css/setLayoutContextTypeChangedMode.html

Backend support for changing the `LayoutContextTypeChangedMode`.

* inspector/agents/InspectorCSSAgent.cpp:
(WebCore::pushChildrenNodesToFrontendIfLayoutContextTypePresent):
- Recursively pushes children node paths to the frontend if a `LayoutContextType` exists for the node, which
allows the frontend to have a complete picture of the layout contexts in the document.
(WebCore::InspectorCSSAgent::setLayoutContextTypeChangedMode):
- If the mode is changed to `All`, then make sure any node with a `LayoutContextType` inside any document is
sent to the frontend.
(WebCore::InspectorCSSAgent::nodeLayoutContextTypeChanged):
- If the `LayoutContextTypeChangedMode` is `All`, inform the frontend of the node when it changes layout
context, even if the node was not previously instrumented.
* inspector/agents/InspectorCSSAgent.h:

Source/WebInspectorUI:

Reviewed by Devin Rousso.

* UserInterface/Controllers/CSSManager.js:
- Added CSS.LayoutContextTypeChangedMode enum values.
(WI.CSSManager.prototype.set layoutContextTypeChangedMode):
* UserInterface/Controllers/DOMManager.js:
(WI.DOMManager.prototype.nodesWithLayoutContextType):
- Added ability to get all instrumented nodes of a specific layout context type.
* UserInterface/Views/LayoutDetailsSidebarPanel.js:
(WI.LayoutDetailsSidebarPanel.prototype.attached):
(WI.LayoutDetailsSidebarPanel.prototype.detached):
- Change the LayoutContextTypeChangedMode when showing/hiding the Layout panel.

LayoutTests:

Reviewed by Devin Rousso

Added layout tests for `CSS.setLayoutContextTypeChangedMode` command.

* inspector/css/setLayoutContextTypeChangedMode-expected.txt: Added.
* inspector/css/setLayoutContextTypeChangedMode.html: Added.


Canonical link: https://commits.webkit.org/233838@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272566 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
patrickangle committed Feb 9, 2021
1 parent ce8b610 commit 50eacad
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 1 deletion.
12 changes: 12 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
2021-02-08 Patrick Angle <pangle@apple.com>

Web Inspector: Add `CSS.setLayoutContextTypeChangedMode` for getting information about all layout contexts
https://bugs.webkit.org/show_bug.cgi?id=221449

Reviewed by Devin Rousso

Added layout tests for `CSS.setLayoutContextTypeChangedMode` command.

* inspector/css/setLayoutContextTypeChangedMode-expected.txt: Added.
* inspector/css/setLayoutContextTypeChangedMode.html: Added.

2021-02-08 Commit Queue <commit-queue@webkit.org>

Unreviewed, reverting r272480, r272481, and r272500.
Expand Down
@@ -0,0 +1,41 @@
Tests for the CSS.setLayoutContextTypeChangedMode command.


== Running test suite: CSS.setLayoutContextTypeChangedMode
-- Running test case: CSS.setLayoutContextTypeChangedMode.queryGrid
PASS: 0 grid nodes should be instrumented.
Querying document for selector `#queryGrid`...
PASS: 1 grid node should be instrumented.
Changing `#queryGrid` to `display: block;`...
PASS: 0 grid nodes should be instrumented.
Changing `#queryGrid` to `display: grid;`...
PASS: 1 grid node should be instrumented.
Changing `#queryGrid` to `display: block;`...
PASS: 0 grid nodes should be instrumented.
Changing `#queryGrid` to `display: inline-grid;`...
PASS: 1 grid node should be instrumented.

-- Running test case: CSS.setLayoutContextTypeChangedMode.normalGrid
PASS: 1 grid node should be instrumented.
Changing `layoutContextTypeChangedMode` to `All`...
PASS: 2 grid nodes should be instrumented.
Changing `layoutContextTypeChangedMode` to `Observed`...
PASS: 2 grid nodes should be instrumented.
Changing `#normalGrid` to `display: block;`...
PASS: 1 grid node should be instrumented.
Changing `#normalGrid` to `display: grid;`...
PASS: 2 grid nodes should be instrumented.

-- Running test case: CSS.setLayoutContextTypeChangedMode.normalNonGrid
PASS: 2 grid nodes should be instrumented.
Changing `#normalNonGrid` to `display: grid;`...
PASS: 2 grid nodes should be instrumented.
Changing `#normalNonGrid` to `display: block;`...
PASS: 2 grid nodes should be instrumented.
Changing `layoutContextTypeChangedMode` to `All`...
PASS: 2 grid nodes should be instrumented.
Changing `#normalNonGrid` to `display: grid;`...
PASS: 3 grid nodes should be instrumented.
Changing `#normalNonGrid` to `display: block;`...
PASS: 2 grid nodes should be instrumented.

173 changes: 173 additions & 0 deletions LayoutTests/inspector/css/setLayoutContextTypeChangedMode.html
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function changeElementDisplayValue(id, value)
{
document.getElementById(id).style.display = value;
}

function test()
{
let suite = InspectorTest.createAsyncSuite("CSS.setLayoutContextTypeChangedMode");

async function changeElementDisplayValue(id, value)
{
await InspectorTest.evaluateInPage(`changeElementDisplayValue("${id}", "${value}")`);
}

async function setLayoutContextTypeChangeMode(layoutContextTypeChangedMode)
{
WI.cssManager.layoutContextTypeChangedMode = layoutContextTypeChangedMode;
}

suite.addTestCase({
name: "CSS.setLayoutContextTypeChangedMode.queryGrid",
description: "Test that the expected number of grids are instrumented without chagning the LayoutContextTypeChangedMode.",
async test() {
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 0, "0 grid nodes should be instrumented.");

// Query for the node, sending it to the frontend.
InspectorTest.log("Querying document for selector `#queryGrid`...");
let documentNode = await WI.domManager.requestDocument();
let queryNode = WI.domManager.nodeForId(await documentNode.querySelector("#queryGrid"));
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 1, "1 grid node should be instrumented.");

InspectorTest.log("Changing `#queryGrid` to `display: block;`...");
await Promise.all([
queryNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("queryGrid", "block"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 0, "0 grid nodes should be instrumented.");

InspectorTest.log("Changing `#queryGrid` to `display: grid;`...");
await Promise.all([
queryNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("queryGrid", "grid"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 1, "1 grid node should be instrumented.");

InspectorTest.log("Changing `#queryGrid` to `display: block;`...");
await Promise.all([
queryNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("queryGrid", "block"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 0, "0 grid nodes should be instrumented.");

InspectorTest.log("Changing `#queryGrid` to `display: inline-grid;`...");
await Promise.all([
queryNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("queryGrid", "inline-grid"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 1, "1 grid node should be instrumented.");
}
});

suite.addTestCase({
name: "CSS.setLayoutContextTypeChangedMode.normalGrid",
description: "Test that grids become instrumented when chagning the mode to `All`.",
async test() {
await WI.domManager.requestDocument();

InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 1, "1 grid node should be instrumented.");

// Grid layout contexts are sent to the frontend when the mode is changed to all.
InspectorTest.log("Changing `layoutContextTypeChangedMode` to `All`...");
await Promise.all([
WI.domManager.awaitEvent(WI.DOMManager.Event.NodeInserted),
setLayoutContextTypeChangeMode(WI.CSSManager.LayoutContextTypeChangedMode.All),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

// Once a node has been observed, it will always be kept up-to-date.
InspectorTest.log("Changing `layoutContextTypeChangedMode` to `Observed`...");
await setLayoutContextTypeChangeMode(WI.CSSManager.LayoutContextTypeChangedMode.Observed),
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

InspectorTest.log("Changing `#normalGrid` to `display: block;`...");
await Promise.all([
WI.DOMNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("normalGrid", "block"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 1, "1 grid node should be instrumented.");

InspectorTest.log("Changing `#normalGrid` to `display: grid;`...");
await Promise.all([
WI.DOMNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("normalGrid", "grid"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");
}
});

suite.addTestCase({
name: "CSS.setLayoutContextTypeChangedMode.normalNonGrid",
description: "Ensure that layout context type changes for unobserved nodes do not fire events when the mode is `Observed`.",
async test() {
await WI.domManager.requestDocument();

InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

// Changes to unobserved nodes should not change the grid count.
InspectorTest.log("Changing `#normalNonGrid` to `display: grid;`...");
await changeElementDisplayValue("normalNonGrid", "grid");
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

InspectorTest.log("Changing `#normalNonGrid` to `display: block;`...");
await changeElementDisplayValue("normalNonGrid", "block");
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

// Enabling `All` mode should not change the grid count.
InspectorTest.log("Changing `layoutContextTypeChangedMode` to `All`...");
await setLayoutContextTypeChangeMode(WI.CSSManager.LayoutContextTypeChangedMode.All),
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");

// Changing a node to a grid after enabling `All` mode will increase the count.
InspectorTest.log("Changing `#normalNonGrid` to `display: grid;`...");
await Promise.all([
WI.DOMNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("normalNonGrid", "grid"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 3, "3 grid nodes should be instrumented.");

InspectorTest.log("Changing `#normalNonGrid` to `display: block;`...");
await Promise.all([
WI.DOMNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
changeElementDisplayValue("normalNonGrid", "block"),
]);
InspectorTest.expectEqual(WI.domManager.nodesWithLayoutContextType(WI.DOMNode.LayoutContextType.Grid).length, 2, "2 grid nodes should be instrumented.");
}
});

suite.runTestCasesAndFinish();
}
</script>
<style>
.grid-container {
display: grid;
}
</style>
</head>
<body onload="runTest()">
<p>Tests for the CSS.setLayoutContextTypeChangedMode command.</p>
<div id="queryGrid" class="grid-container">
<div></div>
<div></div>
</div>

<div>
<div id="normalGrid" class="grid-container">
<div></div>
<div></div>
</div>
</div>

<div>
<div id="normalNonGrid">
<div></div>
<div></div>
</div>
</div>
</body>
</html>
13 changes: 13 additions & 0 deletions Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,16 @@
2021-02-08 Patrick Angle <pangle@apple.com>

Web Inspector: Add `CSS.setLayoutContextTypeChangedMode` for getting information about all layout contexts
https://bugs.webkit.org/show_bug.cgi?id=221449

Reviewed by Devin Rousso.

Added `CSS.setLayoutContextTypeChangedMode` command and `CSS.LayoutContextTypeChangedMode` enum for controlling
if the frontend should be informed of all layout context type changes, or if only currently instrumented nodes
should be observed.

* inspector/protocol/CSS.json:

2021-02-08 Alicia Boya García <aboya@igalia.com>

Add ConsoleMessage::toString()
Expand Down
13 changes: 13 additions & 0 deletions Source/JavaScriptCore/inspector/protocol/CSS.json
Expand Up @@ -258,6 +258,12 @@
"type": "string",
"enum": ["grid"],
"description": "The layout context type of a node."
},
{
"id": "LayoutContextTypeChangedMode",
"type": "string",
"enum": ["observed", "all"],
"description": "The mode for how layout context type changes are handled. <code>Observed</code> limits handling to those nodes already known to the frontend by other means (generally, this means the node is a visible item in the Elements tab). <code>All</code> informs the frontend of all layout context type changes and."
}
],
"commands": [
Expand Down Expand Up @@ -418,6 +424,13 @@
{ "name": "nodeId", "$ref": "DOM.NodeId", "description": "The element id for which to force the pseudo state." },
{ "name": "forcedPseudoClasses", "type": "array", "items": { "type": "string", "enum": ["active", "focus", "hover", "visited"] }, "description": "Element pseudo classes to force when computing the element's style." }
]
},
{
"name": "setLayoutContextTypeChangedMode",
"description": "Change how layout context type changes are handled for nodes. When the new mode would observe nodes the frontend has not yet recieved, those nodes will be sent to the frontend immediately.",
"parameters": [
{ "name": "mode", "$ref": "LayoutContextTypeChangedMode", "description": "The mode for how layout context type changes are handled." }
]
}
],
"events": [
Expand Down
23 changes: 23 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,26 @@
2021-02-08 Patrick Angle <pangle@apple.com>

Web Inspector: Add `CSS.setLayoutContextTypeChangedMode` for getting information about all layout contexts
https://bugs.webkit.org/show_bug.cgi?id=221449

Reviewed by Devin Rousso.

Test: inspector/css/setLayoutContextTypeChangedMode.html

Backend support for changing the `LayoutContextTypeChangedMode`.

* inspector/agents/InspectorCSSAgent.cpp:
(WebCore::pushChildrenNodesToFrontendIfLayoutContextTypePresent):
- Recursively pushes children node paths to the frontend if a `LayoutContextType` exists for the node, which
allows the frontend to have a complete picture of the layout contexts in the document.
(WebCore::InspectorCSSAgent::setLayoutContextTypeChangedMode):
- If the mode is changed to `All`, then make sure any node with a `LayoutContextType` inside any document is
sent to the frontend.
(WebCore::InspectorCSSAgent::nodeLayoutContextTypeChanged):
- If the `LayoutContextTypeChangedMode` is `All`, inform the frontend of the node when it changes layout
context, even if the node was not previously instrumented.
* inspector/agents/InspectorCSSAgent.h:

2021-02-08 Don Olmstead <don.olmstead@sony.com>

[CMake] Cleanup ENABLE_ENCRYPTED_MEDIA build
Expand Down
35 changes: 34 additions & 1 deletion Source/WebCore/inspector/agents/InspectorCSSAgent.cpp
Expand Up @@ -37,9 +37,11 @@
#include "CSSStyleRule.h"
#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
#include "ContainerNode.h"
#include "ContentSecurityPolicy.h"
#include "DOMWindow.h"
#include "ElementAncestorIterator.h"
#include "ElementChildIterator.h"
#include "Font.h"
#include "FontCache.h"
#include "FontCascade.h"
Expand Down Expand Up @@ -932,6 +934,34 @@ Optional<Protocol::CSS::LayoutContextType> InspectorCSSAgent::layoutContextTypeF
return WTF::nullopt;
}

static void pushChildrenNodesToFrontendIfLayoutContextTypePresent(InspectorDOMAgent& domAgent, ContainerNode& node)
{
for (auto& child : childrenOfType<Element>(node))
pushChildrenNodesToFrontendIfLayoutContextTypePresent(domAgent, child);

if (InspectorCSSAgent::layoutContextTypeForRenderer(node.renderer()))
domAgent.pushNodeToFrontend(&node);
}

Protocol::ErrorStringOr<void> InspectorCSSAgent::setLayoutContextTypeChangedMode(Protocol::CSS::LayoutContextTypeChangedMode mode)
{
if (m_layoutContextTypeChangedMode == mode)
return { };

m_layoutContextTypeChangedMode = mode;

if (mode == Protocol::CSS::LayoutContextTypeChangedMode::All) {
auto* domAgent = m_instrumentingAgents.persistentDOMAgent();
if (!domAgent)
return makeUnexpected("DOM domain must be enabled"_s);

for (auto* document : domAgent->documents())
pushChildrenNodesToFrontendIfLayoutContextTypePresent(*domAgent, *document);
}

return { };
}

void InspectorCSSAgent::nodeLayoutContextTypeChanged(Node& node, RenderObject* oldRenderer)
{
auto* domAgent = m_instrumentingAgents.persistentDOMAgent();
Expand All @@ -942,8 +972,11 @@ void InspectorCSSAgent::nodeLayoutContextTypeChanged(Node& node, RenderObject* o
if (newLayoutContextType == layoutContextTypeForRenderer(oldRenderer))
return;

// FIXME: <https://webkit.org/b/221449> Support enabling events for uninstrumented nodes.
auto nodeId = domAgent->boundNodeId(&node);
if (!nodeId && m_layoutContextTypeChangedMode == Protocol::CSS::LayoutContextTypeChangedMode::All) {
// FIXME: <https://webkit.org/b/189687> Preserve DOM.NodeId if a node is removed and re-added
nodeId = domAgent->identifierForNode(node);
}
if (!nodeId)
return;

Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/inspector/agents/InspectorCSSAgent.h
Expand Up @@ -106,6 +106,7 @@ class InspectorCSSAgent final : public InspectorAgentBase , public Inspector::CS
Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSPropertyInfo>>> getSupportedCSSProperties();
Inspector::Protocol::ErrorStringOr<Ref<JSON::ArrayOf<String>>> getSupportedSystemFontFamilyNames();
Inspector::Protocol::ErrorStringOr<void> forcePseudoState(Inspector::Protocol::DOM::NodeId, Ref<JSON::Array>&& forcedPseudoClasses);
Inspector::Protocol::ErrorStringOr<void> setLayoutContextTypeChangedMode(Inspector::Protocol::CSS::LayoutContextTypeChangedMode);

// InspectorStyleSheet::Listener
void styleSheetChanged(InspectorStyleSheet*);
Expand Down Expand Up @@ -171,6 +172,7 @@ class InspectorCSSAgent final : public InspectorAgentBase , public Inspector::CS

int m_lastStyleSheetId { 1 };
bool m_creatingViaInspectorStyleSheet { false };
Inspector::Protocol::CSS::LayoutContextTypeChangedMode m_layoutContextTypeChangedMode { Inspector::Protocol::CSS::LayoutContextTypeChangedMode::Observed };
};

} // namespace WebCore

0 comments on commit 50eacad

Please sign in to comment.