Changeset 224002 in webkit
- Timestamp:
- Oct 25, 2017 9:07:59 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223998 r224002 1 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 3 Web Inspector: provide a way to enable/disable event listeners 4 https://bugs.webkit.org/show_bug.cgi?id=177451 5 <rdar://problem/34994925> 6 7 Reviewed by Joseph Pecoraro. 8 9 * inspector/dom/setEventListenerDisabled-expected.txt: Added. 10 * inspector/dom/setEventListenerDisabled.html: Added. 11 1 12 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 13 -
trunk/Source/JavaScriptCore/ChangeLog
r223989 r224002 1 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 3 Web Inspector: provide a way to enable/disable event listeners 4 https://bugs.webkit.org/show_bug.cgi?id=177451 5 <rdar://problem/34994925> 6 7 Reviewed by Joseph Pecoraro. 8 9 * inspector/protocol/DOM.json: 10 Add `setEventListenerDisabled` command that enables/disables a specific event listener 11 during event dispatch. When a disabled event listener is fired, the listener's callback will 12 not be called. 13 1 14 2017-10-25 Commit Queue <commit-queue@webkit.org> 2 15 -
trunk/Source/JavaScriptCore/inspector/protocol/DOM.json
r223618 r224002 13 13 "type": "integer", 14 14 "description": "Unique DOM node identifier used to reference a node that may not have been pushed to the front-end." 15 }, 16 { 17 "id": "EventListenerId", 18 "type": "integer", 19 "description": "Unique event listener identifier." 15 20 }, 16 21 { … … 75 80 "description": "A structure holding event listener properties.", 76 81 "properties": [ 82 { "name": "eventListenerId", "$ref": "EventListenerId" }, 77 83 { "name": "type", "type": "string", "description": "<code>EventListener</code>'s type." }, 78 84 { "name": "useCapture", "type": "boolean", "description": "<code>EventListener</code>'s useCapture." }, … … 84 90 { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." }, 85 91 { "name": "passive", "type": "boolean", "optional": true, "description": "<code>EventListener</code>'s passive." }, 86 { "name": "once", "type": "boolean", "optional": true, "description": "<code>EventListener</code>'s once." } 92 { "name": "once", "type": "boolean", "optional": true, "description": "<code>EventListener</code>'s once." }, 93 { "name": "disabled", "type": "boolean", "optional": true } 87 94 ] 88 95 }, … … 260 267 }, 261 268 { 269 "name": "setEventListenerDisabled", 270 "description": "Enable/disable the given event listener. A disabled event listener will not fire.", 271 "parameters": [ 272 { "name": "eventListenerId", "$ref": "EventListenerId" }, 273 { "name": "disabled", "type": "boolean" } 274 ] 275 }, 276 { 262 277 "name": "getAccessibilityPropertiesForNode", 263 278 "description": "Returns a dictionary of accessibility properties for the node.", -
trunk/Source/WebCore/ChangeLog
r224001 r224002 1 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 3 Web Inspector: provide a way to enable/disable event listeners 4 https://bugs.webkit.org/show_bug.cgi?id=177451 5 <rdar://problem/34994925> 6 7 Reviewed by Joseph Pecoraro. 8 9 Test: inspector/dom/setEventListenerDisabled.html 10 11 * dom/EventTarget.cpp: 12 (WebCore::EventTarget::fireEventListeners): 13 Add InspectorInstrumentation call to isEventListenerDisabled. If true, the event listener's 14 callback will not be called. 15 16 * inspector/InspectorDOMAgent.h: 17 * inspector/InspectorDOMAgent.cpp: 18 (WebCore::InspectorDOMAgent::discardBindings): 19 (WebCore::InspectorDOMAgent::getEventListenersForNode): 20 (WebCore::InspectorDOMAgent::setEventListenerDisabled): 21 (WebCore::InspectorDOMAgent::buildObjectForEventListener): 22 (WebCore::InspectorDOMAgent::willRemoveEventListener): 23 (WebCore::InspectorDOMAgent::isEventListenerDisabled): 24 Introduce a mapping of `EventListener*` to `InspectorEventListener`, a struct for uniquely 25 identifying event listeners so they can be referenced from the frontend. We only add items 26 to this mapping when `getEventListenersForNode` is called, as that is when EventListener 27 data is sent to the frontend. This allows us to defer creating an Inspector "mirror" object 28 for each EventListener until it is needed. Items are removed whenever an event listener is 29 removed or when the document changes. 30 31 * inspector/InspectorInstrumentation.h: 32 (WebCore::InspectorInstrumentation::isEventListenerDisabled): 33 * inspector/InspectorInstrumentation.cpp: 34 (WebCore::InspectorInstrumentation::willRemoveEventListenerImpl): 35 (WebCore::InspectorInstrumentation::isEventListenerDisabledImpl): 36 Pass additional parameters to InspectorDOMAgent so it can determine if the event listener 37 actually exists. If not, don't dispatch an event to the frontend as nothing will change. 38 1 39 2017-10-25 Keith Miller <keith_miller@apple.com> 2 40 -
trunk/Source/WebCore/dom/EventTarget.cpp
r223644 r224002 279 279 continue; 280 280 281 if (InspectorInstrumentation::isEventListenerDisabled(*this, event.type(), registeredListener->callback(), registeredListener->useCapture())) 282 continue; 283 281 284 // If stopImmediatePropagation has been called, we just break out immediately, without 282 285 // handling any more events on this target. -
trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp
r223644 r224002 487 487 m_documentNodeToIdMap.clear(); 488 488 m_idToNode.clear(); 489 m_eventListenerEntries.clear(); 489 490 releaseDanglingNodes(); 490 491 m_childrenRequested.clear(); … … 831 832 getEventListeners(node, eventInformation, true); 832 833 834 auto addListener = [&] (RegisteredEventListener& listener, const EventListenerInfo& info) { 835 int identifier = 0; 836 bool disabled = false; 837 838 auto it = m_eventListenerEntries.find(&listener.callback()); 839 if (it == m_eventListenerEntries.end()) { 840 InspectorEventListener inspectorEventListener(m_lastEventListenerId++, *info.node, info.eventType, listener.useCapture()); 841 m_eventListenerEntries.add(&listener.callback(), inspectorEventListener); 842 843 identifier = inspectorEventListener.identifier; 844 disabled = inspectorEventListener.disabled; 845 } else { 846 identifier = it->value.identifier; 847 disabled = it->value.disabled; 848 } 849 850 listenersArray->addItem(buildObjectForEventListener(listener, identifier, info.eventType, info.node, objectGroup, disabled)); 851 }; 852 833 853 // Get Capturing Listeners (in this order) 834 854 size_t eventInformationLength = eventInformation.size(); … … 836 856 for (auto& listener : info.eventListenerVector) { 837 857 if (listener->useCapture()) 838 listenersArray->addItem(buildObjectForEventListener(*listener, info.eventType, info.node, objectGroup));858 addListener(*listener, info); 839 859 } 840 860 } … … 845 865 for (auto& listener : info.eventListenerVector) { 846 866 if (!listener->useCapture()) 847 listenersArray->addItem(buildObjectForEventListener(*listener, info.eventType, info.node, objectGroup));867 addListener(*listener, info); 848 868 } 849 869 } … … 880 900 } 881 901 } 902 } 903 904 void InspectorDOMAgent::setEventListenerDisabled(ErrorString& errorString, int eventListenerId, bool disabled) 905 { 906 for (InspectorEventListener& inspectorEventListener : m_eventListenerEntries.values()) { 907 if (inspectorEventListener.identifier == eventListenerId) { 908 inspectorEventListener.disabled = disabled; 909 return; 910 } 911 } 912 913 errorString = ASCIILiteral("No event listener for given identifier."); 882 914 } 883 915 … … 1555 1587 } 1556 1588 1557 Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)1589 Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, int identifier, const AtomicString& eventType, Node* node, const String* objectGroupId, bool disabled) 1558 1590 { 1559 1591 Ref<EventListener> eventListener = registeredEventListener.callback(); … … 1586 1618 1587 1619 auto value = Inspector::Protocol::DOM::EventListener::create() 1620 .setEventListenerId(identifier) 1588 1621 .setType(eventType) 1589 1622 .setUseCapture(registeredEventListener.useCapture()) … … 1611 1644 if (registeredEventListener.isOnce()) 1612 1645 value->setOnce(true); 1646 if (disabled) 1647 value->setDisabled(disabled); 1613 1648 return value; 1614 1649 } … … 2221 2256 } 2222 2257 2223 void InspectorDOMAgent::willRemoveEventListener(EventTarget& target )2258 void InspectorDOMAgent::willRemoveEventListener(EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture) 2224 2259 { 2225 2260 auto node = target.toNode(); … … 2231 2266 return; 2232 2267 2268 bool listenerExists = false; 2269 for (const RefPtr<RegisteredEventListener>& item : node->eventListeners(eventType)) { 2270 if (item->callback() == listener && item->useCapture() == capture) { 2271 listenerExists = true; 2272 break; 2273 } 2274 } 2275 2276 if (!listenerExists) 2277 return; 2278 2279 m_eventListenerEntries.remove(&listener); 2280 2233 2281 m_frontendDispatcher->willRemoveEventListener(nodeId); 2282 } 2283 2284 bool InspectorDOMAgent::isEventListenerDisabled(EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture) 2285 { 2286 auto it = m_eventListenerEntries.find(&listener); 2287 if (it == m_eventListenerEntries.end()) 2288 return false; 2289 2290 if (!it->value.disabled) 2291 return false; 2292 2293 return it->value.eventTarget.get() == &target && it->value.eventType == eventType && it->value.useCapture == capture; 2234 2294 } 2235 2295 -
trunk/Source/WebCore/inspector/InspectorDOMAgent.h
r223728 r224002 124 124 void setNodeValue(ErrorString&, int nodeId, const String& value) override; 125 125 void getEventListenersForNode(ErrorString&, int nodeId, const WTF::String* const objectGroup, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::EventListener>>& listenersArray) override; 126 void setEventListenerDisabled(ErrorString&, int eventListenerId, bool disabled) override; 126 127 void getAccessibilityPropertiesForNode(ErrorString&, int nodeId, RefPtr<Inspector::Protocol::DOM::AccessibilityProperties>& axProperties) override; 127 128 void performSearch(ErrorString&, const String& whitespaceTrimmedQuery, const Inspector::InspectorArray* nodeIds, String* searchId, int* resultCount) override; … … 169 170 void pseudoElementDestroyed(PseudoElement&); 170 171 void didAddEventListener(EventTarget&); 171 void willRemoveEventListener(EventTarget&); 172 void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 173 bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 172 174 173 175 // Callbacks that don't directly correspond to an instrumentation entry point. … … 233 235 Ref<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap); 234 236 RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> buildArrayForPseudoElements(const Element&, NodeToIdMap* nodesMap); 235 Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, const AtomicString& eventType, Node*, const String* objectGroupId);237 Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, int identifier, const AtomicString& eventType, Node*, const String* objectGroupId, bool disabled = false); 236 238 RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> buildObjectForAccessibilityProperties(Node*); 237 239 void processAccessibilityChildren(RefPtr<AccessibilityObject>&&, RefPtr<Inspector::Protocol::Array<int>>&&); … … 274 276 bool m_suppressAttributeModifiedEvent { false }; 275 277 bool m_documentRequested { false }; 278 279 struct InspectorEventListener { 280 int identifier { 1 }; 281 RefPtr<EventTarget> eventTarget; 282 AtomicString eventType; 283 bool useCapture { false }; 284 bool disabled { false }; 285 286 InspectorEventListener() { } 287 288 InspectorEventListener(int identifier, EventTarget& eventTarget, const AtomicString& eventType, bool useCapture) 289 : identifier(identifier) 290 , eventTarget(&eventTarget) 291 , eventType(eventType) 292 , useCapture(useCapture) 293 { 294 } 295 }; 296 297 HashMap<EventListener*, InspectorEventListener> m_eventListenerEntries; 298 int m_lastEventListenerId { 1 }; 276 299 }; 277 300 -
trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp
r223868 r224002 328 328 pageDebuggerAgent->willRemoveEventListener(target, eventType, listener, capture); 329 329 if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent()) 330 domAgent->willRemoveEventListener(target); 330 domAgent->willRemoveEventListener(target, eventType, listener, capture); 331 } 332 333 bool InspectorInstrumentation::isEventListenerDisabledImpl(InstrumentingAgents& instrumentingAgents, EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture) 334 { 335 if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent()) 336 return domAgent->isEventListenerDisabled(target, eventType, listener, capture); 337 return false; 331 338 } 332 339 -
trunk/Source/WebCore/inspector/InspectorInstrumentation.h
r223868 r224002 147 147 static void didAddEventListener(EventTarget&, const AtomicString& eventType); 148 148 static void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 149 static bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 149 150 static InspectorInstrumentationCookie willDispatchEvent(Document&, const Event&, bool hasEventListeners); 150 151 static void didDispatchEvent(const InspectorInstrumentationCookie&); … … 324 325 static void didAddEventListenerImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType); 325 326 static void willRemoveEventListenerImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 327 static bool isEventListenerDisabledImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture); 326 328 static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents&, Document&, const Event&, bool hasEventListeners); 327 329 static void willHandleEventImpl(InstrumentingAgents&, const Event&, const RegisteredEventListener&); … … 688 690 } 689 691 692 inline bool InspectorInstrumentation::isEventListenerDisabled(EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture) 693 { 694 FAST_RETURN_IF_NO_FRONTENDS(false); 695 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(target.scriptExecutionContext())) 696 return isEventListenerDisabledImpl(*instrumentingAgents, target, eventType, listener, capture); 697 return false; 698 } 699 690 700 inline void InspectorInstrumentation::didPostMessage(Frame& frame, TimerBase& timer, JSC::ExecState& state) 691 701 { -
trunk/Source/WebInspectorUI/ChangeLog
r223997 r224002 1 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 3 Web Inspector: provide a way to enable/disable event listeners 4 https://bugs.webkit.org/show_bug.cgi?id=177451 5 <rdar://problem/34994925> 6 7 Reviewed by Joseph Pecoraro. 8 9 * Localizations/en.lproj/localizedStrings.js: 10 11 * UserInterface/Controllers/DOMTreeManager.js: 12 (WI.DOMTreeManager.prototype.setEventListenerDisabled): 13 14 * UserInterface/Views/DOMNodeDetailsSidebarPanel.js: 15 (WI.DOMNodeDetailsSidebarPanel.prototype.attached): 16 (WI.DOMNodeDetailsSidebarPanel.prototype.detached): 17 (WI.DOMNodeDetailsSidebarPanel.prototype._eventListenersChanged): 18 (WI.DOMNodeDetailsSidebarPanel.prototype.addEventListeners): Deleted. 19 (WI.DOMNodeDetailsSidebarPanel.prototype.removeEventListeners): Deleted. 20 Listen for `WI.DOMNode.Event.EventListenersChanged` on all instances of WI.DOMNode, since we 21 will still want to refresh the event listeners section in the event that an event listener 22 is removed from a parent node. 23 24 * UserInterface/Views/EventListenerSectionGroup.js: 25 (WI.EventListenerSectionGroup): 26 (WI.EventListenerSectionGroup.prototype._eventText): 27 (WI.EventListenerSectionGroup.prototype._nodeTextOrLink): 28 (WI.EventListenerSectionGroup.prototype._createDisabledToggleElement): 29 (WI.EventListenerSectionGroup.prototype._createDisabledToggleElement.updateTitle): 30 * UserInterface/Views/EventListenerSectionGroup.css: 31 (.event-listener-section > .content input[type="checkbox"]): 32 33 * UserInterface/Views/DetailsSectionSimpleRow.js: 34 (WI.DetailsSectionSimpleRow.prototype.get label): 35 (WI.DetailsSectionSimpleRow.prototype.set label): 36 1 37 2017-10-25 Devin Rousso <webkit@devinrousso.com> 2 38 -
trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
r223997 r224002 298 298 localizedStrings["Disable Breakpoint"] = "Disable Breakpoint"; 299 299 localizedStrings["Disable Breakpoints"] = "Disable Breakpoints"; 300 localizedStrings["Disable Event Listener"] = "Disable Event Listener"; 300 301 localizedStrings["Disable Program"] = "Disable Program"; 301 302 localizedStrings["Disable all breakpoints (%s)"] = "Disable all breakpoints (%s)"; … … 362 363 localizedStrings["Enable Breakpoint"] = "Enable Breakpoint"; 363 364 localizedStrings["Enable Breakpoints"] = "Enable Breakpoints"; 365 localizedStrings["Enable Event Listener"] = "Enable Event Listener"; 364 366 localizedStrings["Enable Layers Tab"] = "Enable Layers Tab"; 365 367 localizedStrings["Enable Program"] = "Enable Program"; … … 367 369 localizedStrings["Enable breakpoints"] = "Enable breakpoints"; 368 370 localizedStrings["Enable paint flashing"] = "Enable paint flashing"; 371 localizedStrings["Enabled"] = "Enabled"; 369 372 localizedStrings["Encoded"] = "Encoded"; 370 373 localizedStrings["Encoding"] = "Encoding"; -
trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js
r223618 r224002 527 527 } 528 528 529 setEventListenerDisabled(eventListenerId, disabled) 530 { 531 DOMAgent.setEventListenerDisabled(eventListenerId, disabled); 532 } 533 529 534 _buildHighlightConfig(mode = "all") 530 535 { -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js
r223618 r224002 44 44 45 45 super.closed(); 46 }47 48 addEventListeners()49 {50 this.domNode.addEventListener(WI.DOMNode.Event.EventListenersChanged, this._eventListenersChanged, this);51 }52 53 removeEventListeners()54 {55 this.domNode.removeEventListener(WI.DOMNode.Event.EventListenersChanged, this._eventListenersChanged, this);56 46 } 57 47 … … 168 158 // FIXME: <https://webkit.org/b/152269> Web Inspector: Convert DetailsSection classes to use View 169 159 this._attributesDataGridRow.sizeDidChange(); 160 } 161 162 attached() 163 { 164 super.attached(); 165 166 WI.DOMNode.addEventListener(WI.DOMNode.Event.EventListenersChanged, this._eventListenersChanged, this); 167 } 168 169 detached() 170 { 171 WI.DOMNode.removeEventListener(WI.DOMNode.Event.EventListenersChanged, this._eventListenersChanged, this); 172 173 super.detached(); 170 174 } 171 175 … … 754 758 _eventListenersChanged(event) 755 759 { 756 this._refreshEventListeners(); 760 if (event.target === this.domNode || event.target.isAncestor(this.domNode)) 761 this._refreshEventListeners(); 757 762 } 758 763 -
trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSectionSimpleRow.js
r223618 r224002 74 74 get label() 75 75 { 76 return this._label Element.textContent;76 return this._label; 77 77 } 78 78 79 79 set label(label) 80 80 { 81 this._labelElement.textContent = label; 81 this._label = label || ""; 82 83 if (this._label instanceof Node) { 84 this._labelElement.removeChildren(); 85 this._labelElement.appendChild(this._label); 86 } else 87 this._labelElement.textContent = this._label; 82 88 } 83 89 -
trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.css
r223618 r224002 29 29 text-overflow: ellipsis; 30 30 } 31 32 .event-listener-section > .content input[type="checkbox"] { 33 width: 12px; 34 height: 12px; 35 margin: 0; 36 } -
trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js
r223618 r224002 53 53 rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Once"), WI.UIString("Yes"))); 54 54 55 if (DOMAgent.setEventListenerDisabled && this._eventListener.eventListenerId) 56 rows.push(this._createDisabledToggleRow()); 57 55 58 this.rows = rows; 56 59 } … … 105 108 return fragment; 106 109 } 110 111 _createDisabledToggleRow() 112 { 113 let toggleElement = document.createElement("input"); 114 toggleElement.type = "checkbox"; 115 toggleElement.checked = !this._eventListener.disabled; 116 117 let updateTitle = () => { 118 if (this._eventListener.disabled) 119 toggleElement.title = WI.UIString("Enable Event Listener"); 120 else 121 toggleElement.title = WI.UIString("Disable Event Listener"); 122 }; 123 124 updateTitle(); 125 126 toggleElement.addEventListener("change", (event) => { 127 this._eventListener.disabled = !toggleElement.checked; 128 WI.domTreeManager.setEventListenerDisabled(this._eventListener.eventListenerId, this._eventListener.disabled); 129 updateTitle(); 130 }); 131 132 let toggleLabel = document.createElement("span"); 133 toggleLabel.textContent = WI.UIString("Enabled"); 134 toggleLabel.addEventListener("click", (event) => { 135 toggleElement.click(); 136 }); 137 138 return new WI.DetailsSectionSimpleRow(toggleLabel, toggleElement); 139 } 107 140 };
Note: See TracChangeset
for help on using the changeset viewer.