Title: [237431] trunk
Revision
237431
Author
[email protected]
Date
2018-10-25 15:59:29 -0700 (Thu, 25 Oct 2018)

Log Message

Web Inspector: display fullscreen enter/exit events in Timelines and Network node waterfalls
https://bugs.webkit.org/show_bug.cgi?id=189874
<rdar://problem/44700000>

Reviewed by Joseph Pecoraro.

Source/_javascript_Core:

* inspector/protocol/DOM.json:
Allow `data` to be passed to the frontend with `didFireEvent`.

Source/WebCore:

Updated existing test: http/tests/inspector/dom/didFireEvent.html

* inspector/agents/InspectorDOMAgent.h:
* inspector/agents/InspectorDOMAgent.cpp:
(WebCore::EventFiredCallback::handleEvent):
(WebCore::InspectorDOMAgent::didCreateFrontendAndBackend):
(WebCore::InspectorDOMAgent::addEventListenersToNode):
(WebCore::InspectorDOMAgent::discardBindings):
(WebCore::InspectorDOMAgent::eventDidResetAfterDispatch): Added.
Prevent the same event from being sent to the frontend more than once.

* dom/Event.cpp:
(WebCore::Event::resetAfterDispatch):

* dom/Document.cpp:
(WebCore::Document::Document):

* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::eventDidResetAfterDispatch): Added.
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::eventDidResetAfterDispatchImpl): Added.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:

* UserInterface/Protocol/DOMObserver.js:
(WI.DOMObserver.prototype.didFireEvent):
* UserInterface/Controllers/DOMManager.js:
(WI.DOMManager.prototype.didFireEvent):
Allow `data` to be passed to the frontend with `didFireEvent`.

* UserInterface/Models/DOMNode.js:
(WI.DOMNode):
(WI.DOMNode.getFullscreenDOMEvents): Added.
(WI.DOMNode.prototype.didFireEvent):
(WI.DOMNode.prototype._handleDOMNodeDidFireEvent): Added.
(WI.DOMNode.prototype._addDOMEvent):
(WI.DOMNode.prototype._shouldListenForEventListeners): Added.
If an event is fired on an ancestor of this node, also record that event in this node's
`domEvents`, including the `originator` node.

* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView.prototype._populateWaterfallGraph):
* UserInterface/Views/NetworkTableContentView.css:
(.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen): Added.

* UserInterface/Views/DOMEventsBreakdownView.js:
(WI.DOMEventsBreakdownView.prototype.initialLayout):
(WI.DOMEventsBreakdownView.prototype._populateTable):
* UserInterface/Views/DOMEventsBreakdownView.css:
(.dom-events-breakdown .graph > .area.fullscreen): Added.
(.dom-events-breakdown .inherited > .name, .dom-events-breakdown .inherited > .graph > .point): Added.
(.dom-events-breakdown:not(.has-inherited) .originator): Added.

LayoutTests:

* http/tests/inspector/dom/didFireEvent-expected.txt:
* http/tests/inspector/dom/didFireEvent.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (237430 => 237431)


--- trunk/LayoutTests/ChangeLog	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/LayoutTests/ChangeLog	2018-10-25 22:59:29 UTC (rev 237431)
@@ -1,3 +1,14 @@
+2018-10-25  Devin Rousso  <[email protected]>
+
+        Web Inspector: display fullscreen enter/exit events in Timelines and Network node waterfalls
+        https://bugs.webkit.org/show_bug.cgi?id=189874
+        <rdar://problem/44700000>
+
+        Reviewed by Joseph Pecoraro.
+
+        * http/tests/inspector/dom/didFireEvent-expected.txt:
+        * http/tests/inspector/dom/didFireEvent.html:
+
 2018-10-25  Alexey Proskuryakov  <[email protected]>
 
         https://bugs.webkit.org/show_bug.cgi?id=175597

Modified: trunk/LayoutTests/http/tests/inspector/dom/didFireEvent-expected.txt (237430 => 237431)


--- trunk/LayoutTests/http/tests/inspector/dom/didFireEvent-expected.txt	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/LayoutTests/http/tests/inspector/dom/didFireEvent-expected.txt	2018-10-25 22:59:29 UTC (rev 237431)
@@ -3,8 +3,38 @@
 
 
 == Running test suite: DOM.didFireEvent
