Web Inspector: Search box doesn't allow CSS selectors anymore
[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         // Selector evaluation
889         for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
890             Document* document = *it;
891             ExceptionCode ec = 0;
892             RefPtr<NodeList> nodeList = document->querySelectorAll(whitespaceTrimmedQuery, ec);
893             if (ec || !nodeList)
894                 continue;
895
896             unsigned size = nodeList->length();
897             for (unsigned i = 0; i < size; ++i)
898                 resultCollector.add(nodeList->item(i));
899         }
900     }
901
902     *searchId = IdentifiersFactory::createIdentifier();
903     SearchResults::iterator resultsIt = m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).iterator;
904
905     for (ListHashSet<Node*>::iterator it = resultCollector.begin(); it != resultCollector.end(); ++it)
906         resultsIt->second.append(*it);
907
908     *resultCount = resultsIt->second.size();
909 }
910
911 void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<TypeBuilder::Array<int> >& nodeIds)
912 {
913     SearchResults::iterator it = m_searchResults.find(searchId);
914     if (it == m_searchResults.end()) {
915         *errorString = "No search session with given id found";
916         return;
917     }
918
919     int size = it->second.size();
920     if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
921         *errorString = "Invalid search result range";
922         return;
923     }
924
925     nodeIds = TypeBuilder::Array<int>::create();
926     for (int i = fromIndex; i < toIndex; ++i)
927         nodeIds->addItem(pushNodePathToFrontend((it->second)[i].get()));
928 }
929
930 void InspectorDOMAgent::discardSearchResults(ErrorString*, const String& searchId)
931 {
932     m_searchResults.remove(searchId);
933 }
934
935 bool InspectorDOMAgent::handleMousePress()
936 {
937     if (!m_searchingForNode)
938         return false;
939
940     if (m_highlightData && m_highlightData->node) {
941         RefPtr<Node> node = m_highlightData->node;
942         inspect(node.get());
943     }
944     return true;
945 }
946
947 void InspectorDOMAgent::inspect(Node* node)
948 {
949     setSearchingForNode(false, 0);
950
951     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
952         node = node->parentNode();
953     m_nodeToFocus = node;
954
955     focusNode();
956 }
957
958 void InspectorDOMAgent::focusNode()
959 {
960     if (!m_frontend)
961         return;
962
963     ASSERT(m_nodeToFocus);
964
965     RefPtr<Node> node = m_nodeToFocus.get();
966     m_nodeToFocus = 0;
967
968     Document* document = node->ownerDocument();
969     if (!document)
970         return;
971     Frame* frame = document->frame();
972     if (!frame)
973         return;
974
975     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
976     if (injectedScript.hasNoValue())
977         return;
978
979     injectedScript.inspectNode(node.get());
980 }
981
982 void InspectorDOMAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
983 {
984     if (!m_searchingForNode || !m_highlightData)
985         return;
986
987     Node* node = result.innerNode();
988     while (node && node->nodeType() == Node::TEXT_NODE)
989         node = node->parentNode();
990     if (node) {
991         m_highlightData->node = node;
992         highlight();
993     }
994 }
995
996 void InspectorDOMAgent::setSearchingForNode(bool enabled, InspectorObject* highlightConfig)
997 {
998     if (m_searchingForNode == enabled)
999         return;
1000     m_searchingForNode = enabled;
1001     if (enabled)
1002         setHighlightDataFromConfig(highlightConfig);
1003     else {
1004         ErrorString error;
1005         hideHighlight(&error);
1006         m_highlightData.clear();
1007     }
1008 }
1009
1010 void InspectorDOMAgent::setInspectModeEnabled(ErrorString*, bool enabled, const RefPtr<InspectorObject>* highlightConfig)
1011 {
1012     setSearchingForNode(enabled, highlightConfig ? highlightConfig->get() : 0);
1013 }
1014
1015 bool InspectorDOMAgent::setHighlightDataFromConfig(InspectorObject* highlightConfig)
1016 {
1017     if (!highlightConfig) {
1018         m_highlightData.clear();
1019         return false;
1020     }
1021
1022     m_highlightData = adoptPtr(new HighlightData());
1023     bool showInfo = false; // Default: false (do not show a tooltip).
1024     highlightConfig->getBoolean("showInfo", &showInfo);
1025     m_highlightData->showInfo = showInfo;
1026     m_highlightData->content = parseConfigColor("contentColor", highlightConfig);
1027     m_highlightData->contentOutline = parseConfigColor("contentOutlineColor", highlightConfig);
1028     m_highlightData->padding = parseConfigColor("paddingColor", highlightConfig);
1029     m_highlightData->border = parseConfigColor("borderColor", highlightConfig);
1030     m_highlightData->margin = parseConfigColor("marginColor", highlightConfig);
1031     return true;
1032 }
1033
1034 void InspectorDOMAgent::highlight()
1035 {
1036     // This method requires m_highlightData to have been filled in by its client.
1037     ASSERT(m_highlightData);
1038     m_client->highlight();
1039 }
1040
1041 void InspectorDOMAgent::highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
1042 {
1043     m_highlightData = adoptPtr(new HighlightData());
1044     m_highlightData->rect = adoptPtr(new IntRect(x, y, width, height));
1045     m_highlightData->content = parseColor(color);
1046     m_highlightData->contentOutline = parseColor(outlineColor);
1047     m_client->highlight();
1048 }
1049
1050 void InspectorDOMAgent::highlightNode(
1051     ErrorString*,
1052     int nodeId,
1053     const RefPtr<InspectorObject>& highlightConfig)
1054 {
1055     if (Node* node = nodeForId(nodeId)) {
1056         if (setHighlightDataFromConfig(highlightConfig.get())) {
1057             m_highlightData->node = node;
1058             highlight();
1059         }
1060     }
1061 }
1062
1063 void InspectorDOMAgent::highlightFrame(
1064     ErrorString*,
1065     const String& frameId,
1066     const RefPtr<InspectorObject>* color,
1067     const RefPtr<InspectorObject>* outlineColor)
1068 {
1069     Frame* frame = m_pageAgent->frameForId(frameId);
1070     if (frame && frame->ownerElement()) {
1071         m_highlightData = adoptPtr(new HighlightData());
1072         m_highlightData->node = frame->ownerElement();
1073         m_highlightData->showInfo = true; // Always show tooltips for frames.
1074         m_highlightData->content = parseColor(color);
1075         m_highlightData->contentOutline = parseColor(outlineColor);
1076         highlight();
1077     }
1078 }
1079
1080 void InspectorDOMAgent::hideHighlight(ErrorString*)
1081 {
1082     if (m_highlightData) {
1083         m_highlightData->node.clear();
1084         m_highlightData->rect.clear();
1085     }
1086     m_client->hideHighlight();
1087 }
1088
1089 void InspectorDOMAgent::moveTo(ErrorString* errorString, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
1090 {
1091     Node* node = assertEditableNode(errorString, nodeId);
1092     if (!node)
1093         return;
1094
1095     Element* targetElement = assertEditableElement(errorString, targetElementId);
1096     if (!targetElement)
1097         return;
1098
1099     Node* anchorNode = 0;
1100     if (anchorNodeId && *anchorNodeId) {
1101         anchorNode = assertEditableNode(errorString, *anchorNodeId);
1102         if (!anchorNode)
1103             return;
1104         if (anchorNode->parentNode() != targetElement) {
1105             *errorString = "Anchor node must be child of the target element";
1106             return;
1107         }
1108     }
1109
1110     if (!m_domEditor->insertBefore(targetElement, node, anchorNode, errorString))
1111         return;
1112
1113     *newNodeId = pushNodePathToFrontend(node);
1114 }
1115
1116 void InspectorDOMAgent::setTouchEmulationEnabled(ErrorString* error, bool enabled)
1117 {
1118 #if ENABLE(TOUCH_EVENTS)
1119     if (m_state->getBoolean(DOMAgentState::touchEventEmulationEnabled) == enabled)
1120         return;
1121     UNUSED_PARAM(error);
1122     updateTouchEventEmulationInPage(enabled);
1123 #else
1124     *error = "Touch events emulation not supported";
1125     UNUSED_PARAM(enabled);
1126 #endif
1127 }
1128
1129 void InspectorDOMAgent::undo(ErrorString* errorString)
1130 {
1131     ExceptionCode ec = 0;
1132     m_history->undo(ec);
1133     *errorString = InspectorDOMAgent::toErrorString(ec);
1134 }
1135
1136 void InspectorDOMAgent::redo(ErrorString* errorString)
1137 {
1138     ExceptionCode ec = 0;
1139     m_history->redo(ec);
1140     *errorString = InspectorDOMAgent::toErrorString(ec);
1141 }
1142
1143 void InspectorDOMAgent::markUndoableState(ErrorString*)
1144 {
1145     m_history->markUndoableState();
1146 }
1147
1148 void InspectorDOMAgent::resolveNode(ErrorString* error, int nodeId, const String* const objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
1149 {
1150     String objectGroupName = objectGroup ? *objectGroup : "";
1151     Node* node = nodeForId(nodeId);
1152     if (!node) {
1153         *error = "No node with given id found";
1154         return;
1155     }
1156     RefPtr<TypeBuilder::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
1157     if (!object) {
1158         *error = "Node with given id does not belong to the document";
1159         return;
1160     }
1161     result = object;
1162 }
1163
1164 void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<String> >& result)
1165 {
1166     Element* element = assertElement(errorString, nodeId);
1167     if (!element)
1168         return;
1169
1170     result = buildArrayForElementAttributes(element);
1171 }
1172
1173 void InspectorDOMAgent::requestNode(ErrorString*, const String& objectId, int* nodeId)
1174 {
1175     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
1176     Node* node = injectedScript.nodeForObjectId(objectId);
1177     if (node)
1178         *nodeId = pushNodePathToFrontend(node);
1179     else
1180         *nodeId = 0;
1181 }
1182
1183 // static
1184 String InspectorDOMAgent::documentURLString(Document* document)
1185 {
1186     if (!document || document->url().isNull())
1187         return "";
1188     return document->url().string();
1189 }
1190
1191 PassRefPtr<TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
1192 {
1193     int id = bind(node, nodesMap);
1194     String nodeName;
1195     String localName;
1196     String nodeValue;
1197
1198     switch (node->nodeType()) {
1199     case Node::TEXT_NODE:
1200     case Node::COMMENT_NODE:
1201     case Node::CDATA_SECTION_NODE:
1202         nodeValue = node->nodeValue();
1203         if (nodeValue.length() > maxTextSize) {
1204             nodeValue = nodeValue.left(maxTextSize);
1205             nodeValue.append(ellipsisUChar);
1206         }
1207         break;
1208     case Node::ATTRIBUTE_NODE:
1209         localName = node->localName();
1210         break;
1211     case Node::DOCUMENT_FRAGMENT_NODE:
1212     case Node::DOCUMENT_NODE:
1213     case Node::ELEMENT_NODE:
1214     default:
1215         nodeName = node->nodeName();
1216         localName = node->localName();
1217         break;
1218     }
1219
1220     RefPtr<TypeBuilder::DOM::Node> value = TypeBuilder::DOM::Node::create()
1221         .setNodeId(id)
1222         .setNodeType(node->nodeType())
1223         .setNodeName(nodeName)
1224         .setLocalName(localName)
1225         .setNodeValue(nodeValue);
1226
1227     if (node->isContainerNode()) {
1228         int nodeCount = innerChildNodeCount(node);
1229         value->setChildNodeCount(nodeCount);
1230         RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodesMap);
1231         if (children->length() > 0)
1232             value->setChildren(children.release());
1233     }
1234
1235     if (node->isElementNode()) {
1236         Element* element = static_cast<Element*>(node);
1237         value->setAttributes(buildArrayForElementAttributes(element));
1238         if (node->isFrameOwnerElement()) {
1239             HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
1240             Document* doc = frameOwner->contentDocument();
1241             if (doc)
1242                 value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
1243         }
1244
1245         ElementShadow* shadow = element->shadow();
1246         if (shadow) {
1247             RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > shadowRoots = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
1248             for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
1249                 shadowRoots->addItem(buildObjectForNode(root, 0, nodesMap));
1250             value->setShadowRoots(shadowRoots);
1251         }
1252     } else if (node->isDocumentNode()) {
1253         Document* document = static_cast<Document*>(node);
1254         value->setDocumentURL(documentURLString(document));
1255         value->setXmlVersion(document->xmlVersion());
1256     } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1257         DocumentType* docType = static_cast<DocumentType*>(node);
1258         value->setPublicId(docType->publicId());
1259         value->setSystemId(docType->systemId());
1260         value->setInternalSubset(docType->internalSubset());
1261     } else if (node->isAttributeNode()) {
1262         Attr* attribute = static_cast<Attr*>(node);
1263         value->setName(attribute->name());
1264         value->setValue(attribute->value());
1265     }
1266     return value.release();
1267 }
1268
1269 PassRefPtr<TypeBuilder::Array<String> > InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
1270 {
1271     RefPtr<TypeBuilder::Array<String> > attributesValue = TypeBuilder::Array<String>::create();
1272     // Go through all attributes and serialize them.
1273     if (!element->hasAttributes())
1274         return attributesValue.release();
1275     unsigned numAttrs = element->attributeCount();
1276     for (unsigned i = 0; i < numAttrs; ++i) {
1277         // Add attribute pair
1278         const Attribute* attribute = element->attributeItem(i);
1279         attributesValue->addItem(attribute->name().toString());
1280         attributesValue->addItem(attribute->value());
1281     }
1282     return attributesValue.release();
1283 }
1284
1285 PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
1286 {
1287     RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
1288     Node* child = innerFirstChild(container);
1289
1290     if (depth == 0) {
1291         // Special-case the only text child - pretend that container's children have been requested.
1292         if (child && child->nodeType() == Node::TEXT_NODE && !innerNextSibling(child))
1293             return buildArrayForContainerChildren(container, 1, nodesMap);
1294         return children.release();
1295     }
1296
1297     depth--;
1298     m_childrenRequested.add(bind(container, nodesMap));
1299
1300     while (child) {
1301         children->addItem(buildObjectForNode(child, depth, nodesMap));
1302         child = innerNextSibling(child);
1303     }
1304     return children.release();
1305 }
1306
1307 PassRefPtr<TypeBuilder::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node)
1308 {
1309     RefPtr<EventListener> eventListener = registeredEventListener.listener;
1310     RefPtr<TypeBuilder::DOM::EventListener> value = TypeBuilder::DOM::EventListener::create()
1311         .setType(eventType)
1312         .setUseCapture(registeredEventListener.useCapture)
1313         .setIsAttribute(eventListener->isAttribute())
1314         .setNodeId(pushNodePathToFrontend(node))
1315         .setHandlerBody(eventListenerHandlerBody(node->document(), eventListener.get()));
1316     String sourceName;
1317     int lineNumber;
1318     if (eventListenerHandlerLocation(node->document(), eventListener.get(), sourceName, lineNumber)) {
1319         RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
1320             .setScriptId(sourceName)
1321             .setLineNumber(lineNumber);
1322         value->setLocation(location);
1323     }
1324     return value.release();
1325 }
1326
1327 Node* InspectorDOMAgent::innerFirstChild(Node* node)
1328 {
1329     node = node->firstChild();
1330     while (isWhitespace(node))
1331         node = node->nextSibling();
1332     return node;
1333 }
1334
1335 Node* InspectorDOMAgent::innerNextSibling(Node* node)
1336 {
1337     do {
1338         node = node->nextSibling();
1339     } while (isWhitespace(node));
1340     return node;
1341 }
1342
1343 Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
1344 {
1345     do {
1346         node = node->previousSibling();
1347     } while (isWhitespace(node));
1348     return node;
1349 }
1350
1351 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
1352 {
1353     unsigned count = 0;
1354     Node* child = innerFirstChild(node);
1355     while (child) {
1356         count++;
1357         child = innerNextSibling(child);
1358     }
1359     return count;
1360 }
1361
1362 Node* InspectorDOMAgent::innerParentNode(Node* node)
1363 {
1364     if (node->isDocumentNode()) {
1365         Document* document = static_cast<Document*>(node);
1366         return document->ownerElement();
1367     }
1368     return node->parentNode();
1369 }
1370
1371 bool InspectorDOMAgent::isWhitespace(Node* node)
1372 {
1373     //TODO: pull ignoreWhitespace setting from the frontend and use here.
1374     return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
1375 }
1376
1377 void InspectorDOMAgent::mainFrameDOMContentLoaded()
1378 {
1379     // Re-push document once it is loaded.
1380     discardBindings();
1381     if (m_state->getBoolean(DOMAgentState::documentRequested))
1382         m_frontend->documentUpdated();
1383 }
1384
1385 void InspectorDOMAgent::loadEventFired(Document* document)
1386 {
1387     Element* frameOwner = document->ownerElement();
1388     if (!frameOwner)
1389         return;
1390
1391     int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
1392     if (!frameOwnerId)
1393         return;
1394
1395     // Re-add frame owner element together with its new children.
1396     int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
1397     m_frontend->childNodeRemoved(parentId, frameOwnerId);
1398     unbind(frameOwner, &m_documentNodeToIdMap);
1399
1400     RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
1401     Node* previousSibling = innerPreviousSibling(frameOwner);
1402     int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
1403     m_frontend->childNodeInserted(parentId, prevId, value.release());
1404 }
1405
1406 void InspectorDOMAgent::didInsertDOMNode(Node* node)
1407 {
1408     if (isWhitespace(node))
1409         return;
1410
1411     // We could be attaching existing subtree. Forget the bindings.
1412     unbind(node, &m_documentNodeToIdMap);
1413
1414     ContainerNode* parent = node->parentNode();
1415     if (!parent)
1416         return;
1417
1418     int parentId = m_documentNodeToIdMap.get(parent);
1419     // Return if parent is not mapped yet.
1420     if (!parentId)
1421         return;
1422
1423     if (!m_childrenRequested.contains(parentId)) {
1424         // No children are mapped yet -> only notify on changes of hasChildren.
1425         m_frontend->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
1426     } else {
1427         // Children have been requested -> return value of a new child.
1428         Node* prevSibling = innerPreviousSibling(node);
1429         int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
1430         RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
1431         m_frontend->childNodeInserted(parentId, prevId, value.release());
1432     }
1433 }
1434
1435 void InspectorDOMAgent::didRemoveDOMNode(Node* node)
1436 {
1437     if (isWhitespace(node))
1438         return;
1439
1440     ContainerNode* parent = node->parentNode();
1441
1442     // If parent is not mapped yet -> ignore the event.
1443     if (!m_documentNodeToIdMap.contains(parent))
1444         return;
1445
1446     int parentId = m_documentNodeToIdMap.get(parent);
1447
1448     if (m_domListener)
1449         m_domListener->didRemoveDOMNode(node);
1450
1451     if (!m_childrenRequested.contains(parentId)) {
1452         // No children are mapped yet -> only notify on changes of hasChildren.
1453         if (innerChildNodeCount(parent) == 1)
1454             m_frontend->childNodeCountUpdated(parentId, 0);
1455     } else
1456         m_frontend->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
1457     unbind(node, &m_documentNodeToIdMap);
1458 }
1459
1460 void InspectorDOMAgent::willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue)
1461 {
1462     m_suppressAttributeModifiedEvent = (oldValue == newValue);
1463 }
1464
1465 void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
1466 {
1467     bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
1468     m_suppressAttributeModifiedEvent = false;
1469     if (shouldSuppressEvent)
1470         return;
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->attributeModified(id, name, value);
1481 }
1482
1483 void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
1484 {
1485     int id = boundNodeId(element);
1486     // If node is not mapped yet -> ignore the event.
1487     if (!id)
1488         return;
1489
1490     if (m_domListener)
1491         m_domListener->didModifyDOMAttr(element);
1492
1493     m_frontend->attributeRemoved(id, name);
1494 }
1495
1496 void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
1497 {
1498     RefPtr<TypeBuilder::Array<int> > nodeIds = TypeBuilder::Array<int>::create();
1499     for (unsigned i = 0, size = elements.size(); i < size; ++i) {
1500         Element* element = elements.at(i);
1501         int id = boundNodeId(element);
1502         // If node is not mapped yet -> ignore the event.
1503         if (!id)
1504             continue;
1505
1506         if (m_domListener)
1507             m_domListener->didModifyDOMAttr(element);
1508         nodeIds->addItem(id);
1509     }
1510     m_frontend->inlineStyleInvalidated(nodeIds.release());
1511 }
1512
1513 void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
1514 {
1515     int id = m_documentNodeToIdMap.get(characterData);
1516     if (!id)
1517         return;
1518     m_frontend->characterDataModified(id, characterData->data());
1519 }
1520
1521 void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
1522 {
1523     int id = m_documentNodeToIdMap.get(node);
1524     // If node is not mapped yet -> ignore the event.
1525     if (!id)
1526         return;
1527
1528     if (!m_revalidateStyleAttrTask)
1529         m_revalidateStyleAttrTask = adoptPtr(new RevalidateStyleAttributeTask(this));
1530     m_revalidateStyleAttrTask->scheduleFor(static_cast<Element*>(node));
1531 }
1532
1533 void InspectorDOMAgent::didPushShadowRoot(Element* host, ShadowRoot* root)
1534 {
1535     int hostId = m_documentNodeToIdMap.get(host);
1536     if (hostId)
1537         m_frontend->shadowRootPushed(hostId, buildObjectForNode(root, 0, &m_documentNodeToIdMap));
1538 }
1539
1540 void InspectorDOMAgent::willPopShadowRoot(Element* host, ShadowRoot* root)
1541 {
1542     int hostId = m_documentNodeToIdMap.get(host);
1543     int rootId = m_documentNodeToIdMap.get(root);
1544     if (hostId && rootId)
1545         m_frontend->shadowRootPopped(hostId, rootId);
1546 }
1547
1548 Node* InspectorDOMAgent::nodeForPath(const String& path)
1549 {
1550     // The path is of form "1,HTML,2,BODY,1,DIV"
1551     if (!m_document)
1552         return 0;
1553
1554     Node* node = m_document.get();
1555     Vector<String> pathTokens;
1556     path.split(",", false, pathTokens);
1557     if (!pathTokens.size())
1558         return 0;
1559     for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
1560         bool success = true;
1561         unsigned childNumber = pathTokens[i].toUInt(&success);
1562         if (!success)
1563             return 0;
1564         if (childNumber >= innerChildNodeCount(node))
1565             return 0;
1566
1567         Node* child = innerFirstChild(node);
1568         String childName = pathTokens[i + 1];
1569         for (size_t j = 0; child && j < childNumber; ++j)
1570             child = innerNextSibling(child);
1571
1572         if (!child || child->nodeName() != childName)
1573             return 0;
1574         node = child;
1575     }
1576     return node;
1577 }
1578
1579 void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString* errorString, const String& path, int* nodeId)
1580 {
1581     if (Node* node = nodeForPath(path))
1582         *nodeId = pushNodePathToFrontend(node);
1583     else
1584         *errorString = "No node with given path found";
1585 }
1586
1587 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
1588 {
1589     Document* document = node->isDocumentNode() ? node->document() : node->ownerDocument();
1590     Frame* frame = document ? document->frame() : 0;
1591     if (!frame)
1592         return 0;
1593
1594     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
1595     if (injectedScript.hasNoValue())
1596         return 0;
1597
1598     return injectedScript.wrapNode(node, objectGroup);
1599 }
1600
1601 void InspectorDOMAgent::drawHighlight(GraphicsContext& context) const
1602 {
1603     if (!m_highlightData)
1604         return;
1605
1606     DOMNodeHighlighter::drawHighlight(context, m_highlightData->node ? m_highlightData->node->document() : m_document.get(), m_highlightData.get());
1607 }
1608
1609 void InspectorDOMAgent::getHighlight(Highlight* highlight) const
1610 {
1611     if (!m_highlightData)
1612         return;
1613
1614     DOMNodeHighlighter::getHighlight(m_highlightData->node ? m_highlightData->node->document() : m_document.get(), m_highlightData.get(), highlight);
1615 }
1616
1617 } // namespace WebCore
1618
1619 #endif // ENABLE(INSPECTOR)