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