Diff
Modified: trunk/LayoutTests/ChangeLog (219267 => 219268)
--- trunk/LayoutTests/ChangeLog 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/LayoutTests/ChangeLog 2017-07-07 21:30:47 UTC (rev 219268)
@@ -1,3 +1,14 @@
+2017-07-07 Devin Rousso <[email protected]>
+
+ Web Inspector: Show all elements currently using a given CSS Canvas
+ https://bugs.webkit.org/show_bug.cgi?id=173965
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/canvas/css-canvas-clients-expected.txt: Added.
+ * inspector/canvas/css-canvas-clients.html: Added.
+ * platform/mac/TestExpectations:
+
2017-07-07 Matt Lewis <[email protected]>
Adjusted test expectations for webrtc/video-replace-muted-track.html.
Added: trunk/LayoutTests/inspector/canvas/css-canvas-clients-expected.txt (0 => 219268)
--- trunk/LayoutTests/inspector/canvas/css-canvas-clients-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/canvas/css-canvas-clients-expected.txt 2017-07-07 21:30:47 UTC (rev 219268)
@@ -0,0 +1,22 @@
+Test that CanvasAgent tracks changes in the client nodes of a CSS canvas.
+
+
+== Running test suite: Canvas.CSSCanvasClients
+-- Running test case: Canvas.CSSCanvasClients.InitialLoad
+PASS: CanvasManager should have one canvas.
+PASS: Canvas should have CSS name "css-canvas".
+PASS: There should be no client nodes.
+
+-- Running test case: Canvas.CSSCanvasClients.Create
+PASS: Canvas with created client should have CSS name "css-canvas".
+PASS: There should be one client node.
+PASS: Client node "div" is valid.
+
+-- Running test case: Canvas.CSSCanvasClients.Destroy
+PASS: Canvas with destroyed client should have CSS name "css-canvas".
+PASS: There should be no client nodes.
+
+-- Running test case: Canvas.CSSCanvasClients.InvalidCanvasId
+PASS: Should produce an error.
+Error: Invalid canvas identifier
+
Added: trunk/LayoutTests/inspector/canvas/css-canvas-clients.html (0 => 219268)
--- trunk/LayoutTests/inspector/canvas/css-canvas-clients.html (rev 0)
+++ trunk/LayoutTests/inspector/canvas/css-canvas-clients.html 2017-07-07 21:30:47 UTC (rev 219268)
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function load() {
+ window.context2d = document.getCSSCanvasContext("2d", "css-canvas", 10, 10);
+
+ runTest();
+}
+
+let cssCanvasClients = [];
+
+function createCSSCanvasClient() {
+ cssCanvasClients.push(document.body.appendChild(document.createElement("div")));
+}
+
+function destroyCSSCanvasClients() {
+ for (let cssCanvasClient of cssCanvasClients)
+ cssCanvasClient.remove();
+
+ cssCanvasClients = [];
+
+ setTimeout(() => { GCController.collect(); }, 0);
+}
+
+function test() {
+ let suite = InspectorTest.createAsyncSuite("Canvas.CSSCanvasClients");
+
+ function logClientNodes(clientNodes) {
+ for (let clientNode of clientNodes) {
+ if (clientNode)
+ InspectorTest.pass(`Client node "${clientNode.appropriateSelectorFor()}" is valid.`);
+ else
+ InspectorTest.fail("Invalid client node.");
+ }
+ }
+
+ suite.addTestCase({
+ name: "Canvas.CSSCanvasClients.InitialLoad",
+ description: "Check that the CanvasManager has one CSS canvas initially.",
+ test(resolve, reject) {
+ let canvases = WebInspector.canvasManager.canvases;
+ InspectorTest.expectEqual(canvases.length, 1, "CanvasManager should have one canvas.");
+ if (!canvases.length) {
+ reject("Missing canvas.");
+ return;
+ }
+
+ InspectorTest.expectEqual(canvases[0].cssCanvasName, "css-canvas", `Canvas should have CSS name "css-canvas".`);
+ canvases[0].requestCSSCanvasClientNodes((clientNodes) => {
+ InspectorTest.expectEqual(clientNodes.length, 0, "There should be no client nodes.");
+ logClientNodes(clientNodes);
+ resolve();
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "Canvas.CSSCanvasClients.Create",
+ description: "Check that creating a CSS canvas client node is tracked correctly.",
+ test(resolve, reject) {
+ WebInspector.Canvas.awaitEvent(WebInspector.Canvas.Event.CSSCanvasClientNodesChanged)
+ .then((event) => {
+ InspectorTest.expectEqual(event.target.cssCanvasName, "css-canvas", `Canvas with created client should have CSS name "css-canvas".`);
+ event.target.requestCSSCanvasClientNodes((clientNodes) => {
+ InspectorTest.expectEqual(clientNodes.length, 1, "There should be one client node.");
+ logClientNodes(clientNodes);
+ resolve();
+ });
+ });
+
+ InspectorTest.evaluateInPage(`createCSSCanvasClient()`);
+ }
+ });
+
+ suite.addTestCase({
+ name: "Canvas.CSSCanvasClients.Destroy",
+ description: "Check that destroying a CSS canvas client node is tracked correctly.",
+ test(resolve, reject) {
+ WebInspector.Canvas.awaitEvent(WebInspector.Canvas.Event.CSSCanvasClientNodesChanged)
+ .then((event) => {
+ InspectorTest.expectEqual(event.target.cssCanvasName, "css-canvas", `Canvas with destroyed client should have CSS name "css-canvas".`);
+ event.target.requestCSSCanvasClientNodes((clientNodes) => {
+ InspectorTest.expectEqual(clientNodes.length, 0, "There should be no client nodes.");
+ logClientNodes(clientNodes);
+ resolve();
+ });
+ });
+
+ InspectorTest.evaluateInPage(`destroyCSSCanvasClients()`);
+ }
+ });
+
+ // ------
+
+ suite.addTestCase({
+ name: "Canvas.CSSCanvasClients.InvalidCanvasId",
+ description: "Invalid canvas identifiers should cause an error.",
+ test(resolve, reject) {
+ const canvasId = "DOES_NOT_EXIST";
+ CanvasAgent.requestCSSCanvasClientNodes(canvasId, (error, clientNodeIds) => {
+ InspectorTest.expectThat(error, "Should produce an error.");
+ InspectorTest.log("Error: " + error);
+ resolve();
+ });
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+<style>
+ div {
+ width: 10px;
+ height: 10px;
+ background-image: -webkit-canvas(css-canvas);
+ }
+</style>
+</head>
+<body _onload_="load()">
+ <p>Test that CanvasAgent tracks changes in the client nodes of a CSS canvas.</p>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/mac/TestExpectations (219267 => 219268)
--- trunk/LayoutTests/platform/mac/TestExpectations 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2017-07-07 21:30:47 UTC (rev 219268)
@@ -1141,6 +1141,7 @@
webkit.org/b/174066 inspector/canvas/create-context-webgl2.html [ Pass Timeout ]
webkit.org/b/174066 inspector/canvas/create-context-webgpu.html [ Pass Timeout ]
+webkit.org/b/174272 inspector/canvas/css-canvas-clients.html [ Pass Timeout ]
webkit.org/b/170615 inspector/codemirror/prettyprinting-css.html [ Pass Timeout ]
webkit.org/b/153460 inspector/codemirror/prettyprinting-css-rules.html [ Pass Timeout ]
webkit.org/b/160048 [ Debug ] inspector/codemirror/prettyprinting-_javascript_.html [ Pass Timeout ]
Modified: trunk/Source/_javascript_Core/ChangeLog (219267 => 219268)
--- trunk/Source/_javascript_Core/ChangeLog 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-07-07 21:30:47 UTC (rev 219268)
@@ -1,3 +1,16 @@
+2017-07-07 Devin Rousso <[email protected]>
+
+ Web Inspector: Show all elements currently using a given CSS Canvas
+ https://bugs.webkit.org/show_bug.cgi?id=173965
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/protocol/Canvas.json:
+ - Add `requestCSSCanvasClientNodes` command for getting the node IDs all nodes using this
+ canvas via -webkit-canvas.
+ - Add `cssCanvasClientNodesChanged` event that is dispatched whenever a node is
+ added/removed from the list of -webkit-canvas clients.
+
2017-07-07 Mark Lam <[email protected]>
\n\r is not the same as \r\n.
Modified: trunk/Source/_javascript_Core/inspector/protocol/Canvas.json (219267 => 219268)
--- trunk/Source/_javascript_Core/inspector/protocol/Canvas.json 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/_javascript_Core/inspector/protocol/Canvas.json 2017-07-07 21:30:47 UTC (rev 219268)
@@ -73,6 +73,16 @@
]
},
{
+ "name": "requestCSSCanvasClientNodes",
+ "description": "Gets all the nodes that are using this canvas via -webkit-canvas.",
+ "parameters": [
+ { "name": "canvasId", "$ref": "CanvasId" }
+ ],
+ "returns": [
+ { "name": "clientNodeIds", "type": "array", "items": { "$ref": "DOM.NodeId" } }
+ ]
+ },
+ {
"name": "resolveCanvasContext",
"description": "Resolves _javascript_ canvas context object for given canvasId.",
"parameters": [
@@ -103,6 +113,12 @@
{ "name": "canvasId", "$ref": "CanvasId", "description": "Identifier of canvas that changed." },
{ "name": "memoryCost", "type": "number", "description": "New memory cost value for the canvas in bytes." }
]
+ },
+ {
+ "name": "cssCanvasClientNodesChanged",
+ "parameters": [
+ { "name": "canvasId", "$ref": "CanvasId", "description": "Identifier of canvas that changed." }
+ ]
}
]
}
Modified: trunk/Source/WebCore/ChangeLog (219267 => 219268)
--- trunk/Source/WebCore/ChangeLog 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/ChangeLog 2017-07-07 21:30:47 UTC (rev 219268)
@@ -1,3 +1,42 @@
+2017-07-07 Devin Rousso <[email protected]>
+
+ Web Inspector: Show all elements currently using a given CSS Canvas
+ https://bugs.webkit.org/show_bug.cgi?id=173965
+
+ Reviewed by Joseph Pecoraro.
+
+ Test: inspector/canvas/css-canvas-clients.html
+
+ * css/CSSImageGeneratorValue.cpp:
+ (WebCore::CSSImageGeneratorValue::addClient):
+ (WebCore::CSSImageGeneratorValue::removeClient):
+ * css/CSSImageGeneratorValue.h:
+ (WebCore::CSSImageGeneratorValue::clients):
+ * html/HTMLCanvasElement.cpp:
+ (WebCore::HTMLCanvasElement::addObserver):
+ (WebCore::HTMLCanvasElement::removeObserver):
+ (WebCore::HTMLCanvasElement::cssCanvasClients):
+ Each time an observer is added/removed for a given HTMLCanvasElement, send an event to the
+ inspector frontend that the CSS canvas client nodes have changed. Additionally, anytime a
+ client/use is added/removed from one of the observing CSSCanvasValue, fire the same event.
+
+ * css/CSSCanvasValue.h:
+ (isType):
+ * html/HTMLCanvasElement.h:
+ (WebCore::CanvasObserver::isCSSCanvasValueObserver):
+ Allows type traits to distinguish CanvasObserver from CSSCanvasValue::CanvasObserverProxy.
+
+ * inspector/InspectorCanvasAgent.h:
+ * inspector/InspectorCanvasAgent.cpp:
+ (WebCore::InspectorCanvasAgent::requestCSSCanvasClientNodes):
+ (WebCore::InspectorCanvasAgent::didChangeCSSCanvasClientNodes):
+ * inspector/InspectorInstrumentation.h:
+ (WebCore::InspectorInstrumentation::didChangeCSSCanvasClientNodes):
+ * inspector/InspectorInstrumentation.cpp:
+ (WebCore::InspectorInstrumentation::didChangeCSSCanvasClientNodesImpl):
+ Notify the frontend that the list of client nodes has changed for the given canvas. Let the
+ frontend request the actual list of node IDs when it needs, possibly at a later time.
+
2017-07-07 Jer Noble <[email protected]>
AVPlayer can continue to be active after released by MediaPlayerPrivateAVFoundationObjC.
Modified: trunk/Source/WebCore/css/CSSCanvasValue.h (219267 => 219268)
--- trunk/Source/WebCore/css/CSSCanvasValue.h 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/css/CSSCanvasValue.h 2017-07-07 21:30:47 UTC (rev 219268)
@@ -44,19 +44,13 @@
bool isFixedSize() const { return true; }
FloatSize fixedSize(const RenderElement*);
+ HTMLCanvasElement* element() const { return m_element; }
+
bool isPending() const { return false; }
void loadSubimages(CachedResourceLoader&, const ResourceLoaderOptions&) { }
bool equals(const CSSCanvasValue&) const;
-private:
- explicit CSSCanvasValue(const String& name)
- : CSSImageGeneratorValue(CanvasClass)
- , m_canvasObserver(*this)
- , m_name(name)
- {
- }
-
// NOTE: We put the CanvasObserver in a member instead of inheriting from it
// to avoid adding a vptr to CSSCanvasValue.
class CanvasObserverProxy final : public CanvasObserver {
@@ -70,6 +64,10 @@
{
}
+ bool isCanvasObserverProxy() const final { return true; }
+
+ const CSSCanvasValue& ownerValue() const { return m_ownerValue; }
+
private:
void canvasChanged(HTMLCanvasElement& canvas, const FloatRect& changedRect) final
{
@@ -87,6 +85,14 @@
CSSCanvasValue& m_ownerValue;
};
+private:
+ explicit CSSCanvasValue(const String& name)
+ : CSSImageGeneratorValue(CanvasClass)
+ , m_canvasObserver(*this)
+ , m_name(name)
+ {
+ }
+
void canvasChanged(HTMLCanvasElement&, const FloatRect& changedRect);
void canvasResized(HTMLCanvasElement&);
void canvasDestroyed(HTMLCanvasElement&);
@@ -105,3 +111,7 @@
SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSCanvasValue, isCanvasValue())
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::CSSCanvasValue::CanvasObserverProxy)
+ static bool isType(const WebCore::CanvasObserver& canvasObserver) { return canvasObserver.isCanvasObserverProxy(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
Modified: trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp (219267 => 219268)
--- trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2017-07-07 21:30:47 UTC (rev 219268)
@@ -34,6 +34,8 @@
#include "CSSImageValue.h"
#include "CSSNamedImageValue.h"
#include "GeneratedImage.h"
+#include "HTMLCanvasElement.h"
+#include "InspectorInstrumentation.h"
#include "RenderElement.h"
namespace WebCore {
@@ -69,13 +71,27 @@
{
if (m_clients.isEmpty())
ref();
+
m_clients.add(&renderer);
+
+ if (is<CSSCanvasValue>(this)) {
+ if (HTMLCanvasElement* canvasElement = downcast<CSSCanvasValue>(this)->element())
+ InspectorInstrumentation::didChangeCSSCanvasClientNodes(*canvasElement);
+ }
}
void CSSImageGeneratorValue::removeClient(RenderElement& renderer)
{
ASSERT(m_clients.contains(&renderer));
- if (m_clients.remove(&renderer) && m_clients.isEmpty())
+ if (!m_clients.remove(&renderer))
+ return;
+
+ if (is<CSSCanvasValue>(this)) {
+ if (HTMLCanvasElement* canvasElement = downcast<CSSCanvasValue>(this)->element())
+ InspectorInstrumentation::didChangeCSSCanvasClientNodes(*canvasElement);
+ }
+
+ if (m_clients.isEmpty())
deref();
}
Modified: trunk/Source/WebCore/css/CSSImageGeneratorValue.h (219267 => 219268)
--- trunk/Source/WebCore/css/CSSImageGeneratorValue.h 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/css/CSSImageGeneratorValue.h 2017-07-07 21:30:47 UTC (rev 219268)
@@ -45,6 +45,7 @@
void addClient(RenderElement&);
void removeClient(RenderElement&);
+ const HashCountedSet<RenderElement*>& clients() const { return m_clients; }
RefPtr<Image> image(RenderElement&, const FloatSize&);
@@ -61,7 +62,6 @@
GeneratedImage* cachedImageForSize(FloatSize);
void saveCachedImageForSize(FloatSize, GeneratedImage&);
- const HashCountedSet<RenderElement*>& clients() const { return m_clients; }
// Helper functions for Crossfade and Filter.
static CachedImage* cachedImageForCSSValue(CSSValue&, CachedResourceLoader&, const ResourceLoaderOptions&);
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (219267 => 219268)
--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2017-07-07 21:30:47 UTC (rev 219268)
@@ -30,6 +30,7 @@
#include "Blob.h"
#include "BlobCallback.h"
+#include "CSSCanvasValue.h"
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "CanvasRenderingContext2D.h"
@@ -45,6 +46,7 @@
#include "ImageData.h"
#include "InspectorInstrumentation.h"
#include "MIMETypeRegistry.h"
+#include "RenderElement.h"
#include "RenderHTMLCanvas.h"
#include "RuntimeEnabledFeatures.h"
#include "ScriptController.h"
@@ -168,13 +170,35 @@
void HTMLCanvasElement::addObserver(CanvasObserver& observer)
{
m_observers.add(&observer);
+
+ if (is<CSSCanvasValue::CanvasObserverProxy>(observer))
+ InspectorInstrumentation::didChangeCSSCanvasClientNodes(*this);
}
void HTMLCanvasElement::removeObserver(CanvasObserver& observer)
{
m_observers.remove(&observer);
+
+ if (is<CSSCanvasValue::CanvasObserverProxy>(observer))
+ InspectorInstrumentation::didChangeCSSCanvasClientNodes(*this);
}
+HashSet<Element*> HTMLCanvasElement::cssCanvasClients() const
+{
+ HashSet<Element*> cssCanvasClients;
+ for (auto& observer : m_observers) {
+ if (!is<CSSCanvasValue::CanvasObserverProxy>(observer))
+ continue;
+
+ auto clients = downcast<CSSCanvasValue::CanvasObserverProxy>(observer)->ownerValue().clients();
+ for (auto& entry : clients) {
+ if (Element* element = entry.key->element())
+ cssCanvasClients.add(element);
+ }
+ }
+ return cssCanvasClients;
+}
+
void HTMLCanvasElement::setHeight(unsigned value)
{
setAttributeWithoutSynchronization(heightAttr, AtomicString::number(limitToOnlyHTMLNonNegative(value, defaultHeight)));
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (219267 => 219268)
--- trunk/Source/WebCore/html/HTMLCanvasElement.h 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h 2017-07-07 21:30:47 UTC (rev 219268)
@@ -32,6 +32,7 @@
#include "IntSize.h"
#include <memory>
#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
#if ENABLE(WEBGL)
#include "WebGLContextAttributes.h"
@@ -58,6 +59,8 @@
public:
virtual ~CanvasObserver() { }
+ virtual bool isCanvasObserverProxy() const { return false; }
+
virtual void canvasChanged(HTMLCanvasElement&, const FloatRect& changedRect) = 0;
virtual void canvasResized(HTMLCanvasElement&) = 0;
virtual void canvasDestroyed(HTMLCanvasElement&) = 0;
@@ -71,6 +74,7 @@
void addObserver(CanvasObserver&);
void removeObserver(CanvasObserver&);
+ HashSet<Element*> cssCanvasClients() const;
unsigned width() const { return size().width(); }
unsigned height() const { return size().height(); }
Modified: trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp (219267 => 219268)
--- trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/inspector/InspectorCanvasAgent.cpp 2017-07-07 21:30:47 UTC (rev 219268)
@@ -29,6 +29,7 @@
#include "CanvasRenderingContext.h"
#include "CanvasRenderingContext2D.h"
#include "Document.h"
+#include "Element.h"
#include "Frame.h"
#include "InspectorDOMAgent.h"
#include "InspectorPageAgent.h"
@@ -170,6 +171,21 @@
errorString = ASCIILiteral("Unsupported canvas context type");
}
+void InspectorCanvasAgent::requestCSSCanvasClientNodes(ErrorString& errorString, const String& canvasId, RefPtr<Inspector::Protocol::Array<int>>& result)
+{
+ const CanvasEntry* canvasEntry = getCanvasEntry(canvasId);
+ if (!canvasEntry) {
+ errorString = ASCIILiteral("Invalid canvas identifier");
+ return;
+ }
+
+ result = Inspector::Protocol::Array<int>::create();
+ for (Element* element : canvasEntry->element->cssCanvasClients()) {
+ if (int documentNodeId = m_instrumentingAgents.inspectorDOMAgent()->boundNodeId(&element->document()))
+ result->addItem(m_instrumentingAgents.inspectorDOMAgent()->pushNodeToFrontend(errorString, documentNodeId, element));
+ }
+}
+
static JSC::JSValue contextAsScriptValue(JSC::ExecState& state, CanvasRenderingContext* context)
{
JSC::JSLockHolder lock(&state);
@@ -250,6 +266,15 @@
m_canvasToCSSCanvasId.set(&canvasElement, name);
}
+void InspectorCanvasAgent::didChangeCSSCanvasClientNodes(HTMLCanvasElement& canvasElement)
+{
+ const CanvasEntry* canvasEntry = getCanvasEntry(canvasElement);
+ if (!canvasEntry)
+ return;
+
+ m_frontendDispatcher->cssCanvasClientNodesChanged(canvasEntry->identifier);
+}
+
void InspectorCanvasAgent::didCreateCanvasRenderingContext(HTMLCanvasElement& canvasElement)
{
if (m_canvasEntries.contains(&canvasElement)) {
Modified: trunk/Source/WebCore/inspector/InspectorCanvasAgent.h (219267 => 219268)
--- trunk/Source/WebCore/inspector/InspectorCanvasAgent.h 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/inspector/InspectorCanvasAgent.h 2017-07-07 21:30:47 UTC (rev 219268)
@@ -63,11 +63,13 @@
void disable(ErrorString&) override;
void requestNode(ErrorString&, const String& canvasId, int* nodeId) override;
void requestContent(ErrorString&, const String& canvasId, String* content) override;
+ void requestCSSCanvasClientNodes(ErrorString&, const String& canvasId, RefPtr<Inspector::Protocol::Array<int>>&) override;
void resolveCanvasContext(ErrorString&, const String& canvasId, const String* const objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>&) override;
// InspectorInstrumentation
void frameNavigated(Frame&);
void didCreateCSSCanvas(HTMLCanvasElement&, const String&);
+ void didChangeCSSCanvasClientNodes(HTMLCanvasElement&);
void didCreateCanvasRenderingContext(HTMLCanvasElement&);
void didChangeCanvasMemory(HTMLCanvasElement&);
Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (219267 => 219268)
--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp 2017-07-07 21:30:47 UTC (rev 219268)
@@ -999,6 +999,12 @@
canvasAgent->didCreateCSSCanvas(canvasElement, name);
}
+void InspectorInstrumentation::didChangeCSSCanvasClientNodesImpl(InstrumentingAgents* instrumentingAgents, HTMLCanvasElement& canvasElement)
+{
+ if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
+ canvasAgent->didChangeCSSCanvasClientNodes(canvasElement);
+}
+
void InspectorInstrumentation::didCreateCanvasRenderingContextImpl(InstrumentingAgents* instrumentingAgents, HTMLCanvasElement& canvasElement)
{
if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (219267 => 219268)
--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h 2017-07-07 21:30:47 UTC (rev 219268)
@@ -247,6 +247,7 @@
#endif
static void didCreateCSSCanvas(HTMLCanvasElement&, const String&);
+ static void didChangeCSSCanvasClientNodes(HTMLCanvasElement&);
static void didCreateCanvasRenderingContext(HTMLCanvasElement&);
static void didChangeCanvasMemory(HTMLCanvasElement&);
@@ -423,6 +424,7 @@
static void updateApplicationCacheStatusImpl(InstrumentingAgents&, Frame&);
static void didCreateCSSCanvasImpl(InstrumentingAgents*, HTMLCanvasElement&, const String&);
+ static void didChangeCSSCanvasClientNodesImpl(InstrumentingAgents*, HTMLCanvasElement&);
static void didCreateCanvasRenderingContextImpl(InstrumentingAgents*, HTMLCanvasElement&);
static void didChangeCanvasMemoryImpl(InstrumentingAgents*, HTMLCanvasElement&);
@@ -1189,7 +1191,14 @@
if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
didCreateCSSCanvasImpl(instrumentingAgents, canvasElement, name);
}
-
+
+inline void InspectorInstrumentation::didChangeCSSCanvasClientNodes(HTMLCanvasElement& canvasElement)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
+ didChangeCSSCanvasClientNodesImpl(instrumentingAgents, canvasElement);
+}
+
inline void InspectorInstrumentation::didCreateCanvasRenderingContext(HTMLCanvasElement& canvasElement)
{
if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(&canvasElement.document()))
Modified: trunk/Source/WebInspectorUI/ChangeLog (219267 => 219268)
--- trunk/Source/WebInspectorUI/ChangeLog 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/ChangeLog 2017-07-07 21:30:47 UTC (rev 219268)
@@ -1,3 +1,43 @@
+2017-07-07 Devin Rousso <[email protected]>
+
+ Web Inspector: Show all elements currently using a given CSS Canvas
+ https://bugs.webkit.org/show_bug.cgi?id=173965
+
+ Reviewed by Joseph Pecoraro.
+
+ * UserInterface/Controllers/CanvasManager.js:
+ (WebInspector.CanvasManager.prototype.cssCanvasClientNodesChanged):
+ * UserInterface/Models/Canvas.js:
+ (WebInspector.Canvas.prototype.requestCSSCanvasClientNodes):
+ (WebInspector.Canvas.prototype.cssCanvasClientNodesChanged):
+ * UserInterface/Protocol/CanvasObserver.js:
+ (WebInspector.CanvasObserver.prototype.cssCanvasClientNodesChanged):
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Views/CanvasDetailsSidebarPanel.js:
+ (WebInspector.CanvasDetailsSidebarPanel):
+ (WebInspector.CanvasDetailsSidebarPanel.prototype.set canvas):
+ (WebInspector.CanvasDetailsSidebarPanel.prototype.initialLayout):
+ (WebInspector.CanvasDetailsSidebarPanel.prototype.layout):
+ (WebInspector.CanvasDetailsSidebarPanel.prototype._refreshCSSCanvasSection):
+ (WebInspector.CanvasDetailsSidebarPanel.prototype._formatMemoryRow):
+ Add CSS section for CSS canvases. Currently displays a list of node links, each of which is
+ using the selected canvas via -webkit-canvas.
+
+ * UserInterface/Main.html:
+ * UserInterface/Views/CanvasDetailsSidebarPanel.css: Added.
+ (.sidebar > .panel.details.canvas .details-section > .content .row.simple > .value > .node-link):
+
+ * UserInterface/Controllers/DOMTreeManager.js:
+ (WebInspector.DOMTreeManager.prototype.ensureDocument):
+ * UserInterface/Models/Canvas.js:
+ (WebInspector.Canvas.prototype.requestNode):
+ * UserInterface/Views/SearchSidebarPanel.js:
+ (WebInspector.SearchSidebarPanel.prototype.performSearch):
+ Add convenience function that will call DOMAgent.getDocument with an empty function. Should
+ be used when it is necessary that the document has been sent to the frontend, but the
+ document node itself is not needed.
+
2017-07-07 Joseph Pecoraro <[email protected]>
Web Inspector: Clean up some unnecessary constructors
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -139,6 +139,7 @@
localizedStrings["Bubbling"] = "Bubbling";
localizedStrings["Busy"] = "Busy";
localizedStrings["CSP Hash"] = "CSP Hash";
+localizedStrings["CSS"] = "CSS";
localizedStrings["CSS Canvas"] = "CSS Canvas";
localizedStrings["CSS canvas ā%sā"] = "CSS canvas ā%sā";
localizedStrings["Cached"] = "Cached";
@@ -588,6 +589,7 @@
localizedStrings["No preview available"] = "No preview available";
localizedStrings["Node"] = "Node";
localizedStrings["Node Removed"] = "Node Removed";
+localizedStrings["Nodes"] = "Nodes";
localizedStrings["Not found"] = "Not found";
localizedStrings["Number"] = "Number";
localizedStrings["Numeric"] = "Numeric";
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -84,6 +84,18 @@
canvas.memoryCost = memoryCost;
}
+ cssCanvasClientNodesChanged(canvasIdentifier)
+ {
+ // Called from WebInspector.CanvasObserver.
+
+ let canvas = this._canvasIdentifierMap.get(canvasIdentifier);
+ console.assert(canvas);
+ if (!canvas)
+ return;
+
+ canvas.cssCanvasClientNodesChanged();
+ }
+
// Private
_mainResourceDidChange(event)
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -85,6 +85,11 @@
DOMAgent.getDocument(onDocumentAvailable.bind(this));
}
+ ensureDocument()
+ {
+ this.requestDocument(function(){});
+ }
+
pushNodeToFrontend(objectId, callback)
{
this._dispatchWhenDocumentAvailable(DOMAgent.requestNode.bind(DOMAgent, objectId), callback);
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2017-07-07 21:30:47 UTC (rev 219268)
@@ -46,6 +46,7 @@
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Canvas.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Models/Canvas.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Canvas.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -40,6 +40,8 @@
this._cssCanvasName = cssCanvasName || "";
this._contextAttributes = contextAttributes || {};
this._memoryCost = memoryCost || NaN;
+
+ this._cssCanvasClientNodes = null;
}
// Static
@@ -140,16 +142,16 @@
return;
}
- WebInspector.domTreeManager.requestDocument((document) => {
- CanvasAgent.requestNode(this._identifier, (error, nodeId) => {
- if (error) {
- callback(null);
- return;
- }
+ WebInspector.domTreeManager.ensureDocument();
- this._domNode = WebInspector.domTreeManager.nodeForId(nodeId);
- callback(this._domNode);
- });
+ CanvasAgent.requestNode(this._identifier, (error, nodeId) => {
+ if (error) {
+ callback(null);
+ return;
+ }
+
+ this._domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ callback(this._domNode);
});
}
@@ -165,6 +167,33 @@
});
}
+ requestCSSCanvasClientNodes(callback)
+ {
+ if (!this._cssCanvasName) {
+ callback([]);
+ return;
+ }
+
+ if (this._cssCanvasClientNodes) {
+ callback(this._cssCanvasClientNodes);
+ return;
+ }
+
+ WebInspector.domTreeManager.ensureDocument();
+
+ CanvasAgent.requestCSSCanvasClientNodes(this._identifier, (error, clientNodeIds) => {
+ if (error) {
+ callback([]);
+ return;
+ }
+
+ clientNodeIds = Array.isArray(clientNodeIds) ? clientNodeIds : [];
+ this._cssCanvasClientNodes = clientNodeIds.map((clientNodeId) => WebInspector.domTreeManager.nodeForId(clientNodeId));
+
+ callback(this._cssCanvasClientNodes);
+ });
+ }
+
saveIdentityToCookie(cookie)
{
cookie[WebInspector.Canvas.FrameURLCookieKey] = this._frame.url.hash;
@@ -175,6 +204,18 @@
cookie[WebInspector.Canvas.NodePathCookieKey] = this._domNode.path;
}
+
+ cssCanvasClientNodesChanged()
+ {
+ // Called from WebInspector.CanvasManager.
+
+ if (!this._cssCanvasName)
+ return;
+
+ this._cssCanvasClientNodes = null;
+
+ this.dispatchEventToListeners(WebInspector.Canvas.Event.CSSCanvasClientNodesChanged);
+ }
};
WebInspector.Canvas._nextUniqueDisplayNameNumber = 1;
@@ -193,4 +234,5 @@
WebInspector.Canvas.Event = {
MemoryChanged: "canvas-memory-changed",
+ CSSCanvasClientNodesChanged: "canvas-css-canvas-client-nodes-changed",
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/CanvasObserver.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Protocol/CanvasObserver.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/CanvasObserver.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -41,4 +41,9 @@
{
WebInspector.canvasManager.canvasMemoryChanged(canvasId, memoryCost);
}
+
+ cssCanvasClientNodesChanged(canvasId)
+ {
+ WebInspector.canvasManager.cssCanvasClientNodesChanged(canvasId);
+ }
};
Copied: trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.css (from rev 219267, trunk/Source/WebInspectorUI/UserInterface/Protocol/CanvasObserver.js) (0 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.css 2017-07-07 21:30:47 UTC (rev 219268)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.sidebar > .panel.details.canvas .details-section > .content .row.simple > .value > .node-link {
+ display: block;
+}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CanvasDetailsSidebarPanel.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -27,7 +27,7 @@
{
constructor()
{
- super("canvas-details", WebInspector.UIString("Canvas"));
+ super("canvas", WebInspector.UIString("Canvas"));
this.element.classList.add("canvas");
@@ -64,13 +64,17 @@
this._node = null;
}
- if (this._canvas)
+ if (this._canvas) {
this._canvas.removeEventListener(WebInspector.Canvas.Event.MemoryChanged, this._canvasMemoryChanged, this);
+ this._canvas.removeEventListener(WebInspector.Canvas.Event.CSSCanvasClientNodesChanged, this._refreshCSSCanvasSection, this);
+ }
this._canvas = canvas || null;
- if (this._canvas)
+ if (this._canvas) {
this._canvas.addEventListener(WebInspector.Canvas.Event.MemoryChanged, this._canvasMemoryChanged, this);
+ this._canvas.addEventListener(WebInspector.Canvas.Event.CSSCanvasClientNodesChanged, this._refreshCSSCanvasSection, this);
+ }
this.needsLayout();
}
@@ -84,6 +88,7 @@
this._nameRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Name"));
this._typeRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Type"));
this._memoryRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Memory"));
+ this._memoryRow.tooltip = WebInspector.UIString("Memory usage of this canvas");
let identitySection = new WebInspector.DetailsSection("canvas-details", WebInspector.UIString("Identity"));
identitySection.groups = [new WebInspector.DetailsSectionGroup([this._nameRow, this._typeRow, this._memoryRow])];
@@ -104,6 +109,13 @@
let attributesSection = new WebInspector.DetailsSection("canvas-attributes", WebInspector.UIString("Attributes"));
attributesSection.groups = [new WebInspector.DetailsSectionGroup([this._attributesDataGridRow])];
this.contentView.element.appendChild(attributesSection.element);
+
+ this._cssCanvasClientsRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Nodes"));
+
+ this._cssCanvasSection = new WebInspector.DetailsSection("canvas-css", WebInspector.UIString("CSS"));
+ this._cssCanvasSection.groups = [new WebInspector.DetailsSectionGroup([this._cssCanvasClientsRow])];
+ this._cssCanvasSection.element.hidden = true;
+ this.contentView.element.appendChild(this._cssCanvasSection.element);
}
layout()
@@ -116,6 +128,7 @@
this._refreshIdentitySection();
this._refreshSourceSection();
this._refreshAttributesSection();
+ this._refreshCSSCanvasSection();
}
sizeDidChange()
@@ -239,6 +252,31 @@
dataGrid.updateLayoutIfNeeded();
}
+ _refreshCSSCanvasSection()
+ {
+ if (!this._canvas)
+ return;
+
+ if (!this._canvas.cssCanvasName) {
+ this._cssCanvasSection.element.hidden = true;
+ return;
+ }
+
+ this._cssCanvasClientsRow.value = emDash;
+
+ this._cssCanvasSection.element.hidden = false;
+
+ this._canvas.requestCSSCanvasClientNodes((cssCanvasClientNodes) => {
+ if (!cssCanvasClientNodes.length)
+ return;
+
+ let fragment = document.createDocumentFragment();
+ for (let clientNode of cssCanvasClientNodes)
+ fragment.appendChild(WebInspector.linkifyNodeReference(clientNode));
+ this._cssCanvasClientsRow.value = fragment;
+ });
+ }
+
_formatMemoryRow()
{
if (!this._canvas.memoryCost || isNaN(this._canvas.memoryCost)) {
@@ -246,9 +284,7 @@
return;
}
- let canvasMemory = Number.bytesToString(this._canvas.memoryCost);
- this._memoryRow.value = canvasMemory;
- this._memoryRow.tooltip = WebInspector.UIString("Memory usage of this canvas");
+ this._memoryRow.value = Number.bytesToString(this._canvas.memoryCost);
}
_canvasMemoryChanged(event)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SearchSidebarPanel.js (219267 => 219268)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SearchSidebarPanel.js 2017-07-07 20:38:33 UTC (rev 219267)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SearchSidebarPanel.js 2017-07-07 21:30:47 UTC (rev 219268)
@@ -278,7 +278,7 @@
}
if (window.DOMAgent)
- WebInspector.domTreeManager.requestDocument(function(){});
+ WebInspector.domTreeManager.ensureDocument();
if (window.PageAgent)
PageAgent.searchInResources(searchQuery, isCaseSensitive, isRegex, resourcesCallback.bind(this));