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