Changeset 224002 in webkit


Ignore:
Timestamp:
Oct 25, 2017 9:07:59 PM (6 years ago)
Author:
webkit@devinrousso.com
Message:

Web Inspector: provide a way to enable/disable event listeners
https://bugs.webkit.org/show_bug.cgi?id=177451
<rdar://problem/34994925>

Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

  • inspector/protocol/DOM.json:

Add setEventListenerDisabled command that enables/disables a specific event listener
during event dispatch. When a disabled event listener is fired, the listener's callback will
not be called.

Source/WebCore:

Test: inspector/dom/setEventListenerDisabled.html

  • dom/EventTarget.cpp:

(WebCore::EventTarget::fireEventListeners):
Add InspectorInstrumentation call to isEventListenerDisabled. If true, the event listener's
callback will not be called.

  • inspector/InspectorDOMAgent.h:
  • inspector/InspectorDOMAgent.cpp:

(WebCore::InspectorDOMAgent::discardBindings):
(WebCore::InspectorDOMAgent::getEventListenersForNode):
(WebCore::InspectorDOMAgent::setEventListenerDisabled):
(WebCore::InspectorDOMAgent::buildObjectForEventListener):
(WebCore::InspectorDOMAgent::willRemoveEventListener):
(WebCore::InspectorDOMAgent::isEventListenerDisabled):
Introduce a mapping of EventListener* to InspectorEventListener, a struct for uniquely
identifying event listeners so they can be referenced from the frontend. We only add items
to this mapping when getEventListenersForNode is called, as that is when EventListener
data is sent to the frontend. This allows us to defer creating an Inspector "mirror" object
for each EventListener until it is needed. Items are removed whenever an event listener is
removed or when the document changes.

  • inspector/InspectorInstrumentation.h:

(WebCore::InspectorInstrumentation::isEventListenerDisabled):

  • inspector/InspectorInstrumentation.cpp:

(WebCore::InspectorInstrumentation::willRemoveEventListenerImpl):
(WebCore::InspectorInstrumentation::isEventListenerDisabledImpl):
Pass additional parameters to InspectorDOMAgent so it can determine if the event listener
actually exists. If not, don't dispatch an event to the frontend as nothing will change.

Source/WebInspectorUI:

  • Localizations/en.lproj/localizedStrings.js:
  • UserInterface/Controllers/DOMTreeManager.js:

(WI.DOMTreeManager.prototype.setEventListenerDisabled):

  • UserInterface/Views/DOMNodeDetailsSidebarPanel.js:

(WI.DOMNodeDetailsSidebarPanel.prototype.attached):
(WI.DOMNodeDetailsSidebarPanel.prototype.detached):
(WI.DOMNodeDetailsSidebarPanel.prototype._eventListenersChanged):
(WI.DOMNodeDetailsSidebarPanel.prototype.addEventListeners): Deleted.
(WI.DOMNodeDetailsSidebarPanel.prototype.removeEventListeners): Deleted.
Listen for WI.DOMNode.Event.EventListenersChanged on all instances of WI.DOMNode, since we
will still want to refresh the event listeners section in the event that an event listener
is removed from a parent node.

  • UserInterface/Views/EventListenerSectionGroup.js:

(WI.EventListenerSectionGroup):
(WI.EventListenerSectionGroup.prototype._eventText):
(WI.EventListenerSectionGroup.prototype._nodeTextOrLink):
(WI.EventListenerSectionGroup.prototype._createDisabledToggleElement):
(WI.EventListenerSectionGroup.prototype._createDisabledToggleElement.updateTitle):

  • UserInterface/Views/EventListenerSectionGroup.css:

(.event-listener-section > .content input[type="checkbox"]):

  • UserInterface/Views/DetailsSectionSimpleRow.js:

(WI.DetailsSectionSimpleRow.prototype.get label):
(WI.DetailsSectionSimpleRow.prototype.set label):

LayoutTests:

  • inspector/dom/setEventListenerDisabled-expected.txt: Added.
  • inspector/dom/setEventListenerDisabled.html: Added.
