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