5c3e094f1f9f3427404df4de9c1b9b932765487d
[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 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 "AXObjectCache.h"
38 #include "AccessibilityNodeObject.h"
39 #include "Attr.h"
40 #include "CSSComputedStyleDeclaration.h"
41 #include "CSSPropertyNames.h"
42 #include "CSSPropertySourceData.h"
43 #include "CSSRule.h"
44 #include "CSSRuleList.h"
45 #include "CSSStyleRule.h"
46 #include "CSSStyleSheet.h"
47 #include "CharacterData.h"
48 #include "ContainerNode.h"
49 #include "Cookie.h"
50 #include "CookieJar.h"
51 #include "DOMEditor.h"
52 #include "DOMPatchSupport.h"
53 #include "DOMWindow.h"
54 #include "Document.h"
55 #include "DocumentFragment.h"
56 #include "DocumentType.h"
57 #include "Element.h"
58 #include "Event.h"
59 #include "EventListener.h"
60 #include "EventNames.h"
61 #include "ExceptionCodeDescription.h"
62 #include "FrameTree.h"
63 #include "HTMLElement.h"
64 #include "HTMLFrameOwnerElement.h"
65 #include "HTMLNames.h"
66 #include "HTMLTemplateElement.h"
67 #include "HitTestResult.h"
68 #include "InspectorHistory.h"
69 #include "InspectorNodeFinder.h"
70 #include "InspectorPageAgent.h"
71 #include "InstrumentingAgents.h"
72 #include "IntRect.h"
73 #include "JSEventListener.h"
74 #include "JSNode.h"
75 #include "MainFrame.h"
76 #include "MutationEvent.h"
77 #include "Node.h"
78 #include "NodeList.h"
79 #include "Page.h"
80 #include "Pasteboard.h"
81 #include "RenderStyle.h"
82 #include "RenderStyleConstants.h"
83 #include "ScriptState.h"
84 #include "Settings.h"
85 #include "ShadowRoot.h"
86 #include "StyleProperties.h"
87 #include "StyleResolver.h"
88 #include "StyleSheetList.h"
89 #include "Text.h"
90 #include "XPathResult.h"
91 #include "htmlediting.h"
92 #include "markup.h"
93 #include <inspector/IdentifiersFactory.h>
94 #include <inspector/InjectedScript.h>
95 #include <inspector/InjectedScriptManager.h>
96 #include <runtime/JSCInlines.h>
97 #include <wtf/text/CString.h>
98 #include <wtf/text/WTFString.h>
99
100 using namespace Inspector;
101
102 namespace WebCore {
103
104 using namespace HTMLNames;
105
106 static const size_t maxTextSize = 10000;
107 static const UChar ellipsisUChar[] = { 0x2026, 0 };
108
109 static Color parseColor(const PassRefPtr<InspectorObject> colorObject)
110 {
111     if (!colorObject)
112         return Color::transparent;
113
114     int r;
115     int g;
116     int b;
117     if (!colorObject->getInteger("r", r) || !colorObject->getInteger("g", g) || !colorObject->getInteger("b", b))
118         return Color::transparent;
119
120     double a;
121     if (!colorObject->getDouble("a", a))
122         return Color(r, g, b);
123
124     // Clamp alpha to the [0..1] range.
125     if (a < 0)
126         a = 0;
127     else if (a > 1)
128         a = 1;
129
130     return Color(r, g, b, static_cast<int>(a * 255));
131 }
132
133 static Color parseConfigColor(const String& fieldName, InspectorObject* configObject)
134 {
135     const RefPtr<InspectorObject> colorObject = configObject->getObject(fieldName);
136     return parseColor(colorObject);
137 }
138
139 static bool parseQuad(const RefPtr<InspectorArray>& quadArray, FloatQuad* quad)
140 {
141     if (!quadArray)
142         return false;
143     const size_t coordinatesInQuad = 8;
144     double coordinates[coordinatesInQuad];
145     if (quadArray->length() != coordinatesInQuad)
146         return false;
147     for (size_t i = 0; i < coordinatesInQuad; ++i) {
148         if (!quadArray->get(i)->asDouble(*(coordinates + i)))
149             return false;
150     }
151     quad->setP1(FloatPoint(coordinates[0], coordinates[1]));
152     quad->setP2(FloatPoint(coordinates[2], coordinates[3]));
153     quad->setP3(FloatPoint(coordinates[4], coordinates[5]));
154     quad->setP4(FloatPoint(coordinates[6], coordinates[7]));
155
156     return true;
157 }
158
159 class RevalidateStyleAttributeTask {
160     WTF_MAKE_FAST_ALLOCATED;
161 public:
162     RevalidateStyleAttributeTask(InspectorDOMAgent*);
163     void scheduleFor(Element*);
164     void reset() { m_timer.stop(); }
165     void timerFired(Timer<RevalidateStyleAttributeTask>&);
166
167 private:
168     InspectorDOMAgent* m_domAgent;
169     Timer<RevalidateStyleAttributeTask> m_timer;
170     HashSet<RefPtr<Element>> m_elements;
171 };
172
173 RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
174     : m_domAgent(domAgent)
175     , m_timer(this, &RevalidateStyleAttributeTask::timerFired)
176 {
177 }
178
179 void RevalidateStyleAttributeTask::scheduleFor(Element* element)
180 {
181     m_elements.add(element);
182     if (!m_timer.isActive())
183         m_timer.startOneShot(0);
184 }
185
186 void RevalidateStyleAttributeTask::timerFired(Timer<RevalidateStyleAttributeTask>&)
187 {
188     // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
189     Vector<Element*> elements;
190     for (HashSet<RefPtr<Element>>::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
191         elements.append(it->get());
192     m_domAgent->styleAttributeInvalidated(elements);
193
194     m_elements.clear();
195 }
196
197 String InspectorDOMAgent::toErrorString(const ExceptionCode& ec)
198 {
199     if (ec) {
200         ExceptionCodeDescription description(ec);
201         return description.name;
202     }
203     return "";
204 }
205
206 InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay)
207     : InspectorAgentBase(ASCIILiteral("DOM"), instrumentingAgents)
208     , m_pageAgent(pageAgent)
209     , m_injectedScriptManager(injectedScriptManager)
210     , m_overlay(overlay)
211     , m_domListener(0)
212     , m_lastNodeId(1)
213     , m_lastBackendNodeId(-1)
214     , m_searchingForNode(false)
215     , m_suppressAttributeModifiedEvent(false)
216     , m_documentRequested(false)
217 {
218 }
219
220 InspectorDOMAgent::~InspectorDOMAgent()
221 {
222     reset();
223     ASSERT(!m_searchingForNode);
224 }
225
226 void InspectorDOMAgent::didCreateFrontendAndBackend(InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher)
227 {
228     m_frontendDispatcher = std::make_unique<InspectorDOMFrontendDispatcher>(frontendChannel);
229     m_backendDispatcher = InspectorDOMBackendDispatcher::create(backendDispatcher, this);
230
231     m_history = std::make_unique<InspectorHistory>();
232     m_domEditor = std::make_unique<DOMEditor>(m_history.get());
233
234     m_instrumentingAgents->setInspectorDOMAgent(this);
235     m_document = m_pageAgent->mainFrame()->document();
236
237     if (m_nodeToFocus)
238         focusNode();
239 }
240
241 void InspectorDOMAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason)
242 {
243     m_frontendDispatcher = nullptr;
244     m_backendDispatcher.clear();
245
246     m_history.reset();
247     m_domEditor.reset();
248
249     ErrorString unused;
250     setSearchingForNode(unused, false, 0);
251     hideHighlight(unused);
252
253     m_instrumentingAgents->setInspectorDOMAgent(0);
254     m_documentRequested = false;
255     reset();
256 }
257
258 Vector<Document*> InspectorDOMAgent::documents()
259 {
260     Vector<Document*> result;
261     for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
262         Document* document = frame->document();
263         if (!document)
264             continue;
265         result.append(document);
266     }
267     return result;
268 }
269
270 void InspectorDOMAgent::reset()
271 {
272     if (m_history)
273         m_history->reset();
274     m_searchResults.clear();
275     discardBindings();
276     if (m_revalidateStyleAttrTask)
277         m_revalidateStyleAttrTask->reset();
278     m_document = 0;
279 }
280
281 void InspectorDOMAgent::setDOMListener(DOMListener* listener)
282 {
283     m_domListener = listener;
284 }
285
286 void InspectorDOMAgent::setDocument(Document* doc)
287 {
288     if (doc == m_document.get())
289         return;
290
291     reset();
292
293     m_document = doc;
294
295     if (!m_documentRequested)
296         return;
297
298     // Immediately communicate 0 document or document that has finished loading.
299     if (!doc || !doc->parsing())
300         m_frontendDispatcher->documentUpdated();
301 }
302
303 void InspectorDOMAgent::releaseDanglingNodes()
304 {
305     m_danglingNodeToIdMaps.clear();
306 }
307
308 int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
309 {
310     int id = nodesMap->get(node);
311     if (id)
312         return id;
313     id = m_lastNodeId++;
314     nodesMap->set(node, id);
315     m_idToNode.set(id, node);
316     m_idToNodesMap.set(id, nodesMap);
317     return id;
318 }
319
320 void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
321 {
322     int id = nodesMap->get(node);
323     if (!id)
324         return;
325
326     m_idToNode.remove(id);
327
328     if (node->isFrameOwnerElement()) {
329         const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
330         Document* contentDocument = frameOwner->contentDocument();
331         if (m_domListener)
332             m_domListener->didRemoveDocument(contentDocument);
333         if (contentDocument)
334             unbind(contentDocument, nodesMap);
335     }
336
337     if (is<Element>(*node)) {
338         if (ShadowRoot* root = downcast<Element>(*node).shadowRoot())
339             unbind(root, nodesMap);
340     }
341
342     nodesMap->remove(node);
343     if (m_domListener)
344         m_domListener->didRemoveDOMNode(node);
345
346     bool childrenRequested = m_childrenRequested.contains(id);
347     if (childrenRequested) {
348         // Unbind subtree known to client recursively.
349         m_childrenRequested.remove(id);
350         Node* child = innerFirstChild(node);
351         while (child) {
352             unbind(child, nodesMap);
353             child = innerNextSibling(child);
354         }
355     }
356 }
357
358 Node* InspectorDOMAgent::assertNode(ErrorString& errorString, int nodeId)
359 {
360     Node* node = nodeForId(nodeId);
361     if (!node) {
362         errorString = ASCIILiteral("Could not find node with given id");
363         return nullptr;
364     }
365     return node;
366 }
367
368 Document* InspectorDOMAgent::assertDocument(ErrorString& errorString, int nodeId)
369 {
370     Node* node = assertNode(errorString, nodeId);
371     if (!node)
372         return nullptr;
373     if (!is<Document>(*node)) {
374         errorString = ASCIILiteral("Document is not available");
375         return nullptr;
376     }
377     return downcast<Document>(node);
378 }
379
380 Element* InspectorDOMAgent::assertElement(ErrorString& errorString, int nodeId)
381 {
382     Node* node = assertNode(errorString, nodeId);
383     if (!node)
384         return nullptr;
385     if (!is<Element>(*node)) {
386         errorString = ASCIILiteral("Node is not an Element");
387         return nullptr;
388     }
389     return downcast<Element>(node);
390 }
391
392 Node* InspectorDOMAgent::assertEditableNode(ErrorString& errorString, int nodeId)
393 {
394     Node* node = assertNode(errorString, nodeId);
395     if (!node)
396         return nullptr;
397     if (node->isInShadowTree()) {
398         errorString = ASCIILiteral("Can not edit nodes from shadow trees");
399         return nullptr;
400     }
401     return node;
402 }
403
404 Element* InspectorDOMAgent::assertEditableElement(ErrorString& errorString, int nodeId)
405 {
406     Element* element = assertElement(errorString, nodeId);
407     if (!element)
408         return nullptr;
409     if (element->isInShadowTree()) {
410         errorString = ASCIILiteral("Can not edit elements from shadow trees");
411         return nullptr;
412     }
413     return element;
414 }
415
416 void InspectorDOMAgent::getDocument(ErrorString& errorString, RefPtr<Inspector::Protocol::DOM::Node>& root)
417 {
418     m_documentRequested = true;
419
420     if (!m_document) {
421         errorString = ASCIILiteral("Document is not available");
422         return;
423     }
424
425     // Reset backend state.
426     RefPtr<Document> document = m_document;
427     reset();
428     m_document = document;
429
430     root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
431 }
432
433 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth)
434 {
435     Node* node = nodeForId(nodeId);
436     if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
437         return;
438
439     NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
440
441     if (m_childrenRequested.contains(nodeId)) {
442         if (depth <= 1)
443             return;
444
445         depth--;
446
447         for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
448             int childNodeId = nodeMap->get(node);
449             ASSERT(childNodeId);
450             pushChildNodesToFrontend(childNodeId, depth);
451         }
452
453         return;
454     }
455
456     RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> children = buildArrayForContainerChildren(node, depth, nodeMap);
457     m_frontendDispatcher->setChildNodes(nodeId, children.release());
458 }
459
460 void InspectorDOMAgent::discardBindings()
461 {
462     m_documentNodeToIdMap.clear();
463     m_idToNode.clear();
464     releaseDanglingNodes();
465     m_childrenRequested.clear();
466     m_backendIdToNode.clear();
467     m_nodeGroupToBackendIdMap.clear();
468 }
469
470 int InspectorDOMAgent::pushNodeToFrontend(ErrorString& errorString, int documentNodeId, Node* nodeToPush)
471 {
472     Document* document = assertDocument(errorString, documentNodeId);
473     if (!document)
474         return 0;
475     if (&nodeToPush->document() != document) {
476         errorString = ASCIILiteral("Node is not part of the document with given id");
477         return 0;
478     }
479
480     return pushNodePathToFrontend(nodeToPush);
481 }
482
483 Node* InspectorDOMAgent::nodeForId(int id)
484 {
485     if (!id)
486         return 0;
487
488     HashMap<int, Node*>::iterator it = m_idToNode.find(id);
489     if (it != m_idToNode.end())
490         return it->value;
491     return 0;
492 }
493
494 void InspectorDOMAgent::requestChildNodes(ErrorString& errorString, int nodeId, const int* depth)
495 {
496     int sanitizedDepth;
497
498     if (!depth)
499         sanitizedDepth = 1;
500     else if (*depth == -1)
501         sanitizedDepth = INT_MAX;
502     else if (*depth > 0)
503         sanitizedDepth = *depth;
504     else {
505         errorString = ASCIILiteral("Please provide a positive integer as a depth or -1 for entire subtree");
506         return;
507     }
508
509     pushChildNodesToFrontend(nodeId, sanitizedDepth);
510 }
511
512 void InspectorDOMAgent::querySelector(ErrorString& errorString, int nodeId, const String& selectors, int* elementId)
513 {
514     *elementId = 0;
515     Node* node = assertNode(errorString, nodeId);
516     if (!node)
517         return;
518     if (!is<ContainerNode>(*node)) {
519         assertElement(errorString, nodeId);
520         return;
521     }
522
523     ExceptionCode ec = 0;
524     RefPtr<Element> element = downcast<ContainerNode>(*node).querySelector(selectors, ec);
525     if (ec) {
526         errorString = ASCIILiteral("DOM Error while querying");
527         return;
528     }
529
530     if (element)
531         *elementId = pushNodePathToFrontend(element.get());
532 }
533
534 void InspectorDOMAgent::querySelectorAll(ErrorString& errorString, int nodeId, const String& selectors, RefPtr<Inspector::Protocol::Array<int>>& result)
535 {
536     Node* node = assertNode(errorString, nodeId);
537     if (!node)
538         return;
539     if (!is<ContainerNode>(*node)) {
540         assertElement(errorString, nodeId);
541         return;
542     }
543
544     ExceptionCode ec = 0;
545     RefPtr<NodeList> nodes = downcast<ContainerNode>(*node).querySelectorAll(selectors, ec);
546     if (ec) {
547         errorString = ASCIILiteral("DOM Error while querying");
548         return;
549     }
550
551     result = Inspector::Protocol::Array<int>::create();
552
553     for (unsigned i = 0; i < nodes->length(); ++i)
554         result->addItem(pushNodePathToFrontend(nodes->item(i)));
555 }
556
557 int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
558 {
559     ASSERT(nodeToPush);  // Invalid input
560
561     if (!m_document)
562         return 0;
563     if (!m_documentNodeToIdMap.contains(m_document))
564         return 0;
565
566     // Return id in case the node is known.
567     int result = m_documentNodeToIdMap.get(nodeToPush);
568     if (result)
569         return result;
570
571     Node* node = nodeToPush;
572     Vector<Node*> path;
573     NodeToIdMap* danglingMap = 0;
574
575     while (true) {
576         Node* parent = innerParentNode(node);
577         if (!parent) {
578             // Node being pushed is detached -> push subtree root.
579             auto newMap = std::make_unique<NodeToIdMap>();
580             danglingMap = newMap.get();
581             m_danglingNodeToIdMaps.append(newMap.release());
582             RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> children = Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>::create();
583             children->addItem(buildObjectForNode(node, 0, danglingMap));
584             m_frontendDispatcher->setChildNodes(0, children);
585             break;
586         } else {
587             path.append(parent);
588             if (m_documentNodeToIdMap.get(parent))
589                 break;
590             else
591                 node = parent;
592         }
593     }
594
595     NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
596     for (int i = path.size() - 1; i >= 0; --i) {
597         int nodeId = map->get(path.at(i));
598         ASSERT(nodeId);
599         pushChildNodesToFrontend(nodeId);
600     }
601     return map->get(nodeToPush);
602 }
603
604 int InspectorDOMAgent::boundNodeId(Node* node)
605 {
606     return m_documentNodeToIdMap.get(node);
607 }
608
609 BackendNodeId InspectorDOMAgent::backendNodeIdForNode(Node* node, const String& nodeGroup)
610 {
611     if (!node)
612         return 0;
613
614     if (!m_nodeGroupToBackendIdMap.contains(nodeGroup))
615         m_nodeGroupToBackendIdMap.set(nodeGroup, NodeToBackendIdMap());
616
617     NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
618     BackendNodeId id = map.get(node);
619     if (!id) {
620         id = --m_lastBackendNodeId;
621         map.set(node, id);
622         m_backendIdToNode.set(id, std::make_pair(node, nodeGroup));
623     }
624
625     return id;
626 }
627
628 void InspectorDOMAgent::releaseBackendNodeIds(ErrorString& errorString, const String& nodeGroup)
629 {
630     if (m_nodeGroupToBackendIdMap.contains(nodeGroup)) {
631         NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
632         for (NodeToBackendIdMap::iterator it = map.begin(); it != map.end(); ++it)
633             m_backendIdToNode.remove(it->value);
634         m_nodeGroupToBackendIdMap.remove(nodeGroup);
635         return;
636     }
637     errorString = ASCIILiteral("Group name not found");
638 }
639
640 void InspectorDOMAgent::setAttributeValue(ErrorString& errorString, int elementId, const String& name, const String& value)
641 {
642     Element* element = assertEditableElement(errorString, elementId);
643     if (!element)
644         return;
645
646     m_domEditor->setAttribute(element, name, value, errorString);
647 }
648
649 void InspectorDOMAgent::setAttributesAsText(ErrorString& errorString, int elementId, const String& text, const String* const name)
650 {
651     Element* element = assertEditableElement(errorString, elementId);
652     if (!element)
653         return;
654
655     RefPtr<HTMLElement> parsedElement = createHTMLElement(element->document(), spanTag);
656     ExceptionCode ec = 0;
657     parsedElement.get()->setInnerHTML("<span " + text + "></span>", ec);
658     if (ec) {
659         errorString = InspectorDOMAgent::toErrorString(ec);
660         return;
661     }
662
663     Node* child = parsedElement->firstChild();
664     if (!child) {
665         errorString = ASCIILiteral("Could not parse value as attributes");
666         return;
667     }
668
669     Element* childElement = downcast<Element>(child);
670     if (!childElement->hasAttributes() && name) {
671         m_domEditor->removeAttribute(element, *name, errorString);
672         return;
673     }
674
675     bool foundOriginalAttribute = false;
676     for (const Attribute& attribute : childElement->attributesIterator()) {
677         // Add attribute pair
678         foundOriginalAttribute = foundOriginalAttribute || (name && attribute.name().toString() == *name);
679         if (!m_domEditor->setAttribute(element, attribute.name().toString(), attribute.value(), errorString))
680             return;
681     }
682
683     if (!foundOriginalAttribute && name && !name->stripWhiteSpace().isEmpty())
684         m_domEditor->removeAttribute(element, *name, errorString);
685 }
686
687 void InspectorDOMAgent::removeAttribute(ErrorString& errorString, int elementId, const String& name)
688 {
689     Element* element = assertEditableElement(errorString, elementId);
690     if (!element)
691         return;
692
693     m_domEditor->removeAttribute(element, name, errorString);
694 }
695
696 void InspectorDOMAgent::removeNode(ErrorString& errorString, int nodeId)
697 {
698     Node* node = assertEditableNode(errorString, nodeId);
699     if (!node)
700         return;
701
702     ContainerNode* parentNode = node->parentNode();
703     if (!parentNode) {
704         errorString = ASCIILiteral("Can not remove detached node");
705         return;
706     }
707
708     m_domEditor->removeChild(parentNode, node, errorString);
709 }
710
711 void InspectorDOMAgent::setNodeName(ErrorString& errorString, int nodeId, const String& tagName, int* newId)
712 {
713     *newId = 0;
714
715     Node* oldNode = nodeForId(nodeId);
716     if (!is<Element>(oldNode))
717         return;
718
719     ExceptionCode ec = 0;
720     RefPtr<Element> newElem = oldNode->document().createElement(tagName, ec);
721     if (ec)
722         return;
723
724     // Copy over the original node's attributes.
725     newElem->cloneAttributesFromElement(*downcast<Element>(oldNode));
726
727     // Copy over the original node's children.
728     Node* child;
729     while ((child = oldNode->firstChild())) {
730         if (!m_domEditor->insertBefore(newElem.get(), child, 0, errorString))
731             return;
732     }
733
734     // Replace the old node with the new node
735     ContainerNode* parent = oldNode->parentNode();
736     if (!m_domEditor->insertBefore(parent, newElem.get(), oldNode->nextSibling(), errorString))
737         return;
738     if (!m_domEditor->removeChild(parent, oldNode, errorString))
739         return;
740
741     *newId = pushNodePathToFrontend(newElem.get());
742     if (m_childrenRequested.contains(nodeId))
743         pushChildNodesToFrontend(*newId);
744 }
745
746 void InspectorDOMAgent::getOuterHTML(ErrorString& errorString, int nodeId, WTF::String* outerHTML)
747 {
748     Node* node = assertNode(errorString, nodeId);
749     if (!node)
750         return;
751
752     *outerHTML = createMarkup(*node);
753 }
754
755 void InspectorDOMAgent::setOuterHTML(ErrorString& errorString, int nodeId, const String& outerHTML)
756 {
757     if (!nodeId) {
758         DOMPatchSupport domPatchSupport(m_domEditor.get(), m_document.get());
759         domPatchSupport.patchDocument(outerHTML);
760         return;
761     }
762
763     Node* node = assertEditableNode(errorString, nodeId);
764     if (!node)
765         return;
766
767     Document& document = node->document();
768     if (!document.isHTMLDocument() && !document.isXHTMLDocument() && !document.isSVGDocument()) {
769         errorString = ASCIILiteral("Not an HTML/XML document");
770         return;
771     }
772
773     Node* newNode = 0;
774     if (!m_domEditor->setOuterHTML(*node, outerHTML, &newNode, errorString))
775         return;
776
777     if (!newNode) {
778         // The only child node has been deleted.
779         return;
780     }
781
782     int newId = pushNodePathToFrontend(newNode);
783
784     bool childrenRequested = m_childrenRequested.contains(nodeId);
785     if (childrenRequested)
786         pushChildNodesToFrontend(newId);
787 }
788
789 void InspectorDOMAgent::setNodeValue(ErrorString& errorString, int nodeId, const String& value)
790 {
791     Node* node = assertEditableNode(errorString, nodeId);
792     if (!node)
793         return;
794
795     if (node->nodeType() != Node::TEXT_NODE) {
796         errorString = ASCIILiteral("Can only set value of text nodes");
797         return;
798     }
799
800     m_domEditor->replaceWholeText(downcast<Text>(node), value, errorString);
801 }
802
803 void InspectorDOMAgent::getEventListenersForNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::EventListener>>& listenersArray)
804 {
805     listenersArray = Inspector::Protocol::Array<Inspector::Protocol::DOM::EventListener>::create();
806     Node* node = assertNode(errorString, nodeId);
807     if (!node)
808         return;
809     Vector<EventListenerInfo> eventInformation;
810     getEventListeners(node, eventInformation, true);
811
812     // Get Capturing Listeners (in this order)
813     size_t eventInformationLength = eventInformation.size();
814     for (size_t i = 0; i < eventInformationLength; ++i) {
815         const EventListenerInfo& info = eventInformation[i];
816         const EventListenerVector& vector = info.eventListenerVector;
817         for (size_t j = 0; j < vector.size(); ++j) {
818             const RegisteredEventListener& listener = vector[j];
819             if (listener.useCapture)
820                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
821         }
822     }
823
824     // Get Bubbling Listeners (reverse order)
825     for (size_t i = eventInformationLength; i; --i) {
826         const EventListenerInfo& info = eventInformation[i - 1];
827         const EventListenerVector& vector = info.eventListenerVector;
828         for (size_t j = 0; j < vector.size(); ++j) {
829             const RegisteredEventListener& listener = vector[j];
830             if (!listener.useCapture)
831                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
832         }
833     }
834 }
835
836 void InspectorDOMAgent::getEventListeners(Node* node, Vector<EventListenerInfo>& eventInformation, bool includeAncestors)
837 {
838     // The Node's Ancestors including self.
839     Vector<Node*> ancestors;
840     // Push this node as the firs element.
841     ancestors.append(node);
842     if (includeAncestors) {
843         for (ContainerNode* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
844             ancestors.append(ancestor);
845     }
846
847     // Nodes and their Listeners for the concerned event types (order is top to bottom)
848     for (size_t i = ancestors.size(); i; --i) {
849         Node* ancestor = ancestors[i - 1];
850         EventTargetData* d = ancestor->eventTargetData();
851         if (!d)
852             continue;
853         // Get the list of event types this Node is concerned with
854         Vector<AtomicString> eventTypes = d->eventListenerMap.eventTypes();
855         for (size_t j = 0; j < eventTypes.size(); ++j) {
856             AtomicString& type = eventTypes[j];
857             const EventListenerVector& listeners = ancestor->getEventListeners(type);
858             EventListenerVector filteredListeners;
859             filteredListeners.reserveCapacity(listeners.size());
860             for (size_t k = 0; k < listeners.size(); ++k) {
861                 if (listeners[k].listener->type() == EventListener::JSEventListenerType)
862                     filteredListeners.append(listeners[k]);
863             }
864             if (!filteredListeners.isEmpty())
865                 eventInformation.append(EventListenerInfo(ancestor, type, filteredListeners));
866         }
867     }
868 }
869
870 void InspectorDOMAgent::getAccessibilityPropertiesForNode(ErrorString& errorString, int nodeId, RefPtr<Inspector::Protocol::DOM::AccessibilityProperties>& axProperties)
871 {
872     Node* node = assertNode(errorString, nodeId);
873     if (!node)
874         return;
875
876     axProperties = buildObjectForAccessibilityProperties(node);
877 }
878
879 void InspectorDOMAgent::performSearch(ErrorString& errorString, const String& whitespaceTrimmedQuery, const RefPtr<InspectorArray>* nodeIds, String* searchId, int* resultCount)
880 {
881     // FIXME: Search works with node granularity - number of matches within node is not calculated.
882     InspectorNodeFinder finder(whitespaceTrimmedQuery);
883
884     if (nodeIds) {
885         const RefPtr<InspectorArray>& nodeIdsRef = *nodeIds;
886         for (unsigned i = 0; i < nodeIdsRef->length(); ++i) {
887             RefPtr<InspectorValue> nodeValue = nodeIdsRef->get(i);
888             if (!nodeValue) {
889                 errorString = ASCIILiteral("Invalid nodeIds item.");
890                 return;
891             }
892             int nodeId = 0;
893             if (!nodeValue->asInteger(nodeId)) {
894                 errorString = ASCIILiteral("Invalid nodeIds item type. Expecting integer types.");
895                 return;
896             }
897             Node* node = assertNode(errorString, nodeId);
898             if (!node) {
899                 // assertNode should have filled the errorString for us.
900                 ASSERT(errorString.length());
901                 return;
902             }
903             finder.performSearch(node);
904         }
905     } else if (m_document) {
906         // There's no need to iterate the frames tree because
907         // the search helper will go inside the frame owner elements.
908         finder.performSearch(m_document.get());
909     }
910
911     *searchId = IdentifiersFactory::createIdentifier();
912
913     auto& resultsVector = m_searchResults.add(*searchId, Vector<RefPtr<Node>>()).iterator->value;
914     for (auto iterator = finder.results().begin(); iterator != finder.results().end(); ++iterator)
915         resultsVector.append(*iterator);
916
917     *resultCount = resultsVector.size();
918 }
919
920 void InspectorDOMAgent::getSearchResults(ErrorString& errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<Inspector::Protocol::Array<int>>& nodeIds)
921 {
922     SearchResults::iterator it = m_searchResults.find(searchId);
923     if (it == m_searchResults.end()) {
924         errorString = ASCIILiteral("No search session with given id found");
925         return;
926     }
927
928     int size = it->value.size();
929     if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
930         errorString = ASCIILiteral("Invalid search result range");
931         return;
932     }
933
934     nodeIds = Inspector::Protocol::Array<int>::create();
935     for (int i = fromIndex; i < toIndex; ++i)
936         nodeIds->addItem(pushNodePathToFrontend((it->value)[i].get()));
937 }
938
939 void InspectorDOMAgent::discardSearchResults(ErrorString&, const String& searchId)
940 {
941     m_searchResults.remove(searchId);
942 }
943
944 bool InspectorDOMAgent::handleMousePress()
945 {
946     if (!m_searchingForNode)
947         return false;
948
949     if (Node* node = m_overlay->highlightedNode()) {
950         inspect(node);
951         return true;
952     }
953     return false;
954 }
955
956 bool InspectorDOMAgent::handleTouchEvent(Node* node)
957 {
958     if (!m_searchingForNode)
959         return false;
960     if (node && m_inspectModeHighlightConfig) {
961         m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
962         inspect(node);
963         return true;
964     }
965     return false;
966 }
967
968 void InspectorDOMAgent::inspect(Node* inspectedNode)
969 {
970     ErrorString unused;
971     RefPtr<Node> node = inspectedNode;
972     setSearchingForNode(unused, false, 0);
973
974     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
975         node = node->parentNode();
976     m_nodeToFocus = node;
977
978     focusNode();
979 }
980
981 void InspectorDOMAgent::focusNode()
982 {
983     if (!m_frontendDispatcher)
984         return;
985
986     ASSERT(m_nodeToFocus);
987
988     RefPtr<Node> node = m_nodeToFocus.get();
989     m_nodeToFocus = 0;
990
991     Frame* frame = node->document().frame();
992     if (!frame)
993         return;
994
995     JSC::ExecState* scriptState = mainWorldExecState(frame);
996     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
997     if (injectedScript.hasNoValue())
998         return;
999
1000     injectedScript.inspectObject(InspectorDOMAgent::nodeAsScriptValue(scriptState, node.get()));
1001 }
1002
1003 void InspectorDOMAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
1004 {
1005     if (!m_searchingForNode)
1006         return;
1007
1008     Node* node = result.innerNode();
1009     while (node && node->nodeType() == Node::TEXT_NODE)
1010         node = node->parentNode();
1011     if (node && m_inspectModeHighlightConfig)
1012         m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
1013 }
1014
1015 void InspectorDOMAgent::setSearchingForNode(ErrorString& errorString, bool enabled, InspectorObject* highlightInspectorObject)
1016 {
1017     if (m_searchingForNode == enabled)
1018         return;
1019     m_searchingForNode = enabled;
1020     if (enabled) {
1021         m_inspectModeHighlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject);
1022         if (!m_inspectModeHighlightConfig)
1023             return;
1024     } else
1025         hideHighlight(errorString);
1026
1027     m_overlay->didSetSearchingForNode(m_searchingForNode);
1028 }
1029
1030 std::unique_ptr<HighlightConfig> InspectorDOMAgent::highlightConfigFromInspectorObject(ErrorString& errorString, InspectorObject* highlightInspectorObject)
1031 {
1032     if (!highlightInspectorObject) {
1033         errorString = ASCIILiteral("Internal error: highlight configuration parameter is missing");
1034         return nullptr;
1035     }
1036
1037     auto highlightConfig = std::make_unique<HighlightConfig>();
1038     bool showInfo = false; // Default: false (do not show a tooltip).
1039     highlightInspectorObject->getBoolean("showInfo", showInfo);
1040     highlightConfig->showInfo = showInfo;
1041     highlightConfig->content = parseConfigColor("contentColor", highlightInspectorObject);
1042     highlightConfig->contentOutline = parseConfigColor("contentOutlineColor", highlightInspectorObject);
1043     highlightConfig->padding = parseConfigColor("paddingColor", highlightInspectorObject);
1044     highlightConfig->border = parseConfigColor("borderColor", highlightInspectorObject);
1045     highlightConfig->margin = parseConfigColor("marginColor", highlightInspectorObject);
1046     return highlightConfig;
1047 }
1048
1049 void InspectorDOMAgent::setInspectModeEnabled(ErrorString& errorString, bool enabled, const RefPtr<InspectorObject>* highlightConfig)
1050 {
1051     setSearchingForNode(errorString, enabled, highlightConfig ? highlightConfig->get() : 0);
1052 }
1053
1054 void InspectorDOMAgent::highlightRect(ErrorString&, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1055 {
1056     auto quad = std::make_unique<FloatQuad>(FloatRect(x, y, width, height));
1057     innerHighlightQuad(WTF::move(quad), color, outlineColor, usePageCoordinates);
1058 }
1059
1060 void InspectorDOMAgent::highlightQuad(ErrorString& errorString, const RefPtr<InspectorArray>& quadArray, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1061 {
1062     auto quad = std::make_unique<FloatQuad>();
1063     if (!parseQuad(quadArray, quad.get())) {
1064         errorString = ASCIILiteral("Invalid Quad format");
1065         return;
1066     }
1067     innerHighlightQuad(WTF::move(quad), color, outlineColor, usePageCoordinates);
1068 }
1069
1070 void InspectorDOMAgent::innerHighlightQuad(std::unique_ptr<FloatQuad> quad, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1071 {
1072     auto highlightConfig = std::make_unique<HighlightConfig>();
1073     highlightConfig->content = parseColor(*color);
1074     highlightConfig->contentOutline = parseColor(*outlineColor);
1075     highlightConfig->usePageCoordinates = usePageCoordinates ? *usePageCoordinates : false;
1076     m_overlay->highlightQuad(WTF::move(quad), *highlightConfig);
1077 }
1078
1079 void InspectorDOMAgent::highlightNode(ErrorString& errorString, const RefPtr<InspectorObject>& highlightInspectorObject, const int* nodeId, const String* objectId)
1080 {
1081     Node* node = 0;
1082     if (nodeId) {
1083         node = assertNode(errorString, *nodeId);
1084     } else if (objectId) {
1085         node = nodeForObjectId(*objectId);
1086         if (!node)
1087             errorString = ASCIILiteral("Node for given objectId not found");
1088     } else
1089         errorString = ASCIILiteral("Either nodeId or objectId must be specified");
1090
1091     if (!node)
1092         return;
1093
1094     std::unique_ptr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject.get());
1095     if (!highlightConfig)
1096         return;
1097
1098     m_overlay->highlightNode(node, *highlightConfig);
1099 }
1100
1101 void InspectorDOMAgent::highlightFrame(ErrorString&, const String& frameId, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
1102 {
1103     Frame* frame = m_pageAgent->frameForId(frameId);
1104     if (frame && frame->ownerElement()) {
1105         auto highlightConfig = std::make_unique<HighlightConfig>();
1106         highlightConfig->showInfo = true; // Always show tooltips for frames.
1107         highlightConfig->content = parseColor(*color);
1108         highlightConfig->contentOutline = parseColor(*outlineColor);
1109         m_overlay->highlightNode(frame->ownerElement(), *highlightConfig);
1110     }
1111 }
1112
1113 void InspectorDOMAgent::hideHighlight(ErrorString&)
1114 {
1115     m_overlay->hideHighlight();
1116 }
1117
1118 void InspectorDOMAgent::moveTo(ErrorString& errorString, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
1119 {
1120     Node* node = assertEditableNode(errorString, nodeId);
1121     if (!node)
1122         return;
1123
1124     Element* targetElement = assertEditableElement(errorString, targetElementId);
1125     if (!targetElement)
1126         return;
1127
1128     Node* anchorNode = 0;
1129     if (anchorNodeId && *anchorNodeId) {
1130         anchorNode = assertEditableNode(errorString, *anchorNodeId);
1131         if (!anchorNode)
1132             return;
1133         if (anchorNode->parentNode() != targetElement) {
1134             errorString = ASCIILiteral("Anchor node must be child of the target element");
1135             return;
1136         }
1137     }
1138
1139     if (!m_domEditor->insertBefore(targetElement, node, anchorNode, errorString))
1140         return;
1141
1142     *newNodeId = pushNodePathToFrontend(node);
1143 }
1144
1145 void InspectorDOMAgent::undo(ErrorString& errorString)
1146 {
1147     ExceptionCode ec = 0;
1148     m_history->undo(ec);
1149     errorString = InspectorDOMAgent::toErrorString(ec);
1150 }
1151
1152 void InspectorDOMAgent::redo(ErrorString& errorString)
1153 {
1154     ExceptionCode ec = 0;
1155     m_history->redo(ec);
1156     errorString = InspectorDOMAgent::toErrorString(ec);
1157 }
1158
1159 void InspectorDOMAgent::markUndoableState(ErrorString&)
1160 {
1161     m_history->markUndoableState();
1162 }
1163
1164 void InspectorDOMAgent::focus(ErrorString& errorString, int nodeId)
1165 {
1166     Element* element = assertElement(errorString, nodeId);
1167     if (!element)
1168         return;
1169     if (!element->isFocusable()) {
1170         errorString = ASCIILiteral("Element is not focusable");
1171         return;
1172     }
1173     element->focus();
1174 }
1175
1176 void InspectorDOMAgent::resolveNode(ErrorString& errorString, int nodeId, const String* const objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result)
1177 {
1178     String objectGroupName = objectGroup ? *objectGroup : "";
1179     Node* node = nodeForId(nodeId);
1180     if (!node) {
1181         errorString = ASCIILiteral("No node with given id found");
1182         return;
1183     }
1184     RefPtr<Inspector::Protocol::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
1185     if (!object) {
1186         errorString = ASCIILiteral("Node with given id does not belong to the document");
1187         return;
1188     }
1189     result = object;
1190 }
1191
1192 void InspectorDOMAgent::getAttributes(ErrorString& errorString, int nodeId, RefPtr<Inspector::Protocol::Array<String>>& result)
1193 {
1194     Element* element = assertElement(errorString, nodeId);
1195     if (!element)
1196         return;
1197
1198     result = buildArrayForElementAttributes(element);
1199 }
1200
1201 void InspectorDOMAgent::requestNode(ErrorString&, const String& objectId, int* nodeId)
1202 {
1203     Node* node = nodeForObjectId(objectId);
1204     if (node)
1205         *nodeId = pushNodePathToFrontend(node);
1206     else
1207         *nodeId = 0;
1208 }
1209
1210 // static
1211 String InspectorDOMAgent::documentURLString(Document* document)
1212 {
1213     if (!document || document->url().isNull())
1214         return "";
1215     return document->url().string();
1216 }
1217
1218 static String documentBaseURLString(Document* document)
1219 {
1220     return document->completeURL("").string();
1221 }
1222
1223 PassRefPtr<Inspector::Protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
1224 {
1225     int id = bind(node, nodesMap);
1226     String nodeName;
1227     String localName;
1228     String nodeValue;
1229
1230     switch (node->nodeType()) {
1231     case Node::PROCESSING_INSTRUCTION_NODE:
1232         nodeName = node->nodeName();
1233         localName = node->localName();
1234         FALLTHROUGH;
1235     case Node::TEXT_NODE:
1236     case Node::COMMENT_NODE:
1237     case Node::CDATA_SECTION_NODE:
1238         nodeValue = node->nodeValue();
1239         if (nodeValue.length() > maxTextSize) {
1240             nodeValue = nodeValue.left(maxTextSize);
1241             nodeValue.append(ellipsisUChar);
1242         }
1243         break;
1244     case Node::ATTRIBUTE_NODE:
1245         localName = node->localName();
1246         break;
1247     case Node::DOCUMENT_FRAGMENT_NODE:
1248     case Node::DOCUMENT_NODE:
1249     case Node::ELEMENT_NODE:
1250     default:
1251         nodeName = node->nodeName();
1252         localName = node->localName();
1253         break;
1254     }
1255
1256     RefPtr<Inspector::Protocol::DOM::Node> value = Inspector::Protocol::DOM::Node::create()
1257         .setNodeId(id)
1258         .setNodeType(static_cast<int>(node->nodeType()))
1259         .setNodeName(nodeName)
1260         .setLocalName(localName)
1261         .setNodeValue(nodeValue);
1262
1263     if (node->isContainerNode()) {
1264         int nodeCount = innerChildNodeCount(node);
1265         value->setChildNodeCount(nodeCount);
1266         RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> children = buildArrayForContainerChildren(node, depth, nodesMap);
1267         if (children->length() > 0)
1268             value->setChildren(children.release());
1269     }
1270
1271     if (is<Element>(*node)) {
1272         Element& element = downcast<Element>(*node);
1273         value->setAttributes(buildArrayForElementAttributes(&element));
1274         if (is<HTMLFrameOwnerElement>(element)) {
1275             HTMLFrameOwnerElement& frameOwner = downcast<HTMLFrameOwnerElement>(element);
1276             Frame* frame = frameOwner.contentFrame();
1277             if (frame)
1278                 value->setFrameId(m_pageAgent->frameId(frame));
1279             Document* document = frameOwner.contentDocument();
1280             if (document)
1281                 value->setContentDocument(buildObjectForNode(document, 0, nodesMap));
1282         }
1283
1284         if (ShadowRoot* root = element.shadowRoot()) {
1285             RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> shadowRoots = Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>::create();
1286             shadowRoots->addItem(buildObjectForNode(root, 0, nodesMap));
1287             value->setShadowRoots(shadowRoots);
1288         }
1289
1290 #if ENABLE(TEMPLATE_ELEMENT)
1291         if (is<HTMLTemplateElement>(element))
1292             value->setTemplateContent(buildObjectForNode(downcast<HTMLTemplateElement>(element).content(), 0, nodesMap));
1293 #endif
1294
1295     } else if (is<Document>(*node)) {
1296         Document& document = downcast<Document>(*node);
1297         value->setDocumentURL(documentURLString(&document));
1298         value->setBaseURL(documentBaseURLString(&document));
1299         value->setXmlVersion(document.xmlVersion());
1300     } else if (is<DocumentType>(*node)) {
1301         DocumentType& docType = downcast<DocumentType>(*node);
1302         value->setPublicId(docType.publicId());
1303         value->setSystemId(docType.systemId());
1304         value->setInternalSubset(docType.internalSubset());
1305     } else if (is<Attr>(*node)) {
1306         Attr& attribute = downcast<Attr>(*node);
1307         value->setName(attribute.name());
1308         value->setValue(attribute.value());
1309     }
1310
1311     // Need to enable AX to get the computed role.
1312     if (!WebCore::AXObjectCache::accessibilityEnabled())
1313         WebCore::AXObjectCache::enableAccessibility();
1314
1315     if (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
1316         if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node))
1317             value->setRole(axObject->computedRoleString());
1318     }
1319
1320     return value.release();
1321 }
1322
1323 PassRefPtr<Inspector::Protocol::Array<String>> InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
1324 {
1325     RefPtr<Inspector::Protocol::Array<String>> attributesValue = Inspector::Protocol::Array<String>::create();
1326     // Go through all attributes and serialize them.
1327     if (!element->hasAttributes())
1328         return attributesValue.release();
1329     for (const Attribute& attribute : element->attributesIterator()) {
1330         // Add attribute pair
1331         attributesValue->addItem(attribute.name().toString());
1332         attributesValue->addItem(attribute.value());
1333     }
1334     return attributesValue.release();
1335 }
1336
1337 PassRefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
1338 {
1339     RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> children = Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>::create();
1340     if (depth == 0) {
1341         // Special-case the only text child - pretend that container's children have been requested.
1342         Node* firstChild = container->firstChild();
1343         if (firstChild && firstChild->nodeType() == Node::TEXT_NODE && !firstChild->nextSibling()) {
1344             children->addItem(buildObjectForNode(firstChild, 0, nodesMap));
1345             m_childrenRequested.add(bind(container, nodesMap));
1346         }
1347         return children.release();
1348     }
1349
1350     Node* child = innerFirstChild(container);
1351     depth--;
1352     m_childrenRequested.add(bind(container, nodesMap));
1353
1354     while (child) {
1355         children->addItem(buildObjectForNode(child, depth, nodesMap));
1356         child = innerNextSibling(child);
1357     }
1358     return children.release();
1359 }
1360
1361 PassRefPtr<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
1362 {
1363     RefPtr<EventListener> eventListener = registeredEventListener.listener;
1364
1365     JSC::ExecState* state = nullptr;
1366     JSC::JSObject* handler = nullptr;
1367     String body;
1368     int lineNumber = 0;
1369     String scriptID;
1370     String sourceName;
1371     if (auto scriptListener = JSEventListener::cast(eventListener.get())) {
1372         JSC::JSLockHolder lock(scriptListener->isolatedWorld().vm());
1373         state = execStateFromNode(scriptListener->isolatedWorld(), &node->document());
1374         handler = scriptListener->jsFunction(&node->document());
1375         if (handler) {
1376             body = handler->toString(state)->value(state);
1377             if (auto function = JSC::jsDynamicCast<JSC::JSFunction*>(handler)) {
1378                 if (!function->isHostOrBuiltinFunction()) {
1379                     if (auto executable = function->jsExecutable()) {
1380                         lineNumber = executable->lineNo() - 1;
1381                         scriptID = executable->sourceID() == JSC::SourceProvider::nullID ? emptyString() : String::number(executable->sourceID());
1382                         sourceName = executable->sourceURL();
1383                     }
1384                 }
1385             }
1386         }
1387     }
1388
1389     RefPtr<Inspector::Protocol::DOM::EventListener> value = Inspector::Protocol::DOM::EventListener::create()
1390         .setType(eventType)
1391         .setUseCapture(registeredEventListener.useCapture)
1392         .setIsAttribute(eventListener->isAttribute())
1393         .setNodeId(pushNodePathToFrontend(node))
1394         .setHandlerBody(body);
1395     if (objectGroupId && handler && state) {
1396         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(state);
1397         if (!injectedScript.hasNoValue())
1398             value->setHandler(injectedScript.wrapObject(Deprecated::ScriptValue(state->vm(), handler), *objectGroupId));
1399     }
1400     if (!scriptID.isNull()) {
1401         RefPtr<Inspector::Protocol::Debugger::Location> location = Inspector::Protocol::Debugger::Location::create()
1402             .setScriptId(scriptID)
1403             .setLineNumber(lineNumber);
1404         value->setLocation(location.release());
1405         if (!sourceName.isEmpty())
1406             value->setSourceName(sourceName);
1407     }
1408     return value.release();
1409 }
1410     
1411 void InspectorDOMAgent::processAccessibilityChildren(PassRefPtr<AccessibilityObject> axObject, RefPtr<Inspector::Protocol::Array<int>>& childNodeIds)
1412 {
1413     const auto& children = axObject->children();
1414     if (!children.size())
1415         return;
1416     
1417     if (!childNodeIds)
1418         childNodeIds = Inspector::Protocol::Array<int>::create();
1419     
1420     for (const auto& childObject : children) {
1421         if (Node* childNode = childObject->node())
1422             childNodeIds->addItem(pushNodePathToFrontend(childNode));
1423         else
1424             processAccessibilityChildren(childObject, childNodeIds);
1425     }
1426 }
1427     
1428 PassRefPtr<Inspector::Protocol::DOM::AccessibilityProperties> InspectorDOMAgent::buildObjectForAccessibilityProperties(Node* node)
1429 {
1430     ASSERT(node);
1431     if (!node)
1432         return nullptr;
1433
1434     if (!WebCore::AXObjectCache::accessibilityEnabled())
1435         WebCore::AXObjectCache::enableAccessibility();
1436
1437     Node* activeDescendantNode = nullptr;
1438     bool busy = false;
1439     Inspector::Protocol::DOM::AccessibilityProperties::Checked checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::False;
1440     RefPtr<Inspector::Protocol::Array<int>> childNodeIds;
1441     RefPtr<Inspector::Protocol::Array<int>> controlledNodeIds;
1442     bool exists = false;
1443     bool expanded = false;
1444     bool disabled = false;
1445     RefPtr<Inspector::Protocol::Array<int>> flowedNodeIds;
1446     bool focused = false;
1447     bool ignored = true;
1448     bool ignoredByDefault = false;
1449     Inspector::Protocol::DOM::AccessibilityProperties::Invalid invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False;
1450     bool hidden = false;
1451     String label;
1452     bool liveRegionAtomic = false;
1453     RefPtr<Inspector::Protocol::Array<String>> liveRegionRelevant;
1454     Inspector::Protocol::DOM::AccessibilityProperties::LiveRegionStatus liveRegionStatus = Inspector::Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Off;
1455     Node* mouseEventNode = nullptr;
1456     RefPtr<Inspector::Protocol::Array<int>> ownedNodeIds;
1457     Node* parentNode = nullptr;
1458     bool pressed = false;
1459     bool readonly = false;
1460     bool required = false;
1461     String role;
1462     bool selected = false;
1463     RefPtr<Inspector::Protocol::Array<int>> selectedChildNodeIds;
1464     bool supportsChecked = false;
1465     bool supportsExpanded = false;
1466     bool supportsLiveRegion = false;
1467     bool supportsPressed = false;
1468     bool supportsRequired = false;
1469     bool supportsFocused = false;
1470
1471     if (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
1472         if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node)) {
1473
1474             if (AccessibilityObject* activeDescendant = axObject->activeDescendant())
1475                 activeDescendantNode = activeDescendant->node();
1476
1477             // An AX object is "busy" if it or any ancestor has aria-busy="true" set.
1478             AccessibilityObject* current = axObject;
1479             while (!busy && current) {
1480                 busy = current->ariaLiveRegionBusy();
1481                 current = current->parentObject();
1482             }
1483
1484             supportsChecked = axObject->supportsChecked();
1485             if (supportsChecked) {
1486                 int checkValue = axObject->checkboxOrRadioValue(); // Element using aria-checked.
1487                 if (checkValue == 1)
1488                     checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::True;
1489                 else if (checkValue == 2)
1490                     checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::Mixed;
1491                 else if (axObject->isChecked()) // Native checkbox.
1492                     checked = Inspector::Protocol::DOM::AccessibilityProperties::Checked::True;
1493             }
1494             
1495             processAccessibilityChildren(axObject, childNodeIds);
1496             
1497             if (axObject->supportsARIAControls()) {
1498                 Vector<Element*> controlledElements;
1499                 axObject->elementsFromAttribute(controlledElements, aria_controlsAttr);
1500                 if (controlledElements.size()) {
1501                     controlledNodeIds = Inspector::Protocol::Array<int>::create();
1502                     for (Element* controlledElement : controlledElements)
1503                         controlledNodeIds->addItem(pushNodePathToFrontend(controlledElement));
1504                 }
1505             }
1506
1507             disabled = !axObject->isEnabled(); 
1508             exists = true;
1509             
1510             supportsExpanded = axObject->supportsARIAExpanded();
1511             if (supportsExpanded)
1512                 expanded = axObject->isExpanded();
1513
1514             if (axObject->supportsARIAFlowTo()) {
1515                 Vector<Element*> flowedElements;
1516                 axObject->elementsFromAttribute(flowedElements, aria_flowtoAttr);
1517                 if (flowedElements.size()) {
1518                     flowedNodeIds = Inspector::Protocol::Array<int>::create();
1519                     for (Element* flowedElement : flowedElements)
1520                         flowedNodeIds->addItem(pushNodePathToFrontend(flowedElement));
1521                 }
1522             }
1523             
1524             if (is<Element>(*node)) {
1525                 supportsFocused = downcast<Element>(*node).isFocusable();
1526                 if (supportsFocused)
1527                     focused = axObject->isFocused();
1528             }
1529
1530             ignored = axObject->accessibilityIsIgnored();
1531             ignoredByDefault = axObject->accessibilityIsIgnoredByDefault();
1532             
1533             String invalidValue = axObject->invalidStatus();
1534             if (invalidValue == "false")
1535                 invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False;
1536             else if (invalidValue == "grammar")
1537                 invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::Grammar;
1538             else if (invalidValue == "spelling")
1539                 invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::Spelling;
1540             else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size.
1541                 invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::True;
1542             
1543             if (axObject->isARIAHidden() || axObject->isDOMHidden())
1544                 hidden = true;
1545             
1546             label = axObject->computedLabel();
1547
1548             if (axObject->supportsARIALiveRegion()) {
1549                 supportsLiveRegion = true;
1550                 liveRegionAtomic = axObject->ariaLiveRegionAtomic();
1551
1552                 String ariaRelevantAttrValue = axObject->ariaLiveRegionRelevant();
1553                 if (!ariaRelevantAttrValue.isEmpty()) {
1554                     // FIXME: Pass enum values rather than strings once unblocked. http://webkit.org/b/133711
1555                     String ariaRelevantAdditions = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Additions);
1556                     String ariaRelevantRemovals = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Removals);
1557                     String ariaRelevantText = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::DOM::LiveRegionRelevant::Text);
1558                     liveRegionRelevant = Inspector::Protocol::Array<String>::create();
1559                     const SpaceSplitString& values = SpaceSplitString(ariaRelevantAttrValue, true);
1560                     // @aria-relevant="all" is exposed as ["additions","removals","text"], in order.
1561                     // This order is controlled in WebCore and expected in WebInspectorUI.
1562                     if (values.contains("all")) {
1563                         liveRegionRelevant->addItem(ariaRelevantAdditions);
1564                         liveRegionRelevant->addItem(ariaRelevantRemovals);
1565                         liveRegionRelevant->addItem(ariaRelevantText);
1566                     } else {
1567                         if (values.contains(ariaRelevantAdditions))
1568                             liveRegionRelevant->addItem(ariaRelevantAdditions);
1569                         if (values.contains(ariaRelevantRemovals))
1570                             liveRegionRelevant->addItem(ariaRelevantRemovals);
1571                         if (values.contains(ariaRelevantText))
1572                             liveRegionRelevant->addItem(ariaRelevantText);
1573                     }
1574                 }
1575
1576                 String ariaLive = axObject->ariaLiveRegionStatus();
1577                 if (ariaLive == "assertive")
1578                     liveRegionStatus = Inspector::Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Assertive;
1579                 else if (ariaLive == "polite")
1580                     liveRegionStatus = Inspector::Protocol::DOM::AccessibilityProperties::LiveRegionStatus::Polite;
1581             }
1582
1583             if (axObject->isAccessibilityNodeObject())
1584                 mouseEventNode = toAccessibilityNodeObject(axObject)->mouseButtonListener(MouseButtonListenerResultFilter::IncludeBodyElement);
1585
1586             if (axObject->supportsARIAOwns()) {
1587                 Vector<Element*> ownedElements;
1588                 axObject->elementsFromAttribute(ownedElements, aria_ownsAttr);
1589                 if (ownedElements.size()) {
1590                     ownedNodeIds = Inspector::Protocol::Array<int>::create();
1591                     for (Element* ownedElement : ownedElements)
1592                         ownedNodeIds->addItem(pushNodePathToFrontend(ownedElement));
1593                 }
1594             }
1595
1596             if (AccessibilityObject* parentObject = axObject->parentObjectUnignored())
1597                 parentNode = parentObject->node();
1598
1599             supportsPressed = axObject->ariaPressedIsPresent();
1600             if (supportsPressed)
1601                 pressed = axObject->isPressed();
1602             
1603             if (axObject->isTextControl())
1604                 readonly = axObject->isReadOnly();
1605
1606             supportsRequired = axObject->supportsRequiredAttribute();
1607             if (supportsRequired)
1608                 required = axObject->isRequired();
1609             
1610             role = axObject->computedRoleString();
1611             selected = axObject->isSelected();
1612
1613             AccessibilityObject::AccessibilityChildrenVector selectedChildren;
1614             axObject->selectedChildren(selectedChildren);
1615             if (selectedChildren.size()) {
1616                 selectedChildNodeIds = Inspector::Protocol::Array<int>::create();
1617                 for (auto& selectedChildObject : selectedChildren) {
1618                     if (Node* selectedChildNode = selectedChildObject->node())
1619                         selectedChildNodeIds->addItem(pushNodePathToFrontend(selectedChildNode));
1620                 }
1621             }
1622         }
1623     }
1624     
1625     RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> value = Inspector::Protocol::DOM::AccessibilityProperties::create()
1626         .setExists(exists)
1627         .setLabel(label)
1628         .setRole(role)
1629         .setNodeId(pushNodePathToFrontend(node));
1630
1631     if (exists) {
1632         if (activeDescendantNode)
1633             value->setActiveDescendantNodeId(pushNodePathToFrontend(activeDescendantNode));
1634         if (busy)
1635             value->setBusy(busy);
1636         if (supportsChecked)
1637             value->setChecked(checked);
1638         if (childNodeIds)
1639             value->setChildNodeIds(childNodeIds);
1640         if (controlledNodeIds)
1641             value->setControlledNodeIds(controlledNodeIds);
1642         if (disabled)
1643             value->setDisabled(disabled);
1644         if (supportsExpanded)
1645             value->setExpanded(expanded);
1646         if (flowedNodeIds)
1647             value->setFlowedNodeIds(flowedNodeIds);
1648         if (supportsFocused)
1649             value->setFocused(focused);
1650         if (ignored)
1651             value->setIgnored(ignored);
1652         if (ignoredByDefault)
1653             value->setIgnoredByDefault(ignoredByDefault);
1654         if (invalid != Inspector::Protocol::DOM::AccessibilityProperties::Invalid::False)
1655             value->setInvalid(invalid);
1656         if (hidden)
1657             value->setHidden(hidden);
1658         if (supportsLiveRegion) {
1659             value->setLiveRegionAtomic(liveRegionAtomic);
1660             if (liveRegionRelevant->length())
1661                 value->setLiveRegionRelevant(liveRegionRelevant);
1662             value->setLiveRegionStatus(liveRegionStatus);
1663         }
1664         if (mouseEventNode)
1665             value->setMouseEventNodeId(pushNodePathToFrontend(mouseEventNode));
1666         if (ownedNodeIds)
1667             value->setOwnedNodeIds(ownedNodeIds);
1668         if (parentNode)
1669             value->setParentNodeId(pushNodePathToFrontend(parentNode));
1670         if (supportsPressed)
1671             value->setPressed(pressed);
1672         if (readonly)
1673             value->setReadonly(readonly);
1674         if (supportsRequired)
1675             value->setRequired(required);
1676         if (selected)
1677             value->setSelected(selected);
1678         if (selectedChildNodeIds)
1679             value->setSelectedChildNodeIds(selectedChildNodeIds);
1680     }
1681
1682     return value.release();
1683 }
1684
1685 Node* InspectorDOMAgent::innerFirstChild(Node* node)
1686 {
1687     node = node->firstChild();
1688     while (isWhitespace(node))
1689         node = node->nextSibling();
1690     return node;
1691 }
1692
1693 Node* InspectorDOMAgent::innerNextSibling(Node* node)
1694 {
1695     do {
1696         node = node->nextSibling();
1697     } while (isWhitespace(node));
1698     return node;
1699 }
1700
1701 Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
1702 {
1703     do {
1704         node = node->previousSibling();
1705     } while (isWhitespace(node));
1706     return node;
1707 }
1708
1709 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
1710 {
1711     unsigned count = 0;
1712     Node* child = innerFirstChild(node);
1713     while (child) {
1714         count++;
1715         child = innerNextSibling(child);
1716     }
1717     return count;
1718 }
1719
1720 Node* InspectorDOMAgent::innerParentNode(Node* node)
1721 {
1722     ASSERT(node);
1723     if (is<Document>(*node))
1724         return downcast<Document>(*node).ownerElement();
1725     return node->parentNode();
1726 }
1727
1728 bool InspectorDOMAgent::isWhitespace(Node* node)
1729 {
1730     //TODO: pull ignoreWhitespace setting from the frontend and use here.
1731     return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
1732 }
1733
1734 void InspectorDOMAgent::mainFrameDOMContentLoaded()
1735 {
1736     // Re-push document once it is loaded.
1737     discardBindings();
1738     if (m_documentRequested)
1739         m_frontendDispatcher->documentUpdated();
1740 }
1741
1742 void InspectorDOMAgent::didCommitLoad(Document* document)
1743 {
1744     Element* frameOwner = document->ownerElement();
1745     if (!frameOwner)
1746         return;
1747
1748     int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
1749     if (!frameOwnerId)
1750         return;
1751
1752     // Re-add frame owner element together with its new children.
1753     int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
1754     m_frontendDispatcher->childNodeRemoved(parentId, frameOwnerId);
1755     unbind(frameOwner, &m_documentNodeToIdMap);
1756
1757     RefPtr<Inspector::Protocol::DOM::Node> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
1758     Node* previousSibling = innerPreviousSibling(frameOwner);
1759     int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
1760     m_frontendDispatcher->childNodeInserted(parentId, prevId, value.release());
1761 }
1762
1763 void InspectorDOMAgent::didInsertDOMNode(Node* node)
1764 {
1765     if (isWhitespace(node))
1766         return;
1767
1768     // We could be attaching existing subtree. Forget the bindings.
1769     unbind(node, &m_documentNodeToIdMap);
1770
1771     ContainerNode* parent = node->parentNode();
1772     if (!parent)
1773         return;
1774
1775     int parentId = m_documentNodeToIdMap.get(parent);
1776     // Return if parent is not mapped yet.
1777     if (!parentId)
1778         return;
1779
1780     if (!m_childrenRequested.contains(parentId)) {
1781         // No children are mapped yet -> only notify on changes of hasChildren.
1782         m_frontendDispatcher->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
1783     } else {
1784         // Children have been requested -> return value of a new child.
1785         Node* prevSibling = innerPreviousSibling(node);
1786         int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
1787         RefPtr<Inspector::Protocol::DOM::Node> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
1788         m_frontendDispatcher->childNodeInserted(parentId, prevId, value.release());
1789     }
1790 }
1791
1792 void InspectorDOMAgent::didRemoveDOMNode(Node* node)
1793 {
1794     if (isWhitespace(node))
1795         return;
1796
1797     ContainerNode* parent = node->parentNode();
1798
1799     // If parent is not mapped yet -> ignore the event.
1800     if (!m_documentNodeToIdMap.contains(parent))
1801         return;
1802
1803     int parentId = m_documentNodeToIdMap.get(parent);
1804
1805     if (!m_childrenRequested.contains(parentId)) {
1806         // No children are mapped yet -> only notify on changes of hasChildren.
1807         if (innerChildNodeCount(parent) == 1)
1808             m_frontendDispatcher->childNodeCountUpdated(parentId, 0);
1809     } else
1810         m_frontendDispatcher->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
1811     unbind(node, &m_documentNodeToIdMap);
1812 }
1813
1814 void InspectorDOMAgent::willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue)
1815 {
1816     m_suppressAttributeModifiedEvent = (oldValue == newValue);
1817 }
1818
1819 void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
1820 {
1821     bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
1822     m_suppressAttributeModifiedEvent = false;
1823     if (shouldSuppressEvent)
1824         return;
1825
1826     int id = boundNodeId(element);
1827     // If node is not mapped yet -> ignore the event.
1828     if (!id)
1829         return;
1830
1831     if (m_domListener)
1832         m_domListener->didModifyDOMAttr(element);
1833
1834     m_frontendDispatcher->attributeModified(id, name, value);
1835 }
1836
1837 void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
1838 {
1839     int id = boundNodeId(element);
1840     // If node is not mapped yet -> ignore the event.
1841     if (!id)
1842         return;
1843
1844     if (m_domListener)
1845         m_domListener->didModifyDOMAttr(element);
1846
1847     m_frontendDispatcher->attributeRemoved(id, name);
1848 }
1849
1850 void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
1851 {
1852     RefPtr<Inspector::Protocol::Array<int>> nodeIds = Inspector::Protocol::Array<int>::create();
1853     for (unsigned i = 0, size = elements.size(); i < size; ++i) {
1854         Element* element = elements.at(i);
1855         int id = boundNodeId(element);
1856         // If node is not mapped yet -> ignore the event.
1857         if (!id)
1858             continue;
1859
1860         if (m_domListener)
1861             m_domListener->didModifyDOMAttr(element);
1862         nodeIds->addItem(id);
1863     }
1864     m_frontendDispatcher->inlineStyleInvalidated(nodeIds.release());
1865 }
1866
1867 void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
1868 {
1869     int id = m_documentNodeToIdMap.get(characterData);
1870     if (!id) {
1871         // Push text node if it is being created.
1872         didInsertDOMNode(characterData);
1873         return;
1874     }
1875     m_frontendDispatcher->characterDataModified(id, characterData->data());
1876 }
1877
1878 void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
1879 {
1880     int id = m_documentNodeToIdMap.get(node);
1881     // If node is not mapped yet -> ignore the event.
1882     if (!id)
1883         return;
1884
1885     if (!m_revalidateStyleAttrTask)
1886         m_revalidateStyleAttrTask = std::make_unique<RevalidateStyleAttributeTask>(this);
1887     m_revalidateStyleAttrTask->scheduleFor(downcast<Element>(node));
1888 }
1889
1890 void InspectorDOMAgent::didPushShadowRoot(Element* host, ShadowRoot* root)
1891 {
1892     int hostId = m_documentNodeToIdMap.get(host);
1893     if (hostId)
1894         m_frontendDispatcher->shadowRootPushed(hostId, buildObjectForNode(root, 0, &m_documentNodeToIdMap));
1895 }
1896
1897 void InspectorDOMAgent::willPopShadowRoot(Element* host, ShadowRoot* root)
1898 {
1899     int hostId = m_documentNodeToIdMap.get(host);
1900     int rootId = m_documentNodeToIdMap.get(root);
1901     if (hostId && rootId)
1902         m_frontendDispatcher->shadowRootPopped(hostId, rootId);
1903 }
1904
1905 void InspectorDOMAgent::frameDocumentUpdated(Frame* frame)
1906 {
1907     Document* document = frame->document();
1908     if (!document)
1909         return;
1910
1911     Page* page = frame->page();
1912     ASSERT(page);
1913     if (frame != &page->mainFrame())
1914         return;
1915
1916     // Only update the main frame document, nested frame document updates are not required
1917     // (will be handled by didCommitLoad()).
1918     setDocument(document);
1919 }
1920
1921 Node* InspectorDOMAgent::nodeForPath(const String& path)
1922 {
1923     // The path is of form "1,HTML,2,BODY,1,DIV"
1924     if (!m_document)
1925         return 0;
1926
1927     Node* node = m_document.get();
1928     Vector<String> pathTokens;
1929     path.split(',', false, pathTokens);
1930     if (!pathTokens.size())
1931         return 0;
1932     for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
1933         bool success = true;
1934         unsigned childNumber = pathTokens[i].toUInt(&success);
1935         if (!success)
1936             return 0;
1937         if (childNumber >= innerChildNodeCount(node))
1938             return 0;
1939
1940         Node* child = innerFirstChild(node);
1941         String childName = pathTokens[i + 1];
1942         for (size_t j = 0; child && j < childNumber; ++j)
1943             child = innerNextSibling(child);
1944
1945         if (!child || child->nodeName() != childName)
1946             return 0;
1947         node = child;
1948     }
1949     return node;
1950 }
1951
1952 Node* InspectorDOMAgent::nodeForObjectId(const String& objectId)
1953 {
1954     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
1955     Deprecated::ScriptValue value = injectedScript.findObjectById(objectId);
1956     return InspectorDOMAgent::scriptValueAsNode(value);
1957 }
1958
1959 void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString& errorString, const String& path, int* nodeId)
1960 {
1961     if (Node* node = nodeForPath(path))
1962         *nodeId = pushNodePathToFrontend(node);
1963     else
1964         errorString = ASCIILiteral("No node with given path found");
1965 }
1966
1967 void InspectorDOMAgent::pushNodeByBackendIdToFrontend(ErrorString& errorString, BackendNodeId backendNodeId, int* nodeId)
1968 {
1969     if (!m_backendIdToNode.contains(backendNodeId)) {
1970         errorString = ASCIILiteral("No node with given backend id found");
1971         return;
1972     }
1973
1974     Node* node = m_backendIdToNode.get(backendNodeId).first;
1975     String nodeGroup = m_backendIdToNode.get(backendNodeId).second;
1976     *nodeId = pushNodePathToFrontend(node);
1977
1978     if (nodeGroup == "") {
1979         m_backendIdToNode.remove(backendNodeId);
1980         m_nodeGroupToBackendIdMap.find(nodeGroup)->value.remove(node);
1981     }
1982 }
1983
1984 PassRefPtr<Inspector::Protocol::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
1985 {
1986     Frame* frame = node->document().frame();
1987     if (!frame)
1988         return 0;
1989
1990     JSC::ExecState* scriptState = mainWorldExecState(frame);
1991     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
1992     if (injectedScript.hasNoValue())
1993         return 0;
1994
1995     return injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(scriptState, node), objectGroup);
1996 }
1997
1998 Node* InspectorDOMAgent::scriptValueAsNode(Deprecated::ScriptValue value)
1999 {
2000     if (!value.isObject() || value.isNull())
2001         return nullptr;
2002
2003     return JSNode::toWrapped(value.jsValue());
2004 }
2005
2006 Deprecated::ScriptValue InspectorDOMAgent::nodeAsScriptValue(JSC::ExecState* state, Node* node)
2007 {
2008     if (!shouldAllowAccessToNode(state, node))
2009         return Deprecated::ScriptValue(state->vm(), JSC::jsNull());
2010
2011     JSC::JSLockHolder lock(state);
2012     return Deprecated::ScriptValue(state->vm(), toJS(state, deprecatedGlobalObjectForPrototype(state), node));
2013 }
2014
2015 } // namespace WebCore
2016
2017 #endif // ENABLE(INSPECTOR)