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