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