Web Inspector: Remove recompileAllJSFunctions timer in ScriptDebugServer
[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 Computer, 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 "Attr.h"
38 #include "CSSComputedStyleDeclaration.h"
39 #include "CSSPropertyNames.h"
40 #include "CSSPropertySourceData.h"
41 #include "CSSRule.h"
42 #include "CSSRuleList.h"
43 #include "CSSStyleRule.h"
44 #include "CSSStyleSheet.h"
45 #include "CharacterData.h"
46 #include "ContainerNode.h"
47 #include "Cookie.h"
48 #include "CookieJar.h"
49 #include "DOMEditor.h"
50 #include "DOMPatchSupport.h"
51 #include "DOMWindow.h"
52 #include "Document.h"
53 #include "DocumentFragment.h"
54 #include "DocumentType.h"
55 #include "Element.h"
56 #include "Event.h"
57 #include "EventListener.h"
58 #include "EventNames.h"
59 #include "EventTarget.h"
60 #include "FrameTree.h"
61 #include "HTMLElement.h"
62 #include "HTMLFrameOwnerElement.h"
63 #include "HTMLNames.h"
64 #include "HTMLTemplateElement.h"
65 #include "HitTestResult.h"
66 #include "IdentifiersFactory.h"
67 #include "InspectorHistory.h"
68 #include "InspectorNodeFinder.h"
69 #include "InspectorOverlay.h"
70 #include "InspectorPageAgent.h"
71 #include "InspectorWebFrontendDispatchers.h"
72 #include "InstrumentingAgents.h"
73 #include "IntRect.h"
74 #include "JSEventListener.h"
75 #include "JSNode.h"
76 #include "MainFrame.h"
77 #include "MutationEvent.h"
78 #include "Node.h"
79 #include "NodeList.h"
80 #include "Page.h"
81 #include "Pasteboard.h"
82 #include "RenderStyle.h"
83 #include "RenderStyleConstants.h"
84 #include "ScriptState.h"
85 #include "Settings.h"
86 #include "ShadowRoot.h"
87 #include "StyleProperties.h"
88 #include "StyleResolver.h"
89 #include "StyleSheetList.h"
90 #include "Text.h"
91 #include "XPathResult.h"
92 #include "htmlediting.h"
93 #include "markup.h"
94 #include <inspector/InjectedScript.h>
95 #include <inspector/InjectedScriptManager.h>
96 #include <wtf/HashSet.h>
97 #include <wtf/OwnPtr.h>
98 #include <wtf/Vector.h>
99 #include <wtf/text/CString.h>
100 #include <wtf/text/WTFString.h>
101
102 using namespace Inspector;
103
104 namespace WebCore {
105
106 using namespace HTMLNames;
107
108 static const size_t maxTextSize = 10000;
109 static const UChar ellipsisUChar[] = { 0x2026, 0 };
110
111 static Color parseColor(const RefPtr<InspectorObject>* colorObject)
112 {
113     if (!colorObject || !(*colorObject))
114         return Color::transparent;
115
116     int r;
117     int g;
118     int b;
119     bool success = (*colorObject)->getNumber("r", &r);
120     success |= (*colorObject)->getNumber("g", &g);
121     success |= (*colorObject)->getNumber("b", &b);
122     if (!success)
123         return Color::transparent;
124
125     double a;
126     success = (*colorObject)->getNumber("a", &a);
127     if (!success)
128         return Color(r, g, b);
129
130     // Clamp alpha to the [0..1] range.
131     if (a < 0)
132         a = 0;
133     else if (a > 1)
134         a = 1;
135
136     return Color(r, g, b, static_cast<int>(a * 255));
137 }
138
139 static Color parseConfigColor(const String& fieldName, InspectorObject* configObject)
140 {
141     const RefPtr<InspectorObject> colorObject = configObject->getObject(fieldName);
142     return parseColor(&colorObject);
143 }
144
145 static bool parseQuad(const RefPtr<InspectorArray>& quadArray, FloatQuad* quad)
146 {
147     if (!quadArray)
148         return false;
149     const size_t coordinatesInQuad = 8;
150     double coordinates[coordinatesInQuad];
151     if (quadArray->length() != coordinatesInQuad)
152         return false;
153     for (size_t i = 0; i < coordinatesInQuad; ++i) {
154         if (!quadArray->get(i)->asNumber(coordinates + i))
155             return false;
156     }
157     quad->setP1(FloatPoint(coordinates[0], coordinates[1]));
158     quad->setP2(FloatPoint(coordinates[2], coordinates[3]));
159     quad->setP3(FloatPoint(coordinates[4], coordinates[5]));
160     quad->setP4(FloatPoint(coordinates[6], coordinates[7]));
161
162     return true;
163 }
164
165 class RevalidateStyleAttributeTask {
166     WTF_MAKE_FAST_ALLOCATED;
167 public:
168     RevalidateStyleAttributeTask(InspectorDOMAgent*);
169     void scheduleFor(Element*);
170     void reset() { m_timer.stop(); }
171     void timerFired(Timer<RevalidateStyleAttributeTask>&);
172
173 private:
174     InspectorDOMAgent* m_domAgent;
175     Timer<RevalidateStyleAttributeTask> m_timer;
176     HashSet<RefPtr<Element>> m_elements;
177 };
178
179 RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
180     : m_domAgent(domAgent)
181     , m_timer(this, &RevalidateStyleAttributeTask::timerFired)
182 {
183 }
184
185 void RevalidateStyleAttributeTask::scheduleFor(Element* element)
186 {
187     m_elements.add(element);
188     if (!m_timer.isActive())
189         m_timer.startOneShot(0);
190 }
191
192 void RevalidateStyleAttributeTask::timerFired(Timer<RevalidateStyleAttributeTask>&)
193 {
194     // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
195     Vector<Element*> elements;
196     for (HashSet<RefPtr<Element>>::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
197         elements.append(it->get());
198     m_domAgent->styleAttributeInvalidated(elements);
199
200     m_elements.clear();
201 }
202
203 String InspectorDOMAgent::toErrorString(const ExceptionCode& ec)
204 {
205     if (ec) {
206         ExceptionCodeDescription description(ec);
207         return description.name;
208     }
209     return "";
210 }
211
212 InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay)
213     : InspectorAgentBase(ASCIILiteral("DOM"), instrumentingAgents)
214     , m_pageAgent(pageAgent)
215     , m_injectedScriptManager(injectedScriptManager)
216     , m_overlay(overlay)
217     , m_domListener(0)
218     , m_lastNodeId(1)
219     , m_lastBackendNodeId(-1)
220     , m_searchingForNode(false)
221     , m_suppressAttributeModifiedEvent(false)
222     , m_documentRequested(false)
223 {
224 }
225
226 InspectorDOMAgent::~InspectorDOMAgent()
227 {
228     reset();
229     ASSERT(!m_searchingForNode);
230 }
231
232 void InspectorDOMAgent::didCreateFrontendAndBackend(Inspector::InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher)
233 {
234     m_frontendDispatcher = std::make_unique<InspectorDOMFrontendDispatcher>(frontendChannel);
235     m_backendDispatcher = InspectorDOMBackendDispatcher::create(backendDispatcher, this);
236
237     m_history = adoptPtr(new InspectorHistory());
238     m_domEditor = adoptPtr(new DOMEditor(m_history.get()));
239
240     m_instrumentingAgents->setInspectorDOMAgent(this);
241     m_document = m_pageAgent->mainFrame()->document();
242
243     if (m_nodeToFocus)
244         focusNode();
245 }
246
247 void InspectorDOMAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason)
248 {
249     m_frontendDispatcher = nullptr;
250     m_backendDispatcher.clear();
251
252     m_history.clear();
253     m_domEditor.clear();
254
255     ErrorString error;
256     setSearchingForNode(&error, false, 0);
257     hideHighlight(&error);
258
259     m_instrumentingAgents->setInspectorDOMAgent(0);
260     m_documentRequested = false;
261     reset();
262 }
263
264 Vector<Document*> InspectorDOMAgent::documents()
265 {
266     Vector<Document*> result;
267     for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
268         Document* document = frame->document();
269         if (!document)
270             continue;
271         result.append(document);
272     }
273     return result;
274 }
275
276 void InspectorDOMAgent::reset()
277 {
278     if (m_history)
279         m_history->reset();
280     m_searchResults.clear();
281     discardBindings();
282     if (m_revalidateStyleAttrTask)
283         m_revalidateStyleAttrTask->reset();
284     m_document = 0;
285 }
286
287 void InspectorDOMAgent::setDOMListener(DOMListener* listener)
288 {
289     m_domListener = listener;
290 }
291
292 void InspectorDOMAgent::setDocument(Document* doc)
293 {
294     if (doc == m_document.get())
295         return;
296
297     reset();
298
299     m_document = doc;
300
301     if (!m_documentRequested)
302         return;
303
304     // Immediately communicate 0 document or document that has finished loading.
305     if (!doc || !doc->parsing())
306         m_frontendDispatcher->documentUpdated();
307 }
308
309 void InspectorDOMAgent::releaseDanglingNodes()
310 {
311     m_danglingNodeToIdMaps.clear();
312 }
313
314 int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
315 {
316     int id = nodesMap->get(node);
317     if (id)
318         return id;
319     id = m_lastNodeId++;
320     nodesMap->set(node, id);
321     m_idToNode.set(id, node);
322     m_idToNodesMap.set(id, nodesMap);
323     return id;
324 }
325
326 void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
327 {
328     int id = nodesMap->get(node);
329     if (!id)
330         return;
331
332     m_idToNode.remove(id);
333
334     if (node->isFrameOwnerElement()) {
335         const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
336         Document* contentDocument = frameOwner->contentDocument();
337         if (m_domListener)
338             m_domListener->didRemoveDocument(contentDocument);
339         if (contentDocument)
340             unbind(contentDocument, nodesMap);
341     }
342
343     if (node->isElementNode()) {
344         if (ShadowRoot* root = toElement(node)->shadowRoot())
345             unbind(root, nodesMap);
346     }
347
348     nodesMap->remove(node);
349     if (m_domListener)
350         m_domListener->didRemoveDOMNode(node);
351
352     bool childrenRequested = m_childrenRequested.contains(id);
353     if (childrenRequested) {
354         // Unbind subtree known to client recursively.
355         m_childrenRequested.remove(id);
356         Node* child = innerFirstChild(node);
357         while (child) {
358             unbind(child, nodesMap);
359             child = innerNextSibling(child);
360         }
361     }
362 }
363
364 Node* InspectorDOMAgent::assertNode(ErrorString* errorString, int nodeId)
365 {
366     Node* node = nodeForId(nodeId);
367     if (!node) {
368         *errorString = "Could not find node with given id";
369         return nullptr;
370     }
371     return node;
372 }
373
374 Document* InspectorDOMAgent::assertDocument(ErrorString* errorString, int nodeId)
375 {
376     Node* node = assertNode(errorString, nodeId);
377     if (!node)
378         return nullptr;
379     if (!node->isDocumentNode()) {
380         *errorString = "Document is not available";
381         return nullptr;
382     }
383     return toDocument(node);
384 }
385
386 Element* InspectorDOMAgent::assertElement(ErrorString* errorString, int nodeId)
387 {
388     Node* node = assertNode(errorString, nodeId);
389     if (!node)
390         return nullptr;
391     if (!node->isElementNode()) {
392         *errorString = "Node is not an Element";
393         return nullptr;
394     }
395     return toElement(node);
396 }
397
398 Node* InspectorDOMAgent::assertEditableNode(ErrorString* errorString, int nodeId)
399 {
400     Node* node = assertNode(errorString, nodeId);
401     if (!node)
402         return nullptr;
403     if (node->isInShadowTree()) {
404         *errorString = "Can not edit nodes from shadow trees";
405         return nullptr;
406     }
407     return node;
408 }
409
410 Element* InspectorDOMAgent::assertEditableElement(ErrorString* errorString, int nodeId)
411 {
412     Element* element = assertElement(errorString, nodeId);
413     if (!element)
414         return nullptr;
415     if (element->isInShadowTree()) {
416         *errorString = "Can not edit elements from shadow trees";
417         return nullptr;
418     }
419     return element;
420 }
421
422 void InspectorDOMAgent::getDocument(ErrorString* errorString, RefPtr<Inspector::TypeBuilder::DOM::Node>& root)
423 {
424     m_documentRequested = true;
425
426     if (!m_document) {
427         *errorString = "Document is not available";
428         return;
429     }
430
431     // Reset backend state.
432     RefPtr<Document> document = m_document;
433     reset();
434     m_document = document;
435
436     root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
437 }
438
439 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth)
440 {
441     Node* node = nodeForId(nodeId);
442     if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
443         return;
444
445     NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
446
447     if (m_childrenRequested.contains(nodeId)) {
448         if (depth <= 1)
449             return;
450
451         depth--;
452
453         for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
454             int childNodeId = nodeMap->get(node);
455             ASSERT(childNodeId);
456             pushChildNodesToFrontend(childNodeId, depth);
457         }
458
459         return;
460     }
461
462     RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> children = buildArrayForContainerChildren(node, depth, nodeMap);
463     m_frontendDispatcher->setChildNodes(nodeId, children.release());
464 }
465
466 void InspectorDOMAgent::discardBindings()
467 {
468     m_documentNodeToIdMap.clear();
469     m_idToNode.clear();
470     releaseDanglingNodes();
471     m_childrenRequested.clear();
472     m_backendIdToNode.clear();
473     m_nodeGroupToBackendIdMap.clear();
474 }
475
476 int InspectorDOMAgent::pushNodeToFrontend(ErrorString* errorString, int documentNodeId, Node* nodeToPush)
477 {
478     Document* document = assertDocument(errorString, documentNodeId);
479     if (!document)
480         return 0;
481     if (&nodeToPush->document() != document) {
482         *errorString = "Node is not part of the document with given id";
483         return 0;
484     }
485
486     return pushNodePathToFrontend(nodeToPush);
487 }
488
489 Node* InspectorDOMAgent::nodeForId(int id)
490 {
491     if (!id)
492         return 0;
493
494     HashMap<int, Node*>::iterator it = m_idToNode.find(id);
495     if (it != m_idToNode.end())
496         return it->value;
497     return 0;
498 }
499
500 void InspectorDOMAgent::requestChildNodes(ErrorString* errorString, int nodeId, const int* depth)
501 {
502     int sanitizedDepth;
503
504     if (!depth)
505         sanitizedDepth = 1;
506     else if (*depth == -1)
507         sanitizedDepth = INT_MAX;
508     else if (*depth > 0)
509         sanitizedDepth = *depth;
510     else {
511         *errorString = "Please provide a positive integer as a depth or -1 for entire subtree";
512         return;
513     }
514
515     pushChildNodesToFrontend(nodeId, sanitizedDepth);
516 }
517
518 void InspectorDOMAgent::querySelector(ErrorString* errorString, int nodeId, const String& selectors, int* elementId)
519 {
520     *elementId = 0;
521     Node* node = assertNode(errorString, nodeId);
522     if (!node)
523         return;
524     if (!node->isContainerNode()) {
525         assertElement(errorString, nodeId);
526         return;
527     }
528
529     ExceptionCode ec = 0;
530     RefPtr<Element> element = toContainerNode(node)->querySelector(selectors, ec);
531     if (ec) {
532         *errorString = "DOM Error while querying";
533         return;
534     }
535
536     if (element)
537         *elementId = pushNodePathToFrontend(element.get());
538 }
539
540 void InspectorDOMAgent::querySelectorAll(ErrorString* errorString, int nodeId, const String& selectors, RefPtr<Inspector::TypeBuilder::Array<int>>& result)
541 {
542     Node* node = assertNode(errorString, nodeId);
543     if (!node)
544         return;
545     if (!node->isContainerNode()) {
546         assertElement(errorString, nodeId);
547         return;
548     }
549
550     ExceptionCode ec = 0;
551     RefPtr<NodeList> nodes = toContainerNode(node)->querySelectorAll(selectors, ec);
552     if (ec) {
553         *errorString = "DOM Error while querying";
554         return;
555     }
556
557     result = Inspector::TypeBuilder::Array<int>::create();
558
559     for (unsigned i = 0; i < nodes->length(); ++i)
560         result->addItem(pushNodePathToFrontend(nodes->item(i)));
561 }
562
563 int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
564 {
565     ASSERT(nodeToPush);  // Invalid input
566
567     if (!m_document)
568         return 0;
569     if (!m_documentNodeToIdMap.contains(m_document))
570         return 0;
571
572     // Return id in case the node is known.
573     int result = m_documentNodeToIdMap.get(nodeToPush);
574     if (result)
575         return result;
576
577     Node* node = nodeToPush;
578     Vector<Node*> path;
579     NodeToIdMap* danglingMap = 0;
580
581     while (true) {
582         Node* parent = innerParentNode(node);
583         if (!parent) {
584             // Node being pushed is detached -> push subtree root.
585             OwnPtr<NodeToIdMap> newMap = adoptPtr(new NodeToIdMap);
586             danglingMap = newMap.get();
587             m_danglingNodeToIdMaps.append(newMap.release());
588             RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> children = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>::create();
589             children->addItem(buildObjectForNode(node, 0, danglingMap));
590             m_frontendDispatcher->setChildNodes(0, children);
591             break;
592         } else {
593             path.append(parent);
594             if (m_documentNodeToIdMap.get(parent))
595                 break;
596             else
597                 node = parent;
598         }
599     }
600
601     NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
602     for (int i = path.size() - 1; i >= 0; --i) {
603         int nodeId = map->get(path.at(i));
604         ASSERT(nodeId);
605         pushChildNodesToFrontend(nodeId);
606     }
607     return map->get(nodeToPush);
608 }
609
610 int InspectorDOMAgent::boundNodeId(Node* node)
611 {
612     return m_documentNodeToIdMap.get(node);
613 }
614
615 BackendNodeId InspectorDOMAgent::backendNodeIdForNode(Node* node, const String& nodeGroup)
616 {
617     if (!node)
618         return 0;
619
620     if (!m_nodeGroupToBackendIdMap.contains(nodeGroup))
621         m_nodeGroupToBackendIdMap.set(nodeGroup, NodeToBackendIdMap());
622
623     NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
624     BackendNodeId id = map.get(node);
625     if (!id) {
626         id = --m_lastBackendNodeId;
627         map.set(node, id);
628         m_backendIdToNode.set(id, std::make_pair(node, nodeGroup));
629     }
630
631     return id;
632 }
633
634 void InspectorDOMAgent::releaseBackendNodeIds(ErrorString* errorString, const String& nodeGroup)
635 {
636     if (m_nodeGroupToBackendIdMap.contains(nodeGroup)) {
637         NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
638         for (NodeToBackendIdMap::iterator it = map.begin(); it != map.end(); ++it)
639             m_backendIdToNode.remove(it->value);
640         m_nodeGroupToBackendIdMap.remove(nodeGroup);
641         return;
642     }
643     *errorString = "Group name not found";
644 }
645
646 void InspectorDOMAgent::setAttributeValue(ErrorString* errorString, int elementId, const String& name, const String& value)
647 {
648     Element* element = assertEditableElement(errorString, elementId);
649     if (!element)
650         return;
651
652     m_domEditor->setAttribute(element, name, value, errorString);
653 }
654
655 void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elementId, const String& text, const String* const name)
656 {
657     Element* element = assertEditableElement(errorString, elementId);
658     if (!element)
659         return;
660
661     RefPtr<HTMLElement> parsedElement = createHTMLElement(element->document(), spanTag);
662     ExceptionCode ec = 0;
663     parsedElement.get()->setInnerHTML("<span " + text + "></span>", ec);
664     if (ec) {
665         *errorString = InspectorDOMAgent::toErrorString(ec);
666         return;
667     }
668
669     Node* child = parsedElement->firstChild();
670     if (!child) {
671         *errorString = "Could not parse value as attributes";
672         return;
673     }
674
675     Element* childElement = toElement(child);
676     if (!childElement->hasAttributes() && name) {
677         m_domEditor->removeAttribute(element, *name, errorString);
678         return;
679     }
680
681     bool foundOriginalAttribute = false;
682     for (const Attribute& attribute : childElement->attributesIterator()) {
683         // Add attribute pair
684         foundOriginalAttribute = foundOriginalAttribute || (name && attribute.name().toString() == *name);
685         if (!m_domEditor->setAttribute(element, attribute.name().toString(), attribute.value(), errorString))
686             return;
687     }
688
689     if (!foundOriginalAttribute && name && !name->stripWhiteSpace().isEmpty())
690         m_domEditor->removeAttribute(element, *name, errorString);
691 }
692
693 void InspectorDOMAgent::removeAttribute(ErrorString* errorString, int elementId, const String& name)
694 {
695     Element* element = assertEditableElement(errorString, elementId);
696     if (!element)
697         return;
698
699     m_domEditor->removeAttribute(element, name, errorString);
700 }
701
702 void InspectorDOMAgent::removeNode(ErrorString* errorString, int nodeId)
703 {
704     Node* node = assertEditableNode(errorString, nodeId);
705     if (!node)
706         return;
707
708     ContainerNode* parentNode = node->parentNode();
709     if (!parentNode) {
710         *errorString = "Can not remove detached node";
711         return;
712     }
713
714     m_domEditor->removeChild(parentNode, node, errorString);
715 }
716
717 void InspectorDOMAgent::setNodeName(ErrorString* errorString, int nodeId, const String& tagName, int* newId)
718 {
719     *newId = 0;
720
721     Node* oldNode = nodeForId(nodeId);
722     if (!oldNode || !oldNode->isElementNode())
723         return;
724
725     ExceptionCode ec = 0;
726     RefPtr<Element> newElem = oldNode->document().createElement(tagName, ec);
727     if (ec)
728         return;
729
730     // Copy over the original node's attributes.
731     newElem->cloneAttributesFromElement(*toElement(oldNode));
732
733     // Copy over the original node's children.
734     Node* child;
735     while ((child = oldNode->firstChild())) {
736         if (!m_domEditor->insertBefore(newElem.get(), child, 0, errorString))
737             return;
738     }
739
740     // Replace the old node with the new node
741     ContainerNode* parent = oldNode->parentNode();
742     if (!m_domEditor->insertBefore(parent, newElem.get(), oldNode->nextSibling(), errorString))
743         return;
744     if (!m_domEditor->removeChild(parent, oldNode, errorString))
745         return;
746
747     *newId = pushNodePathToFrontend(newElem.get());
748     if (m_childrenRequested.contains(nodeId))
749         pushChildNodesToFrontend(*newId);
750 }
751
752 void InspectorDOMAgent::getOuterHTML(ErrorString* errorString, int nodeId, WTF::String* outerHTML)
753 {
754     Node* node = assertNode(errorString, nodeId);
755     if (!node)
756         return;
757
758     *outerHTML = createMarkup(*node);
759 }
760
761 void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML)
762 {
763     if (!nodeId) {
764         DOMPatchSupport domPatchSupport(m_domEditor.get(), m_document.get());
765         domPatchSupport.patchDocument(outerHTML);
766         return;
767     }
768
769     Node* node = assertEditableNode(errorString, nodeId);
770     if (!node)
771         return;
772
773     Document& document = node->document();
774     if (!document.isHTMLDocument() && !document.isXHTMLDocument()
775 #if ENABLE(SVG)
776         && !document.isSVGDocument()
777 #endif
778     ) {
779         *errorString = "Not an HTML/XML document";
780         return;
781     }
782
783     Node* newNode = 0;
784     if (!m_domEditor->setOuterHTML(*node, outerHTML, &newNode, errorString))
785         return;
786
787     if (!newNode) {
788         // The only child node has been deleted.
789         return;
790     }
791
792     int newId = pushNodePathToFrontend(newNode);
793
794     bool childrenRequested = m_childrenRequested.contains(nodeId);
795     if (childrenRequested)
796         pushChildNodesToFrontend(newId);
797 }
798
799 void InspectorDOMAgent::setNodeValue(ErrorString* errorString, int nodeId, const String& value)
800 {
801     Node* node = assertEditableNode(errorString, nodeId);
802     if (!node)
803         return;
804
805     if (node->nodeType() != Node::TEXT_NODE) {
806         *errorString = "Can only set value of text nodes";
807         return;
808     }
809
810     m_domEditor->replaceWholeText(toText(node), value, errorString);
811 }
812
813 void InspectorDOMAgent::getEventListenersForNode(ErrorString* errorString, int nodeId, const String* objectGroup, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::EventListener>>& listenersArray)
814 {
815     listenersArray = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::EventListener>::create();
816     Node* node = assertNode(errorString, nodeId);
817     if (!node)
818         return;
819     Vector<EventListenerInfo> eventInformation;
820     getEventListeners(node, eventInformation, true);
821
822     // Get Capturing Listeners (in this order)
823     size_t eventInformationLength = eventInformation.size();
824     for (size_t i = 0; i < eventInformationLength; ++i) {
825         const EventListenerInfo& info = eventInformation[i];
826         const EventListenerVector& vector = info.eventListenerVector;
827         for (size_t j = 0; j < vector.size(); ++j) {
828             const RegisteredEventListener& listener = vector[j];
829             if (listener.useCapture)
830                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
831         }
832     }
833
834     // Get Bubbling Listeners (reverse order)
835     for (size_t i = eventInformationLength; i; --i) {
836         const EventListenerInfo& info = eventInformation[i - 1];
837         const EventListenerVector& vector = info.eventListenerVector;
838         for (size_t j = 0; j < vector.size(); ++j) {
839             const RegisteredEventListener& listener = vector[j];
840             if (!listener.useCapture)
841                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
842         }
843     }
844 }
845
846 void InspectorDOMAgent::getEventListeners(Node* node, Vector<EventListenerInfo>& eventInformation, bool includeAncestors)
847 {
848     // The Node's Ancestors including self.
849     Vector<Node*> ancestors;
850     // Push this node as the firs element.
851     ancestors.append(node);
852     if (includeAncestors) {
853         for (ContainerNode* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
854             ancestors.append(ancestor);
855     }
856
857     // Nodes and their Listeners for the concerned event types (order is top to bottom)
858     for (size_t i = ancestors.size(); i; --i) {
859         Node* ancestor = ancestors[i - 1];
860         EventTargetData* d = ancestor->eventTargetData();
861         if (!d)
862             continue;
863         // Get the list of event types this Node is concerned with
864         Vector<AtomicString> eventTypes = d->eventListenerMap.eventTypes();
865         for (size_t j = 0; j < eventTypes.size(); ++j) {
866             AtomicString& type = eventTypes[j];
867             const EventListenerVector& listeners = ancestor->getEventListeners(type);
868             EventListenerVector filteredListeners;
869             filteredListeners.reserveCapacity(listeners.size());
870             for (size_t k = 0; k < listeners.size(); ++k) {
871                 if (listeners[k].listener->type() == EventListener::JSEventListenerType)
872                     filteredListeners.append(listeners[k]);
873             }
874             if (!filteredListeners.isEmpty())
875                 eventInformation.append(EventListenerInfo(ancestor, type, filteredListeners));
876         }
877     }
878 }
879
880 void InspectorDOMAgent::performSearch(ErrorString* errorString, const String& whitespaceTrimmedQuery, const RefPtr<InspectorArray>* nodeIds, String* searchId, int* resultCount)
881 {
882     // FIXME: Search works with node granularity - number of matches within node is not calculated.
883     InspectorNodeFinder finder(whitespaceTrimmedQuery);
884
885     if (nodeIds) {
886         const RefPtr<InspectorArray>& nodeIdsRef = *nodeIds;
887         for (unsigned i = 0; i < nodeIdsRef->length(); ++i) {
888             RefPtr<InspectorValue> nodeValue = nodeIdsRef->get(i);
889             if (!nodeValue) {
890                 *errorString = "Invalid nodeIds item.";
891                 return;
892             }
893             int nodeId = 0;
894             if (!nodeValue->asNumber(&nodeId)) {
895                 *errorString = "Invalid nodeIds item type. Expecting integer types.";
896                 return;
897             }
898             Node* node = assertNode(errorString, nodeId);
899             if (!node) {
900                 // assertNode should have filled the errorString for us.
901                 ASSERT(errorString->length());
902                 return;
903             }
904             finder.performSearch(node);
905         }
906     } else if (m_document) {
907         // There's no need to iterate the frames tree because
908         // the search helper will go inside the frame owner elements.
909         finder.performSearch(m_document.get());
910     }
911
912     *searchId = IdentifiersFactory::createIdentifier();
913
914     auto& resultsVector = m_searchResults.add(*searchId, Vector<RefPtr<Node>>()).iterator->value;
915     for (auto iterator = finder.results().begin(); iterator != finder.results().end(); ++iterator)
916         resultsVector.append(*iterator);
917
918     *resultCount = resultsVector.size();
919 }
920
921 void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<Inspector::TypeBuilder::Array<int>>& nodeIds)
922 {
923     SearchResults::iterator it = m_searchResults.find(searchId);
924     if (it == m_searchResults.end()) {
925         *errorString = "No search session with given id found";
926         return;
927     }
928
929     int size = it->value.size();
930     if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
931         *errorString = "Invalid search result range";
932         return;
933     }
934
935     nodeIds = Inspector::TypeBuilder::Array<int>::create();
936     for (int i = fromIndex; i < toIndex; ++i)
937         nodeIds->addItem(pushNodePathToFrontend((it->value)[i].get()));
938 }
939
940 void InspectorDOMAgent::discardSearchResults(ErrorString*, const String& searchId)
941 {
942     m_searchResults.remove(searchId);
943 }
944
945 bool InspectorDOMAgent::handleMousePress()
946 {
947     if (!m_searchingForNode)
948         return false;
949
950     if (Node* node = m_overlay->highlightedNode()) {
951         inspect(node);
952         return true;
953     }
954     return false;
955 }
956
957 bool InspectorDOMAgent::handleTouchEvent(Node* node)
958 {
959     if (!m_searchingForNode)
960         return false;
961     if (node && m_inspectModeHighlightConfig) {
962         m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
963         inspect(node);
964         return true;
965     }
966     return false;
967 }
968
969 void InspectorDOMAgent::inspect(Node* inspectedNode)
970 {
971     ErrorString error;
972     RefPtr<Node> node = inspectedNode;
973     setSearchingForNode(&error, false, 0);
974
975     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
976         node = node->parentNode();
977     m_nodeToFocus = node;
978
979     focusNode();
980 }
981
982 void InspectorDOMAgent::focusNode()
983 {
984     if (!m_frontendDispatcher)
985         return;
986
987     ASSERT(m_nodeToFocus);
988
989     RefPtr<Node> node = m_nodeToFocus.get();
990     m_nodeToFocus = 0;
991
992     Frame* frame = node->document().frame();
993     if (!frame)
994         return;
995
996     JSC::ExecState* scriptState = mainWorldExecState(frame);
997     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
998     if (injectedScript.hasNoValue())
999         return;
1000
1001     injectedScript.inspectObject(InspectorDOMAgent::nodeAsScriptValue(scriptState, node.get()));
1002 }
1003
1004 void InspectorDOMAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
1005 {
1006     if (!m_searchingForNode)
1007         return;
1008
1009     Node* node = result.innerNode();
1010     while (node && node->nodeType() == Node::TEXT_NODE)
1011         node = node->parentNode();
1012     if (node && m_inspectModeHighlightConfig)
1013         m_overlay->highlightNode(node, *m_inspectModeHighlightConfig);
1014 }
1015
1016 void InspectorDOMAgent::setSearchingForNode(ErrorString* errorString, bool enabled, InspectorObject* highlightInspectorObject)
1017 {
1018     if (m_searchingForNode == enabled)
1019         return;
1020     m_searchingForNode = enabled;
1021     if (enabled) {
1022         m_inspectModeHighlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject);
1023         if (!m_inspectModeHighlightConfig)
1024             return;
1025     } else
1026         hideHighlight(errorString);
1027
1028     m_overlay->didSetSearchingForNode(m_searchingForNode);
1029 }
1030
1031 PassOwnPtr<HighlightConfig> InspectorDOMAgent::highlightConfigFromInspectorObject(ErrorString* errorString, InspectorObject* highlightInspectorObject)
1032 {
1033     if (!highlightInspectorObject) {
1034         *errorString = "Internal error: highlight configuration parameter is missing";
1035         return nullptr;
1036     }
1037
1038     OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
1039     bool showInfo = false; // Default: false (do not show a tooltip).
1040     highlightInspectorObject->getBoolean("showInfo", &showInfo);
1041     highlightConfig->showInfo = showInfo;
1042     bool showRulers = false; // Default: false (do not show rulers).
1043     highlightInspectorObject->getBoolean("showRulers", &showRulers);
1044     highlightConfig->showRulers = showRulers;
1045     highlightConfig->content = parseConfigColor("contentColor", highlightInspectorObject);
1046     highlightConfig->contentOutline = parseConfigColor("contentOutlineColor", highlightInspectorObject);
1047     highlightConfig->padding = parseConfigColor("paddingColor", highlightInspectorObject);
1048     highlightConfig->border = parseConfigColor("borderColor", highlightInspectorObject);
1049     highlightConfig->margin = parseConfigColor("marginColor", highlightInspectorObject);
1050     return highlightConfig.release();
1051 }
1052
1053 void InspectorDOMAgent::setInspectModeEnabled(ErrorString* errorString, bool enabled, const RefPtr<InspectorObject>* highlightConfig)
1054 {
1055     setSearchingForNode(errorString, enabled, highlightConfig ? highlightConfig->get() : 0);
1056 }
1057
1058 void InspectorDOMAgent::highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1059 {
1060     OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad(FloatRect(x, y, width, height)));
1061     innerHighlightQuad(quad.release(), color, outlineColor, usePageCoordinates);
1062 }
1063
1064 void InspectorDOMAgent::highlightQuad(ErrorString* errorString, const RefPtr<InspectorArray>& quadArray, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1065 {
1066     OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad());
1067     if (!parseQuad(quadArray, quad.get())) {
1068         *errorString = "Invalid Quad format";
1069         return;
1070     }
1071     innerHighlightQuad(quad.release(), color, outlineColor, usePageCoordinates);
1072 }
1073
1074 void InspectorDOMAgent::innerHighlightQuad(PassOwnPtr<FloatQuad> quad, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor, const bool* usePageCoordinates)
1075 {
1076     OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
1077     highlightConfig->content = parseColor(color);
1078     highlightConfig->contentOutline = parseColor(outlineColor);
1079     highlightConfig->usePageCoordinates = usePageCoordinates ? *usePageCoordinates : false;
1080     m_overlay->highlightQuad(quad, *highlightConfig);
1081 }
1082
1083 void InspectorDOMAgent::highlightNode(ErrorString* errorString, const RefPtr<InspectorObject>& highlightInspectorObject, const int* nodeId, const String* objectId)
1084 {
1085     Node* node = 0;
1086     if (nodeId) {
1087         node = assertNode(errorString, *nodeId);
1088     } else if (objectId) {
1089         node = nodeForObjectId(*objectId);
1090         if (!node)
1091             *errorString = "Node for given objectId not found";
1092     } else
1093         *errorString = "Either nodeId or objectId must be specified";
1094
1095     if (!node)
1096         return;
1097
1098     OwnPtr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject.get());
1099     if (!highlightConfig)
1100         return;
1101
1102     m_overlay->highlightNode(node, *highlightConfig);
1103 }
1104
1105 void InspectorDOMAgent::highlightFrame(
1106     ErrorString*,
1107     const String& frameId,
1108     const RefPtr<InspectorObject>* color,
1109     const RefPtr<InspectorObject>* outlineColor)
1110 {
1111     Frame* frame = m_pageAgent->frameForId(frameId);
1112     if (frame && frame->ownerElement()) {
1113         OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
1114         highlightConfig->showInfo = true; // Always show tooltips for frames.
1115         highlightConfig->content = parseColor(color);
1116         highlightConfig->contentOutline = parseColor(outlineColor);
1117         m_overlay->highlightNode(frame->ownerElement(), *highlightConfig);
1118     }
1119 }
1120
1121 void InspectorDOMAgent::hideHighlight(ErrorString*)
1122 {
1123     m_overlay->hideHighlight();
1124 }
1125
1126 void InspectorDOMAgent::moveTo(ErrorString* errorString, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
1127 {
1128     Node* node = assertEditableNode(errorString, nodeId);
1129     if (!node)
1130         return;
1131
1132     Element* targetElement = assertEditableElement(errorString, targetElementId);
1133     if (!targetElement)
1134         return;
1135
1136     Node* anchorNode = 0;
1137     if (anchorNodeId && *anchorNodeId) {
1138         anchorNode = assertEditableNode(errorString, *anchorNodeId);
1139         if (!anchorNode)
1140             return;
1141         if (anchorNode->parentNode() != targetElement) {
1142             *errorString = "Anchor node must be child of the target element";
1143             return;
1144         }
1145     }
1146
1147     if (!m_domEditor->insertBefore(targetElement, node, anchorNode, errorString))
1148         return;
1149
1150     *newNodeId = pushNodePathToFrontend(node);
1151 }
1152
1153 void InspectorDOMAgent::undo(ErrorString* errorString)
1154 {
1155     ExceptionCode ec = 0;
1156     m_history->undo(ec);
1157     *errorString = InspectorDOMAgent::toErrorString(ec);
1158 }
1159
1160 void InspectorDOMAgent::redo(ErrorString* errorString)
1161 {
1162     ExceptionCode ec = 0;
1163     m_history->redo(ec);
1164     *errorString = InspectorDOMAgent::toErrorString(ec);
1165 }
1166
1167 void InspectorDOMAgent::markUndoableState(ErrorString*)
1168 {
1169     m_history->markUndoableState();
1170 }
1171
1172 void InspectorDOMAgent::focus(ErrorString* errorString, int nodeId)
1173 {
1174     Element* element = assertElement(errorString, nodeId);
1175     if (!element)
1176         return;
1177     if (!element->isFocusable()) {
1178         *errorString = "Element is not focusable";
1179         return;
1180     }
1181     element->focus();
1182 }
1183
1184 void InspectorDOMAgent::resolveNode(ErrorString* errorString, int nodeId, const String* const objectGroup, RefPtr<Inspector::TypeBuilder::Runtime::RemoteObject>& result)
1185 {
1186     String objectGroupName = objectGroup ? *objectGroup : "";
1187     Node* node = nodeForId(nodeId);
1188     if (!node) {
1189         *errorString = "No node with given id found";
1190         return;
1191     }
1192     RefPtr<Inspector::TypeBuilder::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
1193     if (!object) {
1194         *errorString = "Node with given id does not belong to the document";
1195         return;
1196     }
1197     result = object;
1198 }
1199
1200 void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<Inspector::TypeBuilder::Array<String>>& result)
1201 {
1202     Element* element = assertElement(errorString, nodeId);
1203     if (!element)
1204         return;
1205
1206     result = buildArrayForElementAttributes(element);
1207 }
1208
1209 void InspectorDOMAgent::requestNode(ErrorString*, const String& objectId, int* nodeId)
1210 {
1211     Node* node = nodeForObjectId(objectId);
1212     if (node)
1213         *nodeId = pushNodePathToFrontend(node);
1214     else
1215         *nodeId = 0;
1216 }
1217
1218 // static
1219 String InspectorDOMAgent::documentURLString(Document* document)
1220 {
1221     if (!document || document->url().isNull())
1222         return "";
1223     return document->url().string();
1224 }
1225
1226 static String documentBaseURLString(Document* document)
1227 {
1228     return document->completeURL("").string();
1229 }
1230
1231 PassRefPtr<Inspector::TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
1232 {
1233     int id = bind(node, nodesMap);
1234     String nodeName;
1235     String localName;
1236     String nodeValue;
1237
1238     switch (node->nodeType()) {
1239     case Node::TEXT_NODE:
1240     case Node::COMMENT_NODE:
1241     case Node::CDATA_SECTION_NODE:
1242         nodeValue = node->nodeValue();
1243         if (nodeValue.length() > maxTextSize) {
1244             nodeValue = nodeValue.left(maxTextSize);
1245             nodeValue.append(ellipsisUChar);
1246         }
1247         break;
1248     case Node::ATTRIBUTE_NODE:
1249         localName = node->localName();
1250         break;
1251     case Node::DOCUMENT_FRAGMENT_NODE:
1252     case Node::DOCUMENT_NODE:
1253     case Node::ELEMENT_NODE:
1254     default:
1255         nodeName = node->nodeName();
1256         localName = node->localName();
1257         break;
1258     }
1259
1260     RefPtr<Inspector::TypeBuilder::DOM::Node> value = Inspector::TypeBuilder::DOM::Node::create()
1261         .setNodeId(id)
1262         .setNodeType(static_cast<int>(node->nodeType()))
1263         .setNodeName(nodeName)
1264         .setLocalName(localName)
1265         .setNodeValue(nodeValue);
1266
1267     if (node->isContainerNode()) {
1268         int nodeCount = innerChildNodeCount(node);
1269         value->setChildNodeCount(nodeCount);
1270         RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> children = buildArrayForContainerChildren(node, depth, nodesMap);
1271         if (children->length() > 0)
1272             value->setChildren(children.release());
1273     }
1274
1275     if (node->isElementNode()) {
1276         Element* element = toElement(node);
1277         value->setAttributes(buildArrayForElementAttributes(element));
1278         if (node->isFrameOwnerElement()) {
1279             HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node);
1280             Frame* frame = frameOwner->contentFrame();
1281             if (frame)
1282                 value->setFrameId(m_pageAgent->frameId(frame));
1283             Document* doc = frameOwner->contentDocument();
1284             if (doc)
1285                 value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
1286         }
1287
1288         if (ShadowRoot* root = element->shadowRoot()) {
1289             RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> shadowRoots = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>::create();
1290             shadowRoots->addItem(buildObjectForNode(root, 0, nodesMap));
1291             value->setShadowRoots(shadowRoots);
1292         }
1293
1294 #if ENABLE(TEMPLATE_ELEMENT)
1295         if (element->hasTagName(HTMLNames::templateTag))
1296             value->setTemplateContent(buildObjectForNode(toHTMLTemplateElement(element)->content(), 0, nodesMap));
1297 #endif
1298
1299     } else if (node->isDocumentNode()) {
1300         Document* document = toDocument(node);
1301         value->setDocumentURL(documentURLString(document));
1302         value->setBaseURL(documentBaseURLString(document));
1303         value->setXmlVersion(document->xmlVersion());
1304     } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1305         DocumentType* docType = toDocumentType(node);
1306         value->setPublicId(docType->publicId());
1307         value->setSystemId(docType->systemId());
1308         value->setInternalSubset(docType->internalSubset());
1309     } else if (node->isAttributeNode()) {
1310         Attr* attribute = toAttr(node);
1311         value->setName(attribute->name());
1312         value->setValue(attribute->value());
1313     }
1314     return value.release();
1315 }
1316
1317 PassRefPtr<Inspector::TypeBuilder::Array<String>> InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
1318 {
1319     RefPtr<Inspector::TypeBuilder::Array<String>> attributesValue = Inspector::TypeBuilder::Array<String>::create();
1320     // Go through all attributes and serialize them.
1321     if (!element->hasAttributes())
1322         return attributesValue.release();
1323     for (const Attribute& attribute : element->attributesIterator()) {
1324         // Add attribute pair
1325         attributesValue->addItem(attribute.name().toString());
1326         attributesValue->addItem(attribute.value());
1327     }
1328     return attributesValue.release();
1329 }
1330
1331 PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
1332 {
1333     RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>> children = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::DOM::Node>::create();
1334     if (depth == 0) {
1335         // Special-case the only text child - pretend that container's children have been requested.
1336         Node* firstChild = container->firstChild();
1337         if (firstChild && firstChild->nodeType() == Node::TEXT_NODE && !firstChild->nextSibling()) {
1338             children->addItem(buildObjectForNode(firstChild, 0, nodesMap));
1339             m_childrenRequested.add(bind(container, nodesMap));
1340         }
1341         return children.release();
1342     }
1343
1344     Node* child = innerFirstChild(container);
1345     depth--;
1346     m_childrenRequested.add(bind(container, nodesMap));
1347
1348     while (child) {
1349         children->addItem(buildObjectForNode(child, depth, nodesMap));
1350         child = innerNextSibling(child);
1351     }
1352     return children.release();
1353 }
1354
1355 PassRefPtr<Inspector::TypeBuilder::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
1356 {
1357     RefPtr<EventListener> eventListener = registeredEventListener.listener;
1358
1359     JSC::ExecState* state = nullptr;
1360     JSC::JSObject* handler = nullptr;
1361     String body;
1362     int lineNumber = 0;
1363     String scriptID;
1364     String sourceName;
1365     if (auto scriptListener = JSEventListener::cast(eventListener.get())) {
1366         JSC::JSLockHolder lock(scriptListener->isolatedWorld().vm());
1367         state = execStateFromNode(scriptListener->isolatedWorld(), &node->document());
1368         handler = scriptListener->jsFunction(&node->document());
1369         if (handler) {
1370             body = handler->toString(state)->value(state);
1371             if (auto function = JSC::jsDynamicCast<JSC::JSFunction*>(handler)) {
1372                 if (!function->isHostFunction()) {
1373                     if (auto executable = function->jsExecutable()) {
1374                         lineNumber = executable->lineNo() - 1;
1375                         scriptID = executable->sourceID() == JSC::SourceProvider::nullID ? emptyString() : String::number(executable->sourceID());
1376                         sourceName = executable->sourceURL();
1377                     }
1378                 }
1379             }
1380         }
1381     }
1382
1383     RefPtr<Inspector::TypeBuilder::DOM::EventListener> value = Inspector::TypeBuilder::DOM::EventListener::create()
1384         .setType(eventType)
1385         .setUseCapture(registeredEventListener.useCapture)
1386         .setIsAttribute(eventListener->isAttribute())
1387         .setNodeId(pushNodePathToFrontend(node))
1388         .setHandlerBody(body);
1389     if (objectGroupId && handler && state) {
1390         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(state);
1391         if (!injectedScript.hasNoValue())
1392             value->setHandler(injectedScript.wrapObject(Deprecated::ScriptValue(state->vm(), handler), *objectGroupId));
1393     }
1394     if (!scriptID.isNull()) {
1395         RefPtr<Inspector::TypeBuilder::Debugger::Location> location = Inspector::TypeBuilder::Debugger::Location::create()
1396             .setScriptId(scriptID)
1397             .setLineNumber(lineNumber);
1398         value->setLocation(location.release());
1399         if (!sourceName.isEmpty())
1400             value->setSourceName(sourceName);
1401     }
1402     return value.release();
1403 }
1404
1405 Node* InspectorDOMAgent::innerFirstChild(Node* node)
1406 {
1407     node = node->firstChild();
1408     while (isWhitespace(node))
1409         node = node->nextSibling();
1410     return node;
1411 }
1412
1413 Node* InspectorDOMAgent::innerNextSibling(Node* node)
1414 {
1415     do {
1416         node = node->nextSibling();
1417     } while (isWhitespace(node));
1418     return node;
1419 }
1420
1421 Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
1422 {
1423     do {
1424         node = node->previousSibling();
1425     } while (isWhitespace(node));
1426     return node;
1427 }
1428
1429 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
1430 {
1431     unsigned count = 0;
1432     Node* child = innerFirstChild(node);
1433     while (child) {
1434         count++;
1435         child = innerNextSibling(child);
1436     }
1437     return count;
1438 }
1439
1440 Node* InspectorDOMAgent::innerParentNode(Node* node)
1441 {
1442     if (node->isDocumentNode()) {
1443         Document* document = toDocument(node);
1444         return document->ownerElement();
1445     }
1446     return node->parentNode();
1447 }
1448
1449 bool InspectorDOMAgent::isWhitespace(Node* node)
1450 {
1451     //TODO: pull ignoreWhitespace setting from the frontend and use here.
1452     return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
1453 }
1454
1455 void InspectorDOMAgent::mainFrameDOMContentLoaded()
1456 {
1457     // Re-push document once it is loaded.
1458     discardBindings();
1459     if (m_documentRequested)
1460         m_frontendDispatcher->documentUpdated();
1461 }
1462
1463 void InspectorDOMAgent::didCommitLoad(Document* document)
1464 {
1465     Element* frameOwner = document->ownerElement();
1466     if (!frameOwner)
1467         return;
1468
1469     int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
1470     if (!frameOwnerId)
1471         return;
1472
1473     // Re-add frame owner element together with its new children.
1474     int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
1475     m_frontendDispatcher->childNodeRemoved(parentId, frameOwnerId);
1476     unbind(frameOwner, &m_documentNodeToIdMap);
1477
1478     RefPtr<Inspector::TypeBuilder::DOM::Node> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
1479     Node* previousSibling = innerPreviousSibling(frameOwner);
1480     int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
1481     m_frontendDispatcher->childNodeInserted(parentId, prevId, value.release());
1482 }
1483
1484 void InspectorDOMAgent::didInsertDOMNode(Node* node)
1485 {
1486     if (isWhitespace(node))
1487         return;
1488
1489     // We could be attaching existing subtree. Forget the bindings.
1490     unbind(node, &m_documentNodeToIdMap);
1491
1492     ContainerNode* parent = node->parentNode();
1493     if (!parent)
1494         return;
1495
1496     int parentId = m_documentNodeToIdMap.get(parent);
1497     // Return if parent is not mapped yet.
1498     if (!parentId)
1499         return;
1500
1501     if (!m_childrenRequested.contains(parentId)) {
1502         // No children are mapped yet -> only notify on changes of hasChildren.
1503         m_frontendDispatcher->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
1504     } else {
1505         // Children have been requested -> return value of a new child.
1506         Node* prevSibling = innerPreviousSibling(node);
1507         int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
1508         RefPtr<Inspector::TypeBuilder::DOM::Node> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
1509         m_frontendDispatcher->childNodeInserted(parentId, prevId, value.release());
1510     }
1511 }
1512
1513 void InspectorDOMAgent::didRemoveDOMNode(Node* node)
1514 {
1515     if (isWhitespace(node))
1516         return;
1517
1518     ContainerNode* parent = node->parentNode();
1519
1520     // If parent is not mapped yet -> ignore the event.
1521     if (!m_documentNodeToIdMap.contains(parent))
1522         return;
1523
1524     int parentId = m_documentNodeToIdMap.get(parent);
1525
1526     if (!m_childrenRequested.contains(parentId)) {
1527         // No children are mapped yet -> only notify on changes of hasChildren.
1528         if (innerChildNodeCount(parent) == 1)
1529             m_frontendDispatcher->childNodeCountUpdated(parentId, 0);
1530     } else
1531         m_frontendDispatcher->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
1532     unbind(node, &m_documentNodeToIdMap);
1533 }
1534
1535 void InspectorDOMAgent::willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue)
1536 {
1537     m_suppressAttributeModifiedEvent = (oldValue == newValue);
1538 }
1539
1540 void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
1541 {
1542     bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
1543     m_suppressAttributeModifiedEvent = false;
1544     if (shouldSuppressEvent)
1545         return;
1546
1547     int id = boundNodeId(element);
1548     // If node is not mapped yet -> ignore the event.
1549     if (!id)
1550         return;
1551
1552     if (m_domListener)
1553         m_domListener->didModifyDOMAttr(element);
1554
1555     m_frontendDispatcher->attributeModified(id, name, value);
1556 }
1557
1558 void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
1559 {
1560     int id = boundNodeId(element);
1561     // If node is not mapped yet -> ignore the event.
1562     if (!id)
1563         return;
1564
1565     if (m_domListener)
1566         m_domListener->didModifyDOMAttr(element);
1567
1568     m_frontendDispatcher->attributeRemoved(id, name);
1569 }
1570
1571 void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
1572 {
1573     RefPtr<Inspector::TypeBuilder::Array<int>> nodeIds = Inspector::TypeBuilder::Array<int>::create();
1574     for (unsigned i = 0, size = elements.size(); i < size; ++i) {
1575         Element* element = elements.at(i);
1576         int id = boundNodeId(element);
1577         // If node is not mapped yet -> ignore the event.
1578         if (!id)
1579             continue;
1580
1581         if (m_domListener)
1582             m_domListener->didModifyDOMAttr(element);
1583         nodeIds->addItem(id);
1584     }
1585     m_frontendDispatcher->inlineStyleInvalidated(nodeIds.release());
1586 }
1587
1588 void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
1589 {
1590     int id = m_documentNodeToIdMap.get(characterData);
1591     if (!id) {
1592         // Push text node if it is being created.
1593         didInsertDOMNode(characterData);
1594         return;
1595     }
1596     m_frontendDispatcher->characterDataModified(id, characterData->data());
1597 }
1598
1599 void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
1600 {
1601     int id = m_documentNodeToIdMap.get(node);
1602     // If node is not mapped yet -> ignore the event.
1603     if (!id)
1604         return;
1605
1606     if (!m_revalidateStyleAttrTask)
1607         m_revalidateStyleAttrTask = adoptPtr(new RevalidateStyleAttributeTask(this));
1608     m_revalidateStyleAttrTask->scheduleFor(toElement(node));
1609 }
1610
1611 void InspectorDOMAgent::didPushShadowRoot(Element* host, ShadowRoot* root)
1612 {
1613     int hostId = m_documentNodeToIdMap.get(host);
1614     if (hostId)
1615         m_frontendDispatcher->shadowRootPushed(hostId, buildObjectForNode(root, 0, &m_documentNodeToIdMap));
1616 }
1617
1618 void InspectorDOMAgent::willPopShadowRoot(Element* host, ShadowRoot* root)
1619 {
1620     int hostId = m_documentNodeToIdMap.get(host);
1621     int rootId = m_documentNodeToIdMap.get(root);
1622     if (hostId && rootId)
1623         m_frontendDispatcher->shadowRootPopped(hostId, rootId);
1624 }
1625
1626 void InspectorDOMAgent::frameDocumentUpdated(Frame* frame)
1627 {
1628     Document* document = frame->document();
1629     if (!document)
1630         return;
1631
1632     Page* page = frame->page();
1633     ASSERT(page);
1634     if (frame != &page->mainFrame())
1635         return;
1636
1637     // Only update the main frame document, nested frame document updates are not required
1638     // (will be handled by didCommitLoad()).
1639     setDocument(document);
1640 }
1641
1642 Node* InspectorDOMAgent::nodeForPath(const String& path)
1643 {
1644     // The path is of form "1,HTML,2,BODY,1,DIV"
1645     if (!m_document)
1646         return 0;
1647
1648     Node* node = m_document.get();
1649     Vector<String> pathTokens;
1650     path.split(",", false, pathTokens);
1651     if (!pathTokens.size())
1652         return 0;
1653     for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
1654         bool success = true;
1655         unsigned childNumber = pathTokens[i].toUInt(&success);
1656         if (!success)
1657             return 0;
1658         if (childNumber >= innerChildNodeCount(node))
1659             return 0;
1660
1661         Node* child = innerFirstChild(node);
1662         String childName = pathTokens[i + 1];
1663         for (size_t j = 0; child && j < childNumber; ++j)
1664             child = innerNextSibling(child);
1665
1666         if (!child || child->nodeName() != childName)
1667             return 0;
1668         node = child;
1669     }
1670     return node;
1671 }
1672
1673 Node* InspectorDOMAgent::nodeForObjectId(const String& objectId)
1674 {
1675     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
1676     Deprecated::ScriptValue value = injectedScript.findObjectById(objectId);
1677     return InspectorDOMAgent::scriptValueAsNode(value);
1678 }
1679
1680 void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString* errorString, const String& path, int* nodeId)
1681 {
1682     if (Node* node = nodeForPath(path))
1683         *nodeId = pushNodePathToFrontend(node);
1684     else
1685         *errorString = "No node with given path found";
1686 }
1687
1688 void InspectorDOMAgent::pushNodeByBackendIdToFrontend(ErrorString* errorString, BackendNodeId backendNodeId, int* nodeId)
1689 {
1690     if (!m_backendIdToNode.contains(backendNodeId)) {
1691         *errorString = "No node with given backend id found";
1692         return;
1693     }
1694
1695     Node* node = m_backendIdToNode.get(backendNodeId).first;
1696     String nodeGroup = m_backendIdToNode.get(backendNodeId).second;
1697     *nodeId = pushNodePathToFrontend(node);
1698
1699     if (nodeGroup == "") {
1700         m_backendIdToNode.remove(backendNodeId);
1701         m_nodeGroupToBackendIdMap.find(nodeGroup)->value.remove(node);
1702     }
1703 }
1704
1705 PassRefPtr<Inspector::TypeBuilder::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
1706 {
1707     Frame* frame = node->document().frame();
1708     if (!frame)
1709         return 0;
1710
1711     JSC::ExecState* scriptState = mainWorldExecState(frame);
1712     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
1713     if (injectedScript.hasNoValue())
1714         return 0;
1715
1716     return injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(scriptState, node), objectGroup);
1717 }
1718
1719 Node* InspectorDOMAgent::scriptValueAsNode(Deprecated::ScriptValue value)
1720 {
1721     if (!value.isObject() || value.isNull())
1722         return nullptr;
1723
1724     return toNode(value.jsValue());
1725 }
1726
1727 Deprecated::ScriptValue InspectorDOMAgent::nodeAsScriptValue(JSC::ExecState* state, Node* node)
1728 {
1729     if (!shouldAllowAccessToNode(state, node))
1730         return Deprecated::ScriptValue(state->vm(), JSC::jsNull());
1731
1732     JSC::JSLockHolder lock(state);
1733     return Deprecated::ScriptValue(state->vm(), toJS(state, deprecatedGlobalObjectForPrototype(state), node));
1734 }
1735
1736 } // namespace WebCore
1737
1738 #endif // ENABLE(INSPECTOR)