--- Running test case: DOM.didFireEvent
+-- Running test case: DOM.didFireEvent.Basic
 Adding video source "resources/white.mp4"...
-PASS: Should recieve a "loadstart" event.
+PASS: Should receive a "loadstart" event.
 PASS: Event timestamp should be greater than 0.
 
+-- Running test case: DOM.didFireEvent.Fullscreen
+Entering fullscreen on #video...
+PASS: Should receive a "webkitfullscreenchange" event.
+PASS: Event timestamp should be greater than 0.
+PASS: Event should have data.
+PASS: Fullscreen should be true.
+Target: video#video
+Exiting fullscreen...
+PASS: Should receive a "webkitfullscreenchange" event.
+PASS: Event timestamp should be greater than 0.
+PASS: Event should have data.
+PASS: Fullscreen should be false.
+Target: video#video
+
+-- Running test case: DOM.didFireEvent.Inherited
+Entering fullscreen on #container...
+PASS: Should receive a "webkitfullscreenchange" event.
+PASS: Event timestamp should be greater than 0.
+PASS: Event should have data.
+PASS: Fullscreen should be true.
+Target: video#video
+Originator: div#container
+Exiting fullscreen...
+PASS: Should receive a "webkitfullscreenchange" event.
+PASS: Event timestamp should be greater than 0.
+PASS: Event should have data.
+PASS: Fullscreen should be false.
+Target: video#video
+Originator: div#container
+

Modified: trunk/LayoutTests/http/tests/inspector/dom/didFireEvent.html (237430 => 237431)


--- trunk/LayoutTests/http/tests/inspector/dom/didFireEvent.html	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/LayoutTests/http/tests/inspector/dom/didFireEvent.html	2018-10-25 22:59:29 UTC (rev 237431)
@@ -11,14 +11,80 @@
     document.getElementById("video").appendChild(sourceElement);
 }
 
