Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Unified Diff: third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp

Issue 2633343003: Adds DOM.getFlatDocument which returns an array of nodes (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 =

Powered by Google App Engine
This is Rietveld 408576698