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