Changeset 48809 in webkit


Ignore:
Timestamp:
Sep 28, 2009 5:36:44 AM (15 years ago)
Author:
pfeldman@chromium.org
Message:

2009-09-28 Joseph Pecoraro <Joseph Pecoraro>

Reviewed by Timothy Hatcher.

Inspector Should Show Event Listeners/Handlers Registered on each Node
https://bugs.webkit.org/show_bug.cgi?id=17429


Extracted a method from dispatchEvent to get the event ancestor chain


  • dom/Node.cpp: (WebCore::Node::eventAncestors): the extracted method (WebCore::Node::dispatchGenericEvent): use eventAncestors
  • dom/Node.h:

Asynchronous Flow For the Inspector, Backend -> DOM Agent -> Frontend
The DOMAgent's getEventListenersForNode handles the logic of finding
all the relevant listeners in the event flow.

  • inspector/InspectorBackend.cpp: (WebCore::InspectorBackend::getEventListenersForNode):
  • inspector/InspectorBackend.h:
  • inspector/InspectorBackend.idl:
  • inspector/InspectorDOMAgent.cpp: (WebCore::InspectorDOMAgent::getEventListenersForNode): (WebCore::InspectorDOMAgent::buildObjectForEventListener): (WebCore::InspectorDOMAgent::buildObjectForNode): added localName
  • inspector/InspectorDOMAgent.h: (WebCore::EventListenerInfo::EventListenerInfo):
  • inspector/InspectorFrontend.cpp: (WebCore::InspectorFrontend::didGetEventListenersForNode):
  • inspector/InspectorFrontend.h: (WebCore::InspectorFrontend::scriptState):
  • inspector/front-end/DOMAgent.js: added localName to WebInspector.DOMNode from payload (WebInspector.EventListeners.getEventListenersForNodeAsync.mycallback): (WebInspector.EventListeners.getEventListenersForNodeAsync):

New Sidebar Pane in the Element's Panel
Includes Gear Menu for filtering the Event Listeners on the
"Selected Node Only" or "All Nodes"

  • inspector/front-end/ElementsPanel.js: Handles refreshing the Pane when necessary (WebInspector.ElementsPanel.this.treeOutline.focusedNodeChanged): (WebInspector.ElementsPanel): (WebInspector.ElementsPanel.prototype.updateEventListeners):
  • inspector/front-end/EventListenersSidebarPane.js: Added. (WebInspector.EventListenersSidebarPane): The 1st level in the Pane (WebInspector.EventListenersSidebarPane.prototype.update.callback): (WebInspector.EventListenersSidebarPane.prototype.update): (WebInspector.EventListenersSection): The 2nd level in the Pane (WebInspector.EventListenersSection.prototype.update): filters on Preference (WebInspector.EventListenersSection.prototype.addListener): (WebInspector.EventListenerBar): The 3rd level in the Pane (WebInspector.EventListenerBar.prototype._getNodeDisplayName): (WebInspector.EventListenerBar.prototype._getFunctionDisplayName): (WebInspector.EventListenersSidebarPane.prototype._changeSetting): For the Gear Menu


Consolidated "appropriateSelectorForNode"

  • inspector/front-end/StylesSidebarPane.js:
  • inspector/front-end/utilities.js:

Miscellaneous Updates

  • English.lproj/localizedStrings.js: "Event Listeners", "No Event Listeners", "Selected Node Only", "All Nodes"
  • WebCore.gypi: included the new inspector files
  • WebCore.vcproj/WebCore.vcproj: included source files that were missing
  • inspector/front-end/Images/grayConnectorPoint.png: Added. Thanks to Timothy Hatcher.
  • inspector/front-end/Images/whiteConnectorPoint.png: Added. Thanks to Timothy Hatcher.
  • inspector/front-end/inspector.js: Preferences for the Gear Menu Event Listeners filter
  • inspector/front-end/inspector.css: reused as much as possible
  • inspector/front-end/inspector.html: include the new script
  • inspector/front-end/WebKit.qrc: included the new inspector files