+function enterFullscreen(element) {
+    document.addEventListener("keydown", (event) => {
+        document.addEventListener("webkitfullscreenchange", (event) => {
+            console.assert(document.webkitFullscreenElement === element);
+
+            TestPage.dispatchEventToFrontend("TestPage-enteredFullscreen");
+        }, {once: true});
+
+        element.webkitRequestFullscreen();
+    }, {once: true});
+
+    if (window.testRunner) {
+        // DumpRenderTree changes the firstResponder to the WebInspector window when it opens.
+        // This refocuses the test page, ensuring it gets the event.
+        if (window.testRunner.setMainFrameIsFirstResponder)
+            window.testRunner.setMainFrameIsFirstResponder(true);
+
+        eventSender.keyDown(" ");
+    }
+}
+
+function exitFullscreen() {
+    document.addEventListener("webkitfullscreenchange", (event) => {
+        console.assert(!document.webkitFullscreenElement);
+
+        TestPage.dispatchEventToFrontend("TestPage-exitedFullscreen");
+    }, {once: true});
+
+    document.webkitExitFullscreen();
+}
+
 function test()
 {
+    InspectorTest.debug();
+
     let suite = InspectorTest.createAsyncSuite("DOM.didFireEvent");
 
     let videoNode = null;
 
+    function fullscreenTest(fullscreenElementId, resolve, reject) {
+        InspectorTest.awaitEvent("TestPage-exitedFullscreen")
+        .then(resolve, reject);
+
+        InspectorTest.awaitEvent("TestPage-enteredFullscreen")
+        .then((event) => {
+            InspectorTest.log("Exiting fullscreen...");
+            InspectorTest.evaluateInPage(`exitFullscreen()`).catch(reject);
+        });
+
+        let enabled = false;
+        let listener = videoNode.addEventListener(WI.DOMNode.Event.DidFireEvent, (event) => {
+            let {domEvent} = event.data;
+            if (domEvent.eventName !== "webkitfullscreenchange")
+                return;
+
+            InspectorTest.pass(`Should receive a "webkitfullscreenchange" event.`);
+            InspectorTest.expectGreaterThan(domEvent.timestamp, 0, "Event timestamp should be greater than 0.");
+            InspectorTest.expectThat(domEvent.data, "Event should have data.");
+            InspectorTest.expectNotEqual(domEvent.data.enabled, enabled, `Fullscreen should be ${!enabled}.`);
+            InspectorTest.log("Target: " + event.target.displayName);
+            if (domEvent.originator)
+                InspectorTest.log("Originator: " + domEvent.originator.displayName);
+
+            enabled = domEvent.data.enabled;
+            if (!enabled)
+                videoNode.removeEventListener(WI.DOMNode.Event.DidFireEvent, listener);
+        });
+
+        InspectorTest.log(`Entering fullscreen on #${fullscreenElementId}...`);
+        InspectorTest.evaluateInPage(`enterFullscreen(document.getElementById("${fullscreenElementId}"))`).catch(reject);
+    }
+
     suite.addTestCase({
-        name: "DOM.didFireEvent",
+        name: "DOM.didFireEvent.Basic",
         description: "Check that HTMLMediaElement events work.",
         test(resolve, reject) {
             const file = "white.mp4";
@@ -28,7 +94,7 @@
                 if (domEvent.eventName !== "loadstart")
                     return;
 
-                InspectorTest.pass(`Should recieve a "loadstart" event.`)
+                InspectorTest.pass(`Should receive a "loadstart" event.`)
                 InspectorTest.expectGreaterThan(domEvent.timestamp, 0, "Event timestamp should be greater than 0.");
 
                 videoNode.removeEventListener(WI.DOMNode.Event.DidFireEvent, listener);
@@ -40,6 +106,22 @@
         }
     });
 
+    suite.addTestCase({
+        name: "DOM.didFireEvent.Fullscreen",
+        description: "Check that fullscreen events work.",
+        test(resolve, reject) {
+            fullscreenTest("video", resolve, reject);
+        }
+    });
+
+    suite.addTestCase({
+        name: "DOM.didFireEvent.Inherited",
+        description: "Check that inherited events work.",
+        test(resolve, reject) {
+            fullscreenTest("container", resolve, reject);
+        }
+    });
+
     WI.domManager.requestDocument((documentNode) => {
         WI.domManager.querySelector(documentNode.id, "#video", (videoNodeId) => {
             videoNode = WI.domManager.nodeForId(videoNodeId);
@@ -56,6 +138,8 @@
 </head>
 <body _onload_="runTest()">
     <p>Tests that listeners registered by InspectorDOMAgent::addEventListenersToNode are working.</p>
-    <video id="video" muted autoplay></video>
+    <div id="container">
+        <video id="video" muted autoplay></video>
+    </div>
 </body>
 </html>

Modified: trunk/Source/_javascript_Core/ChangeLog (237430 => 237431)


--- trunk/Source/_javascript_Core/ChangeLog	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-10-25 22:59:29 UTC (rev 237431)
@@ -1,3 +1,14 @@
+2018-10-25  Devin Rousso  <[email protected]>
+
+        Web Inspector: display fullscreen enter/exit events in Timelines and Network node waterfalls
+        https://bugs.webkit.org/show_bug.cgi?id=189874
+        <rdar://problem/44700000>
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/protocol/DOM.json:
+        Allow `data` to be passed to the frontend with `didFireEvent`.
+
 2018-10-25  Ross Kirsling  <[email protected]>
 
         Cleanup: inline constexpr is redundant as constexpr implies inline

Modified: trunk/Source/_javascript_Core/inspector/protocol/DOM.json (237430 => 237431)


--- trunk/Source/_javascript_Core/inspector/protocol/DOM.json	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/_javascript_Core/inspector/protocol/DOM.json	2018-10-25 22:59:29 UTC (rev 237431)
@@ -666,7 +666,8 @@
             "parameters": [
                 { "name": "nodeId", "$ref": "NodeId" },
                 { "name": "eventName", "type": "string" },
-                { "name": "timestamp", "$ref": "Network.Timestamp", "description": "Time when the event was fired" }
+                { "name": "timestamp", "$ref": "Network.Timestamp", "description": "Time when the event was fired" },
+                { "name": "data", "type": "object", "optional": true, "description": "Holds ancillary information about the event or its target." }
             ]
         }
     ]

Modified: trunk/Source/WebCore/ChangeLog (237430 => 237431)


--- trunk/Source/WebCore/ChangeLog	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/ChangeLog	2018-10-25 22:59:29 UTC (rev 237431)
@@ -1,3 +1,33 @@
+2018-10-25  Devin Rousso  <[email protected]>
+
+        Web Inspector: display fullscreen enter/exit events in Timelines and Network node waterfalls
+        https://bugs.webkit.org/show_bug.cgi?id=189874
+        <rdar://problem/44700000>
+
+        Reviewed by Joseph Pecoraro.
+
+        Updated existing test: http/tests/inspector/dom/didFireEvent.html
+
+        * inspector/agents/InspectorDOMAgent.h:
+        * inspector/agents/InspectorDOMAgent.cpp:
+        (WebCore::EventFiredCallback::handleEvent):
+        (WebCore::InspectorDOMAgent::didCreateFrontendAndBackend):
+        (WebCore::InspectorDOMAgent::addEventListenersToNode):
+        (WebCore::InspectorDOMAgent::discardBindings):
+        (WebCore::InspectorDOMAgent::eventDidResetAfterDispatch): Added.
+        Prevent the same event from being sent to the frontend more than once.
+
+        * dom/Event.cpp:
+        (WebCore::Event::resetAfterDispatch):
+
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::eventDidResetAfterDispatch): Added.
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::eventDidResetAfterDispatchImpl): Added.
+
 2018-10-25  Michael Catanzaro  <[email protected]>
 
         Unreviewed, silence a -Wreturn-type warning

Modified: trunk/Source/WebCore/dom/Document.cpp (237430 => 237431)


--- trunk/Source/WebCore/dom/Document.cpp	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-10-25 22:59:29 UTC (rev 237431)
@@ -560,6 +560,8 @@
 
     for (auto& nodeListAndCollectionCount : m_nodeListAndCollectionCounts)
         nodeListAndCollectionCount = 0;
+
+    InspectorInstrumentation::addEventListenersToNode(*this);
 }
 
 #if ENABLE(FULLSCREEN_API)

