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