Chromium Code Reviews| Index: third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| index 5412baed6b920b849264a4b8eff25754b339e212..c57637994f6d9add95a77cd4317b6145724d38fc 100644 |
| --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| @@ -496,6 +496,30 @@ Response InspectorDOMAgent::getDocument( |
| return Response::OK(); |
| } |
| +Response InspectorDOMAgent::getFlatDocument( |
| + Maybe<int> depth, |
| + Maybe<bool> pierce, |
| + std::unique_ptr<protocol::Array<protocol::DOM::Node>>* nodes) { |
| + // Backward compatibility. Mark agent as enabled when it requests document. |
| + if (!enabled()) |
| + innerEnable(); |
| + |
| + if (!m_document) |
| + return Response::Error("Document is not available"); |
| + |
| + discardFrontendBindings(); |
| + |
| + int sanitizedDepth = depth.fromMaybe(2); |
|
Sami
2017/01/17 17:57:43
The comment says the default is 1. Should this be
alex clarke (OOO till 29th)
2017/01/18 16:31:08
Just copying the above - I assume that's right?
Sami
2017/01/18 18:10:46
Ah, I see. A little surprising to me at least :)
|
| + if (sanitizedDepth == -1) |
| + sanitizedDepth = INT_MAX; |
| + |
| + nodes->reset(new protocol::Array<protocol::DOM::Node>()); |
| + buildFlatObjectsForNode(m_document.get(), sanitizedDepth, |
| + pierce.fromMaybe(false), m_documentNodeToIdMap.get(), |
| + nodes->get()); |
| + return Response::OK(); |
| +} |
| + |
| void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, |
| int depth, |
| bool pierce) { |
| @@ -1691,6 +1715,191 @@ std::unique_ptr<protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode( |
| return value; |
| } |
| +void InspectorDOMAgent::buildFlatObjectsForNode( |
| + Node* node, |
| + int depth, |
| + bool pierce, |
| + NodeToIdMap* nodesMap, |
| + protocol::Array<protocol::DOM::Node>* result) { |
| + int id = bind(node, nodesMap); |
|
Sami
2017/01/17 17:57:43
Are we missing a termination condition on |depth|
alex clarke (OOO till 29th)
2017/01/18 16:31:08
Acknowledged.
|
| + String localName; |
| + String nodeValue; |
| + |
| + switch (node->getNodeType()) { |
|
pfeldman
2017/01/17 18:34:58
Can we extract some (all) code here to be reused w
alex clarke (OOO till 29th)
2017/01/18 16:31:08
Done.
|
| + case Node::kTextNode: |
| + case Node::kCommentNode: |
| + case Node::kCdataSectionNode: |
| + nodeValue = node->nodeValue(); |
| + if (nodeValue.length() > maxTextSize) |
| + nodeValue = nodeValue.left(maxTextSize) + ellipsisUChar; |
| + break; |
| + case Node::kAttributeNode: |
| + localName = toAttr(node)->localName(); |
| + break; |
| + case Node::kElementNode: |
| + localName = toElement(node)->localName(); |
| + break; |
| + default: |
| + break; |
| + } |
| + |
| + std::unique_ptr<protocol::DOM::Node> value = |
| + protocol::DOM::Node::create() |
| + .setNodeId(id) |
| + .setBackendNodeId(DOMNodeIds::idForNode(node)) |
| + .setNodeType(static_cast<int>(node->getNodeType())) |
| + .setNodeName(node->nodeName()) |
| + .setLocalName(localName) |
| + .setNodeValue(nodeValue) |
| + .build(); |
| + |
| + if (node->isSVGElement()) |
| + value->setIsSVG(true); |
| + |
| + bool forcePushChildren = false; |
| + if (node->isElementNode()) { |
| + Element* element = toElement(node); |
| + value->setAttributes(buildArrayForElementAttributes(element)); |
| + |
| + if (node->isFrameOwnerElement()) { |
| + HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node); |
| + if (LocalFrame* frame = frameOwner->contentFrame() && |
| + frameOwner->contentFrame()->isLocalFrame() |
| + ? toLocalFrame(frameOwner->contentFrame()) |
| + : nullptr) |
| + value->setFrameId(IdentifiersFactory::frameId(frame)); |
| + if (Document* doc = frameOwner->contentDocument()) { |
| + size_t nextIndex = result->length(); |
| + buildFlatObjectsForNode(doc, pierce ? depth : 0, pierce, nodesMap, |
| + result); |
| + value->setContentDocument(minimalCopy(result->get(nextIndex))); |
| + } |
| + } |
| + |
| + if (node->parentNode() && node->parentNode()->isDocumentNode()) { |
| + LocalFrame* frame = node->document().frame(); |
| + if (frame) |
| + value->setFrameId(IdentifiersFactory::frameId(frame)); |
| + } |
| + |
| + ElementShadow* shadow = element->shadow(); |
| + if (shadow) { |
| + std::unique_ptr<protocol::Array<protocol::DOM::Node>> shadowRoots = |
| + protocol::Array<protocol::DOM::Node>::create(); |
| + for (ShadowRoot* root = &shadow->youngestShadowRoot(); root; |
| + root = root->olderShadowRoot()) { |
| + size_t nextIndex = result->length(); |
| + buildFlatObjectsForNode(root, pierce ? depth : 0, pierce, nodesMap, |
| + result); |
| + shadowRoots->addItem(minimalCopy(result->get(nextIndex))); |
| + } |
| + value->setShadowRoots(std::move(shadowRoots)); |
| + forcePushChildren = true; |
| + } |
| + |
| + if (isHTMLLinkElement(*element)) { |
| + HTMLLinkElement& linkElement = toHTMLLinkElement(*element); |
| + if (linkElement.isImport() && linkElement.import() && |
| + innerParentNode(linkElement.import()) == linkElement) { |
| + value->setImportedDocument( |
| + buildObjectForNode(linkElement.import(), 0, pierce, nodesMap)); |
| + } |
| + forcePushChildren = true; |
| + } |
| + |
| + if (isHTMLTemplateElement(*element)) { |
| + value->setTemplateContent(buildObjectForNode( |
| + toHTMLTemplateElement(*element).content(), 0, pierce, nodesMap)); |
| + forcePushChildren = true; |
| + } |
| + |
| + if (element->getPseudoId()) { |
| + protocol::DOM::PseudoType pseudoType; |
| + if (InspectorDOMAgent::getPseudoElementType(element->getPseudoId(), |
| + &pseudoType)) |
| + value->setPseudoType(pseudoType); |
| + } else { |
| + std::unique_ptr<protocol::Array<protocol::DOM::Node>> pseudoElements = |
| + buildArrayForPseudoElements(element, nodesMap); |
| + if (pseudoElements) { |
| + value->setPseudoElements(std::move(pseudoElements)); |
| + forcePushChildren = true; |
| + } |
| + if (!element->ownerDocument()->xmlVersion().isEmpty()) |
| + value->setXmlVersion(element->ownerDocument()->xmlVersion()); |
| + } |
| + |
| + if (element->isInsertionPoint()) { |
| + value->setDistributedNodes( |
| + buildArrayForDistributedNodes(toInsertionPoint(element))); |
| + forcePushChildren = true; |
| + } |
| + if (isHTMLSlotElement(*element)) { |
| + value->setDistributedNodes( |
| + buildDistributedNodesForSlot(toHTMLSlotElement(element))); |
| + forcePushChildren = true; |
| + } |
| + } else if (node->isDocumentNode()) { |
| + Document* document = toDocument(node); |
| + value->setDocumentURL(documentURLString(document)); |
| + value->setBaseURL(documentBaseURLString(document)); |
| + value->setXmlVersion(document->xmlVersion()); |
| + } else if (node->isDocumentTypeNode()) { |
| + DocumentType* docType = toDocumentType(node); |
| + value->setPublicId(docType->publicId()); |
| + value->setSystemId(docType->systemId()); |
| + } else if (node->isAttributeNode()) { |
| + Attr* attribute = toAttr(node); |
| + value->setName(attribute->name()); |
| + value->setValue(attribute->value()); |
| + } else if (node->isShadowRoot()) { |
| + value->setShadowRootType(shadowRootType(toShadowRoot(node))); |
| + } |
| + |
| + if (node->isContainerNode()) { |
| + int nodeCount = innerChildNodeCount(node); |
| + value->setChildNodeCount(nodeCount); |
| + if (nodesMap == m_documentNodeToIdMap) |
| + m_cachedChildCount.set(id, nodeCount); |
| + if (forcePushChildren && !depth) |
| + depth = 1; |
| + |
| + std::unique_ptr<protocol::Array<protocol::DOM::Node>> children( |
| + new protocol::Array<protocol::DOM::Node>); |
| + |
| + Node* child = innerFirstChild(node); |
| + m_childrenRequested.add(bind(node, nodesMap)); |
| + |
| + while (child) { |
| + size_t nextIndex = result->length(); |
| + buildFlatObjectsForNode(child, depth - 1, pierce, nodesMap, result); |
| + children->addItem(minimalCopy(result->get(nextIndex))); |
| + child = innerNextSibling(child); |
| + } |
| + |
| + if (children->length() > 0 || |
| + depth) // Push children along with shadow in any case. |
| + value->setChildren(std::move(children)); |
| + } |
| + |
| + result->addItem(std::move(value)); |
| +} |
| + |
| +std::unique_ptr<protocol::DOM::Node> InspectorDOMAgent::minimalCopy( |
| + protocol::DOM::Node* node) const { |
| + // This is intended for use by buildFlatObjectsForNode where a Node's shadow |
| + // nodes, child nodes etc only point to the ID of the real full object which |
| + // is returned in the array of nodes. |
| + return protocol::DOM::Node::create() |
| + .setNodeId(node->getNodeId()) |
| + .setBackendNodeId(node->getBackendNodeId()) |
| + .setNodeType(node->getNodeType()) |
| + .setNodeName("") |
| + .setLocalName("") |
| + .setNodeValue("") |
| + .build(); |
| +} |
| + |
| std::unique_ptr<protocol::Array<String>> |
| InspectorDOMAgent::buildArrayForElementAttributes(Element* element) { |
| std::unique_ptr<protocol::Array<String>> attributesValue = |