Modified: trunk/Source/WebCore/dom/Event.cpp (237430 => 237431)


--- trunk/Source/WebCore/dom/Event.cpp	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/dom/Event.cpp	2018-10-25 22:59:29 UTC (rev 237431)
@@ -171,6 +171,8 @@
     m_eventPhase = NONE;
     m_propagationStopped = false;
     m_immediatePropagationStopped = false;
+
+    InspectorInstrumentation::eventDidResetAfterDispatch(*this);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (237430 => 237431)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp	2018-10-25 22:59:29 UTC (rev 237431)
@@ -429,6 +429,12 @@
         timelineAgent->didDispatchEvent();
 }
 
+void InspectorInstrumentation::eventDidResetAfterDispatchImpl(InstrumentingAgents& instrumentingAgents, const Event& event)
+{
+    if (auto* domAgent = instrumentingAgents.inspectorDOMAgent())
+        domAgent->eventDidResetAfterDispatch(event);
+}
+
 InspectorInstrumentationCookie InspectorInstrumentation::willEvaluateScriptImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const String& url, int lineNumber)
 {
     int timelineAgentId = 0;

Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (237430 => 237431)


--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h	2018-10-25 22:59:29 UTC (rev 237431)
@@ -157,6 +157,7 @@
     static void didHandleEvent(ScriptExecutionContext&);
     static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event&, DOMWindow&);
     static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
+    static void eventDidResetAfterDispatch(const Event&);
     static InspectorInstrumentationCookie willEvaluateScript(Frame&, const String& url, int lineNumber);
     static void didEvaluateScript(const InspectorInstrumentationCookie&, Frame&);
     static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId, bool oneShot);
@@ -343,6 +344,7 @@
     static void didDispatchEventImpl(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents&, const Event&, DOMWindow&);
     static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
+    static void eventDidResetAfterDispatchImpl(InstrumentingAgents&, const Event&);
     static InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents&, Frame&, const String& url, int lineNumber);
     static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&, Frame&);
     static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, bool oneShot, ScriptExecutionContext&);
@@ -809,6 +811,18 @@
         didDispatchEventOnWindowImpl(cookie);
 }
 
+inline void InspectorInstrumentation::eventDidResetAfterDispatch(const Event& event)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+
+    if (!is<Node>(event.target()))
+        return;
+
+    auto* node = downcast<Node>(event.target());
+    if (auto* instrumentingAgents = instrumentingAgentsForContext(node->scriptExecutionContext()))
+        return eventDidResetAfterDispatchImpl(*instrumentingAgents, event);
+}
+
 inline InspectorInstrumentationCookie InspectorInstrumentation::willEvaluateScript(Frame& frame, const String& url, int lineNumber)
 {
     FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());

Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (237430 => 237431)


