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