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