Home | History | Annotate | Download | only in inspector
      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 #include "core/inspector/InspectorDOMAgent.h"
     33 
     34 #include "HTMLNames.h"
     35 #include "bindings/v8/ExceptionState.h"
     36 #include "bindings/v8/ScriptEventListener.h"
     37 #include "core/dom/Attr.h"
     38 #include "core/dom/CharacterData.h"
     39 #include "core/dom/ContainerNode.h"
     40 #include "core/dom/DOMException.h"
     41 #include "core/dom/Document.h"
     42 #include "core/dom/DocumentFragment.h"
     43 #include "core/dom/DocumentType.h"
     44 #include "core/dom/Element.h"
     45 #include "core/events/EventListener.h"
     46 #include "core/events/EventTarget.h"
     47 #include "core/dom/Node.h"
     48 #include "core/dom/NodeList.h"
     49 #include "core/dom/NodeTraversal.h"
     50 #include "core/dom/PseudoElement.h"
     51 #include "core/dom/Text.h"
     52 #include "core/dom/shadow/ElementShadow.h"
     53 #include "core/dom/shadow/ShadowRoot.h"
     54 #include "core/editing/markup.h"
     55 #include "core/fileapi/File.h"
     56 #include "core/fileapi/FileList.h"
     57 #include "core/html/HTMLFrameOwnerElement.h"
     58 #include "core/html/HTMLInputElement.h"
     59 #include "core/html/HTMLTemplateElement.h"
     60 #include "core/inspector/DOMEditor.h"
     61 #include "core/inspector/DOMPatchSupport.h"
     62 #include "core/inspector/IdentifiersFactory.h"
     63 #include "core/inspector/InspectorHistory.h"
     64 #include "core/inspector/InspectorOverlay.h"
     65 #include "core/inspector/InspectorPageAgent.h"
     66 #include "core/inspector/InspectorState.h"
     67 #include "core/inspector/InstrumentingAgents.h"
     68 #include "core/loader/DocumentLoader.h"
     69 #include "core/frame/Frame.h"
     70 #include "core/page/FrameTree.h"
     71 #include "core/page/Page.h"
     72 #include "core/rendering/HitTestResult.h"
     73 #include "core/rendering/RenderView.h"
     74 #include "core/xml/DocumentXPathEvaluator.h"
     75 #include "core/xml/XPathResult.h"
     76 #include "platform/PlatformGestureEvent.h"
     77 #include "platform/PlatformMouseEvent.h"
     78 #include "platform/PlatformTouchEvent.h"
     79 #include "wtf/ListHashSet.h"
     80 #include "wtf/text/CString.h"
     81 #include "wtf/text/WTFString.h"
     82 
     83 namespace WebCore {
     84 
     85 using namespace HTMLNames;
     86 
     87 namespace DOMAgentState {
     88 static const char documentRequested[] = "documentRequested";
     89 };
     90 
     91 static const size_t maxTextSize = 10000;
     92 static const UChar ellipsisUChar[] = { 0x2026, 0 };
     93 
     94 static Color parseColor(const RefPtr<JSONObject>* colorObject)
     95 {
     96     if (!colorObject || !(*colorObject))
     97         return Color::transparent;
     98 
     99     int r;
    100     int g;
    101     int b;
    102     bool success = (*colorObject)->getNumber("r", &r);
    103     success |= (*colorObject)->getNumber("g", &g);
    104     success |= (*colorObject)->getNumber("b", &b);
    105     if (!success)
    106         return Color::transparent;
    107 
    108     double a;
    109     success = (*colorObject)->getNumber("a", &a);
    110     if (!success)
    111         return Color(r, g, b);
    112 
    113     // Clamp alpha to the [0..1] range.
    114     if (a < 0)
    115         a = 0;
    116     else if (a > 1)
    117         a = 1;
    118 
    119     return Color(r, g, b, static_cast<int>(a * 255));
    120 }
    121 
    122 static Color parseConfigColor(const String& fieldName, JSONObject* configObject)
    123 {
    124     const RefPtr<JSONObject> colorObject = configObject->getObject(fieldName);
    125     return parseColor(&colorObject);
    126 }
    127 
    128 static bool parseQuad(const RefPtr<JSONArray>& quadArray, FloatQuad* quad)
    129 {
    130     if (!quadArray)
    131         return false;
    132     const size_t coordinatesInQuad = 8;
    133     double coordinates[coordinatesInQuad];
    134     if (quadArray->length() != coordinatesInQuad)
    135         return false;
    136     for (size_t i = 0; i < coordinatesInQuad; ++i) {
    137         if (!quadArray->get(i)->asNumber(coordinates + i))
    138             return false;
    139     }
    140     quad->setP1(FloatPoint(coordinates[0], coordinates[1]));
    141     quad->setP2(FloatPoint(coordinates[2], coordinates[3]));
    142     quad->setP3(FloatPoint(coordinates[4], coordinates[5]));
    143     quad->setP4(FloatPoint(coordinates[6], coordinates[7]));
    144 
    145     return true;
    146 }
    147 
    148 static Node* hoveredNodeForPoint(Frame* frame, const IntPoint& point, bool ignorePointerEventsNone)
    149 {
    150     HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent;
    151     if (ignorePointerEventsNone)
    152         hitType |= HitTestRequest::IgnorePointerEventsNone;
    153     HitTestRequest request(hitType);
    154     HitTestResult result(frame->view()->windowToContents(point));
    155     frame->contentRenderer()->hitTest(request, result);
    156     Node* node = result.innerPossiblyPseudoNode();
    157     while (node && node->nodeType() == Node::TEXT_NODE)
    158         node = node->parentNode();
    159     return node;
    160 }
    161 
    162 static Node* hoveredNodeForEvent(Frame* frame, const PlatformGestureEvent& event, bool ignorePointerEventsNone)
    163 {
    164     return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone);
    165 }
    166 
    167 static Node* hoveredNodeForEvent(Frame* frame, const PlatformMouseEvent& event, bool ignorePointerEventsNone)
    168 {
    169     return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone);
    170 }
    171 
    172 static Node* hoveredNodeForEvent(Frame* frame, const PlatformTouchEvent& event, bool ignorePointerEventsNone)
    173 {
    174     const Vector<PlatformTouchPoint>& points = event.touchPoints();
    175     if (!points.size())
    176         return 0;
    177     return hoveredNodeForPoint(frame, points[0].pos(), ignorePointerEventsNone);
    178 }
    179 
    180 class RevalidateStyleAttributeTask {
    181     WTF_MAKE_FAST_ALLOCATED;
    182 public:
    183     RevalidateStyleAttributeTask(InspectorDOMAgent*);
    184     void scheduleFor(Element*);
    185     void reset() { m_timer.stop(); }
    186     void onTimer(Timer<RevalidateStyleAttributeTask>*);
    187 
    188 private:
    189     InspectorDOMAgent* m_domAgent;
    190     Timer<RevalidateStyleAttributeTask> m_timer;
    191     HashSet<RefPtr<Element> > m_elements;
    192 };
    193 
    194 RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
    195     : m_domAgent(domAgent)
    196     , m_timer(this, &RevalidateStyleAttributeTask::onTimer)
    197 {
    198 }
    199 
    200 void RevalidateStyleAttributeTask::scheduleFor(Element* element)
    201 {
    202     m_elements.add(element);
    203     if (!m_timer.isActive())
    204         m_timer.startOneShot(0);
    205 }
    206 
    207 void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
    208 {
    209     // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
    210     Vector<Element*> elements;
    211     for (HashSet<RefPtr<Element> >::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
    212         elements.append(it->get());
    213     m_domAgent->styleAttributeInvalidated(elements);
    214 
    215     m_elements.clear();
    216 }
    217 
    218 String InspectorDOMAgent::toErrorString(ExceptionState& exceptionState)
    219 {
    220     if (exceptionState.hadException())
    221         return DOMException::getErrorName(exceptionState.code());
    222     return "";
    223 }
    224 
    225 InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay, InspectorClient* client)
    226     : InspectorBaseAgent<InspectorDOMAgent>("DOM", instrumentingAgents, inspectorState)
    227     , m_pageAgent(pageAgent)
    228     , m_injectedScriptManager(injectedScriptManager)
    229     , m_overlay(overlay)
    230     , m_client(client)
    231     , m_frontend(0)
    232     , m_domListener(0)
    233     , m_lastNodeId(1)
    234     , m_lastBackendNodeId(-1)
    235     , m_searchingForNode(NotSearching)
    236     , m_suppressAttributeModifiedEvent(false)
    237 {
    238 }
    239 
    240 InspectorDOMAgent::~InspectorDOMAgent()
    241 {
    242     reset();
    243     ASSERT(m_searchingForNode == NotSearching);
    244 }
    245 
    246 void InspectorDOMAgent::setFrontend(InspectorFrontend* frontend)
    247 {
    248     ASSERT(!m_frontend);
    249     m_history = adoptPtr(new InspectorHistory());
    250     m_domEditor = adoptPtr(new DOMEditor(m_history.get()));
    251 
    252     m_frontend = frontend->dom();
    253     m_instrumentingAgents->setInspectorDOMAgent(this);
    254     m_document = m_pageAgent->mainFrame()->document();
    255 }
    256 
    257 void InspectorDOMAgent::clearFrontend()
    258 {
    259     ASSERT(m_frontend);
    260 
    261     m_history.clear();
    262     m_domEditor.clear();
    263 
    264     ErrorString error;
    265     setSearchingForNode(&error, NotSearching, 0);
    266     hideHighlight(&error);
    267 
    268     m_frontend = 0;
    269     m_instrumentingAgents->setInspectorDOMAgent(0);
    270     m_state->setBoolean(DOMAgentState::documentRequested, false);
    271     reset();
    272 }
    273 
    274 void InspectorDOMAgent::restore()
    275 {
    276     // Reset document to avoid early return from setDocument.
    277     m_document = 0;
    278     setDocument(m_pageAgent->mainFrame()->document());
    279 }
    280 
    281 Vector<Document*> InspectorDOMAgent::documents()
    282 {
    283     Vector<Document*> result;
    284     for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
    285         Document* document = frame->document();
    286         if (!document)
    287             continue;
    288         result.append(document);
    289     }
    290     return result;
    291 }
    292 
    293 void InspectorDOMAgent::reset()
    294 {
    295     discardFrontendBindings();
    296     discardBackendBindings();
    297     m_document = 0;
    298 }
    299 
    300 void InspectorDOMAgent::setDOMListener(DOMListener* listener)
    301 {
    302     m_domListener = listener;
    303 }
    304 
    305 void InspectorDOMAgent::setDocument(Document* doc)
    306 {
    307     if (doc == m_document.get())
    308         return;
    309 
    310     reset();
    311 
    312     m_document = doc;
    313 
    314     if (!m_state->getBoolean(DOMAgentState::documentRequested))
    315         return;
    316 
    317     // Immediately communicate 0 document or document that has finished loading.
    318     if (!doc || !doc->parsing())
    319         m_frontend->documentUpdated();
    320 }
    321 
    322 void InspectorDOMAgent::releaseDanglingNodes()
    323 {
    324     m_danglingNodeToIdMaps.clear();
    325 }
    326 
    327 int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
    328 {
    329     int id = nodesMap->get(node);
    330     if (id)
    331         return id;
    332     id = m_lastNodeId++;
    333     nodesMap->set(node, id);
    334     m_idToNode.set(id, node);
    335     m_idToNodesMap.set(id, nodesMap);
    336     return id;
    337 }
    338 
    339 void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
    340 {
    341     int id = nodesMap->get(node);
    342     if (!id)
    343         return;
    344 
    345     m_idToNode.remove(id);
    346 
    347     if (node->isFrameOwnerElement()) {
    348         Document* contentDocument = toHTMLFrameOwnerElement(node)->contentDocument();
    349         if (m_domListener)
    350             m_domListener->didRemoveDocument(contentDocument);
    351         if (contentDocument)
    352             unbind(contentDocument, nodesMap);
    353     }
    354 
    355     for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
    356         unbind(root, nodesMap);
    357 
    358     if (node->isElementNode()) {
    359         Element* element = toElement(node);
    360         if (element->pseudoElement(BEFORE))
    361             unbind(element->pseudoElement(BEFORE), nodesMap);
    362         if (element->pseudoElement(AFTER))
    363             unbind(element->pseudoElement(AFTER), nodesMap);
    364     }
    365 
    366     nodesMap->remove(node);
    367     if (m_domListener)
    368         m_domListener->didRemoveDOMNode(node);
    369 
    370     bool childrenRequested = m_childrenRequested.contains(id);
    371     if (childrenRequested) {
    372         // Unbind subtree known to client recursively.
    373         m_childrenRequested.remove(id);
    374         Node* child = innerFirstChild(node);
    375         while (child) {
    376             unbind(child, nodesMap);
    377             child = innerNextSibling(child);
    378         }
    379     }
    380 }
    381 
    382 Node* InspectorDOMAgent::assertNode(ErrorString* errorString, int nodeId)
    383 {
    384     Node* node = nodeForId(nodeId);
    385     if (!node) {
    386         *errorString = "Could not find node with given id";
    387         return 0;
    388     }
    389     return node;
    390 }
    391 
    392 Document* InspectorDOMAgent::assertDocument(ErrorString* errorString, int nodeId)
    393 {
    394     Node* node = assertNode(errorString, nodeId);
    395     if (!node)
    396         return 0;
    397 
    398     if (!(node->isDocumentNode())) {
    399         *errorString = "Document is not available";
    400         return 0;
    401     }
    402     return toDocument(node);
    403 }
    404 
    405 Element* InspectorDOMAgent::assertElement(ErrorString* errorString, int nodeId)
    406 {
    407     Node* node = assertNode(errorString, nodeId);
    408     if (!node)
    409         return 0;
    410 
    411     if (node->nodeType() != Node::ELEMENT_NODE) {
    412         *errorString = "Node is not an Element";
    413         return 0;
    414     }
    415     return toElement(node);
    416 }
    417 
    418 Node* InspectorDOMAgent::assertEditableNode(ErrorString* errorString, int nodeId)
    419 {
    420     Node* node = assertNode(errorString, nodeId);
    421     if (!node)
    422         return 0;
    423 
    424     if (node->isInShadowTree()) {
    425         *errorString = "Cannot edit nodes from shadow trees";
    426         return 0;
    427     }
    428 
    429     if (node->isPseudoElement()) {
    430         *errorString = "Cannot edit pseudo elements";
    431         return 0;
    432     }
    433 
    434     return node;
    435 }
    436 
    437 Element* InspectorDOMAgent::assertEditableElement(ErrorString* errorString, int nodeId)
    438 {
    439     Element* element = assertElement(errorString, nodeId);
    440     if (!element)
    441         return 0;
    442 
    443     if (element->isInShadowTree()) {
    444         *errorString = "Cannot edit elements from shadow trees";
    445         return 0;
    446     }
    447 
    448     if (element->isPseudoElement()) {
    449         *errorString = "Cannot edit pseudo elements";
    450         return 0;
    451     }
    452 
    453     return element;
    454 }
    455 
    456 void InspectorDOMAgent::getDocument(ErrorString* errorString, RefPtr<TypeBuilder::DOM::Node>& root)
    457 {
    458     m_state->setBoolean(DOMAgentState::documentRequested, true);
    459 
    460     if (!m_document) {
    461         *errorString = "Document is not available";
    462         return;
    463     }
    464 
    465     discardFrontendBindings();
    466 
    467     root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
    468 }
    469 
    470 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth)
    471 {
    472     Node* node = nodeForId(nodeId);
    473     if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
    474         return;
    475 
    476     NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
    477 
    478     if (m_childrenRequested.contains(nodeId)) {
    479         if (depth <= 1)
    480             return;
    481 
    482         depth--;
    483 
    484         for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
    485             int childNodeId = nodeMap->get(node);
    486             ASSERT(childNodeId);
    487             pushChildNodesToFrontend(childNodeId, depth);
    488         }
    489 
    490         return;
    491     }
    492 
    493     RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodeMap);
    494     m_frontend->setChildNodes(nodeId, children.release());
    495 }
    496 
    497 void InspectorDOMAgent::discardFrontendBindings()
    498 {
    499     if (m_history)
    500         m_history->reset();
    501     m_searchResults.clear();
    502     m_documentNodeToIdMap.clear();
    503     m_idToNode.clear();
    504     releaseDanglingNodes();
    505     m_childrenRequested.clear();
    506     if (m_revalidateStyleAttrTask)
    507         m_revalidateStyleAttrTask->reset();
    508 }
    509 
    510 void InspectorDOMAgent::discardBackendBindings()
    511 {
    512     m_backendIdToNode.clear();
    513     m_nodeGroupToBackendIdMap.clear();
    514 }
    515 
    516 int InspectorDOMAgent::pushNodeToFrontend(ErrorString* errorString, int documentNodeId, Node* nodeToPush)
    517 {
    518     Document* document = assertDocument(errorString, documentNodeId);
    519     if (!document)
    520         return 0;
    521     if (nodeToPush->document() != document) {
    522         *errorString = "Node is not part of the document with given id";
    523         return 0;
    524     }
    525 
    526     return pushNodePathToFrontend(nodeToPush);
    527 }
    528 
    529 Node* InspectorDOMAgent::nodeForId(int id)
    530 {
    531     if (!id)
    532         return 0;
    533 
    534     HashMap<int, Node*>::iterator it = m_idToNode.find(id);
    535     if (it != m_idToNode.end())
    536         return it->value;
    537     return 0;
    538 }
    539 
    540 void InspectorDOMAgent::requestChildNodes(ErrorString* errorString, int nodeId, const int* depth)
    541 {
    542     int sanitizedDepth;
    543 
    544     if (!depth)
    545         sanitizedDepth = 1;
    546     else if (*depth == -1)
    547         sanitizedDepth = INT_MAX;
    548     else if (*depth > 0)
    549         sanitizedDepth = *depth;
    550     else {
    551         *errorString = "Please provide a positive integer as a depth or -1 for entire subtree";
    552         return;
    553     }
    554 
    555     pushChildNodesToFrontend(nodeId, sanitizedDepth);
    556 }
    557 
    558 void InspectorDOMAgent::querySelector(ErrorString* errorString, int nodeId, const String& selectors, int* elementId)
    559 {
    560     *elementId = 0;
    561     Node* node = assertNode(errorString, nodeId);
    562     if (!node)
    563         return;
    564 
    565     TrackExceptionState exceptionState;
    566     RefPtr<Element> element = node->querySelector(selectors, exceptionState);
    567     if (exceptionState.hadException()) {
    568         *errorString = "DOM Error while querying";
    569         return;
    570     }
    571 
    572     if (element)
    573         *elementId = pushNodePathToFrontend(element.get());
    574 }
    575 
    576 void InspectorDOMAgent::querySelectorAll(ErrorString* errorString, int nodeId, const String& selectors, RefPtr<TypeBuilder::Array<int> >& result)
    577 {
    578     Node* node = assertNode(errorString, nodeId);
    579     if (!node)
    580         return;
    581 
    582     TrackExceptionState exceptionState;
    583     RefPtr<NodeList> nodes = node->querySelectorAll(selectors, exceptionState);
    584     if (exceptionState.hadException()) {
    585         *errorString = "DOM Error while querying";
    586         return;
    587     }
    588 
    589     result = TypeBuilder::Array<int>::create();
    590 
    591     for (unsigned i = 0; i < nodes->length(); ++i)
    592         result->addItem(pushNodePathToFrontend(nodes->item(i)));
    593 }
    594 
    595 int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
    596 {
    597     ASSERT(nodeToPush);  // Invalid input
    598 
    599     if (!m_document)
    600         return 0;
    601     if (!m_documentNodeToIdMap.contains(m_document))
    602         return 0;
    603 
    604     // Return id in case the node is known.
    605     int result = m_documentNodeToIdMap.get(nodeToPush);
    606     if (result)
    607         return result;
    608 
    609     Node* node = nodeToPush;
    610     Vector<Node*> path;
    611     NodeToIdMap* danglingMap = 0;
    612 
    613     while (true) {
    614         Node* parent = innerParentNode(node);
    615         if (!parent) {
    616             // Node being pushed is detached -> push subtree root.
    617             OwnPtr<NodeToIdMap> newMap = adoptPtr(new NodeToIdMap);
    618             danglingMap = newMap.get();
    619             m_danglingNodeToIdMaps.append(newMap.release());
    620             RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
    621             children->addItem(buildObjectForNode(node, 0, danglingMap));
    622             m_frontend->setChildNodes(0, children);
    623             break;
    624         } else {
    625             path.append(parent);
    626             if (m_documentNodeToIdMap.get(parent))
    627                 break;
    628             else
    629                 node = parent;
    630         }
    631     }
    632 
    633     NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
    634     for (int i = path.size() - 1; i >= 0; --i) {
    635         int nodeId = map->get(path.at(i));
    636         ASSERT(nodeId);
    637         pushChildNodesToFrontend(nodeId);
    638     }
    639     return map->get(nodeToPush);
    640 }
    641 
    642 int InspectorDOMAgent::boundNodeId(Node* node)
    643 {
    644     return m_documentNodeToIdMap.get(node);
    645 }
    646 
    647 BackendNodeId InspectorDOMAgent::backendNodeIdForNode(Node* node, const String& nodeGroup)
    648 {
    649     if (!node)
    650         return 0;
    651 
    652     if (!m_nodeGroupToBackendIdMap.contains(nodeGroup))
    653         m_nodeGroupToBackendIdMap.set(nodeGroup, NodeToBackendIdMap());
    654 
    655     NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
    656     BackendNodeId id = map.get(node);
    657     if (!id) {
    658         id = --m_lastBackendNodeId;
    659         map.set(node, id);
    660         m_backendIdToNode.set(id, std::make_pair(node, nodeGroup));
    661     }
    662 
    663     return id;
    664 }
    665 
    666 void InspectorDOMAgent::releaseBackendNodeIds(ErrorString* errorString, const String& nodeGroup)
    667 {
    668     if (m_nodeGroupToBackendIdMap.contains(nodeGroup)) {
    669         NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
    670         for (NodeToBackendIdMap::iterator it = map.begin(); it != map.end(); ++it)
    671             m_backendIdToNode.remove(it->value);
    672         m_nodeGroupToBackendIdMap.remove(nodeGroup);
    673         return;
    674     }
    675     *errorString = "Group name not found";
    676 }
    677 
    678 void InspectorDOMAgent::setAttributeValue(ErrorString* errorString, int elementId, const String& name, const String& value)
    679 {
    680     Element* element = assertEditableElement(errorString, elementId);
    681     if (!element)
    682         return;
    683 
    684     m_domEditor->setAttribute(element, name, value, errorString);
    685 }
    686 
    687 void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elementId, const String& text, const String* const name)
    688 {
    689     Element* element = assertEditableElement(errorString, elementId);
    690     if (!element)
    691         return;
    692 
    693     String markup = "<span " + text + "></span>";
    694     RefPtr<DocumentFragment> fragment = element->document().createDocumentFragment();
    695 
    696     bool shouldIgnoreCase = element->document().isHTMLDocument() && element->isHTMLElement();
    697     // Not all elements can represent the context (i.e. IFRAME), hence using document.body.
    698     if (shouldIgnoreCase && element->document().body())
    699         fragment->parseHTML(markup, element->document().body(), DisallowScriptingContent);
    700     else
    701         fragment->parseXML(markup, 0, DisallowScriptingContent);
    702 
    703     Element* parsedElement = fragment->firstChild() && fragment->firstChild()->isElementNode() ? toElement(fragment->firstChild()) : 0;
    704     if (!parsedElement) {
    705         *errorString = "Could not parse value as attributes";
    706         return;
    707     }
    708 
    709     String caseAdjustedName = name ? (shouldIgnoreCase ? name->lower() : *name) : String();
    710 
    711     if (!parsedElement->hasAttributes() && name) {
    712         m_domEditor->removeAttribute(element, caseAdjustedName, errorString);
    713         return;
    714     }
    715 
    716     bool foundOriginalAttribute = false;
    717     unsigned numAttrs = parsedElement->attributeCount();
    718     for (unsigned i = 0; i < numAttrs; ++i) {
    719         // Add attribute pair
    720         const Attribute* attribute = parsedElement->attributeItem(i);
    721         String attributeName = attribute->name().toString();
    722         if (shouldIgnoreCase)
    723             attributeName = attributeName.lower();
    724         foundOriginalAttribute |= name && attributeName == caseAdjustedName;
    725         if (!m_domEditor->setAttribute(element, attributeName, attribute->value(), errorString))
    726             return;
    727     }
    728 
    729     if (!foundOriginalAttribute && name && !name->stripWhiteSpace().isEmpty())
    730         m_domEditor->removeAttribute(element, caseAdjustedName, errorString);
    731 }
    732 
    733 void InspectorDOMAgent::removeAttribute(ErrorString* errorString, int elementId, const String& name)
    734 {
    735     Element* element = assertEditableElement(errorString, elementId);
    736     if (!element)
    737         return;
    738 
    739     m_domEditor->removeAttribute(element, name, errorString);
    740 }
    741 
    742 void InspectorDOMAgent::removeNode(ErrorString* errorString, int nodeId)
    743 {
    744     Node* node = assertEditableNode(errorString, nodeId);
    745     if (!node)
    746         return;
    747 
    748     ContainerNode* parentNode = node->parentNode();
    749     if (!parentNode) {
    750         *errorString = "Cannot remove detached node";
    751         return;
    752     }
    753 
    754     m_domEditor->removeChild(parentNode, node, errorString);
    755 }
    756 
    757 void InspectorDOMAgent::setNodeName(ErrorString* errorString, int nodeId, const String& tagName, int* newId)
    758 {
    759     *newId = 0;
    760 
    761     Node* oldNode = nodeForId(nodeId);
    762     if (!oldNode || !oldNode->isElementNode())
    763         return;
    764 
    765     TrackExceptionState exceptionState;
    766     RefPtr<Element> newElem = oldNode->document().createElement(tagName, exceptionState);
    767     if (exceptionState.hadException())
    768         return;
    769 
    770     // Copy over the original node's attributes.
    771     newElem->cloneAttributesFromElement(*toElement(oldNode));
    772 
    773     // Copy over the original node's children.
    774     Node* child;
    775     while ((child = oldNode->firstChild())) {
    776         if (!m_domEditor->insertBefore(newElem.get(), child, 0, errorString))
    777             return;
    778     }
    779 
    780     // Replace the old node with the new node
    781     ContainerNode* parent = oldNode->parentNode();
    782     if (!m_domEditor->insertBefore(parent, newElem.get(), oldNode->nextSibling(), errorString))
    783         return;
    784     if (!m_domEditor->removeChild(parent, oldNode, errorString))
    785         return;
    786 
    787     *newId = pushNodePathToFrontend(newElem.get());
    788     if (m_childrenRequested.contains(nodeId))
    789         pushChildNodesToFrontend(*newId);
    790 }
    791 
    792 void InspectorDOMAgent::getOuterHTML(ErrorString* errorString, int nodeId, WTF::String* outerHTML)
    793 {
    794     Node* node = assertNode(errorString, nodeId);
    795     if (!node)
    796         return;
    797 
    798     *outerHTML = createMarkup(node);
    799 }
    800 
    801 void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML)
    802 {
    803     if (!nodeId) {
    804         ASSERT(m_document);
    805         DOMPatchSupport domPatchSupport(m_domEditor.get(), *m_document.get());
    806         domPatchSupport.patchDocument(outerHTML);
    807         return;
    808     }
    809 
    810     Node* node = assertEditableNode(errorString, nodeId);
    811     if (!node)
    812         return;
    813 
    814     Document* document = node->isDocumentNode() ? toDocument(node) : node->ownerDocument();
    815     if (!document || (!document->isHTMLDocument() && !document->isXHTMLDocument() && !document->isSVGDocument())) {
    816         *errorString = "Not an HTML/XML document";
    817         return;
    818     }
    819 
    820     Node* newNode = 0;
    821     if (!m_domEditor->setOuterHTML(node, outerHTML, &newNode, errorString))
    822         return;
    823 
    824     if (!newNode) {
    825         // The only child node has been deleted.
    826         return;
    827     }
    828 
    829     int newId = pushNodePathToFrontend(newNode);
    830 
    831     bool childrenRequested = m_childrenRequested.contains(nodeId);
    832     if (childrenRequested)
    833         pushChildNodesToFrontend(newId);
    834 }
    835 
    836 void InspectorDOMAgent::setNodeValue(ErrorString* errorString, int nodeId, const String& value)
    837 {
    838     Node* node = assertEditableNode(errorString, nodeId);
    839     if (!node)
    840         return;
    841 
    842     if (node->nodeType() != Node::TEXT_NODE) {
    843         *errorString = "Can only set value of text nodes";
    844         return;
    845     }
    846 
    847     m_domEditor->replaceWholeText(toText(node), value, errorString);
    848 }
    849 
    850 void InspectorDOMAgent::getEventListenersForNode(ErrorString* errorString, int nodeId, const String* objectGroup, RefPtr<TypeBuilder::Array<TypeBuilder::DOM::EventListener> >& listenersArray)
    851 {
    852     listenersArray = TypeBuilder::Array<TypeBuilder::DOM::EventListener>::create();
    853     Node* node = assertNode(errorString, nodeId);
    854     if (!node)
    855         return;
    856     Vector<EventListenerInfo> eventInformation;
    857     getEventListeners(node, eventInformation, true);
    858 
    859     // Get Capturing Listeners (in this order)
    860     size_t eventInformationLength = eventInformation.size();
    861     for (size_t i = 0; i < eventInformationLength; ++i) {
    862         const EventListenerInfo& info = eventInformation[i];
    863         const EventListenerVector& vector = info.eventListenerVector;
    864         for (size_t j = 0; j < vector.size(); ++j) {
    865             const RegisteredEventListener& listener = vector[j];
    866             if (listener.useCapture)
    867                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
    868         }
    869     }
    870 
    871     // Get Bubbling Listeners (reverse order)
    872     for (size_t i = eventInformationLength; i; --i) {
    873         const EventListenerInfo& info = eventInformation[i - 1];
    874         const EventListenerVector& vector = info.eventListenerVector;
    875         for (size_t j = 0; j < vector.size(); ++j) {
    876             const RegisteredEventListener& listener = vector[j];
    877             if (!listener.useCapture)
    878                 listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
    879         }
    880     }
    881 }
    882 
    883 void InspectorDOMAgent::getEventListeners(Node* node, Vector<EventListenerInfo>& eventInformation, bool includeAncestors)
    884 {
    885     // The Node's Ancestors including self.
    886     Vector<Node*> ancestors;
    887     // Push this node as the firs element.
    888     ancestors.append(node);
    889     if (includeAncestors) {
    890         for (ContainerNode* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
    891             ancestors.append(ancestor);
    892     }
    893 
    894     // Nodes and their Listeners for the concerned event types (order is top to bottom)
    895     for (size_t i = ancestors.size(); i; --i) {
    896         Node* ancestor = ancestors[i - 1];
    897         EventTargetData* d = ancestor->eventTargetData();
    898         if (!d)
    899             continue;
    900         // Get the list of event types this Node is concerned with
    901         Vector<AtomicString> eventTypes = d->eventListenerMap.eventTypes();
    902         for (size_t j = 0; j < eventTypes.size(); ++j) {
    903             AtomicString& type = eventTypes[j];
    904             const EventListenerVector& listeners = ancestor->getEventListeners(type);
    905             EventListenerVector filteredListeners;
    906             filteredListeners.reserveCapacity(listeners.size());
    907             for (size_t k = 0; k < listeners.size(); ++k) {
    908                 if (listeners[k].listener->type() == EventListener::JSEventListenerType)
    909                     filteredListeners.append(listeners[k]);
    910             }
    911             if (!filteredListeners.isEmpty())
    912                 eventInformation.append(EventListenerInfo(ancestor, type, filteredListeners));
    913         }
    914     }
    915 }
    916 
    917 void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrimmedQuery, String* searchId, int* resultCount)
    918 {
    919     // FIXME: Few things are missing here:
    920     // 1) Search works with node granularity - number of matches within node is not calculated.
    921     // 2) There is no need to push all search results to the front-end at a time, pushing next / previous result
    922     //    is sufficient.
    923 
    924     unsigned queryLength = whitespaceTrimmedQuery.length();
    925     bool startTagFound = !whitespaceTrimmedQuery.find('<');
    926     bool endTagFound = whitespaceTrimmedQuery.reverseFind('>') + 1 == queryLength;
    927     bool startQuoteFound = !whitespaceTrimmedQuery.find('"');
    928     bool endQuoteFound = whitespaceTrimmedQuery.reverseFind('"') + 1 == queryLength;
    929     bool exactAttributeMatch = startQuoteFound && endQuoteFound;
    930 
    931     String tagNameQuery = whitespaceTrimmedQuery;
    932     String attributeQuery = whitespaceTrimmedQuery;
    933     if (startTagFound)
    934         tagNameQuery = tagNameQuery.right(tagNameQuery.length() - 1);
    935     if (endTagFound)
    936         tagNameQuery = tagNameQuery.left(tagNameQuery.length() - 1);
    937     if (startQuoteFound)
    938         attributeQuery = attributeQuery.right(attributeQuery.length() - 1);
    939     if (endQuoteFound)
    940         attributeQuery = attributeQuery.left(attributeQuery.length() - 1);
    941 
    942     Vector<Document*> docs = documents();
    943     ListHashSet<Node*> resultCollector;
    944 
    945     for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
    946         Document* document = *it;
    947         Node* node = document->documentElement();
    948         if (!node)
    949             continue;
    950 
    951         // Manual plain text search.
    952         while ((node = NodeTraversal::next(*node, document->documentElement()))) {
    953             switch (node->nodeType()) {
    954             case Node::TEXT_NODE:
    955             case Node::COMMENT_NODE:
    956             case Node::CDATA_SECTION_NODE: {
    957                 String text = node->nodeValue();
    958                 if (text.findIgnoringCase(whitespaceTrimmedQuery) != kNotFound)
    959                     resultCollector.add(node);
    960                 break;
    961             }
    962             case Node::ELEMENT_NODE: {
    963                 if ((!startTagFound && !endTagFound && (node->nodeName().findIgnoringCase(tagNameQuery) != kNotFound))
    964                     || (startTagFound && endTagFound && equalIgnoringCase(node->nodeName(), tagNameQuery))
    965                     || (startTagFound && !endTagFound && node->nodeName().startsWith(tagNameQuery, false))
    966                     || (!startTagFound && endTagFound && node->nodeName().endsWith(tagNameQuery, false))) {
    967                     resultCollector.add(node);
    968                     break;
    969                 }
    970                 // Go through all attributes and serialize them.
    971                 const Element* element = toElement(node);
    972                 if (!element->hasAttributes())
    973                     break;
    974 
    975                 unsigned numAttrs = element->attributeCount();
    976                 for (unsigned i = 0; i < numAttrs; ++i) {
    977                     // Add attribute pair
    978                     const Attribute* attribute = element->attributeItem(i);
    979                     if (attribute->localName().find(whitespaceTrimmedQuery, 0, false) != kNotFound) {
    980                         resultCollector.add(node);
    981                         break;
    982                     }
    983                     size_t foundPosition = attribute->value().find(attributeQuery, 0, false);
    984                     if (foundPosition != kNotFound) {
    985                         if (!exactAttributeMatch || (!foundPosition && attribute->value().length() == attributeQuery.length())) {
    986                             resultCollector.add(node);
    987                             break;
    988                         }
    989                     }
    990                 }
    991                 break;
    992             }
    993             default:
    994                 break;
    995             }
    996         }
    997 
    998         // XPath evaluation
    999         for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
   1000             Document* document = *it;
   1001             TrackExceptionState exceptionState;
   1002             RefPtr<XPathResult> result = DocumentXPathEvaluator::evaluate(document, whitespaceTrimmedQuery, document, 0, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, 0, exceptionState);
   1003             if (exceptionState.hadException() || !result)
   1004                 continue;
   1005 
   1006             unsigned long size = result->snapshotLength(exceptionState);
   1007             for (unsigned long i = 0; !exceptionState.hadException() && i < size; ++i) {
   1008                 Node* node = result->snapshotItem(i, exceptionState);
   1009                 if (exceptionState.hadException())
   1010                     break;
   1011 
   1012                 if (node->nodeType() == Node::ATTRIBUTE_NODE)
   1013                     node = toAttr(node)->ownerElement();
   1014                 resultCollector.add(node);
   1015             }
   1016         }
   1017 
   1018         // Selector evaluation
   1019         for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
   1020             Document* document = *it;
   1021             TrackExceptionState exceptionState;
   1022             RefPtr<NodeList> nodeList = document->querySelectorAll(whitespaceTrimmedQuery, exceptionState);
   1023             if (exceptionState.hadException() || !nodeList)
   1024                 continue;
   1025 
   1026             unsigned size = nodeList->length();
   1027             for (unsigned i = 0; i < size; ++i)
   1028                 resultCollector.add(nodeList->item(i));
   1029         }
   1030     }
   1031 
   1032     *searchId = IdentifiersFactory::createIdentifier();
   1033     SearchResults::iterator resultsIt = m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).iterator;
   1034 
   1035     for (ListHashSet<Node*>::iterator it = resultCollector.begin(); it != resultCollector.end(); ++it)
   1036         resultsIt->value.append(*it);
   1037 
   1038     *resultCount = resultsIt->value.size();
   1039 }
   1040 
   1041 void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<TypeBuilder::Array<int> >& nodeIds)
   1042 {
   1043     SearchResults::iterator it = m_searchResults.find(searchId);
   1044     if (it == m_searchResults.end()) {
   1045         *errorString = "No search session with given id found";
   1046         return;
   1047     }
   1048 
   1049     int size = it->value.size();
   1050     if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
   1051         *errorString = "Invalid search result range";
   1052         return;
   1053     }
   1054 
   1055     nodeIds = TypeBuilder::Array<int>::create();
   1056     for (int i = fromIndex; i < toIndex; ++i)
   1057         nodeIds->addItem(pushNodePathToFrontend((it->value)[i].get()));
   1058 }
   1059 
   1060 void InspectorDOMAgent::discardSearchResults(ErrorString*, const String& searchId)
   1061 {
   1062     m_searchResults.remove(searchId);
   1063 }
   1064 
   1065 bool InspectorDOMAgent::handleMousePress()
   1066 {
   1067     if (m_searchingForNode == NotSearching)
   1068         return false;
   1069 
   1070     if (Node* node = m_overlay->highlightedNode()) {
   1071         inspect(node);
   1072         return true;
   1073     }
   1074     return false;
   1075 }
   1076 
   1077 bool InspectorDOMAgent::handleGestureEvent(Frame* frame, const PlatformGestureEvent& event)
   1078 {
   1079     if (m_searchingForNode == NotSearching || event.type() != PlatformEvent::GestureTap)
   1080         return false;
   1081     Node* node = hoveredNodeForEvent(frame, event, false);
   1082     if (node && m_inspectModeHighlightConfig) {
   1083         m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig);
   1084         inspect(node);
   1085         return true;
   1086     }
   1087     return false;
   1088 }
   1089 
   1090 bool InspectorDOMAgent::handleTouchEvent(Frame* frame, const PlatformTouchEvent& event)
   1091 {
   1092     if (m_searchingForNode == NotSearching)
   1093         return false;
   1094     Node* node = hoveredNodeForEvent(frame, event, false);
   1095     if (node && m_inspectModeHighlightConfig) {
   1096         m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig);
   1097         inspect(node);
   1098         return true;
   1099     }
   1100     return false;
   1101 }
   1102 
   1103 void InspectorDOMAgent::inspect(Node* inspectedNode)
   1104 {
   1105     if (!m_frontend || !inspectedNode)
   1106         return;
   1107 
   1108     Node* node = inspectedNode;
   1109     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
   1110         node = node->parentNode();
   1111 
   1112     int nodeId = pushNodePathToFrontend(node);
   1113     if (nodeId)
   1114         m_frontend->inspectNodeRequested(nodeId);
   1115 }
   1116 
   1117 void InspectorDOMAgent::handleMouseMove(Frame* frame, const PlatformMouseEvent& event)
   1118 {
   1119     if (m_searchingForNode == NotSearching)
   1120         return;
   1121 
   1122     if (!frame->view() || !frame->contentRenderer())
   1123         return;
   1124     Node* node = hoveredNodeForEvent(frame, event, event.shiftKey());
   1125 
   1126     while (m_searchingForNode != SearchingForShadow && node && node->isInShadowTree())
   1127         node = node->parentOrShadowHostNode();
   1128 
   1129     Node* eventTarget = event.shiftKey() ? hoveredNodeForEvent(frame, event, false) : 0;
   1130     if (eventTarget == node)
   1131         eventTarget = 0;
   1132 
   1133     if (node && m_inspectModeHighlightConfig)
   1134         m_overlay->highlightNode(node, eventTarget, *m_inspectModeHighlightConfig);
   1135 }
   1136 
   1137 void InspectorDOMAgent::setSearchingForNode(ErrorString* errorString, SearchMode searchMode, JSONObject* highlightInspectorObject)
   1138 {
   1139     if (m_searchingForNode == searchMode)
   1140         return;
   1141 
   1142     m_searchingForNode = searchMode;
   1143     m_overlay->setInspectModeEnabled(searchMode != NotSearching);
   1144     if (searchMode != NotSearching) {
   1145         m_inspectModeHighlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject);
   1146         if (!m_inspectModeHighlightConfig)
   1147             return;
   1148     } else
   1149         hideHighlight(errorString);
   1150 }
   1151 
   1152 PassOwnPtr<HighlightConfig> InspectorDOMAgent::highlightConfigFromInspectorObject(ErrorString* errorString, JSONObject* highlightInspectorObject)
   1153 {
   1154     if (!highlightInspectorObject) {
   1155         *errorString = "Internal error: highlight configuration parameter is missing";
   1156         return nullptr;
   1157     }
   1158 
   1159     OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
   1160     bool showInfo = false; // Default: false (do not show a tooltip).
   1161     highlightInspectorObject->getBoolean("showInfo", &showInfo);
   1162     highlightConfig->showInfo = showInfo;
   1163     bool showRulers = false; // Default: false (do not show rulers).
   1164     highlightInspectorObject->getBoolean("showRulers", &showRulers);
   1165     highlightConfig->showRulers = showRulers;
   1166     highlightConfig->content = parseConfigColor("contentColor", highlightInspectorObject);
   1167     highlightConfig->contentOutline = parseConfigColor("contentOutlineColor", highlightInspectorObject);
   1168     highlightConfig->padding = parseConfigColor("paddingColor", highlightInspectorObject);
   1169     highlightConfig->border = parseConfigColor("borderColor", highlightInspectorObject);
   1170     highlightConfig->margin = parseConfigColor("marginColor", highlightInspectorObject);
   1171     highlightConfig->eventTarget = parseConfigColor("eventTargetColor", highlightInspectorObject);
   1172     return highlightConfig.release();
   1173 }
   1174 
   1175 void InspectorDOMAgent::setInspectModeEnabled(ErrorString* errorString, bool enabled, const bool* inspectShadowDOM, const RefPtr<JSONObject>* highlightConfig)
   1176 {
   1177     if (enabled && !pushDocumentUponHandlelessOperation(errorString))
   1178         return;
   1179     SearchMode searchMode = enabled ? (inspectShadowDOM && *inspectShadowDOM ? SearchingForShadow : SearchingForNormal) : NotSearching;
   1180     setSearchingForNode(errorString, searchMode, highlightConfig ? highlightConfig->get() : 0);
   1181 }
   1182 
   1183 void InspectorDOMAgent::highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<JSONObject>* color, const RefPtr<JSONObject>* outlineColor)
   1184 {
   1185     OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad(FloatRect(x, y, width, height)));
   1186     innerHighlightQuad(quad.release(), color, outlineColor);
   1187 }
   1188 
   1189 void InspectorDOMAgent::highlightQuad(ErrorString* errorString, const RefPtr<JSONArray>& quadArray, const RefPtr<JSONObject>* color, const RefPtr<JSONObject>* outlineColor)
   1190 {
   1191     OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad());
   1192     if (!parseQuad(quadArray, quad.get())) {
   1193         *errorString = "Invalid Quad format";
   1194         return;
   1195     }
   1196     innerHighlightQuad(quad.release(), color, outlineColor);
   1197 }
   1198 
   1199 void InspectorDOMAgent::innerHighlightQuad(PassOwnPtr<FloatQuad> quad, const RefPtr<JSONObject>* color, const RefPtr<JSONObject>* outlineColor)
   1200 {
   1201     OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
   1202     highlightConfig->content = parseColor(color);
   1203     highlightConfig->contentOutline = parseColor(outlineColor);
   1204     m_overlay->highlightQuad(quad, *highlightConfig);
   1205 }
   1206 
   1207 void InspectorDOMAgent::highlightNode(ErrorString* errorString, const RefPtr<JSONObject>& highlightInspectorObject, const int* nodeId, const String* objectId)
   1208 {
   1209     Node* node = 0;
   1210     if (nodeId) {
   1211         node = assertNode(errorString, *nodeId);
   1212     } else if (objectId) {
   1213         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*objectId);
   1214         node = injectedScript.nodeForObjectId(*objectId);
   1215         if (!node)
   1216             *errorString = "Node for given objectId not found";
   1217     } else
   1218         *errorString = "Either nodeId or objectId must be specified";
   1219 
   1220     if (!node)
   1221         return;
   1222 
   1223     OwnPtr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject.get());
   1224     if (!highlightConfig)
   1225         return;
   1226 
   1227     m_overlay->highlightNode(node, 0 /* eventTarget */, *highlightConfig);
   1228 }
   1229 
   1230 void InspectorDOMAgent::highlightFrame(
   1231     ErrorString*,
   1232     const String& frameId,
   1233     const RefPtr<JSONObject>* color,
   1234     const RefPtr<JSONObject>* outlineColor)
   1235 {
   1236     Frame* frame = m_pageAgent->frameForId(frameId);
   1237     if (frame && frame->ownerElement()) {
   1238         OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
   1239         highlightConfig->showInfo = true; // Always show tooltips for frames.
   1240         highlightConfig->content = parseColor(color);
   1241         highlightConfig->contentOutline = parseColor(outlineColor);
   1242         m_overlay->highlightNode(frame->ownerElement(), 0 /* eventTarget */, *highlightConfig);
   1243     }
   1244 }
   1245 
   1246 void InspectorDOMAgent::hideHighlight(ErrorString*)
   1247 {
   1248     m_overlay->hideHighlight();
   1249 }
   1250 
   1251 void InspectorDOMAgent::moveTo(ErrorString* errorString, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
   1252 {
   1253     Node* node = assertEditableNode(errorString, nodeId);
   1254     if (!node)
   1255         return;
   1256 
   1257     Element* targetElement = assertEditableElement(errorString, targetElementId);
   1258     if (!targetElement)
   1259         return;
   1260 
   1261     Node* anchorNode = 0;
   1262     if (anchorNodeId && *anchorNodeId) {
   1263         anchorNode = assertEditableNode(errorString, *anchorNodeId);
   1264         if (!anchorNode)
   1265             return;
   1266         if (anchorNode->parentNode() != targetElement) {
   1267             *errorString = "Anchor node must be child of the target element";
   1268             return;
   1269         }
   1270     }
   1271 
   1272     if (!m_domEditor->insertBefore(targetElement, node, anchorNode, errorString))
   1273         return;
   1274 
   1275     *newNodeId = pushNodePathToFrontend(node);
   1276 }
   1277 
   1278 void InspectorDOMAgent::undo(ErrorString* errorString)
   1279 {
   1280     TrackExceptionState exceptionState;
   1281     m_history->undo(exceptionState);
   1282     *errorString = InspectorDOMAgent::toErrorString(exceptionState);
   1283 }
   1284 
   1285 void InspectorDOMAgent::redo(ErrorString* errorString)
   1286 {
   1287     TrackExceptionState exceptionState;
   1288     m_history->redo(exceptionState);
   1289     *errorString = InspectorDOMAgent::toErrorString(exceptionState);
   1290 }
   1291 
   1292 void InspectorDOMAgent::markUndoableState(ErrorString*)
   1293 {
   1294     m_history->markUndoableState();
   1295 }
   1296 
   1297 void InspectorDOMAgent::focus(ErrorString* errorString, int nodeId)
   1298 {
   1299     Element* element = assertElement(errorString, nodeId);
   1300     if (!element)
   1301         return;
   1302     if (!element->isFocusable()) {
   1303         *errorString = "Element is not focusable";
   1304         return;
   1305     }
   1306     element->focus();
   1307 }
   1308 
   1309 void InspectorDOMAgent::setFileInputFiles(ErrorString* errorString, int nodeId, const RefPtr<JSONArray>& files)
   1310 {
   1311     Node* node = assertNode(errorString, nodeId);
   1312     if (!node)
   1313         return;
   1314     if (!node->hasTagName(inputTag) || !toHTMLInputElement(node)->isFileUpload()) {
   1315         *errorString = "Node is not a file input element";
   1316         return;
   1317     }
   1318 
   1319     RefPtr<FileList> fileList = FileList::create();
   1320     for (JSONArray::const_iterator iter = files->begin(); iter != files->end(); ++iter) {
   1321         String path;
   1322         if (!(*iter)->asString(&path)) {
   1323             *errorString = "Files must be strings";
   1324             return;
   1325         }
   1326         fileList->append(File::create(path));
   1327     }
   1328     toHTMLInputElement(node)->setFiles(fileList);
   1329 }
   1330 
   1331 static RefPtr<TypeBuilder::Array<double> > buildArrayForQuad(const FloatQuad& quad)
   1332 {
   1333     RefPtr<TypeBuilder::Array<double> > array = TypeBuilder::Array<double>::create();
   1334     array->addItem(quad.p1().x());
   1335     array->addItem(quad.p1().y());
   1336     array->addItem(quad.p2().x());
   1337     array->addItem(quad.p2().y());
   1338     array->addItem(quad.p3().x());
   1339     array->addItem(quad.p3().y());
   1340     array->addItem(quad.p4().x());
   1341     array->addItem(quad.p4().y());
   1342     return array.release();
   1343 }
   1344 
   1345 void InspectorDOMAgent::getBoxModel(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::DOM::BoxModel>& model)
   1346 {
   1347     Node* node = assertNode(errorString, nodeId);
   1348     if (!node)
   1349         return;
   1350 
   1351     Vector<FloatQuad> quads;
   1352     bool isInlineOrBox = m_overlay->getBoxModel(node, &quads);
   1353     if (!isInlineOrBox) {
   1354         *errorString = "Could not compute box model.";
   1355         return;
   1356     }
   1357 
   1358     RenderObject* renderer = node->renderer();
   1359     Frame* frame = node->document().frame();
   1360     FrameView* view = frame->view();
   1361 
   1362     IntRect boundingBox = pixelSnappedIntRect(view->contentsToRootView(renderer->absoluteBoundingBoxRect()));
   1363     RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
   1364 
   1365     model = TypeBuilder::DOM::BoxModel::create()
   1366         .setContent(buildArrayForQuad(quads.at(3)))
   1367         .setPadding(buildArrayForQuad(quads.at(2)))
   1368         .setBorder(buildArrayForQuad(quads.at(1)))
   1369         .setMargin(buildArrayForQuad(quads.at(0)))
   1370         .setWidth(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width())
   1371         .setHeight(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height());
   1372 }
   1373 
   1374 void InspectorDOMAgent::getNodeForLocation(ErrorString* errorString, int x, int y, int* nodeId)
   1375 {
   1376     if (!pushDocumentUponHandlelessOperation(errorString))
   1377         return;
   1378 
   1379     Node* node = hoveredNodeForPoint(m_document->frame(), IntPoint(x, y), false);
   1380     if (!node) {
   1381         *errorString = "No node found at given location";
   1382         return;
   1383     }
   1384     *nodeId = pushNodePathToFrontend(node);
   1385 }
   1386 
   1387 void InspectorDOMAgent::resolveNode(ErrorString* errorString, int nodeId, const String* const objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
   1388 {
   1389     String objectGroupName = objectGroup ? *objectGroup : "";
   1390     Node* node = nodeForId(nodeId);
   1391     if (!node) {
   1392         *errorString = "No node with given id found";
   1393         return;
   1394     }
   1395     RefPtr<TypeBuilder::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
   1396     if (!object) {
   1397         *errorString = "Node with given id does not belong to the document";
   1398         return;
   1399     }
   1400     result = object;
   1401 }
   1402 
   1403 void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<String> >& result)
   1404 {
   1405     Element* element = assertElement(errorString, nodeId);
   1406     if (!element)
   1407         return;
   1408 
   1409     result = buildArrayForElementAttributes(element);
   1410 }
   1411 
   1412 void InspectorDOMAgent::requestNode(ErrorString*, const String& objectId, int* nodeId)
   1413 {
   1414     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
   1415     Node* node = injectedScript.nodeForObjectId(objectId);
   1416     if (node)
   1417         *nodeId = pushNodePathToFrontend(node);
   1418     else
   1419         *nodeId = 0;
   1420 }
   1421 
   1422 // static
   1423 String InspectorDOMAgent::documentURLString(Document* document)
   1424 {
   1425     if (!document || document->url().isNull())
   1426         return "";
   1427     return document->url().string();
   1428 }
   1429 
   1430 static String documentBaseURLString(Document* document)
   1431 {
   1432     return document->completeURL("").string();
   1433 }
   1434 
   1435 static TypeBuilder::DOM::ShadowRootType::Enum shadowRootType(ShadowRoot* shadowRoot)
   1436 {
   1437     switch (shadowRoot->type()) {
   1438     case ShadowRoot::UserAgentShadowRoot:
   1439         return TypeBuilder::DOM::ShadowRootType::User_agent;
   1440     case ShadowRoot::AuthorShadowRoot:
   1441         return TypeBuilder::DOM::ShadowRootType::Author;
   1442     }
   1443     ASSERT_NOT_REACHED();
   1444     return TypeBuilder::DOM::ShadowRootType::User_agent;
   1445 }
   1446 
   1447 PassRefPtr<TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
   1448 {
   1449     int id = bind(node, nodesMap);
   1450     String nodeName;
   1451     String localName;
   1452     String nodeValue;
   1453 
   1454     switch (node->nodeType()) {
   1455     case Node::TEXT_NODE:
   1456     case Node::COMMENT_NODE:
   1457     case Node::CDATA_SECTION_NODE:
   1458         nodeValue = node->nodeValue();
   1459         if (nodeValue.length() > maxTextSize) {
   1460             nodeValue = nodeValue.left(maxTextSize);
   1461             nodeValue.append(ellipsisUChar);
   1462         }
   1463         break;
   1464     case Node::ATTRIBUTE_NODE:
   1465         localName = node->localName();
   1466         break;
   1467     case Node::DOCUMENT_FRAGMENT_NODE:
   1468     case Node::DOCUMENT_NODE:
   1469     case Node::ELEMENT_NODE:
   1470     default:
   1471         nodeName = node->nodeName();
   1472         localName = node->localName();
   1473         break;
   1474     }
   1475 
   1476     RefPtr<TypeBuilder::DOM::Node> value = TypeBuilder::DOM::Node::create()
   1477         .setNodeId(id)
   1478         .setNodeType(static_cast<int>(node->nodeType()))
   1479         .setNodeName(nodeName)
   1480         .setLocalName(localName)
   1481         .setNodeValue(nodeValue);
   1482 
   1483     bool forcePushChildren = false;
   1484     if (node->isElementNode()) {
   1485         Element* element = toElement(node);
   1486         value->setAttributes(buildArrayForElementAttributes(element));
   1487         if (node->isFrameOwnerElement()) {
   1488             HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node);
   1489             if (Frame* frame = frameOwner->contentFrame())
   1490                 value->setFrameId(m_pageAgent->frameId(frame));
   1491             if (Document* doc = frameOwner->contentDocument())
   1492                 value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
   1493         }
   1494 
   1495         ElementShadow* shadow = element->shadow();
   1496         if (shadow) {
   1497             RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > shadowRoots = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
   1498             for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
   1499                 shadowRoots->addItem(buildObjectForNode(root, 0, nodesMap));
   1500             value->setShadowRoots(shadowRoots);
   1501             forcePushChildren = true;
   1502         }
   1503 
   1504         if (element->hasTagName(templateTag)) {
   1505             value->setTemplateContent(buildObjectForNode(toHTMLTemplateElement(element)->content(), 0, nodesMap));
   1506             forcePushChildren = true;
   1507         }
   1508 
   1509         switch (element->pseudoId()) {
   1510         case BEFORE:
   1511             value->setPseudoType(TypeBuilder::DOM::PseudoType::Before);
   1512             break;
   1513         case AFTER:
   1514             value->setPseudoType(TypeBuilder::DOM::PseudoType::After);
   1515             break;
   1516         default: {
   1517             RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > pseudoElements = buildArrayForPseudoElements(element, nodesMap);
   1518             if (pseudoElements) {
   1519                 value->setPseudoElements(pseudoElements.release());
   1520                 forcePushChildren = true;
   1521             }
   1522             break;
   1523         }
   1524         }
   1525     } else if (node->isDocumentNode()) {
   1526         Document* document = toDocument(node);
   1527         value->setDocumentURL(documentURLString(document));
   1528         value->setBaseURL(documentBaseURLString(document));
   1529         value->setXmlVersion(document->xmlVersion());
   1530     } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
   1531         DocumentType* docType = toDocumentType(node);
   1532         value->setPublicId(docType->publicId());
   1533         value->setSystemId(docType->systemId());
   1534         value->setInternalSubset(docType->internalSubset());
   1535     } else if (node->isAttributeNode()) {
   1536         Attr* attribute = toAttr(node);
   1537         value->setName(attribute->name());
   1538         value->setValue(attribute->value());
   1539     } else if (node->isShadowRoot()) {
   1540         value->setShadowRootType(shadowRootType(toShadowRoot(node)));
   1541     }
   1542 
   1543     if (node->isContainerNode()) {
   1544         int nodeCount = innerChildNodeCount(node);
   1545         value->setChildNodeCount(nodeCount);
   1546         if (forcePushChildren && !depth)
   1547             depth = 1;
   1548         RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodesMap);
   1549         if (children->length() > 0 || depth) // Push children along with shadow in any case.
   1550             value->setChildren(children.release());
   1551     }
   1552 
   1553     return value.release();
   1554 }
   1555 
   1556 PassRefPtr<TypeBuilder::Array<String> > InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
   1557 {
   1558     RefPtr<TypeBuilder::Array<String> > attributesValue = TypeBuilder::Array<String>::create();
   1559     // Go through all attributes and serialize them.
   1560     if (!element->hasAttributes())
   1561         return attributesValue.release();
   1562     unsigned numAttrs = element->attributeCount();
   1563     for (unsigned i = 0; i < numAttrs; ++i) {
   1564         // Add attribute pair
   1565         const Attribute* attribute = element->attributeItem(i);
   1566         attributesValue->addItem(attribute->name().toString());
   1567         attributesValue->addItem(attribute->value());
   1568     }
   1569     return attributesValue.release();
   1570 }
   1571 
   1572 PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
   1573 {
   1574     RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
   1575     if (depth == 0) {
   1576         // Special-case the only text child - pretend that container's children have been requested.
   1577         Node* firstChild = container->firstChild();
   1578         if (firstChild && firstChild->nodeType() == Node::TEXT_NODE && !firstChild->nextSibling()) {
   1579             children->addItem(buildObjectForNode(firstChild, 0, nodesMap));
   1580             m_childrenRequested.add(bind(container, nodesMap));
   1581         }
   1582         return children.release();
   1583     }
   1584 
   1585     Node* child = innerFirstChild(container);
   1586     depth--;
   1587     m_childrenRequested.add(bind(container, nodesMap));
   1588 
   1589     while (child) {
   1590         children->addItem(buildObjectForNode(child, depth, nodesMap));
   1591         child = innerNextSibling(child);
   1592     }
   1593     return children.release();
   1594 }
   1595 
   1596 PassRefPtr<TypeBuilder::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
   1597 {
   1598     RefPtr<EventListener> eventListener = registeredEventListener.listener;
   1599     Document& document = node->document();
   1600     RefPtr<TypeBuilder::DOM::EventListener> value = TypeBuilder::DOM::EventListener::create()
   1601         .setType(eventType)
   1602         .setUseCapture(registeredEventListener.useCapture)
   1603         .setIsAttribute(eventListener->isAttribute())
   1604         .setNodeId(pushNodePathToFrontend(node))
   1605         .setHandlerBody(eventListenerHandlerBody(&document, eventListener.get()));
   1606     if (objectGroupId) {
   1607         ScriptValue functionValue = eventListenerHandler(&document, eventListener.get());
   1608         if (!functionValue.hasNoValue()) {
   1609             Frame* frame = document.frame();
   1610             if (frame) {
   1611                 ScriptState* scriptState = eventListenerHandlerScriptState(frame, eventListener.get());
   1612                 if (scriptState) {
   1613                     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
   1614                     if (!injectedScript.hasNoValue()) {
   1615                         RefPtr<TypeBuilder::Runtime::RemoteObject> valueJson = injectedScript.wrapObject(functionValue, *objectGroupId);
   1616                         value->setHandler(valueJson);
   1617                     }
   1618                 }
   1619             }
   1620         }
   1621     }
   1622     String sourceName;
   1623     String scriptId;
   1624     int lineNumber;
   1625     if (eventListenerHandlerLocation(&node->document(), eventListener.get(), sourceName, scriptId, lineNumber)) {
   1626         RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
   1627             .setScriptId(scriptId)
   1628             .setLineNumber(lineNumber);
   1629         value->setLocation(location);
   1630         if (!sourceName.isEmpty())
   1631             value->setSourceName(sourceName);
   1632     }
   1633     return value.release();
   1634 }
   1635 
   1636 PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > InspectorDOMAgent::buildArrayForPseudoElements(Element* element, NodeToIdMap* nodesMap)
   1637 {
   1638     if (!element->pseudoElement(BEFORE) && !element->pseudoElement(AFTER))
   1639         return 0;
   1640 
   1641     RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > pseudoElements = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
   1642     if (element->pseudoElement(BEFORE))
   1643         pseudoElements->addItem(buildObjectForNode(element->pseudoElement(BEFORE), 0, nodesMap));
   1644     if (element->pseudoElement(AFTER))
   1645         pseudoElements->addItem(buildObjectForNode(element->pseudoElement(AFTER), 0, nodesMap));
   1646     return pseudoElements.release();
   1647 }
   1648 
   1649 Node* InspectorDOMAgent::innerFirstChild(Node* node)
   1650 {
   1651     node = node->firstChild();
   1652     while (isWhitespace(node))
   1653         node = node->nextSibling();
   1654     return node;
   1655 }
   1656 
   1657 Node* InspectorDOMAgent::innerNextSibling(Node* node)
   1658 {
   1659     do {
   1660         node = node->nextSibling();
   1661     } while (isWhitespace(node));
   1662     return node;
   1663 }
   1664 
   1665 Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
   1666 {
   1667     do {
   1668         node = node->previousSibling();
   1669     } while (isWhitespace(node));
   1670     return node;
   1671 }
   1672 
   1673 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
   1674 {
   1675     unsigned count = 0;
   1676     Node* child = innerFirstChild(node);
   1677     while (child) {
   1678         count++;
   1679         child = innerNextSibling(child);
   1680     }
   1681     return count;
   1682 }
   1683 
   1684 Node* InspectorDOMAgent::innerParentNode(Node* node)
   1685 {
   1686     if (node->isDocumentNode()) {
   1687         Document* document = toDocument(node);
   1688         return document->ownerElement();
   1689     }
   1690     return node->parentOrShadowHostNode();
   1691 }
   1692 
   1693 bool InspectorDOMAgent::isWhitespace(Node* node)
   1694 {
   1695     //TODO: pull ignoreWhitespace setting from the frontend and use here.
   1696     return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
   1697 }
   1698 
   1699 void InspectorDOMAgent::domContentLoadedEventFired(Frame* frame)
   1700 {
   1701     if (!frame->isMainFrame())
   1702         return;
   1703 
   1704     // Re-push document once it is loaded.
   1705     discardFrontendBindings();
   1706     if (m_state->getBoolean(DOMAgentState::documentRequested))
   1707         m_frontend->documentUpdated();
   1708 }
   1709 
   1710 void InspectorDOMAgent::invalidateFrameOwnerElement(Frame* frame)
   1711 {
   1712     Element* frameOwner = frame->document()->ownerElement();
   1713     if (!frameOwner)
   1714         return;
   1715 
   1716     int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
   1717     if (!frameOwnerId)
   1718         return;
   1719 
   1720     // Re-add frame owner element together with its new children.
   1721     int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
   1722     m_frontend->childNodeRemoved(parentId, frameOwnerId);
   1723     unbind(frameOwner, &m_documentNodeToIdMap);
   1724 
   1725     RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
   1726     Node* previousSibling = innerPreviousSibling(frameOwner);
   1727     int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
   1728     m_frontend->childNodeInserted(parentId, prevId, value.release());
   1729 }
   1730 
   1731 void InspectorDOMAgent::didCommitLoad(Frame* frame, DocumentLoader* loader)
   1732 {
   1733     // FIXME: If "frame" is always guarenteed to be in the same Page as loader->frame()
   1734     // then all we need to check here is loader->frame()->isMainFrame()
   1735     // and we don't need "frame" at all.
   1736     Frame* mainFrame = frame->page()->mainFrame();
   1737     if (loader->frame() != mainFrame) {
   1738         invalidateFrameOwnerElement(loader->frame());
   1739         return;
   1740     }
   1741 
   1742     setDocument(mainFrame->document());
   1743 }
   1744 
   1745 void InspectorDOMAgent::didInsertDOMNode(Node* node)
   1746 {
   1747     if (isWhitespace(node))
   1748         return;
   1749 
   1750     // We could be attaching existing subtree. Forget the bindings.
   1751     unbind(node, &m_documentNodeToIdMap);
   1752 
   1753     ContainerNode* parent = node->parentNode();
   1754     if (!parent)
   1755         return;
   1756 
   1757     int parentId = m_documentNodeToIdMap.get(parent);
   1758     // Return if parent is not mapped yet.
   1759     if (!parentId)
   1760         return;
   1761 
   1762     if (!m_childrenRequested.contains(parentId)) {
   1763         // No children are mapped yet -> only notify on changes of hasChildren.
   1764         m_frontend->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
   1765     } else {
   1766         // Children have been requested -> return value of a new child.
   1767         Node* prevSibling = innerPreviousSibling(node);
   1768         int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
   1769         RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
   1770         m_frontend->childNodeInserted(parentId, prevId, value.release());
   1771     }
   1772 }
   1773 
   1774 void InspectorDOMAgent::willRemoveDOMNode(Node* node)
   1775 {
   1776     if (isWhitespace(node))
   1777         return;
   1778 
   1779     ContainerNode* parent = node->parentNode();
   1780 
   1781     // If parent is not mapped yet -> ignore the event.
   1782     if (!m_documentNodeToIdMap.contains(parent))
   1783         return;
   1784 
   1785     int parentId = m_documentNodeToIdMap.get(parent);
   1786 
   1787     if (!m_childrenRequested.contains(parentId)) {
   1788         // No children are mapped yet -> only notify on changes of hasChildren.
   1789         if (innerChildNodeCount(parent) == 1)
   1790             m_frontend->childNodeCountUpdated(parentId, 0);
   1791     } else
   1792         m_frontend->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
   1793     unbind(node, &m_documentNodeToIdMap);
   1794 }
   1795 
   1796 void InspectorDOMAgent::willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue)
   1797 {
   1798     m_suppressAttributeModifiedEvent = (oldValue == newValue);
   1799 }
   1800 
   1801 void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
   1802 {
   1803     bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
   1804     m_suppressAttributeModifiedEvent = false;
   1805     if (shouldSuppressEvent)
   1806         return;
   1807 
   1808     int id = boundNodeId(element);
   1809     // If node is not mapped yet -> ignore the event.
   1810     if (!id)
   1811         return;
   1812 
   1813     if (m_domListener)
   1814         m_domListener->didModifyDOMAttr(element);
   1815 
   1816     m_frontend->attributeModified(id, name, value);
   1817 }
   1818 
   1819 void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
   1820 {
   1821     int id = boundNodeId(element);
   1822     // If node is not mapped yet -> ignore the event.
   1823     if (!id)
   1824         return;
   1825 
   1826     if (m_domListener)
   1827         m_domListener->didModifyDOMAttr(element);
   1828 
   1829     m_frontend->attributeRemoved(id, name);
   1830 }
   1831 
   1832 void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
   1833 {
   1834     RefPtr<TypeBuilder::Array<int> > nodeIds = TypeBuilder::Array<int>::create();
   1835     for (unsigned i = 0, size = elements.size(); i < size; ++i) {
   1836         Element* element = elements.at(i);
   1837         int id = boundNodeId(element);
   1838         // If node is not mapped yet -> ignore the event.
   1839         if (!id)
   1840             continue;
   1841 
   1842         if (m_domListener)
   1843             m_domListener->didModifyDOMAttr(element);
   1844         nodeIds->addItem(id);
   1845     }
   1846     m_frontend->inlineStyleInvalidated(nodeIds.release());
   1847 }
   1848 
   1849 void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
   1850 {
   1851     int id = m_documentNodeToIdMap.get(characterData);
   1852     if (!id) {
   1853         // Push text node if it is being created.
   1854         didInsertDOMNode(characterData);
   1855         return;
   1856     }
   1857     m_frontend->characterDataModified(id, characterData->data());
   1858 }
   1859 
   1860 void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
   1861 {
   1862     int id = m_documentNodeToIdMap.get(node);
   1863     // If node is not mapped yet -> ignore the event.
   1864     if (!id)
   1865         return;
   1866 
   1867     if (!m_revalidateStyleAttrTask)
   1868         m_revalidateStyleAttrTask = adoptPtr(new RevalidateStyleAttributeTask(this));
   1869     m_revalidateStyleAttrTask->scheduleFor(toElement(node));
   1870 }
   1871 
   1872 void InspectorDOMAgent::didPushShadowRoot(Element* host, ShadowRoot* root)
   1873 {
   1874     if (!host->ownerDocument())
   1875         return;
   1876 
   1877     int hostId = m_documentNodeToIdMap.get(host);
   1878     if (!hostId)
   1879         return;
   1880 
   1881     pushChildNodesToFrontend(hostId, 1);
   1882     m_frontend->shadowRootPushed(hostId, buildObjectForNode(root, 0, &m_documentNodeToIdMap));
   1883 }
   1884 
   1885 void InspectorDOMAgent::willPopShadowRoot(Element* host, ShadowRoot* root)
   1886 {
   1887     if (!host->ownerDocument())
   1888         return;
   1889 
   1890     int hostId = m_documentNodeToIdMap.get(host);
   1891     int rootId = m_documentNodeToIdMap.get(root);
   1892     if (hostId && rootId)
   1893         m_frontend->shadowRootPopped(hostId, rootId);
   1894 }
   1895 
   1896 void InspectorDOMAgent::frameDocumentUpdated(Frame* frame)
   1897 {
   1898     Document* document = frame->document();
   1899     if (!document)
   1900         return;
   1901 
   1902     Page* page = frame->page();
   1903     ASSERT(page);
   1904     if (frame != page->mainFrame())
   1905         return;
   1906 
   1907     // Only update the main frame document, nested frame document updates are not required
   1908     // (will be handled by invalidateFrameOwnerElement()).
   1909     setDocument(document);
   1910 }
   1911 
   1912 void InspectorDOMAgent::pseudoElementCreated(PseudoElement* pseudoElement)
   1913 {
   1914     Element* parent = pseudoElement->parentOrShadowHostElement();
   1915     if (!parent)
   1916         return;
   1917     int parentId = m_documentNodeToIdMap.get(parent);
   1918     if (!parentId)
   1919         return;
   1920 
   1921     pushChildNodesToFrontend(parentId, 1);
   1922     m_frontend->pseudoElementAdded(parentId, buildObjectForNode(pseudoElement, 0, &m_documentNodeToIdMap));
   1923 }
   1924 
   1925 void InspectorDOMAgent::pseudoElementDestroyed(PseudoElement* pseudoElement)
   1926 {
   1927     int pseudoElementId = m_documentNodeToIdMap.get(pseudoElement);
   1928     if (!pseudoElementId)
   1929         return;
   1930 
   1931     // If a PseudoElement is bound, its parent element must be bound, too.
   1932     Element* parent = pseudoElement->parentOrShadowHostElement();
   1933     ASSERT(parent);
   1934     int parentId = m_documentNodeToIdMap.get(parent);
   1935     ASSERT(parentId);
   1936 
   1937     unbind(pseudoElement, &m_documentNodeToIdMap);
   1938     m_frontend->pseudoElementRemoved(parentId, pseudoElementId);
   1939 }
   1940 
   1941 Node* InspectorDOMAgent::nodeForPath(const String& path)
   1942 {
   1943     // The path is of form "1,HTML,2,BODY,1,DIV"
   1944     if (!m_document)
   1945         return 0;
   1946 
   1947     Node* node = m_document.get();
   1948     Vector<String> pathTokens;
   1949     path.split(",", false, pathTokens);
   1950     if (!pathTokens.size())
   1951         return 0;
   1952     for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
   1953         bool success = true;
   1954         unsigned childNumber = pathTokens[i].toUInt(&success);
   1955         if (!success)
   1956             return 0;
   1957         if (childNumber >= innerChildNodeCount(node))
   1958             return 0;
   1959 
   1960         Node* child = innerFirstChild(node);
   1961         String childName = pathTokens[i + 1];
   1962         for (size_t j = 0; child && j < childNumber; ++j)
   1963             child = innerNextSibling(child);
   1964 
   1965         if (!child || child->nodeName() != childName)
   1966             return 0;
   1967         node = child;
   1968     }
   1969     return node;
   1970 }
   1971 
   1972 void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString* errorString, const String& path, int* nodeId)
   1973 {
   1974     if (Node* node = nodeForPath(path))
   1975         *nodeId = pushNodePathToFrontend(node);
   1976     else
   1977         *errorString = "No node with given path found";
   1978 }
   1979 
   1980 void InspectorDOMAgent::pushNodeByBackendIdToFrontend(ErrorString* errorString, BackendNodeId backendNodeId, int* nodeId)
   1981 {
   1982     if (!m_backendIdToNode.contains(backendNodeId)) {
   1983         *errorString = "No node with given backend id found";
   1984         return;
   1985     }
   1986 
   1987     Node* node = m_backendIdToNode.get(backendNodeId).first;
   1988     String nodeGroup = m_backendIdToNode.get(backendNodeId).second;
   1989     *nodeId = pushNodePathToFrontend(node);
   1990 
   1991     if (nodeGroup == "") {
   1992         m_backendIdToNode.remove(backendNodeId);
   1993         m_nodeGroupToBackendIdMap.find(nodeGroup)->value.remove(node);
   1994     }
   1995 }
   1996 
   1997 void InspectorDOMAgent::getRelayoutBoundary(ErrorString* errorString, int nodeId, int* relayoutBoundaryNodeId)
   1998 {
   1999     Node* node = assertNode(errorString, nodeId);
   2000     if (!node)
   2001         return;
   2002     RenderObject* renderer = node->renderer();
   2003     if (!renderer) {
   2004         *errorString = "No renderer for node, perhaps orphan or hidden node";
   2005         return;
   2006     }
   2007     while (renderer && !renderer->isRoot() && !renderer->isRelayoutBoundaryForInspector())
   2008         renderer = renderer->container();
   2009     Node* resultNode = renderer ? renderer->generatingNode() : node->ownerDocument();
   2010     *relayoutBoundaryNodeId = pushNodePathToFrontend(resultNode);
   2011 }
   2012 
   2013 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
   2014 {
   2015     Document* document = node->isDocumentNode() ? &node->document() : node->ownerDocument();
   2016     Frame* frame = document ? document->frame() : 0;
   2017     if (!frame)
   2018         return 0;
   2019 
   2020     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
   2021     if (injectedScript.hasNoValue())
   2022         return 0;
   2023 
   2024     return injectedScript.wrapNode(node, objectGroup);
   2025 }
   2026 
   2027 bool InspectorDOMAgent::pushDocumentUponHandlelessOperation(ErrorString* errorString)
   2028 {
   2029     if (!m_documentNodeToIdMap.contains(m_document)) {
   2030         RefPtr<TypeBuilder::DOM::Node> root;
   2031         getDocument(errorString, root);
   2032         return errorString->isEmpty();
   2033     }
   2034     return true;
   2035 }
   2036 
   2037 } // namespace WebCore
   2038 
   2039