Location:
trunk
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r223998 r224002  
     12017-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
    1122017-10-25  Devin Rousso  <webkit@devinrousso.com>
    213
  • trunk/Source/JavaScriptCore/ChangeLog

    r223989 r224002  
     12017-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
    1142017-10-25  Commit Queue  <commit-queue@webkit.org>
    215
  • trunk/Source/JavaScriptCore/inspector/protocol/DOM.json

    r223618 r224002  
    1313            "type": "integer",
    1414            "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."
    1520        },
    1621        {
     
    7580            "description": "A structure holding event listener properties.",
    7681            "properties": [
     82                { "name": "eventListenerId", "$ref": "EventListenerId" },
    7783                { "name": "type", "type": "string", "description": "<code>EventListener</code>'s type." },
    7884                { "name": "useCapture", "type": "boolean", "description": "<code>EventListener</code>'s useCapture." },
     
    8490                { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." },
    8591                { "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 }
    8794            ]
    8895        },
     
    260267        },
    261268        {
     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        {
    262277            "name": "getAccessibilityPropertiesForNode",
    263278            "description": "Returns a dictionary of accessibility properties for the node.",
  • trunk/Source/WebCore/ChangeLog

    r224001 r224002  
     12017-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
    1392017-10-25  Keith Miller  <keith_miller@apple.com>
    240
  • trunk/Source/WebCore/dom/EventTarget.cpp

    r223644 r224002  
    279279            continue;
    280280
     281        if (InspectorInstrumentation::isEventListenerDisabled(*this, event.type(), registeredListener->callback(), registeredListener->useCapture()))
     282            continue;
     283
    281284        // If stopImmediatePropagation has been called, we just break out immediately, without
    282285        // handling any more events on this target.
  • trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp

    r223644 r224002  
    487487    m_documentNodeToIdMap.clear();
    488488    m_idToNode.clear();
     489    m_eventListenerEntries.clear();
    489490    releaseDanglingNodes();
    490491    m_childrenRequested.clear();
     
    831832    getEventListeners(node, eventInformation, true);
    832833
     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
    833853    // Get Capturing Listeners (in this order)
    834854    size_t eventInformationLength = eventInformation.size();
     
    836856        for (auto& listener : info.eventListenerVector) {
    837857            if (listener->useCapture())
    838                 listenersArray->addItem(buildObjectForEventListener(*listener, info.eventType, info.node, objectGroup));
     858                addListener(*listener, info);
    839859        }
    840860    }
     
    845865        for (auto& listener : info.eventListenerVector) {
    846866            if (!listener->useCapture())
    847                 listenersArray->addItem(buildObjectForEventListener(*listener, info.eventType, info.node, objectGroup));
     867                addListener(*listener, info);
    848868        }
    849869    }
     
    880900        }
    881901    }
     902}
     903
     904void 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.");
    882914}
    883915
     
    15551587}
    15561588
    1557 Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
     1589Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, int identifier, const AtomicString& eventType, Node* node, const String* objectGroupId, bool disabled)
    15581590{
    15591591    Ref<EventListener> eventListener = registeredEventListener.callback();
     
    15861618
    15871619    auto value = Inspector::Protocol::DOM::EventListener::create()
     1620        .setEventListenerId(identifier)
    15881621        .setType(eventType)
    15891622        .setUseCapture(registeredEventListener.useCapture())
     
    16111644    if (registeredEventListener.isOnce())
    16121645        value->setOnce(true);
     1646    if (disabled)
     1647        value->setDisabled(disabled);
    16131648    return value;
    16141649}
     
    22212256}
    22222257
    2223 void InspectorDOMAgent::willRemoveEventListener(EventTarget& target)
     2258void InspectorDOMAgent::willRemoveEventListener(EventTarget& target, const AtomicString& eventType, EventListener& listener, bool capture)
    22242259{
    22252260    auto node = target.toNode();
     
    22312266        return;
    22322267
     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
    22332281    m_frontendDispatcher->willRemoveEventListener(nodeId);
     2282}
     2283
     2284bool 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;
    22342294}
    22352295
  • trunk/Source/WebCore/inspector/InspectorDOMAgent.h

    r223728 r224002  
    124124    void setNodeValue(ErrorString&, int nodeId, const String& value) override;
    125125    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;
    126127    void getAccessibilityPropertiesForNode(ErrorString&, int nodeId, RefPtr<Inspector::Protocol::DOM::AccessibilityProperties>& axProperties) override;
    127128    void performSearch(ErrorString&, const String& whitespaceTrimmedQuery, const Inspector::InspectorArray* nodeIds, String* searchId, int* resultCount) override;
     
    169170    void pseudoElementDestroyed(PseudoElement&);
    170171    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);
    172174
    173175    // Callbacks that don't directly correspond to an instrumentation entry point.
     
    233235    Ref<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
    234236    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);
    236238    RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> buildObjectForAccessibilityProperties(Node*);
    237239    void processAccessibilityChildren(RefPtr<AccessibilityObject>&&, RefPtr<Inspector::Protocol::Array<int>>&&);
     
    274276    bool m_suppressAttributeModifiedEvent { false };
    275277    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 };
    276299};
    277300
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp

    r223868 r224002  
    328328        pageDebuggerAgent->willRemoveEventListener(target, eventType, listener, capture);
    329329    if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
    330         domAgent->willRemoveEventListener(target);
     330        domAgent->willRemoveEventListener(target, eventType, listener, capture);
     331}
     332
     333bool 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;
    331338}
    332339
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.h

    r223868 r224002  
    147147    static void didAddEventListener(EventTarget&, const AtomicString& eventType);
    148148    static void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     149    static bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
    149150    static InspectorInstrumentationCookie willDispatchEvent(Document&, const Event&, bool hasEventListeners);
    150151    static void didDispatchEvent(const InspectorInstrumentationCookie&);
     
    324325    static void didAddEventListenerImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType);
    325326    static void willRemoveEventListenerImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     327    static bool isEventListenerDisabledImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
    326328    static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents&, Document&, const Event&, bool hasEventListeners);
    327329    static void willHandleEventImpl(InstrumentingAgents&, const Event&, const RegisteredEventListener&);
     
    688690}
    689691
     692inline 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
    690700inline void InspectorInstrumentation::didPostMessage(Frame& frame, TimerBase& timer, JSC::ExecState& state)
    691701{
  • trunk/Source/WebInspectorUI/ChangeLog

    r223997 r224002  
     12017-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
    1372017-10-25  Devin Rousso  <webkit@devinrousso.com>
    238
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r223997 r224002  
    298298localizedStrings["Disable Breakpoint"] = "Disable Breakpoint";
    299299localizedStrings["Disable Breakpoints"] = "Disable Breakpoints";
     300localizedStrings["Disable Event Listener"] = "Disable Event Listener";
    300301localizedStrings["Disable Program"] = "Disable Program";
    301302localizedStrings["Disable all breakpoints (%s)"] = "Disable all breakpoints (%s)";
     
    362363localizedStrings["Enable Breakpoint"] = "Enable Breakpoint";
    363364localizedStrings["Enable Breakpoints"] = "Enable Breakpoints";
     365localizedStrings["Enable Event Listener"] = "Enable Event Listener";
    364366localizedStrings["Enable Layers Tab"] = "Enable Layers Tab";
    365367localizedStrings["Enable Program"] = "Enable Program";
     
    367369localizedStrings["Enable breakpoints"] = "Enable breakpoints";
    368370localizedStrings["Enable paint flashing"] = "Enable paint flashing";
     371localizedStrings["Enabled"] = "Enabled";
    369372localizedStrings["Encoded"] = "Encoded";
    370373localizedStrings["Encoding"] = "Encoding";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js

    r223618 r224002  
    527527    }
    528528
     529    setEventListenerDisabled(eventListenerId, disabled)
     530    {
     531        DOMAgent.setEventListenerDisabled(eventListenerId, disabled);
     532    }
     533
    529534    _buildHighlightConfig(mode = "all")
    530535    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js

    r223618 r224002  
    4444
    4545        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);
    5646    }
    5747
     
    168158        // FIXME: <https://webkit.org/b/152269> Web Inspector: Convert DetailsSection classes to use View
    169159        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();
    170174    }
    171175
     
    754758    _eventListenersChanged(event)
    755759    {
    756         this._refreshEventListeners();
     760        if (event.target === this.domNode || event.target.isAncestor(this.domNode))
     761            this._refreshEventListeners();
    757762    }
    758763
  • trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSectionSimpleRow.js

    r223618 r224002  
    7474    get label()
    7575    {
    76         return this._labelElement.textContent;
     76        return this._label;
    7777    }
    7878
    7979    set label(label)
    8080    {
    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;
    8288    }
    8389
  • trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.css

    r223618 r224002  
    2929    text-overflow: ellipsis;
    3030}
     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  
    5353            rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Once"), WI.UIString("Yes")));
    5454
     55        if (DOMAgent.setEventListenerDisabled && this._eventListener.eventListenerId)
     56            rows.push(this._createDisabledToggleRow());
     57
    5558        this.rows = rows;
    5659    }
     
    105108        return fragment;
    106109    }
     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    }
    107140};
Note: See TracChangeset for help on using the changeset viewer.