1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2011 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef InspectorDOMAgent_h 31 #define InspectorDOMAgent_h 32 33 #include "EventTarget.h" 34 #include "InjectedScript.h" 35 #include "InjectedScriptManager.h" 36 #include "InspectorFrontend.h" 37 #include "InspectorValues.h" 38 #include "Timer.h" 39 40 #include <wtf/Deque.h> 41 #include <wtf/ListHashSet.h> 42 #include <wtf/HashMap.h> 43 #include <wtf/HashSet.h> 44 #include <wtf/OwnPtr.h> 45 #include <wtf/PassOwnPtr.h> 46 #include <wtf/RefPtr.h> 47 #include <wtf/Vector.h> 48 #include <wtf/text/AtomicString.h> 49 50 namespace WebCore { 51 class ContainerNode; 52 class CharacterData; 53 class Document; 54 class Element; 55 class Event; 56 class GraphicsContext; 57 class InspectorClient; 58 class InspectorDOMAgent; 59 class InspectorFrontend; 60 class HitTestResult; 61 class MatchJob; 62 class HTMLElement; 63 class InspectorState; 64 class InstrumentingAgents; 65 class NameNodeMap; 66 class Node; 67 class Page; 68 class RevalidateStyleAttributeTask; 69 class ScriptValue; 70 71 typedef String ErrorString; 72 73 #if ENABLE(INSPECTOR) 74 75 struct EventListenerInfo { 76 EventListenerInfo(Node* node, const AtomicString& eventType, const EventListenerVector& eventListenerVector) 77 : node(node) 78 , eventType(eventType) 79 , eventListenerVector(eventListenerVector) 80 { 81 } 82 83 Node* node; 84 const AtomicString eventType; 85 const EventListenerVector eventListenerVector; 86 }; 87 88 class InspectorDOMAgent { 89 public: 90 struct DOMListener { 91 virtual ~DOMListener() 92 { 93 } 94 virtual void didRemoveDocument(Document*) = 0; 95 virtual void didRemoveDOMNode(Node*) = 0; 96 virtual void didModifyDOMAttr(Element*) = 0; 97 }; 98 99 static PassOwnPtr<InspectorDOMAgent> create(InstrumentingAgents* instrumentingAgents, Page* page, InspectorClient* client, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager) 100 { 101 return adoptPtr(new InspectorDOMAgent(instrumentingAgents, page, client, inspectorState, injectedScriptManager)); 102 } 103 104 ~InspectorDOMAgent(); 105 106 void setFrontend(InspectorFrontend*); 107 void clearFrontend(); 108 void restore(); 109 110 Vector<Document*> documents(); 111 void reset(); 112 113 // Methods called from the frontend for DOM nodes inspection. 114 void querySelector(ErrorString*, int nodeId, const String& selectors, int* elementId); 115 void querySelectorAll(ErrorString*, int nodeId, const String& selectors, RefPtr<InspectorArray>* result); 116 void getDocument(ErrorString*, RefPtr<InspectorObject>* root); 117 void getChildNodes(ErrorString*, int nodeId); 118 void setAttribute(ErrorString*, int elementId, const String& name, const String& value); 119 void removeAttribute(ErrorString*, int elementId, const String& name); 120 void removeNode(ErrorString*, int nodeId); 121 void setNodeName(ErrorString*, int nodeId, const String& name, int* newId); 122 void getOuterHTML(ErrorString*, int nodeId, WTF::String* outerHTML); 123 void setOuterHTML(ErrorString*, int nodeId, const String& outerHTML, int* newId); 124 void setNodeValue(ErrorString*, int nodeId, const String& value); 125 void getEventListenersForNode(ErrorString*, int nodeId, RefPtr<InspectorArray>* listenersArray); 126 void performSearch(ErrorString*, const String& whitespaceTrimmedQuery, const bool* const runSynchronously); 127 void cancelSearch(ErrorString*); 128 void resolveNode(ErrorString*, int nodeId, RefPtr<InspectorObject>* result); 129 void setSearchingForNode(ErrorString*, bool enabled); 130 void pushNodeToFrontend(ErrorString*, const String& objectId, int* nodeId); 131 void pushNodeByPathToFrontend(ErrorString*, const String& path, int* nodeId); 132 void hideHighlight(ErrorString*); 133 void highlightDOMNode(ErrorString*, int nodeId); 134 void hideDOMNodeHighlight(ErrorString* error) { hideHighlight(error); } 135 void highlightFrame(ErrorString*, const String& frameId); 136 void hideFrameHighlight(ErrorString* error) { hideHighlight(error); } 137 Node* highlightedNode() const { return m_highlightedNode.get(); } 138 139 // Methods called from the InspectorInstrumentation. 140 void setDocument(Document*); 141 void releaseDanglingNodes(); 142 143 void mainFrameDOMContentLoaded(); 144 void loadEventFired(Document*); 145 146 void didInsertDOMNode(Node*); 147 void didRemoveDOMNode(Node*); 148 void didModifyDOMAttr(Element*); 149 void characterDataModified(CharacterData*); 150 void didInvalidateStyleAttr(Node*); 151 152 Node* nodeForId(int nodeId); 153 int boundNodeId(Node*); 154 void copyNode(ErrorString*, int nodeId); 155 void setDOMListener(DOMListener*); 156 157 String documentURLString(Document*) const; 158 159 PassRefPtr<InspectorObject> resolveNode(Node*); 160 bool handleMousePress(); 161 bool searchingForNodeInPage() const; 162 void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); 163 void inspect(Node*); 164 void focusNode(); 165 166 void drawNodeHighlight(GraphicsContext&) const; 167 168 // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. 169 // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. 170 static Node* innerFirstChild(Node*); 171 static Node* innerNextSibling(Node*); 172 static Node* innerPreviousSibling(Node*); 173 static unsigned innerChildNodeCount(Node*); 174 static Node* innerParentNode(Node*); 175 static bool isWhitespace(Node*); 176 177 private: 178 InspectorDOMAgent(InstrumentingAgents*, Page*, InspectorClient*, InspectorState*, InjectedScriptManager*); 179 180 void setSearchingForNode(bool enabled); 181 void highlight(ErrorString*, Node*); 182 183 // Node-related methods. 184 typedef HashMap<RefPtr<Node>, int> NodeToIdMap; 185 int bind(Node*, NodeToIdMap*); 186 void unbind(Node*, NodeToIdMap*); 187 Node* assertNode(ErrorString*, int nodeId); 188 Element* assertElement(ErrorString*, int nodeId); 189 HTMLElement* assertHTMLElement(ErrorString*, int nodeId); 190 191 int pushNodePathToFrontend(Node*); 192 void pushChildNodesToFrontend(int nodeId); 193 194 bool hasBreakpoint(Node*, int type); 195 void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value); 196 void descriptionForDOMEvent(Node* target, int breakpointType, bool insertion, PassRefPtr<InspectorObject> description); 197 198 PassRefPtr<InspectorObject> buildObjectForNode(Node*, int depth, NodeToIdMap*); 199 PassRefPtr<InspectorArray> buildArrayForElementAttributes(Element*); 200 PassRefPtr<InspectorArray> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap); 201 PassRefPtr<InspectorObject> buildObjectForEventListener(const RegisteredEventListener&, const AtomicString& eventType, Node*); 202 203 void onMatchJobsTimer(Timer<InspectorDOMAgent>*); 204 void reportNodesAsSearchResults(ListHashSet<Node*>& resultCollector); 205 206 Node* nodeForPath(const String& path); 207 PassRefPtr<InspectorArray> toArray(const Vector<String>& data); 208 209 void discardBindings(); 210 211 InstrumentingAgents* m_instrumentingAgents; 212 Page* m_inspectedPage; 213 InspectorClient* m_client; 214 InspectorState* m_inspectorState; 215 InjectedScriptManager* m_injectedScriptManager; 216 InspectorFrontend::DOM* m_frontend; 217 DOMListener* m_domListener; 218 NodeToIdMap m_documentNodeToIdMap; 219 // Owns node mappings for dangling nodes. 220 Vector<NodeToIdMap*> m_danglingNodeToIdMaps; 221 HashMap<int, Node*> m_idToNode; 222 HashMap<int, NodeToIdMap*> m_idToNodesMap; 223 HashSet<int> m_childrenRequested; 224 int m_lastNodeId; 225 RefPtr<Document> m_document; 226 Deque<MatchJob*> m_pendingMatchJobs; 227 Timer<InspectorDOMAgent> m_matchJobsTimer; 228 HashSet<RefPtr<Node> > m_searchResults; 229 OwnPtr<RevalidateStyleAttributeTask> m_revalidateStyleAttrTask; 230 RefPtr<Node> m_highlightedNode; 231 RefPtr<Node> m_nodeToFocus; 232 bool m_searchingForNode; 233 }; 234 235 #endif // ENABLE(INSPECTOR) 236 237 } // namespace WebCore 238 239 #endif // !defined(InspectorDOMAgent_h) 240