--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp	2018-10-25 22:59:29 UTC (rev 237431)
@@ -234,7 +234,7 @@
 
     void handleEvent(ScriptExecutionContext&, Event& event) final
     {
-        if (!is<Node>(event.target()))
+        if (!is<Node>(event.target()) || m_domAgent.m_dispatchedEvents.contains(&event))
             return;
 
         auto* node = downcast<Node>(event.target());
@@ -242,8 +242,15 @@
         if (!nodeId)
             return;
 
+        m_domAgent.m_dispatchedEvents.add(&event);
+
+        RefPtr<JSON::Object> data = ""
+
+        if (event.type() == eventNames().webkitfullscreenchangeEvent)
+            data->setBoolean("enabled"_s, !!node->document().webkitFullscreenElement());
+
         auto timestamp = m_domAgent.m_environment.executionStopwatch()->elapsedTime().seconds();
-        m_domAgent.m_frontendDispatcher->didFireEvent(nodeId, event.type(), timestamp);
+        m_domAgent.m_frontendDispatcher->didFireEvent(nodeId, event.type(), timestamp, data->size() ? WTFMove(data) : nullptr);
     }
 
 private:
@@ -290,6 +297,9 @@
     m_instrumentingAgents.setInspectorDOMAgent(this);
     m_document = m_pageAgent->mainFrame().document();
 
+    if (m_document)
+        addEventListenersToNode(*m_document);
+
     for (auto* mediaElement : HTMLMediaElement::allMediaElements())
         addEventListenersToNode(*mediaElement);
 
@@ -523,6 +533,7 @@
 {
     m_documentNodeToIdMap.clear();
     m_idToNode.clear();
+    m_dispatchedEvents.clear();
     m_eventListenerEntries.clear();
     releaseDanglingNodes();
     m_childrenRequested.clear();
@@ -2138,7 +2149,10 @@
         node.addEventListener(eventName, callback.copyRef(), false);
     };
 
