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