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