-    if (is<HTMLMediaElement>(node)) {
+    if (is<Document>(node))
+        createEventListener(eventNames().webkitfullscreenchangeEvent);
+    else if (is<HTMLMediaElement>(node)) {
+        createEventListener(eventNames().webkitfullscreenchangeEvent);
         createEventListener(eventNames().abortEvent);
         createEventListener(eventNames().canplayEvent);
         createEventListener(eventNames().canplaythroughEvent);
@@ -2406,6 +2420,11 @@
     return false;
 }
 
+void InspectorDOMAgent::eventDidResetAfterDispatch(const Event& event)
+{
+    m_dispatchedEvents.remove(&event);
+}
+
 bool InspectorDOMAgent::hasBreakpointForEventListener(EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture)
 {
     for (auto& inspectorEventListener : m_eventListenerEntries.values()) {

Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h (237430 => 237431)


--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h	2018-10-25 22:59:29 UTC (rev 237431)
@@ -177,6 +177,7 @@
     void didAddEventListener(EventTarget&);
     void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
+    void eventDidResetAfterDispatch(const Event&);
 
     // Callbacks that don't directly correspond to an instrumentation entry point.
     void setDocument(Document*);
@@ -319,6 +320,7 @@
 
     friend class EventFiredCallback;
 
+    HashSet<const Event*> m_dispatchedEvents;
     HashMap<int, InspectorEventListener> m_eventListenerEntries;
     int m_lastEventListenerId { 1 };
 };

Modified: trunk/Source/WebInspectorUI/ChangeLog (237430 => 237431)


--- trunk/Source/WebInspectorUI/ChangeLog	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/ChangeLog	2018-10-25 22:59:29 UTC (rev 237431)
@@ -1,5 +1,44 @@
 2018-10-25  Devin Rousso  <[email protected]>
 
+        Web Inspector: display fullscreen enter/exit events in Timelines and Network node waterfalls
+        https://bugs.webkit.org/show_bug.cgi?id=189874
+        <rdar://problem/44700000>
+
+        Reviewed by Joseph Pecoraro.
+
+        * Localizations/en.lproj/localizedStrings.js:
+
+        * UserInterface/Protocol/DOMObserver.js:
+        (WI.DOMObserver.prototype.didFireEvent):
+        * UserInterface/Controllers/DOMManager.js:
+        (WI.DOMManager.prototype.didFireEvent):
+        Allow `data` to be passed to the frontend with `didFireEvent`.
+
+        * UserInterface/Models/DOMNode.js:
+        (WI.DOMNode):
+        (WI.DOMNode.getFullscreenDOMEvents): Added.
+        (WI.DOMNode.prototype.didFireEvent):
+        (WI.DOMNode.prototype._handleDOMNodeDidFireEvent): Added.
+        (WI.DOMNode.prototype._addDOMEvent):
+        (WI.DOMNode.prototype._shouldListenForEventListeners): Added.
+        If an event is fired on an ancestor of this node, also record that event in this node's
+        `domEvents`, including the `originator` node.
+
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView.prototype._populateWaterfallGraph):
+        * UserInterface/Views/NetworkTableContentView.css:
+        (.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen): Added.
+
+        * UserInterface/Views/DOMEventsBreakdownView.js:
+        (WI.DOMEventsBreakdownView.prototype.initialLayout):
+        (WI.DOMEventsBreakdownView.prototype._populateTable):
+        * UserInterface/Views/DOMEventsBreakdownView.css:
+        (.dom-events-breakdown .graph > .area.fullscreen): Added.
+        (.dom-events-breakdown .inherited > .name, .dom-events-breakdown .inherited > .graph > .point): Added.
+        (.dom-events-breakdown:not(.has-inherited) .originator): Added.
+
+2018-10-25  Devin Rousso  <[email protected]>
+
         Web Inspector: Network: more aggressively snap timing blocks together
         https://bugs.webkit.org/show_bug.cgi?id=190439
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -404,6 +404,7 @@
 localizedStrings["Frames %d \u2013 %d"] = "Frames %d \u2013 %d";
 localizedStrings["Full Garbage Collection"] = "Full Garbage Collection";
 localizedStrings["Full URL"] = "Full URL";
+localizedStrings["Fullscreen from “%s“"] = "Fullscreen from “%s“";
 localizedStrings["Function"] = "Function";
 localizedStrings["Function Name Variable"] = "Function Name Variable";
 localizedStrings["Garbage Collection"] = "Garbage Collection";
@@ -594,6 +595,7 @@
 localizedStrings["Original"] = "Original";
 localizedStrings["Original formatting"] = "Original formatting";
 localizedStrings["Originally %s"] = "Originally %s";
+localizedStrings["Originator"] = "Originator";
 localizedStrings["Other"] = "Other";
 localizedStrings["Other Issue"] = "Other Issue";
 localizedStrings["Outgoing message"] = "Outgoing message";

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -122,7 +122,7 @@
         node.dispatchEventToListeners(WI.DOMNode.Event.EventListenersChanged);
     }
 
-    didFireEvent(nodeId, eventName, timestamp)
+    didFireEvent(nodeId, eventName, timestamp, data)
     {
         // Called from WI.DOMObserver.
 
@@ -130,7 +130,7 @@
         if (!node)
             return;
 
-        node.didFireEvent(eventName, timestamp);
+        node.didFireEvent(eventName, timestamp, data);
     }
 
     // Private

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -139,8 +139,22 @@
         }
 
         this._domEvents = [];
+
+        if (this._shouldListenForEventListeners())
+            WI.DOMNode.addEventListener(WI.DOMNode.Event.DidFireEvent, this._handleDOMNodeDidFireEvent, this);
     }
 
+    // Static
+
+    static getFullscreenDOMEvents(domEvents)
+    {
+        return domEvents.reduce((accumulator, current) => {
+            if (current.eventName === "webkitfullscreenchange" && current.data && (!accumulator.length || accumulator.lastValue.data.enabled !== current.data.enabled))
+                accumulator.push(current);
+            return accumulator;
+        }, []);
+    }
+
     // Public
 
     get domEvents() { return this._domEvents; }
@@ -701,7 +715,7 @@
         return !!this.ownerSVGElement;
     }
 
-    didFireEvent(eventName, timestamp)
+    didFireEvent(eventName, timestamp, data)
     {
         // Called from WI.DOMManager.
 
@@ -708,9 +722,21 @@
         this._addDOMEvent({
             eventName,
             timestamp: WI.timelineManager.computeElapsedTime(timestamp),
+            data,
         });
     }
 