Location:
trunk/WebCore
Files:
3 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r48806 r48809  
     12009-09-28  Joseph Pecoraro  <joepeck@webkit.org>
     2
     3        Reviewed by Timothy Hatcher.
     4
     5        Inspector Should Show Event Listeners/Handlers Registered on each Node
     6        https://bugs.webkit.org/show_bug.cgi?id=17429
     7       
     8          Extracted a method from dispatchEvent to get the event ancestor chain
     9       
     10        * dom/Node.cpp:
     11        (WebCore::Node::eventAncestors): the extracted method
     12        (WebCore::Node::dispatchGenericEvent): use eventAncestors
     13        * dom/Node.h:
     14
     15          Asynchronous Flow For the Inspector, Backend -> DOM Agent -> Frontend
     16          The DOMAgent's getEventListenersForNode handles the logic of finding
     17          all the relevant listeners in the event flow.
     18
     19        * inspector/InspectorBackend.cpp:
     20        (WebCore::InspectorBackend::getEventListenersForNode):
     21        * inspector/InspectorBackend.h:
     22        * inspector/InspectorBackend.idl:
     23        * inspector/InspectorDOMAgent.cpp:
     24        (WebCore::InspectorDOMAgent::getEventListenersForNode):
     25        (WebCore::InspectorDOMAgent::buildObjectForEventListener):
     26        (WebCore::InspectorDOMAgent::buildObjectForNode): added localName
     27        * inspector/InspectorDOMAgent.h:
     28        (WebCore::EventListenerInfo::EventListenerInfo):
     29        * inspector/InspectorFrontend.cpp:
     30        (WebCore::InspectorFrontend::didGetEventListenersForNode):
     31        * inspector/InspectorFrontend.h:
     32        (WebCore::InspectorFrontend::scriptState):
     33        * inspector/front-end/DOMAgent.js: added localName to WebInspector.DOMNode from payload
     34        (WebInspector.EventListeners.getEventListenersForNodeAsync.mycallback):
     35        (WebInspector.EventListeners.getEventListenersForNodeAsync):
     36
     37          New Sidebar Pane in the Element's Panel
     38          Includes Gear Menu for filtering the Event Listeners on the
     39          "Selected Node Only" or "All Nodes"
     40
     41        * inspector/front-end/ElementsPanel.js: Handles refreshing the Pane when necessary
     42        (WebInspector.ElementsPanel.this.treeOutline.focusedNodeChanged):
     43        (WebInspector.ElementsPanel):
     44        (WebInspector.ElementsPanel.prototype.updateEventListeners):
     45        * inspector/front-end/EventListenersSidebarPane.js: Added.
     46        (WebInspector.EventListenersSidebarPane): The 1st level in the Pane
     47        (WebInspector.EventListenersSidebarPane.prototype.update.callback):
     48        (WebInspector.EventListenersSidebarPane.prototype.update):
     49        (WebInspector.EventListenersSection): The 2nd level in the Pane
     50        (WebInspector.EventListenersSection.prototype.update): filters on Preference
     51        (WebInspector.EventListenersSection.prototype.addListener):
     52        (WebInspector.EventListenerBar): The 3rd level in the Pane
     53        (WebInspector.EventListenerBar.prototype._getNodeDisplayName):
     54        (WebInspector.EventListenerBar.prototype._getFunctionDisplayName):
     55        (WebInspector.EventListenersSidebarPane.prototype._changeSetting): For the Gear Menu
     56       
     57          Consolidated "appropriateSelectorForNode"
     58
     59        * inspector/front-end/StylesSidebarPane.js:
     60        * inspector/front-end/utilities.js:
     61
     62          Miscellaneous Updates
     63
     64        * English.lproj/localizedStrings.js: "Event Listeners", "No Event Listeners", "Selected Node Only", "All Nodes"
     65        * WebCore.gypi: included the new inspector files
     66        * WebCore.vcproj/WebCore.vcproj: included source files that were missing
     67        * inspector/front-end/Images/grayConnectorPoint.png: Added. Thanks to Timothy Hatcher.
     68        * inspector/front-end/Images/whiteConnectorPoint.png: Added. Thanks to Timothy Hatcher.
     69        * inspector/front-end/inspector.js: Preferences for the Gear Menu Event Listeners filter
     70        * inspector/front-end/inspector.css: reused as much as possible
     71        * inspector/front-end/inspector.html: include the new script
     72        * inspector/front-end/WebKit.qrc: included the new inspector files
     73
    1742009-09-27  Sam Weinig  <sam@webkit.org>
    275
  • trunk/WebCore/WebCore.gypi

    r48781 r48809  
    35473547            'inspector/front-end/ElementsPanel.js',
    35483548            'inspector/front-end/ElementsTreeOutline.js',
     3549            'inspector/front-end/EventListenersSidebarPane.js',
    35493550            'inspector/front-end/FontView.js',
    35503551            'inspector/front-end/ImageView.js',
     
    36313632            'inspector/front-end/Images/graphLabelCalloutLeft.png',
    36323633            'inspector/front-end/Images/graphLabelCalloutRight.png',
     3634            'inspector/front-end/Images/grayConnectorPoint.png',
    36333635            'inspector/front-end/Images/largerResourcesButtonGlyph.png',
    36343636            'inspector/front-end/Images/localStorage.png',
     
    37133715            'inspector/front-end/Images/warningMediumIcon.png',
    37143716            'inspector/front-end/Images/warningsErrors.png',
     3717            'inspector/front-end/Images/whiteConnectorPoint.png'
    37153718        ],
    37163719    }
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r48748 r48809  
    3142831428                                </File>
    3142931429                                <File
    31430                                         RelativePath="..\inspector\front-end\DatabasesPanel.js"
    31431                                         >
    31432                                 </File>
    31433                                 <File
    3143431430                                        RelativePath="..\inspector\front-end\DatabaseTableView.js"
    3143531431                                        >
     
    3146431460                                </File>
    3146531461                                <File
     31462                                        RelativePath="..\inspector\front-end\ElementsTreeOutline.js"
     31463                                        >
     31464                                </File>
     31465                                <File
     31466                                        RelativePath="..\inspector\front-end\EventListenersSidebarPane.js"
     31467                                        >
     31468                                </File>
     31469                                <File
    3146631470                                        RelativePath="..\inspector\front-end\FontView.js"
    3146731471                                        >
     
    3158131585                                <File
    3158231586                                        RelativePath="..\inspector\front-end\StatusBarButton.js"
     31587                                        >
     31588                                </File>
     31589                                <File
     31590                                        RelativePath="..\inspector\front-end\StoragePanel.js"
    3158331591                                        >
    3158431592                                </File>
  • trunk/WebCore/dom/Node.cpp

    r48723 r48809  
    24232423}
    24242424
    2425 bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
    2426 {
    2427     RefPtr<EventTarget> protect = this;
    2428     RefPtr<Event> event = prpEvent;
    2429 
    2430     event->setTarget(eventTargetRespectingSVGTargetRules(this));
    2431 
    2432     RefPtr<FrameView> view = document()->view();
    2433     return dispatchGenericEvent(event.release());
    2434 }
    2435 
    2436 bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
    2437 {
    2438     RefPtr<Event> event(prpEvent);
    2439 
    2440     ASSERT(!eventDispatchForbidden());
    2441     ASSERT(event->target());
    2442     ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
    2443 
    2444 #if ENABLE(INSPECTOR)
    2445     InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent();
    2446     if (timelineAgent)
    2447         timelineAgent->willDispatchDOMEvent(*event);
    2448 #endif
    2449 
    2450     // Make a vector of ancestors to send the event to.
    2451     // If the node is not in a document just send the event to it.
    2452     // Be sure to ref all of nodes since event handlers could result in the last reference going away.
    2453     RefPtr<Node> thisNode(this);
    2454     Vector<RefPtr<ContainerNode> > ancestors;
     2425void Node::eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors)
     2426{
    24552427    if (inDocument()) {
    24562428        for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) {
     
    24632435        }
    24642436    }
     2437}
     2438
     2439bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
     2440{
     2441    RefPtr<EventTarget> protect = this;
     2442    RefPtr<Event> event = prpEvent;
     2443
     2444    event->setTarget(eventTargetRespectingSVGTargetRules(this));
     2445
     2446    RefPtr<FrameView> view = document()->view();
     2447    return dispatchGenericEvent(event.release());
     2448}
     2449
     2450bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
     2451{
     2452    RefPtr<Event> event(prpEvent);
     2453
     2454    ASSERT(!eventDispatchForbidden());
     2455    ASSERT(event->target());
     2456    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
     2457
     2458#if ENABLE(INSPECTOR)
     2459    InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent();
     2460    if (timelineAgent)
     2461        timelineAgent->willDispatchDOMEvent(*event);
     2462#endif
     2463
     2464    // Make a vector of ancestors to send the event to.
     2465    // If the node is not in a document just send the event to it.
     2466    // Be sure to ref all of nodes since event handlers could result in the last reference going away.
     2467    RefPtr<Node> thisNode(this);
     2468    Vector<RefPtr<ContainerNode> > ancestors;
     2469    eventAncestors(ancestors);
    24652470
    24662471    // Set up a pointer to indicate whether / where to dispatch window events.
  • trunk/WebCore/dom/Node.h

    r48701 r48809  
    207207    virtual ContainerNode* eventParentNode();
    208208
     209    // Node ancestors when concerned about event flow
     210    void eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors);
     211
    209212    bool isBlockFlow() const;
    210213    bool isBlockFlowOrBlockTable() const;
  • trunk/WebCore/inspector/InspectorBackend.cpp

    r48716 r48809  
    277277}
    278278
    279 void InspectorBackend::getCookies(long callId)
    280 {
    281     if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
    282         domAgent->getCookies(callId);
    283 }
    284 
    285 void InspectorBackend::deleteCookie(const String& cookieName)
    286 {
    287     if (!m_inspectorController)
    288         return;
    289     m_inspectorController->deleteCookie(cookieName);
    290 }
    291 
    292279#if ENABLE(JAVASCRIPT_DEBUGGER)
    293280const ProfilesArray& InspectorBackend::profiles() const
     
    450437}
    451438
     439void InspectorBackend::getEventListenersForNode(long callId, long nodeId)
     440{
     441    if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
     442        domAgent->getEventListenersForNode(callId, nodeId);
     443}
     444
    452445void InspectorBackend::copyNode(long nodeId)
    453446{
     
    457450    String markup = createMarkup(node);
    458451    Pasteboard::generalPasteboard()->writePlainText(markup);
     452}
     453
     454void InspectorBackend::getCookies(long callId)
     455{
     456    if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
     457        domAgent->getCookies(callId);
     458}
     459
     460void InspectorBackend::deleteCookie(const String& cookieName)
     461{
     462    if (!m_inspectorController)
     463        return;
     464    m_inspectorController->deleteCookie(cookieName);
    459465}
    460466
  • trunk/WebCore/inspector/InspectorBackend.h

    r48716 r48809  
    100100    bool timelineEnabled() const;
    101101
    102     void getCookies(long callId);
    103     void deleteCookie(const String& cookieName);
    104 
    105102#if ENABLE(JAVASCRIPT_DEBUGGER)
    106103    const ProfilesArray& profiles() const;
     
    139136    void removeAttribute(long callId, long elementId, const String& name);
    140137    void setTextNodeValue(long callId, long nodeId, const String& value);
     138    void getEventListenersForNode(long callId, long nodeId);
    141139    void copyNode(long nodeId);
     140
     141    void getCookies(long callId);
     142    void deleteCookie(const String& cookieName);
    142143
    143144    // Generic code called from custom implementations.
  • trunk/WebCore/inspector/InspectorBackend.idl

    r48716 r48809  
    7272        void storeLastActivePanel(in DOMString panelName);
    7373
    74         void getCookies(in long callId);
    75         void deleteCookie(in DOMString cookieName);
    76 
    7774#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER
    7875        boolean debuggerEnabled();
     
    110107        void removeAttribute(in long callId, in long elementId, in DOMString name);
    111108        void setTextNodeValue(in long callId, in long nodeId, in DOMString value);
     109        void getEventListenersForNode(in long callId, in long nodeId);
    112110        void copyNode(in long nodeId);
     111
     112        void getCookies(in long callId);
     113        void deleteCookie(in DOMString cookieName);
    113114
    114115        // Called from InjectedScript.
  • trunk/WebCore/inspector/InspectorDOMAgent.cpp

    r48798 r48809  
    5757#include <wtf/Vector.h>
    5858
     59#if USE(JSC)
     60#include "JSDOMWindow.h"
     61#include <runtime/JSObject.h>
     62#endif
     63
    5964namespace WebCore {
    6065
     
    364369}
    365370
     371void InspectorDOMAgent::getEventListenersForNode(long callId, long nodeId)
     372{
     373    Node* node = nodeForId(nodeId);
     374    ScriptArray listenersArray = m_frontend->newScriptArray();
     375    unsigned counter = 0;
     376    EventTargetData* d;
     377
     378    // Quick break if a null node or no listeners at all
     379    if (!node || !(d = node->eventTargetData())) {
     380        m_frontend->didGetEventListenersForNode(callId, nodeId, listenersArray);
     381        return;
     382    }
     383
     384    // Get the list of event types this Node is concerned with
     385    Vector<AtomicString> eventTypes;
     386    const EventListenerMap& listenerMap = d->eventListenerMap;
     387    HashMap<AtomicString, EventListenerVector>::const_iterator end = listenerMap.end();
     388    for (HashMap<AtomicString, EventListenerVector>::const_iterator iter = listenerMap.begin(); iter != end; ++iter)
     389        eventTypes.append(iter->first);
     390
     391    // Quick break if no useful listeners
     392    size_t eventTypesLength = eventTypes.size();
     393    if (eventTypesLength == 0) {
     394        m_frontend->didGetEventListenersForNode(callId, nodeId, listenersArray);
     395        return;
     396    }
     397
     398    // The Node's Event Ancestors (not including self)
     399    Vector<RefPtr<ContainerNode> > ancestors;
     400    node->eventAncestors(ancestors);
     401
     402    // Nodes and their Listeners for the concerned event types (order is top to bottom)
     403    Vector<EventListenerInfo> eventInformation;
     404    for (size_t i = ancestors.size(); i; --i) {
     405        ContainerNode* ancestor = ancestors[i - 1].get();
     406        for (size_t j = 0; j < eventTypesLength; ++j) {
     407            AtomicString& type = eventTypes[j];
     408            if (ancestor->hasEventListeners(type))
     409                eventInformation.append(EventListenerInfo(static_cast<Node*>(ancestor), type, ancestor->getEventListeners(type)));
     410        }
     411    }
     412
     413    // Insert the Current Node at the end of that list (last in capturing, first in bubbling)
     414    for (size_t i = 0; i < eventTypesLength; ++i) {
     415        const AtomicString& type = eventTypes[i];
     416        eventInformation.append(EventListenerInfo(node, type, node->getEventListeners(type)));
     417    }
     418
     419    // Get Capturing Listeners (in this order)
     420    size_t eventInformationLength = eventInformation.size();
     421    for (size_t i = 0; i < eventInformationLength; ++i) {
     422        const EventListenerInfo& info = eventInformation[i];
     423        const EventListenerVector& vector = info.eventListenerVector;
     424        for (size_t j = 0; j < vector.size(); ++j) {
     425            const RegisteredEventListener& listener = vector[j];
     426            if (listener.useCapture)
     427                listenersArray.set(counter++, buildObjectForEventListener(listener, info.eventType, info.node));
     428        }
     429    }
     430
     431    // Get Bubbling Listeners (reverse order)
     432    for (size_t i = eventInformationLength; i; --i) {
     433        const EventListenerInfo& info = eventInformation[i - 1];
     434        const EventListenerVector& vector = info.eventListenerVector;
     435        for (size_t j = 0; j < vector.size(); ++j) {
     436            const RegisteredEventListener& listener = vector[j];
     437            if (!listener.useCapture)
     438                listenersArray.set(counter++, buildObjectForEventListener(listener, info.eventType, info.node));
     439        }
     440    }
     441
     442    m_frontend->didGetEventListenersForNode(callId, nodeId, listenersArray);
     443}
     444
    366445void InspectorDOMAgent::getCookies(long callId)
    367446{
     
    382461    long id = bind(node, nodesMap);
    383462    String nodeName;
     463    String localName;
    384464    String nodeValue;
    385465
     
    390470            break;
    391471        case Node::ATTRIBUTE_NODE:
     472            localName = node->localName();
     473            break;
    392474        case Node::DOCUMENT_FRAGMENT_NODE:
    393475            break;
     
    396478        default:
    397479            nodeName = node->nodeName();
     480            localName = node->localName();
    398481            break;
    399482    }
     
    402485    value.set("nodeType", node->nodeType());
    403486    value.set("nodeName", nodeName);
     487    value.set("localName", localName);
    404488    value.set("nodeValue", nodeValue);
    405489
     
    458542}
    459543
     544ScriptObject InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node)
     545{
     546    RefPtr<EventListener> eventListener = registeredEventListener.listener;
     547    ScriptObject value = m_frontend->newScriptObject();
     548    value.set("type", eventType);
     549    value.set("useCapture", registeredEventListener.useCapture);
     550    value.set("isAttribute", eventListener->isAttribute());
     551    value.set("nodeId", static_cast<long long>(pushNodePathToFrontend(node)));
     552#if USE(JSC)
     553    JSC::JSObject* functionObject = eventListener->jsFunction();
     554    if (functionObject)
     555        value.set("listener", ScriptObject(m_frontend->scriptState(), functionObject));
     556#endif
     557    return value;
     558}
     559
    460560ScriptObject InspectorDOMAgent::buildObjectForCookie(const Cookie& cookie)
    461561{
  • trunk/WebCore/inspector/InspectorDOMAgent.h

    r48798 r48809  
    3131#define InspectorDOMAgent_h
    3232
     33#include "AtomicString.h"
    3334#include "EventListener.h"
     35#include "EventTarget.h"
    3436#include "ScriptArray.h"
    3537#include "ScriptObject.h"
     
    5456    struct Cookie;
    5557
     58    struct EventListenerInfo {
     59        EventListenerInfo(Node* node, const AtomicString& eventType, const EventListenerVector& eventListenerVector)
     60            : node(node)
     61            , eventType(eventType)
     62            , eventListenerVector(eventListenerVector)
     63        {
     64        }
     65
     66        Node* node;
     67        const AtomicString eventType;
     68        const EventListenerVector eventListenerVector;
     69    };
     70
    5671    class InspectorDOMAgent : public EventListener {
    5772    public:
     
    7388        void removeAttribute(long callId, long elementId, const String& name);
    7489        void setTextNodeValue(long callId, long nodeId, const String& value);
     90        void getEventListenersForNode(long callId, long nodeId);
    7591        void getCookies(long callId);
    7692
     
    98114        ScriptArray buildArrayForElementAttributes(Element* element);
    99115        ScriptArray buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
     116
     117        ScriptObject buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node);
    100118
    101119        ScriptObject buildObjectForCookie(const Cookie& cookie);
  • trunk/WebCore/inspector/InspectorFrontend.cpp

    r48717 r48809  
    369369}
    370370
     371void InspectorFrontend::didGetEventListenersForNode(int callId, int nodeId, ScriptArray& listenersArray)
     372{
     373    OwnPtr<ScriptFunctionCall> function(newFunctionCall("didGetEventListenersForNode"));
     374    function->appendArgument(callId);
     375    function->appendArgument(nodeId);
     376    function->appendArgument(listenersArray);
     377    function->call();
     378}
     379
    371380void InspectorFrontend::didGetCookies(int callId, const ScriptArray& cookies, const String& cookiesString)
    372381{
  • trunk/WebCore/inspector/InspectorFrontend.h

    r48659 r48809  
    116116        void didGetChildNodes(int callId);
    117117        void didApplyDomChange(int callId, bool success);
     118        void didGetEventListenersForNode(int callId, int nodeId, ScriptArray& listenersArray);
    118119
    119120        void timelineWasEnabled();
     
    125126
    126127        void addNodesToSearchResult(const String& nodeIds);
     128
     129        ScriptState* scriptState() const { return m_scriptState; }
    127130
    128131    private:
  • trunk/WebCore/inspector/front-end/DOMAgent.js

    r48046 r48809  
    3636    this.nodeType = payload.nodeType;
    3737    this.nodeName = payload.nodeName;
     38    this.localName = payload.localName;
    3839    this._nodeValue = payload.nodeValue;
    3940    this.textContent = this.nodeValue;
     
    474475}
    475476
     477WebInspector.EventListeners = {}
     478
     479WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callback)
     480{
     481    if (!node)
     482        return;
     483
     484    var callId = WebInspector.Callback.wrap(callback);
     485    InspectorController.getEventListenersForNode(callId, node.id);
     486}
     487
    476488WebInspector.CSSStyleDeclaration = function(payload)
    477489{
     
    649661WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback;
    650662WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback;
     663WebInspector.didGetEventListenersForNode = WebInspector.Callback.processCallback;
  • trunk/WebCore/inspector/front-end/ElementsPanel.js

    r48716 r48809  
    5757        this.panel.updateMetrics();
    5858        this.panel.updateProperties();
     59        this.panel.updateEventListeners();
    5960
    6061        if (InspectorController.searchingForNode()) {
     
    7778    this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
    7879    this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
     80    this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane();
    7981
    8082    this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
    8183    this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
    8284    this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
     85    this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this);
    8386
    8487    this.sidebarPanes.styles.expanded = true;
     
    9497    this.sidebarElement.appendChild(this.sidebarPanes.metrics.element);
    9598    this.sidebarElement.appendChild(this.sidebarPanes.properties.element);
     99    this.sidebarElement.appendChild(this.sidebarPanes.eventListeners.element);
    96100
    97101    this.sidebarResizeElement = document.createElement("div");
     
    978982    },
    979983
     984    updateEventListeners: function()
     985    {
     986        var eventListenersSidebarPane = this.sidebarPanes.eventListeners;
     987        if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate)
     988            return;
     989
     990        eventListenersSidebarPane.update(this.focusedDOMNode);
     991        eventListenersSidebarPane.needsUpdate = false;
     992    },
     993
    980994    handleKeyEvent: function(event)
    981995    {
  • trunk/WebCore/inspector/front-end/StylesSidebarPane.js

    r48437 r48809  
    349349    addBlankSection: function()
    350350    {
    351         var blankSection = new WebInspector.BlankStylePropertiesSection(this.appropriateSelectorForNode());
     351        var blankSection = new WebInspector.BlankStylePropertiesSection(appropriateSelectorForNode(this.node, true));
    352352        blankSection.pane = this;
    353353
     
    368368        if (section.element.parentNode)
    369369            section.element.parentNode.removeChild(section.element);
    370     },
    371 
    372     appropriateSelectorForNode: function()
    373     {
    374         var node = this.node;
    375         if (!node)
    376             return "";
    377 
    378         var id = node.getAttribute("id");
    379         if (id)
    380             return "#" + id;
    381 
    382         var className = node.getAttribute("class");
    383         if (className)
    384             return "." + className.replace(/\s+/, ".");
    385 
    386         var nodeName = node.nodeName.toLowerCase();
    387         if (nodeName === "input" && node.getAttribute("type"))
    388             return nodeName + "[type=\"" + node.getAttribute("type") + "\"]";
    389 
    390         return nodeName;
    391370    }
    392371}
  • trunk/WebCore/inspector/front-end/WebKit.qrc

    r48804 r48809  
    2222    <file>ElementsPanel.js</file>
    2323    <file>ElementsTreeOutline.js</file>
     24    <file>EventListenersSidebarPane.js</file>
    2425    <file>FontView.js</file>
    2526    <file>ImageView.js</file>
     
    104105    <file>Images/graphLabelCalloutLeft.png</file>
    105106    <file>Images/graphLabelCalloutRight.png</file>
     107    <file>Images/grayConnectorPoint.png</file>
    106108    <file>Images/largerResourcesButtonGlyph.png</file>
    107109    <file>Images/localStorage.png</file>
     
    189191    <file>Images/warningOrangeDot.png</file>
    190192    <file>Images/warningsErrors.png</file>
     193    <file>Images/whiteConnectorPoint.png</file>
    191194</qresource>
    192195</RCC>
  • trunk/WebCore/inspector/front-end/inspector.css

    r48718 r48809  
    12231223}
    12241224
    1225 .section:nth-last-of-type(1) {
     1225.section:nth-last-of-type(1), .event-bar:nth-last-of-type(1) {
    12261226    margin-bottom: 1px;
    12271227}
     
    12291229.watch-expressions-buttons-container {
    12301230    text-align: center;
     1231}
     1232
     1233.event-bar:first-child {
     1234    margin-top: 1px;
     1235}
     1236
     1237.event-bar:nth-last-of-type(1) .header {
     1238    border-bottom: 1px solid rgb(163, 163, 163);
    12311239}
    12321240
     
    12621270}
    12631271
    1264 .section .header .title {
     1272.section .header .title, .event-bar .header .title {
    12651273    color: white;
    12661274    font-weight: bold;
     
    12731281}
    12741282
    1275 .section .header label {
    1276     display: none;
    1277 }
    1278 
    1279 .section.expanded .header label {
     1283.section .header label, .event-bar .header label {
     1284    display: none;
     1285}
     1286
     1287.section.expanded .header label, .event-bar.expanded .header label {
    12801288    display: inline;
    12811289}
     
    12901298}
    12911299
    1292 .section .header .subtitle {
     1300.section .header .subtitle, .event-bar .header .subtitle {
    12931301    float: right;
    12941302    font-size: 10px;
     
    13041312}
    13051313
    1306 .section .properties {
     1314.section .properties, .event-bar .event-properties {
    13071315    display: none;
    13081316    margin: 0;
     
    13211329}
    13221330
    1323 .section.expanded .properties {
     1331.section.expanded .properties, .event-bar.expanded .event-properties {
    13241332    display: block;
    13251333}
    13261334
    1327 .section .properties li {
     1335.section .properties li, .event-properties li {
    13281336    margin-left: 12px;
    13291337    white-space: nowrap;
     
    13341342}
    13351343
    1336 .section .properties li.parent {
     1344.section .properties li.parent, .event-properties li.parent {
    13371345    margin-left: 1px;
    13381346}
    13391347
    1340 .section .properties ol {
     1348.section .properties ol, .event-properties ol {
    13411349    display: none;
    13421350    margin: 0;
     
    13451353}
    13461354
    1347 .section .properties ol.expanded {
     1355.section .properties ol.expanded, .event-properties ol.expanded {
    13481356    display: block;
    13491357}
    13501358
    1351 .section .properties li.parent::before {
     1359.section .properties li.parent::before, .event-properties li.parent::before {
    13521360    content: url(Images/treeRightTriangleBlack.png);
    13531361    opacity: 0.75;
     
    13611369}
    13621370
    1363 .section .properties li.parent.expanded::before {
     1371.section .properties li.parent.expanded::before, .event-properties li.parent.expanded::before {
    13641372    content: url(Images/treeDownTriangleBlack.png);
    13651373    margin-top: 1px;
    13661374}
    13671375
    1368 .section .properties li .info {
     1376.section .properties li .info, .event-properties li .info {
    13691377    padding-top: 4px;
    13701378    padding-bottom: 3px;
     1379}
     1380
     1381.section .event-bars {
     1382    display: none;
     1383}
     1384
     1385.section.expanded .event-bars {
     1386    display: block;
     1387}
     1388
     1389.event-bar {
     1390    position: relative;
     1391}
     1392
     1393.event-bar-connector {
     1394    position: absolute;
     1395    left: 75%;
     1396    bottom: -7px;
     1397    margin-left: -7px;
     1398    content: url(Images/grayConnectorPoint.png);
     1399    z-index: 3;
     1400}
     1401
     1402.event-bar.expanded .event-bar-connector {
     1403    content: url(Images/whiteConnectorPoint.png);
     1404}
     1405
     1406.event-bars .event-bar .header {
     1407    padding: 2px 8px 4px 18px;
     1408    border-top: 1px solid rgb(163, 163, 163);
     1409    background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), to(rgb(207, 207, 207)));
     1410    min-height: 18px;
     1411    white-space: nowrap;
     1412    -webkit-background-origin: padding;
     1413    -webkit-background-clip: padding;
     1414}
     1415
     1416.event-bars .event-bar.expanded .header {
     1417    border-bottom: 1px solid rgb(163, 163, 163);
     1418}
     1419
     1420.event-bars .event-bar .header .title {
     1421    font-weight: bold;
     1422    color: #333;
     1423    text-shadow: white 0 1px 0;
     1424}
     1425
     1426.event-bars .event-bar .header .subtitle {
     1427    color: rgba(90, 90, 90, 0.742188);
     1428}
     1429
     1430.event-bars .event-bar .header::before {
     1431    position: absolute;
     1432    top: 4px;
     1433    left: 7px;
     1434    width: 8px;
     1435    height: 8px;
     1436    opacity: 0.75;
     1437    content: url(Images/treeRightTriangleBlack.png);
     1438}
     1439
     1440.event-bars .event-bar.expanded .header::before {
     1441    content: url(Images/treeDownTriangleBlack.png);
    13711442}
    13721443
     
    14621533}
    14631534
    1464 .section .properties .name {
     1535.section .properties .name, .event-properties .name {
    14651536    color: rgb(136, 19, 145);
    14661537}
     
    14701541}
    14711542
    1472 .section .properties .number {
     1543.section .properties .number, .event-properties .number {
    14731544    color: blue;
    14741545}
     
    14781549}
    14791550
    1480 .section .properties .keyword {
     1551.section .properties .keyword, .event-properties .keyword {
    14811552    color: rgb(136, 19, 79);
    14821553}
    14831554
    1484 .section .properties .color {
     1555.section .properties .color, .event-properties .color {
    14851556    color: rgb(118, 15, 21);
    14861557}
  • trunk/WebCore/inspector/front-end/inspector.html

    r48431 r48809  
    6666    <script type="text/javascript" src="MetricsSidebarPane.js"></script>
    6767    <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
     68    <script type="text/javascript" src="EventListenersSidebarPane.js"></script>
    6869    <script type="text/javascript" src="Color.js"></script>
    6970    <script type="text/javascript" src="StylesSidebarPane.js"></script>
  • trunk/WebCore/inspector/front-end/inspector.js

    r48659 r48809  
    4343    samplingCPUProfiler: false,
    4444    showColorNicknames: true,
    45     colorFormat: "hex"
     45    colorFormat: "hex",
     46    eventListenersFilter: "all"
    4647}
    4748
     
    354355    if (colorFormat)
    355356        Preferences.colorFormat = colorFormat;
     357
     358    var eventListenersFilter = InspectorController.setting("event-listeners-filter");
     359    if (eventListenersFilter)
     360        Preferences.eventListenersFilter = eventListenersFilter;
    356361
    357362    this.drawer = new WebInspector.Drawer();
  • trunk/WebCore/inspector/front-end/utilities.js

    r48536 r48809  
    622622}
    623623
    624 function getDocumentForNode(node) {
     624function appropriateSelectorForNode(node, justSelector)
     625{
     626    if (!node)
     627        return "";
     628
     629    var lowerCaseName = node.localName || node.nodeName.toLowerCase();
     630
     631    var id = node.getAttribute("id");
     632    if (id) {
     633        var selector = "#" + id;
     634        return (justSelector ? selector : lowerCaseName + selector);
     635    }
     636
     637    var className = node.getAttribute("class");
     638    if (className) {
     639        var selector = "." + className.replace(/\s+/, ".");
     640        return (justSelector ? selector : lowerCaseName + selector);
     641    }
     642
     643    if (lowerCaseName === "input" && node.getAttribute("type"))
     644        return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]";
     645
     646    return lowerCaseName;
     647}
     648
     649function getDocumentForNode(node)
     650{
    625651    return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
    626652}
    627653
    628 function parentNode(node) {
     654function parentNode(node)
     655{
    629656    return node.parentNode;
    630657}
Note: See TracChangeset for help on using the changeset viewer.