Web Inspector: CodeGeneratorInspector.py: use generated types in method parameters
[WebKit-https.git] / Source / WebCore / inspector / InspectorDOMAgent.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  * Copyright (C) 2009 Joseph Pecoraro
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "InspectorDOMAgent.h"
33
34 #if ENABLE(INSPECTOR)
35
36 #include "Attr.h"
37 #include "CSSComputedStyleDeclaration.h"
38 #include "CSSMutableStyleDeclaration.h"
39 #include "CSSPropertyNames.h"
40 #include "CSSPropertySourceData.h"
41 #include "CSSRule.h"
42 #include "CSSRuleList.h"
43 #include "CSSStyleRule.h"
44 #include "CSSStyleSelector.h"
45 #include "CSSStyleSheet.h"
46 #include "CharacterData.h"
47 #include "ContainerNode.h"
48 #include "Cookie.h"
49 #include "CookieJar.h"
50 #include "DOMNodeHighlighter.h"
51 #include "DOMWindow.h"
52 #include "Document.h"
53 #include "DocumentFragment.h"
54 #include "DocumentType.h"
55 #include "Event.h"
56 #include "EventContext.h"
57 #include "EventListener.h"
58 #include "EventNames.h"
59 #include "EventTarget.h"
60 #include "Frame.h"
61 #include "FrameTree.h"
62 #include "HitTestResult.h"
63 #include "HTMLElement.h"
64 #include "HTMLFrameOwnerElement.h"
65 #include "IdentifiersFactory.h"
66 #include "InjectedScriptManager.h"
67 #include "InspectorClient.h"
68 #include "InspectorFrontend.h"
69 #include "InspectorPageAgent.h"
70 #include "InspectorState.h"
71 #include "InstrumentingAgents.h"
72 #include "IntRect.h"
73 #include "MutationEvent.h"
74 #include "Node.h"
75 #include "NodeList.h"
76 #include "Page.h"
77 #include "Pasteboard.h"
78 #include "RenderStyle.h"
79 #include "RenderStyleConstants.h"
80 #include "ScriptEventListener.h"
81 #include "StyleSheetList.h"
82 #include "Text.h"
83 #include "XPathResult.h"
84
85 #include "markup.h"
86
87 #include <wtf/text/CString.h>
88 #include <wtf/text/WTFString.h>
89 #include <wtf/HashSet.h>
90 #include <wtf/ListHashSet.h>
91 #include <wtf/OwnPtr.h>
92 #include <wtf/Vector.h>
93
94 namespace WebCore {
95
96 namespace DOMAgentState {
97 static const char documentRequested[] = "documentRequested";
98 };
99
100 static const size_t maxTextSize = 10000;
101 static const UChar ellipsisUChar[] = { 0x2026, 0 };
102
103 static Color parseColor(const RefPtr<InspectorObject>* colorObject)
104 {
105     if (!colorObject || !(*colorObject))
106         return Color::transparent;
107
108     int r;
109     int g;
110     int b;
111     bool success = (*colorObject)->getNumber("r", &r);
112     success |= (*colorObject)->getNumber("g", &g);
113     success |= (*colorObject)->getNumber("b", &b);
114     if (!success)
115         return Color::transparent;
116
117     double a;
118     success = (*colorObject)->getNumber("a", &a);
119     if (!success)
120         return Color(r, g, b);
121
122     // Clamp alpha to the [0..1] range.
123     if (a < 0)
124         a = 0;
125     else if (a > 1)
126         a = 1;
127
128     return Color(r, g, b, static_cast<int>(a * 255));
129 }
130
131 static Color parseConfigColor(const String& fieldName, InspectorObject* configObject)
132 {
133     const RefPtr<InspectorObject> colorObject = configObject->getObject(fieldName);
134     return parseColor(&colorObject);
135 }
136
137 class RevalidateStyleAttributeTask {
138 public:
139     RevalidateStyleAttributeTask(InspectorDOMAgent*);
140     void scheduleFor(Element*);
141     void reset() { m_timer.stop(); }
142     void onTimer(Timer<RevalidateStyleAttributeTask>*);
143
144 private:
145     InspectorDOMAgent* m_domAgent;
146     Timer<RevalidateStyleAttributeTask> m_timer;
147     HashSet<RefPtr<Element> > m_elements;
148 };
149
150 RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
151     : m_domAgent(domAgent)
152     , m_timer(this, &RevalidateStyleAttributeTask::onTimer)
153 {
154 }
155
156 void RevalidateStyleAttributeTask::scheduleFor(Element* element)
157 {
158     m_elements.add(element);
159     if (!m_timer.isActive())
160         m_timer.startOneShot(0);
161 }
162
163 void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
164 {
165     // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
166     Vector<Element*> elements;
167     for (HashSet<RefPtr<Element> >::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
168         elements.append(it->get());
169     m_domAgent->styleAttributeInvalidated(elements);
170
171     m_elements.clear();
172 }
173
174 InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager)
175     : InspectorBaseAgent<InspectorDOMAgent>("DOM", instrumentingAgents, inspectorState)
176     , m_pageAgent(pageAgent)
177     , m_client(client)
178     , m_injectedScriptManager(injectedScriptManager)
179     , m_frontend(0)
180     , m_domListener(0)
181     , m_lastNodeId(1)
182     , m_searchingForNode(false)
183 {
184 }
185
186 InspectorDOMAgent::~InspectorDOMAgent()
187 {
188     reset();
189     ASSERT(!m_highlightData || (!m_highlightData->node && !m_highlightData->rect));
190     ASSERT(!m_searchingForNode);
191 }
192
193 void InspectorDOMAgent::setFrontend(InspectorFrontend* frontend)
194 {
195     ASSERT(!m_frontend);
196     m_frontend = frontend->dom();
197     m_instrumentingAgents->setInspectorDOMAgent(this);
198     m_document = m_pageAgent->mainFrame()->document();
199
200     if (m_nodeToFocus)
201         focusNode();
202 }
203
204 void InspectorDOMAgent::clearFrontend()
205 {
206     ASSERT(m_frontend);
207     setSearchingForNode(false, 0);
208
209     ErrorString error;
210     hideHighlight(&error);
211
212     m_frontend = 0;
213     m_instrumentingAgents->setInspectorDOMAgent(0);
214     m_state->setBoolean(DOMAgentState::documentRequested, false);
215     reset();
216 }
217
218 void InspectorDOMAgent::restore()
219 {
220     // Reset document to avoid early return from setDocument.
221     m_document = 0;
222     setDocument(m_pageAgent->mainFrame()->document());
223 }
224
225 Vector<Document*> InspectorDOMAgent::documents()
226 {
227     Vector<Document*> result;
228     for (Frame* frame = m_document->frame(); frame; frame = frame->tree()->traverseNext()) {
229         Document* document = frame->document();
230         if (!document)
231             continue;
232         result.append(document);
233     }
234     return result;
235 }
236
237 Node* InspectorDOMAgent::highlightedNode() const
238 {
239     return m_highlightData ? m_highlightData->node.get() : 0;
240 }
241
242 void InspectorDOMAgent::reset()
243 {
244     ErrorString error;
245     m_searchResults.clear();
246     discardBindings();
247     if (m_revalidateStyleAttrTask)
248         m_revalidateStyleAttrTask->reset();
249     m_document = 0;
250 }
251
252 void InspectorDOMAgent::setDOMListener(DOMListener* listener)
253 {
254     m_domListener = listener;
255 }
256
257 void InspectorDOMAgent::setDocument(Document* doc)
258 {
259     if (doc == m_document.get())
260         return;
261
262     reset();
263
264     m_document = doc;
265
266     if (!m_state->getBoolean(DOMAgentState::documentRequested))
267         return;
268
269     // Immediately communicate 0 document or document that has finished loading.
270     if (!doc || !doc->parsing())
271         m_frontend->documentUpdated();
272 }
273
274 void InspectorDOMAgent::releaseDanglingNodes()
275 {
276     deleteAllValues(m_danglingNodeToIdMaps);
277     m_danglingNodeToIdMaps.clear();
278 }
279
280 int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
281 {
282     int id = nodesMap->get(node);
283     if (id)
284         return id;
285     id = m_lastNodeId++;
286     nodesMap->set(node, id);
287     m_idToNode.set(id, node);
288     m_idToNodesMap.set(id, nodesMap);
289     return id;
290 }
291
292 void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
293 {
294     if (node->isFrameOwnerElement()) {
295         const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
296         if (m_domListener)
297             m_domListener->didRemoveDocument(frameOwner->contentDocument());
298     }
299
300     int id = nodesMap->get(node);
301     if (!id)
302         return;
303     m_idToNode.remove(id);
304     nodesMap->remove(node);
305     bool childrenRequested = m_childrenRequested.contains(id);
306     if (childrenRequested) {
307         // Unbind subtree known to client recursively.
308         m_childrenRequested.remove(id);
309         Node* child = innerFirstChild(node);
310         while (child) {
311             unbind(child, nodesMap);
312             child = innerNextSibling(child);
313         }
314     }
315 }
316
317 Node* InspectorDOMAgent::assertNode(ErrorString* errorString, int nodeId)
318 {
319     Node* node = nodeForId(nodeId);
320     if (!node) {
321         *errorString = "Could not find node with given id";
322         return 0;
323     }
324     return node;
325 }
326
327 Element* InspectorDOMAgent::assertElement(ErrorString* errorString, int nodeId)
328 {
329     Node* node = assertNode(errorString, nodeId);
330     if (!node)
331         return 0;
332
333     if (node->nodeType() != Node::ELEMENT_NODE) {
334         *errorString = "Node is not an Element";
335         return 0;
336     }
337     return toElement(node);
338 }
339
340
341 HTMLElement* InspectorDOMAgent::assertHTMLElement(ErrorString* errorString, int nodeId)
342 {
343     Element* element = assertElement(errorString, nodeId);
344     if (!element)
345         return 0;
346
347     if (!element->isHTMLElement()) {
348         *errorString = "Node is not an HTML Element";
349         return 0;
350     }
351     return toHTMLElement(element);
352 }
353
354 void InspectorDOMAgent::getDocument(ErrorString*, RefPtr<InspectorObject>* root)
355 {
356     m_state->setBoolean(DOMAgentState::documentRequested, true);
357
358     if (!m_document)
359         return;
360
361     // Reset backend state.
362     RefPtr<Document> doc = m_document;
363     reset();
364     m_document = doc;
365
366     *root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
367 }
368
369 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId)
370 {
371     Node* node = nodeForId(nodeId);
372     if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
373         return;
374     if (m_childrenRequested.contains(nodeId))
375         return;
376
377     NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
378     RefPtr<InspectorArray> children = buildArrayForContainerChildren(node, 1, nodeMap);
379     m_frontend->setChildNodes(nodeId, children.release());
380 }
381
382 void InspectorDOMAgent::discardBindings()
383 {
384     m_documentNodeToIdMap.clear();
385     m_idToNode.clear();
386     releaseDanglingNodes();
387     m_childrenRequested.clear();
388 }
389
390 Node* InspectorDOMAgent::nodeForId(int id)
391 {
392     if (!id)
393         return 0;
394
395     HashMap<int, Node*>::iterator it = m_idToNode.find(id);
396     if (it != m_idToNode.end())
397         return it->second;
398     return 0;
399 }
400
401 void InspectorDOMAgent::requestChildNodes(ErrorString*, int nodeId)
402 {
403     pushChildNodesToFrontend(nodeId);
404 }
405
406 void InspectorDOMAgent::querySelector(ErrorString* errorString, int nodeId, const String& selectors, int* elementId)
407 {
408     *elementId = 0;
409     Node* node = assertNode(errorString, nodeId);
410     if (!node)
411         return;
412
413     ExceptionCode ec = 0;
414     RefPtr<Element> element = node->querySelector(selectors, ec);
415     if (ec) {
416         *errorString = "DOM Error while querying";
417         return;
418     }
419
420     if (element)
421         *elementId = pushNodePathToFrontend(element.get());
422 }
423
424 void InspectorDOMAgent::querySelectorAll(ErrorString* errorString, int nodeId, const String& selectors, RefPtr<InspectorArray>* result)
425 {
426     Node* node = assertNode(errorString, nodeId);
427     if (!node)
428         return;
429
430     ExceptionCode ec = 0;
431     RefPtr<NodeList> nodes = node->querySelectorAll(selectors, ec);
432     if (ec) {
433         *errorString = "DOM Error while querying";
434         return;
435     }
436
437     for (unsigned i = 0; i < nodes->length(); ++i)
438         (*result)->pushNumber(pushNodePathToFrontend(nodes->item(i)));
439 }
440
441 int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
442 {
443     ASSERT(nodeToPush);  // Invalid input
444
445     if (!m_document)
446         return 0;
447     if (!m_documentNodeToIdMap.contains(m_document))
448         return 0;
449
450     // Return id in case the node is known.
451     int result = m_documentNodeToIdMap.get(nodeToPush);
452     if (result)
453         return result;
454
455     Node* node = nodeToPush;
456     Vector<Node*> path;
457     NodeToIdMap* danglingMap = 0;
458
459     while (true) {
460         Node* parent = innerParentNode(node);
461         if (!parent) {
462             // Node being pushed is detached -> push subtree root.
463             danglingMap = new NodeToIdMap();
464             m_danglingNodeToIdMaps.append(danglingMap);
465             RefPtr<InspectorArray> children = InspectorArray::create();
466             children->pushObject(buildObjectForNode(node, 0, danglingMap));
467             m_frontend->setChildNodes(0, children);
468             break;
469         } else {
470             path.append(parent);
471             if (m_documentNodeToIdMap.get(parent))
472                 break;
473             else
474                 node = parent;
475         }
476     }
477
478     NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
479     for (int i = path.size() - 1; i >= 0; --i) {
480         int nodeId = map->get(path.at(i));
481         ASSERT(nodeId);
482         pushChildNodesToFrontend(nodeId);
483     }
484     return map->get(nodeToPush);
485 }
486
487 int InspectorDOMAgent::boundNodeId(Node* node)
488 {
489     return m_documentNodeToIdMap.get(node);
490 }
491
492 void InspectorDOMAgent::setAttributeValue(ErrorString* errorString, int elementId, const String& name, const String& value)
493 {
494     Element* element = assertElement(errorString, elementId);
495     if (!element)
496         return;
497
498     ExceptionCode ec = 0;
499     element->setAttribute(name, value, ec);
500     if (ec)
501         *errorString = "Internal error: could not set attribute value";
502 }
503
504 void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elementId, const String& text, const String* const name)
505 {
506     Element* element = assertElement(errorString, elementId);
507     if (!element)
508         return;
509
510     ExceptionCode ec = 0;
511     RefPtr<Element> parsedElement = element->document()->createElement("span", ec);
512     if (ec) {
513         *errorString = "Internal error: could not set attribute value";
514         return;
515     }
516
517     toHTMLElement(parsedElement.get())->setInnerHTML("<span " + text + "></span>", ec);
518     if (ec) {
519         *errorString = "Could not parse value as attributes";
520         return;
521     }
522
523     Node* child = parsedElement->firstChild();
524     if (!child) {
525         *errorString = "Could not parse value as attributes";
526         return;
527     }
528
529     const NamedNodeMap* attrMap = toHTMLElement(child)->attributes(true);
530     if (!attrMap && name) {
531         element->removeAttribute(*name, ec);
532         if (ec)
533             *errorString = "Could not remove attribute";
534         return;
535     }
536
537     bool foundOriginalAttribute = false;
538     unsigned numAttrs = attrMap->length();
539     for (unsigned i = 0; i < numAttrs; ++i) {
540         // Add attribute pair
541         const Attribute* attribute = attrMap->attributeItem(i);
542         foundOriginalAttribute = foundOriginalAttribute || (name && attribute->name().toString() == *name);
543         element->setAttribute(attribute->name(), attribute->value(), ec);
544         if (ec) {
545             *errorString = "Internal error: could not set attribute value";
546             return;
547         }
548     }
549
550     if (!foundOriginalAttribute && name) {
551         element->removeAttribute(*name, ec);
552         if (ec)
553             *errorString = "Could not remove attribute";
554         return;
555     }
556 }
557
558 void InspectorDOMAgent::removeAttribute(ErrorString* errorString, int elementId, const String& name)
559 {
560     Element* element = assertElement(errorString, elementId);
561     if (element) {
562         ExceptionCode ec = 0;
563         element->removeAttribute(name, ec);
564         if (ec)
565             *errorString = "Exception while removing attribute";
566     }
567 }
568
569 void InspectorDOMAgent::removeNode(ErrorString* errorString, int nodeId)
570 {
571     Node* node = assertNode(errorString, nodeId);
572     if (!node)
573         return;
574
575     ContainerNode* parentNode = node->parentNode();
576     if (!parentNode) {
577         *errorString = "Can not remove detached node";
578         return;
579     }
580
581     ExceptionCode ec = 0;
582     parentNode->removeChild(node, ec);
583     if (ec)
584         *errorString = "Could not remove node due to DOM exception";
585 }
586
587 void InspectorDOMAgent::setNodeName(ErrorString*, int nodeId, const String& tagName, int* newId)
588 {
589     *newId = 0;
590
591     Node* oldNode = nodeForId(nodeId);
592     if (!oldNode || !oldNode->isElementNode())
593         return;
594
595     ExceptionCode ec = 0;
596     RefPtr<Element> newElem = oldNode->document()->createElement(tagName, ec);
597     if (ec)
598         return;
599
600     // Copy over the original node's attributes.
601     Element* oldElem = static_cast<Element*>(oldNode);
602     if (oldElem->attributes())
603         newElem->attributes()->setAttributes(*(oldElem->attributes(true)));
604
605     // Copy over the original node's children.
606     Node* child;
607     while ((child = oldNode->firstChild()))
608         newElem->appendChild(child, ec);
609
610     // Replace the old node with the new node
611     ContainerNode* parent = oldNode->parentNode();
612     parent->insertBefore(newElem, oldNode->nextSibling(), ec);
613     parent->removeChild(oldNode, ec);
614
615     if (ec)
616         return;
617
618     *newId = pushNodePathToFrontend(newElem.get());
619     if (m_childrenRequested.contains(nodeId))
620         pushChildNodesToFrontend(*newId);
621 }
622
623 void InspectorDOMAgent::getOuterHTML(ErrorString* errorString, int nodeId, WTF::String* outerHTML)
624 {
625     Node* node = assertNode(errorString, nodeId);
626     if (!node)
627         return;
628
629     if (node->isHTMLElement()) {
630         *outerHTML = static_cast<HTMLElement*>(node)->outerHTML();
631         return;
632     }
633
634     if (node->isCommentNode()) {
635         *outerHTML = "<!--" + node->nodeValue() + "-->";
636         return;
637     }
638
639     if (node->isTextNode()) {
640         *outerHTML = node->nodeValue();
641         return;
642     }
643
644     *errorString = "Only HTMLElements, Comments, and Text nodes are supported";
645 }
646
647 void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML, int* newId)
648 {
649     Node* node = assertNode(errorString, nodeId);
650     if (!node)
651         return;
652
653     Element* parentElement = node->parentElement();
654     if (!parentElement)
655         return;
656
657     Document* document = node->ownerDocument();
658     if (!document->isHTMLDocument()) {
659         *errorString = "Not an HTML document";
660         return;
661     }
662
663     Node* previousSibling = node->previousSibling(); // Remember previous sibling before replacing node.
664
665     RefPtr<DocumentFragment> fragment = DocumentFragment::create(document);
666     fragment->parseHTML(outerHTML, parentElement);
667
668     ExceptionCode ec = 0;
669     parentElement->replaceChild(fragment.release(), node, ec);
670     if (ec) {
671         *errorString = "Failed to replace Node with new contents";
672         return;
673     }
674
675     bool requiresTotalUpdate = false;
676     if (node->isHTMLElement())
677         requiresTotalUpdate = node->nodeName() == "HTML" || node->nodeName() == "BODY" || node->nodeName() == "HEAD";
678
679     if (requiresTotalUpdate) {
680         RefPtr<Document> document = m_document;
681         reset();
682         setDocument(document.get());
683         *newId = 0;
684         return;
685     }
686
687     Node* newNode = previousSibling ? previousSibling->nextSibling() : parentElement->firstChild();
688     if (!newNode) {
689         // The only child node has been deleted.
690         *newId = 0;
691         return;
692     }
693
694     *newId = pushNodePathToFrontend(newNode);
695
696     bool childrenRequested = m_childrenRequested.contains(nodeId);
697     if (childrenRequested)
698         pushChildNodesToFrontend(*newId);
699 }
700
701 void InspectorDOMAgent::setNodeValue(ErrorString* errorString, int nodeId, const String& value)
702 {
703     Node* node = assertNode(errorString, nodeId);
704     if (!node)
705         return;
706
707     if (node->nodeType() != Node::TEXT_NODE) {
708         *errorString = "Can only set value of text nodes";
709         return;
710     }
711
712     Text* textNode = static_cast<Text*>(node);
713     ExceptionCode ec = 0;
714     textNode->replaceWholeText(value, ec);
715     if (ec)
716         *errorString = "DOM Error while setting the node value";
717 }
718
719 void InspectorDOMAgent::getEventListenersForNode(ErrorString*, int nodeId, RefPtr<InspectorArray>* listenersArray)
720 {
721     Node* node = nodeForId(nodeId);
722     EventTargetData* d;
723
724     // Quick break if a null node or no listeners at all
725     if (!node || !(d = node->eventTargetData()))
726         return;
727
728     // Get the list of event types this Node is concerned with
729     Vector<AtomicString> eventTypes = d->eventListenerMap.eventTypes();
730
731     // Quick break if no useful listeners
732     size_t eventTypesLength = eventTypes.size();
733     if (!eventTypesLength)
734         return;
735
736     // The Node's Ancestors (not including self)
737     Vector<ContainerNode*> ancestors;
738     for (ContainerNode* ancestor = node->parentOrHostNode(); ancestor; ancestor = ancestor->parentOrHostNode())
739         ancestors.append(ancestor);
740
741     // Nodes and their Listeners for the concerned event types (order is top to bottom)
742     Vector<EventListenerInfo> eventInformation;
743     for (size_t i = ancestors.size(); i; --i) {
744         ContainerNode* ancestor = ancestors[i - 1];
745         for (size_t j = 0; j < eventTypesLength; ++j) {
746             AtomicString& type = eventTypes[j];
747             if (ancestor->hasEventListeners(type))
748                 eventInformation.append(EventListenerInfo(ancestor, type, ancestor->getEventListeners(type)));
749         }
750     }
751
752     // Insert the Current Node at the end of that list (last in capturing, first in bubbling)
753     for (size_t i = 0; i < eventTypesLength; ++i) {
754         const AtomicString& type = eventTypes[i];
755         eventInformation.append(EventListenerInfo(node, type, node->getEventListeners(type)));
756     }
757
758     // Get Capturing Listeners (in this order)
759     size_t eventInformationLength = eventInformation.size();
760     for (size_t i = 0; i < eventInformationLength; ++i) {
761         const EventListenerInfo& info = eventInformation[i];
762         const EventListenerVector& vector = info.eventListenerVector;
763         for (size_t j = 0; j < vector.size(); ++j) {
764             const RegisteredEventListener& listener = vector[j];
765             if (listener.useCapture)
766                 (*listenersArray)->pushObject(buildObjectForEventListener(listener, info.eventType, info.node));
767         }
768     }
769
770     // Get Bubbling Listeners (reverse order)
771     for (size_t i = eventInformationLength; i; --i) {
772         const EventListenerInfo& info = eventInformation[i - 1];
773         const EventListenerVector& vector = info.eventListenerVector;
774         for (size_t j = 0; j < vector.size(); ++j) {
775             const RegisteredEventListener& listener = vector[j];
776             if (!listener.useCapture)
777                 (*listenersArray)->pushObject(buildObjectForEventListener(listener, info.eventType, info.node));
778         }
779     }
780 }
781
782 void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrimmedQuery, String* searchId, int* resultCount)
783 {
784     // FIXME: Few things are missing here:
785     // 1) Search works with node granularity - number of matches within node is not calculated.
786     // 2) There is no need to push all search results to the front-end at a time, pushing next / previous result
787     //    is sufficient.
788
789     unsigned queryLength = whitespaceTrimmedQuery.length();
790     bool startTagFound = !whitespaceTrimmedQuery.find('<');
791     bool endTagFound = whitespaceTrimmedQuery.reverseFind('>') + 1 == queryLength;
792
793     String tagNameQuery = whitespaceTrimmedQuery;
794     if (startTagFound)
795         tagNameQuery = tagNameQuery.right(tagNameQuery.length() - 1);
796     if (endTagFound)
797         tagNameQuery = tagNameQuery.left(tagNameQuery.length() - 1);
798
799     Vector<Document*> docs = documents();
800     ListHashSet<Node*> resultCollector;
801
802     for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
803         Document* document = *it;
804         Node* node = document->documentElement();
805
806         // Manual plain text search.
807         while ((node = node->traverseNextNode(document->documentElement()))) {
808             switch (node->nodeType()) {
809             case Node::TEXT_NODE:
810             case Node::COMMENT_NODE:
811             case Node::CDATA_SECTION_NODE: {
812                 String text = node->nodeValue();
813                 if (text.findIgnoringCase(whitespaceTrimmedQuery) != notFound)
814                     resultCollector.add(node);
815                 break;
816             }
817             case Node::ELEMENT_NODE: {
818                 if (node->nodeName().findIgnoringCase(tagNameQuery) != notFound) {
819                     resultCollector.add(node);
820                     break;
821                 }
822                 // Go through all attributes and serialize them.
823                 const NamedNodeMap* attrMap = static_cast<Element*>(node)->attributes(true);
824                 if (!attrMap)
825                     break;
826
827                 unsigned numAttrs = attrMap->length();
828                 for (unsigned i = 0; i < numAttrs; ++i) {
829                     // Add attribute pair
830                     const Attribute* attribute = attrMap->attributeItem(i);
831                     if (attribute->localName().find(whitespaceTrimmedQuery) != notFound) {
832                         resultCollector.add(node);
833                         break;
834                     }
835                     if (attribute->value().find(whitespaceTrimmedQuery) != notFound) {
836                         resultCollector.add(node);
837                         break;
838                     }
839                 }
840                 break;
841             }
842             default:
843                 break;
844             }
845         }
846
847         // XPath evaluation
848         for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
849             Document* document = *it;
850             ExceptionCode ec = 0;
851             RefPtr<XPathResult> result = document->evaluate(whitespaceTrimmedQuery, document, 0, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, 0, ec);
852             if (ec || !result)
853                 continue;
854
855             unsigned long size = result->snapshotLength(ec);
856             for (unsigned long i = 0; !ec && i < size; ++i) {
857                 Node* node = result->snapshotItem(i, ec);
858                 if (ec)
859                     break;
860
861                 if (node->nodeType() == Node::ATTRIBUTE_NODE)
862                     node = static_cast<Attr*>(node)->ownerElement();
863                 resultCollector.add(node);
864             }
865         }
866     }
867
868     *searchId = IdentifiersFactory::createIdentifier();
869     SearchResults::iterator resultsIt = m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).first;
870
871     for (ListHashSet<Node*>::iterator it = resultCollector.begin(); it != resultCollector.end(); ++it)
872         resultsIt->second.append(*it);
873
874     *resultCount = resultsIt->second.size();
875 }
876
877 void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<InspectorArray>* nodeIds)
878 {
879     SearchResults::iterator it = m_searchResults.find(searchId);
880     if (it == m_searchResults.end()) {
881         *errorString = "No search session with given id found";
882         return;
883     }
884
885     int size = it->second.size();
886     if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
887         *errorString = "Invalid search result range";
888         return;
889     }
890
891     for (int i = fromIndex; i < toIndex; ++i)
892         (*nodeIds)->pushNumber(pushNodePathToFrontend((it->second)[i].get()));
893 }
894
895 void InspectorDOMAgent::discardSearchResults(ErrorString*, const String& searchId)
896 {
897     m_searchResults.remove(searchId);
898 }
899
900 bool InspectorDOMAgent::handleMousePress()
901 {
902     if (!m_searchingForNode)
903         return false;
904
905     if (m_highlightData && m_highlightData->node) {
906         RefPtr<Node> node = m_highlightData->node;
907         setSearchingForNode(false, 0);
908         inspect(node.get());
909     }
910     return true;
911 }
912
913 void InspectorDOMAgent::inspect(Node* node)
914 {
915     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
916         node = node->parentNode();
917     m_nodeToFocus = node;
918
919     focusNode();
920 }
921
922 void InspectorDOMAgent::focusNode()
923 {
924     if (!m_frontend)
925         return;
926
927     ASSERT(m_nodeToFocus);
928
929     RefPtr<Node> node = m_nodeToFocus.get();
930     m_nodeToFocus = 0;
931
932     Document* document = node->ownerDocument();
933     if (!document)
934         return;
935     Frame* frame = document->frame();
936     if (!frame)
937         return;
938
939     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
940     if (injectedScript.hasNoValue())
941         return;
942
943     injectedScript.inspectNode(node.get());
944 }
945
946 void InspectorDOMAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
947 {
948     if (!m_searchingForNode || !m_highlightData)
949         return;
950
951     Node* node = result.innerNode();
952     while (node && node->nodeType() == Node::TEXT_NODE)
953         node = node->parentNode();
954     if (node) {
955         m_highlightData->node = node;
956         highlight();
957     }
958 }
959
960 void InspectorDOMAgent::setSearchingForNode(bool enabled, InspectorObject* highlightConfig)
961 {
962     if (m_searchingForNode == enabled)
963         return;
964     m_searchingForNode = enabled;
965     if (enabled)
966         setHighlightDataFromConfig(highlightConfig);
967     else {
968         ErrorString error;
969         hideHighlight(&error);
970         m_highlightData.clear();
971     }
972 }
973
974 void InspectorDOMAgent::setInspectModeEnabled(ErrorString*, bool enabled, const RefPtr<InspectorObject>* highlightConfig)
975 {
976     setSearchingForNode(enabled, highlightConfig ? highlightConfig->get() : 0);
977 }
978
979 bool InspectorDOMAgent::setHighlightDataFromConfig(InspectorObject* highlightConfig)
980 {
981     if (!highlightConfig) {
982         m_highlightData.clear();
983         return false;
984     }
985
986     m_highlightData = adoptPtr(new HighlightData());
987     bool showInfo = false; // Default: false (do not show a tooltip).
988     highlightConfig->getBoolean("showInfo", &showInfo);
989     m_highlightData->showInfo = showInfo;
990     m_highlightData->content = parseConfigColor("contentColor", highlightConfig);
991     m_highlightData->contentOutline = parseConfigColor("contentOutlineColor", highlightConfig);
992     m_highlightData->padding = parseConfigColor("paddingColor", highlightConfig);
993     m_highlightData->border = parseConfigColor("borderColor", highlightConfig);
994     m_highlightData->margin = parseConfigColor("marginColor", highlightConfig);
995     return true;
996 }
997
998 void InspectorDOMAgent::highlight()
999 {
1000     // This method requires m_highlightData to have been filled in by its client.
1001     ASSERT(m_highlightData);
1002     m_client->highlight();
1003 }
1004
1005 void InspectorDOMAgent::highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
1006 {
1007     m_highlightData = adoptPtr(new HighlightData());
1008     m_highlightData->rect = adoptPtr(new IntRect(x, y, width, height));
1009     m_highlightData->content = parseColor(color);
1010     m_highlightData->contentOutline = parseColor(outlineColor);
1011     m_client->highlight();
1012 }
1013
1014 void InspectorDOMAgent::highlightNode(
1015     ErrorString*,
1016     int nodeId,
1017     const RefPtr<InspectorObject> highlightConfig)
1018 {
1019     if (Node* node = nodeForId(nodeId)) {
1020         if (setHighlightDataFromConfig(highlightConfig.get())) {
1021             m_highlightData->node = node;
1022             highlight();
1023         }
1024     }
1025 }
1026
1027 void InspectorDOMAgent::highlightFrame(
1028     ErrorString*,
1029     const String& frameId,
1030     const RefPtr<InspectorObject>* color,
1031     const RefPtr<InspectorObject>* outlineColor)
1032 {
1033     Frame* frame = m_pageAgent->frameForId(frameId);
1034     if (frame && frame->ownerElement()) {
1035         m_highlightData = adoptPtr(new HighlightData());
1036         m_highlightData->node = frame->ownerElement();
1037         m_highlightData->showInfo = true; // Always show tooltips for frames.
1038         m_highlightData->content = parseColor(color);
1039         m_highlightData->contentOutline = parseColor(outlineColor);
1040         highlight();
1041     }
1042 }
1043
1044 void InspectorDOMAgent::hideHighlight(ErrorString*)
1045 {
1046     if (m_highlightData) {
1047         m_highlightData->node.clear();
1048         m_highlightData->rect.clear();
1049     }
1050     m_client->hideHighlight();
1051 }
1052
1053 void InspectorDOMAgent::moveTo(ErrorString* error, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
1054 {
1055     Node* node = assertNode(error, nodeId);
1056     if (!node)
1057         return;
1058
1059     Element* targetElement = assertElement(error, targetElementId);
1060     if (!targetElement)
1061         return;
1062
1063     Node* anchorNode = 0;
1064     if (anchorNodeId && *anchorNodeId) {
1065         anchorNode = assertNode(error, *anchorNodeId);
1066         if (!anchorNode)
1067             return;
1068         if (anchorNode->parentNode() != targetElement) {
1069             *error = "Anchor node must be child of the target element";
1070             return;
1071         }
1072     }
1073
1074     ExceptionCode ec = 0;
1075     bool success = targetElement->insertBefore(node, anchorNode, ec);
1076     if (ec || !success) {
1077         *error = "Could not drop node";
1078         return;
1079     }
1080     *newNodeId = pushNodePathToFrontend(node);
1081 }
1082
1083 void InspectorDOMAgent::resolveNode(ErrorString* error, int nodeId, const String* const objectGroup, RefPtr<InspectorObject>* result)
1084 {
1085     String objectGroupName = objectGroup ? *objectGroup : "";
1086     Node* node = nodeForId(nodeId);
1087     if (!node) {
1088         *error = "No node with given id found";
1089         return;
1090     }
1091     RefPtr<InspectorObject> object = resolveNode(node, objectGroupName);
1092     if (!object) {
1093         *error = "Node with given id does not belong to the document";
1094         return;
1095     }
1096     *result = object;
1097 }
1098
1099 void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<InspectorArray>* result)
1100 {
1101     Element* element = assertElement(errorString, nodeId);
1102     if (!element)
1103         return;
1104
1105     *result = buildArrayForElementAttributes(element);
1106 }
1107
1108 void InspectorDOMAgent::requestNode(ErrorString*, const String& objectId, int* nodeId)
1109 {
1110     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
1111     Node* node = injectedScript.nodeForObjectId(objectId);
1112     if (node)
1113         *nodeId = pushNodePathToFrontend(node);
1114     else
1115         *nodeId = 0;
1116 }
1117
1118 // static
1119 String InspectorDOMAgent::documentURLString(Document* document)
1120 {
1121     if (!document || document->url().isNull())
1122         return "";
1123     return document->url().string();
1124 }
1125
1126 PassRefPtr<InspectorObject> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
1127 {
1128     RefPtr<InspectorObject> value = InspectorObject::create();
1129
1130     int id = bind(node, nodesMap);
1131     String nodeName;
1132     String localName;
1133     String nodeValue;
1134
1135     switch (node->nodeType()) {
1136     case Node::TEXT_NODE:
1137     case Node::COMMENT_NODE:
1138     case Node::CDATA_SECTION_NODE:
1139         nodeValue = node->nodeValue();
1140         if (nodeValue.length() > maxTextSize) {
1141             nodeValue = nodeValue.left(maxTextSize);
1142             nodeValue.append(ellipsisUChar);
1143         }
1144         break;
1145     case Node::ATTRIBUTE_NODE:
1146         localName = node->localName();
1147         break;
1148     case Node::DOCUMENT_FRAGMENT_NODE:
1149         break;
1150     case Node::DOCUMENT_NODE:
1151     case Node::ELEMENT_NODE:
1152     default:
1153         nodeName = node->nodeName();
1154         localName = node->localName();
1155         break;
1156     }
1157
1158     value->setNumber("nodeId", id);
1159     value->setNumber("nodeType", node->nodeType());
1160     value->setString("nodeName", nodeName);
1161     value->setString("localName", localName);
1162     value->setString("nodeValue", nodeValue);
1163
1164     if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::DOCUMENT_NODE || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
1165         int nodeCount = innerChildNodeCount(node);
1166         value->setNumber("childNodeCount", nodeCount);
1167         RefPtr<InspectorArray> children = buildArrayForContainerChildren(node, depth, nodesMap);
1168         if (children->length() > 0)
1169             value->setArray("children", children.release());
1170
1171         if (node->nodeType() == Node::ELEMENT_NODE) {
1172             Element* element = static_cast<Element*>(node);
1173             value->setArray("attributes", buildArrayForElementAttributes(element));
1174             if (node->isFrameOwnerElement()) {
1175                 HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
1176                 value->setString("documentURL", documentURLString(frameOwner->contentDocument()));
1177             }
1178         } else if (node->nodeType() == Node::DOCUMENT_NODE) {
1179             Document* document = static_cast<Document*>(node);
1180             value->setString("documentURL", documentURLString(document));
1181             value->setString("xmlVersion", document->xmlVersion());
1182         }
1183     } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1184         DocumentType* docType = static_cast<DocumentType*>(node);
1185         value->setString("publicId", docType->publicId());
1186         value->setString("systemId", docType->systemId());
1187         value->setString("internalSubset", docType->internalSubset());
1188     } else if (node->nodeType() == Node::ATTRIBUTE_NODE) {
1189         Attr* attribute = static_cast<Attr*>(node);
1190         value->setString("name", attribute->name());
1191         value->setString("value", attribute->value());
1192     }
1193     return value.release();
1194 }
1195
1196 PassRefPtr<InspectorArray> InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
1197 {
1198     RefPtr<InspectorArray> attributesValue = InspectorArray::create();
1199     // Go through all attributes and serialize them.
1200     const NamedNodeMap* attrMap = element->attributes(true);
1201     if (!attrMap)
1202         return attributesValue.release();
1203     unsigned numAttrs = attrMap->length();
1204     for (unsigned i = 0; i < numAttrs; ++i) {
1205         // Add attribute pair
1206         const Attribute* attribute = attrMap->attributeItem(i);
1207         attributesValue->pushString(attribute->name().toString());
1208         attributesValue->pushString(attribute->value());
1209     }
1210     return attributesValue.release();
1211 }
1212
1213 PassRefPtr<InspectorArray> InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
1214 {
1215     RefPtr<InspectorArray> children = InspectorArray::create();
1216     Node* child = innerFirstChild(container);
1217
1218     if (depth == 0) {
1219         // Special-case the only text child - pretend that container's children have been requested.
1220         if (child && child->nodeType() == Node::TEXT_NODE && !innerNextSibling(child))
1221             return buildArrayForContainerChildren(container, 1, nodesMap);
1222         return children.release();
1223     }
1224
1225     depth--;
1226     m_childrenRequested.add(bind(container, nodesMap));
1227
1228     while (child) {
1229         children->pushObject(buildObjectForNode(child, depth, nodesMap));
1230         child = innerNextSibling(child);
1231     }
1232     return children.release();
1233 }
1234
1235 PassRefPtr<InspectorObject> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node)
1236 {
1237     RefPtr<EventListener> eventListener = registeredEventListener.listener;
1238     RefPtr<InspectorObject> value = InspectorObject::create();
1239     value->setString("type", eventType);
1240     value->setBoolean("useCapture", registeredEventListener.useCapture);
1241     value->setBoolean("isAttribute", eventListener->isAttribute());
1242     value->setNumber("nodeId", pushNodePathToFrontend(node));
1243     value->setString("handlerBody", eventListenerHandlerBody(node->document(), eventListener.get()));
1244     String sourceName;
1245     int lineNumber;
1246     if (eventListenerHandlerLocation(node->document(), eventListener.get(), sourceName, lineNumber)) {
1247         RefPtr<InspectorObject> location = InspectorObject::create();
1248         location->setString("scriptId", sourceName);
1249         location->setNumber("lineNumber", lineNumber);
1250         value->setObject("location", location);
1251     }
1252     return value.release();
1253 }
1254
1255 Node* InspectorDOMAgent::innerFirstChild(Node* node)
1256 {
1257     if (node->isFrameOwnerElement()) {
1258         HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
1259         Document* doc = frameOwner->contentDocument();
1260         if (doc)
1261             return doc->firstChild();
1262     }
1263     node = node->firstChild();
1264     while (isWhitespace(node))
1265         node = node->nextSibling();
1266     return node;
1267 }
1268
1269 Node* InspectorDOMAgent::innerNextSibling(Node* node)
1270 {
1271     do {
1272         node = node->nextSibling();
1273     } while (isWhitespace(node));
1274     return node;
1275 }
1276
1277 Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
1278 {
1279     do {
1280         node = node->previousSibling();
1281     } while (isWhitespace(node));
1282     return node;
1283 }
1284
1285 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
1286 {
1287     unsigned count = 0;
1288     Node* child = innerFirstChild(node);
1289     while (child) {
1290         count++;
1291         child = innerNextSibling(child);
1292     }
1293     return count;
1294 }
1295
1296 Node* InspectorDOMAgent::innerParentNode(Node* node)
1297 {
1298     ContainerNode* parent = node->parentNode();
1299     if (parent && parent->isDocumentNode())
1300         return static_cast<Document*>(parent)->ownerElement();
1301     return parent;
1302 }
1303
1304 bool InspectorDOMAgent::isWhitespace(Node* node)
1305 {
1306     //TODO: pull ignoreWhitespace setting from the frontend and use here.
1307     return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
1308 }
1309
1310 void InspectorDOMAgent::mainFrameDOMContentLoaded()
1311 {
1312     // Re-push document once it is loaded.
1313     discardBindings();
1314     if (m_state->getBoolean(DOMAgentState::documentRequested))
1315         m_frontend->documentUpdated();
1316 }
1317
1318 void InspectorDOMAgent::loadEventFired(Document* document)
1319 {
1320     Element* frameOwner = document->ownerElement();
1321     if (!frameOwner)
1322         return;
1323
1324     int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
1325     if (!frameOwnerId)
1326         return;
1327
1328     if (!m_childrenRequested.contains(frameOwnerId)) {
1329         // No children are mapped yet -> only notify on changes of hasChildren.
1330         m_frontend->childNodeCountUpdated(frameOwnerId, innerChildNodeCount(frameOwner));
1331     } else {
1332         // Re-add frame owner element together with its new children.
1333         int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
1334         m_frontend->childNodeRemoved(parentId, frameOwnerId);
1335         RefPtr<InspectorObject> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
1336         Node* previousSibling = innerPreviousSibling(frameOwner);
1337         int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
1338         m_frontend->childNodeInserted(parentId, prevId, value.release());
1339         // Invalidate children requested flag for the element.
1340         m_childrenRequested.remove(m_childrenRequested.find(frameOwnerId));
1341     }
1342 }
1343
1344 void InspectorDOMAgent::didInsertDOMNode(Node* node)
1345 {
1346     if (isWhitespace(node))
1347         return;
1348
1349     // We could be attaching existing subtree. Forget the bindings.
1350     unbind(node, &m_documentNodeToIdMap);
1351
1352     ContainerNode* parent = node->parentNode();
1353     int parentId = m_documentNodeToIdMap.get(parent);
1354     // Return if parent is not mapped yet.
1355     if (!parentId)
1356         return;
1357
1358     if (!m_childrenRequested.contains(parentId)) {
1359         // No children are mapped yet -> only notify on changes of hasChildren.
1360         m_frontend->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
1361     } else {
1362         // Children have been requested -> return value of a new child.
1363         Node* prevSibling = innerPreviousSibling(node);
1364         int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
1365         RefPtr<InspectorObject> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
1366         m_frontend->childNodeInserted(parentId, prevId, value.release());
1367     }
1368 }
1369
1370 void InspectorDOMAgent::didRemoveDOMNode(Node* node)
1371 {
1372     if (isWhitespace(node))
1373         return;
1374
1375     ContainerNode* parent = node->parentNode();
1376     int parentId = m_documentNodeToIdMap.get(parent);
1377     // If parent is not mapped yet -> ignore the event.
1378     if (!parentId)
1379         return;
1380
1381     if (m_domListener)
1382         m_domListener->didRemoveDOMNode(node);
1383
1384     if (!m_childrenRequested.contains(parentId)) {
1385         // No children are mapped yet -> only notify on changes of hasChildren.
1386         if (innerChildNodeCount(parent) == 1)
1387             m_frontend->childNodeCountUpdated(parentId, 0);
1388     } else
1389         m_frontend->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
1390     unbind(node, &m_documentNodeToIdMap);
1391 }
1392
1393 void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
1394 {
1395     int id = boundNodeId(element);
1396     // If node is not mapped yet -> ignore the event.
1397     if (!id)
1398         return;
1399
1400     if (m_domListener)
1401         m_domListener->didModifyDOMAttr(element);
1402
1403     m_frontend->attributeModified(id, name, value);
1404 }
1405
1406 void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
1407 {
1408     int id = boundNodeId(element);
1409     // If node is not mapped yet -> ignore the event.
1410     if (!id)
1411         return;
1412
1413     if (m_domListener)
1414         m_domListener->didModifyDOMAttr(element);
1415
1416     m_frontend->attributeRemoved(id, name);
1417 }
1418
1419 void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
1420 {
1421     RefPtr<InspectorArray> nodeIds = InspectorArray::create();
1422     for (unsigned i = 0, size = elements.size(); i < size; ++i) {
1423         Element* element = elements.at(i);
1424         int id = boundNodeId(element);
1425         // If node is not mapped yet -> ignore the event.
1426         if (!id)
1427             continue;
1428
1429         if (m_domListener)
1430             m_domListener->didModifyDOMAttr(element);
1431         nodeIds->pushNumber(id);
1432     }
1433     m_frontend->inlineStyleInvalidated(nodeIds.release());
1434 }
1435
1436 void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
1437 {
1438     int id = m_documentNodeToIdMap.get(characterData);
1439     if (!id)
1440         return;
1441     m_frontend->characterDataModified(id, characterData->data());
1442 }
1443
1444 void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
1445 {
1446     int id = m_documentNodeToIdMap.get(node);
1447     // If node is not mapped yet -> ignore the event.
1448     if (!id)
1449         return;
1450
1451     if (!m_revalidateStyleAttrTask)
1452         m_revalidateStyleAttrTask = adoptPtr(new RevalidateStyleAttributeTask(this));
1453     m_revalidateStyleAttrTask->scheduleFor(static_cast<Element*>(node));
1454 }
1455
1456 Node* InspectorDOMAgent::nodeForPath(const String& path)
1457 {
1458     // The path is of form "1,HTML,2,BODY,1,DIV"
1459     if (!m_document)
1460         return 0;
1461
1462     Node* node = m_document.get();
1463     Vector<String> pathTokens;
1464     path.split(",", false, pathTokens);
1465     if (!pathTokens.size())
1466         return 0;
1467     for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
1468         bool success = true;
1469         unsigned childNumber = pathTokens[i].toUInt(&success);
1470         if (!success)
1471             return 0;
1472         if (childNumber >= innerChildNodeCount(node))
1473             return 0;
1474
1475         Node* child = innerFirstChild(node);
1476         String childName = pathTokens[i + 1];
1477         for (size_t j = 0; child && j < childNumber; ++j)
1478             child = innerNextSibling(child);
1479
1480         if (!child || child->nodeName() != childName)
1481             return 0;
1482         node = child;
1483     }
1484     return node;
1485 }
1486
1487 void InspectorDOMAgent::copyNode(ErrorString*, int nodeId)
1488 {
1489     Node* node = nodeForId(nodeId);
1490     if (!node)
1491         return;
1492     String markup = createMarkup(node);
1493     Pasteboard::generalPasteboard()->writePlainText(markup);
1494 }
1495
1496 void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString*, const String& path, int* nodeId)
1497 {
1498     if (Node* node = nodeForPath(path))
1499         *nodeId = pushNodePathToFrontend(node);
1500 }
1501
1502 PassRefPtr<InspectorObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
1503 {
1504     Document* document = node->isDocumentNode() ? node->document() : node->ownerDocument();
1505     Frame* frame = document ? document->frame() : 0;
1506     if (!frame)
1507         return 0;
1508
1509     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
1510     if (injectedScript.hasNoValue())
1511         return 0;
1512
1513     return injectedScript.wrapNode(node, objectGroup);
1514 }
1515
1516 void InspectorDOMAgent::drawHighlight(GraphicsContext& context) const
1517 {
1518     if (!m_highlightData)
1519         return;
1520
1521     DOMNodeHighlighter::drawHighlight(context, m_highlightData->node ? m_highlightData->node->document() : m_document.get(), m_highlightData.get());
1522 }
1523
1524 } // namespace WebCore
1525
1526 #endif // ENABLE(INSPECTOR)