+    _handleDOMNodeDidFireEvent(event)
+    {
+        if (event.target === this || !event.target.isAncestor(this))
+            return;
+
+        let domEvent = Object.shallowCopy(event.data.domEvent);
+        domEvent.originator = event.target;
+
+        this._addDOMEvent(domEvent);
+    }
+
     _addDOMEvent(domEvent)
     {
         this._domEvents.push(domEvent);
@@ -718,6 +744,12 @@
         this.dispatchEventToListeners(WI.DOMNode.Event.DidFireEvent, {domEvent});
     }
 
+    _shouldListenForEventListeners()
+    {
+        let lowerCaseName = this.localName() || this.nodeName().toLowerCase();
+        return lowerCaseName === "video" || lowerCaseName === "audio";
+    }
+
     _setAttributesPayload(attrs)
     {
         this._attributes = [];

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -112,8 +112,8 @@
         WI.domManager.willRemoveEventListener(nodeId);
     }
 
-    didFireEvent(nodeId, eventName, timestamp)
+    didFireEvent(nodeId, eventName, timestamp, data)
     {
-        WI.domManager.didFireEvent(nodeId, eventName, timestamp);
+        WI.domManager.didFireEvent(nodeId, eventName, timestamp, data);
     }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.css	2018-10-25 22:59:29 UTC (rev 237431)
@@ -69,6 +69,21 @@
     border-radius: 50%;
 }
 
+.dom-events-breakdown .graph > .area.fullscreen {
+    top: 0;
+    height: 100%;
+    background-color: var(--panel-background-color);
+}
+
 .dom-events-breakdown .time {
     text-align: end;
 }
+
+.dom-events-breakdown .inherited > .name,
+.dom-events-breakdown .inherited > .graph > .point {
+    opacity: 0.5;
+}
+
+.dom-events-breakdown:not(.has-inherited) .originator {
+    display: none;
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMEventsBreakdownView.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -69,6 +69,10 @@
         timeHeadCell.classList.add("time");
         timeHeadCell.textContent = WI.UIString("Time");
 
+        let originatorHeadCell = headRowElement.appendChild(document.createElement("th"));
+        originatorHeadCell.classList.add("originator");
+        originatorHeadCell.textContent = WI.UIString("Originator");
+
         this._tableBodyElement = tableElement.appendChild(document.createElement("tbody"));
 
         this._populateTable();
@@ -89,6 +93,18 @@
             return time / totalTime * 100;
         }
 
+        let fullscreenRanges = [];
+        let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(this._domEvents);
+        for (let fullscreenDOMEvent of fullscreenDOMEvents) {
+            let {enabled} = fullscreenDOMEvent.data;
+            if (enabled || !fullscreenRanges.length) {
+                fullscreenRanges.push({
+                    startTimestamp: enabled ? fullscreenDOMEvent.timestamp : startTimestamp,
+                });
+            }
+            fullscreenRanges.lastValue.endTimestamp = (enabled && fullscreenDOMEvent === fullscreenDOMEvents.lastValue) ? endTimestamp : fullscreenDOMEvent.timestamp;
+        }
+
         for (let domEvent of this._domEvents) {
             let rowElement = this._tableBodyElement.appendChild(document.createElement("tr"));
 
@@ -100,6 +116,14 @@
                 let graphCell = rowElement.appendChild(document.createElement("td"));
                 graphCell.classList.add("graph");
 
+                let fullscreenRange = fullscreenRanges.find((range) => domEvent.timestamp >= range.startTimestamp && domEvent.timestamp <= range.endTimestamp);
+                if (fullscreenRange) {
+                    let fullscreenArea = graphCell.appendChild(document.createElement("div"));
+                    fullscreenArea.classList.add("area", "fullscreen");
+                    fullscreenArea.style.setProperty(styleAttribute, percentOfTotalTime(fullscreenRange.startTimestamp - startTimestamp) + "%");
+                    fullscreenArea.style.setProperty("width", percentOfTotalTime(fullscreenRange.endTimestamp - fullscreenRange.startTimestamp) + "%");
+                }
+
                 let graphPoint = graphCell.appendChild(document.createElement("div"));
                 graphPoint.classList.add("point");
                 graphPoint.style.setProperty(styleAttribute, `calc(${percentOfTotalTime(domEvent.timestamp - startTimestamp)}% - (var(--point-size) / 2))`);
@@ -110,6 +134,15 @@
 
             const higherResolution = true;
             timeCell.textContent = Number.secondsToString(domEvent.timestamp - this._startTimestamp, higherResolution);
+
+            let originatorCell = rowElement.appendChild(document.createElement("td"));
+            originatorCell.classList.add("originator");
+            if (domEvent.originator) {
+                originatorCell.appendChild(WI.linkifyNodeReference(domEvent.originator));
+
+                rowElement.classList.add("inherited");
+                this.element.classList.add("has-inherited");
+            }
         }
     }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css	2018-10-25 22:59:29 UTC (rev 237431)
