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