@@ -182,6 +182,16 @@
     overflow: hidden;
 }
 
+.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-fullscreen {
+    position: absolute;
+    top: var(--dom-fullscreen-vertical-padding);
+    height: calc(100% - (var(--dom-fullscreen-vertical-padding) * 2));
+    background-color: lightgrey;
+
+    /* Half of the vertical space above any .dom-event node */
+    --dom-fullscreen-vertical-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
+}
+
 .network-table .timeline-ruler > .header {
     top: calc(var(--navigation-bar-height) - var(--timeline-ruler-height));
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (237430 => 237431)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2018-10-25 22:57:45 UTC (rev 237430)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2018-10-25 22:59:29 UTC (rev 237431)
@@ -660,18 +660,43 @@
         if (domNode) {
             const domEventElementSize = 8; // Keep this in sync with `--node-waterfall-dom-event-size`.
 
-            let groupedDOMEvents = domNode.domEvents.reduce((accumulator, current) => {
-                if (!accumulator.length || (current.timestamp - accumulator.lastValue.endTimestamp) >= (domEventElementSize * secondsPerPixel)) {
-                    accumulator.push({
-                        startTimestamp: current.timestamp,
+            let groupedDOMEvents = [];
+            for (let domEvent of domNode.domEvents) {
+                if (domEvent.originator)
+                    continue;
+
+                if (!groupedDOMEvents.length || (domEvent.timestamp - groupedDOMEvents.lastValue.endTimestamp) >= (domEventElementSize * secondsPerPixel)) {
+                    groupedDOMEvents.push({
+                        startTimestamp: domEvent.timestamp,
                         domEvents: [],
                     });
                 }
-                accumulator.lastValue.endTimestamp = current.timestamp;
-                accumulator.lastValue.domEvents.push(current);
-                return accumulator;
-            }, []);
+                groupedDOMEvents.lastValue.endTimestamp = domEvent.timestamp;
+                groupedDOMEvents.lastValue.domEvents.push(domEvent);
+            }
 
+            let fullscreenDOMEvents = WI.DOMNode.getFullscreenDOMEvents(domNode.domEvents);
+            if (fullscreenDOMEvents.length) {
+                if (!fullscreenDOMEvents[0].data.enabled)
+                    fullscreenDOMEvents.unshift({timestamp: graphStartTime});
+
+                if (fullscreenDOMEvents.lastValue.data.enabled)
+                    fullscreenDOMEvents.push({timestamp: this._waterfallEndTime});
+
+                console.assert((fullscreenDOMEvents.length % 2) === 0, "Every enter/exit of fullscreen should have a corresponding exit/enter.");
+
+                for (let i = 0; i < fullscreenDOMEvents.length; i += 2) {
+                    let fullscreenElement = container.appendChild(document.createElement("div"));
+                    fullscreenElement.classList.add("dom-fullscreen");
+                    positionByStartOffset(fullscreenElement, fullscreenDOMEvents[i].timestamp);
+                    setWidthForDuration(fullscreenElement, fullscreenDOMEvents[i].timestamp, fullscreenDOMEvents[i + 1].timestamp);
+
+                    let originator = fullscreenDOMEvents[i].originator || fullscreenDOMEvents[i + 1].originator;
+                    if (originator)
+                        fullscreenElement.title = WI.UIString("Fullscreen from “%s“").format(originator.displayName);
+                }
+            }
+
             let playing = false;
 
             function createDOMEventLine(domEvents, startTimestamp, endTimestamp) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to