Index: third_party/WebKit/Source/web/WebFrameContentDumper.cpp |
diff --git a/third_party/WebKit/Source/web/WebFrameContentDumper.cpp b/third_party/WebKit/Source/web/WebFrameContentDumper.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c28d1fc6b208da451b2aa6c1d5fdfee9094e1314 |
--- /dev/null |
+++ b/third_party/WebKit/Source/web/WebFrameContentDumper.cpp |
@@ -0,0 +1,112 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "public/web/WebFrameContentDumper.h" |
+ |
+#include "core/editing/EphemeralRange.h" |
+#include "core/editing/iterators/TextIterator.h" |
+#include "core/editing/serializers/Serialization.h" |
+#include "core/frame/LocalFrame.h" |
+#include "core/layout/LayoutPart.h" |
+#include "core/layout/LayoutTreeAsText.h" |
+#include "core/layout/LayoutView.h" |
+#include "public/web/WebDocument.h" |
+#include "public/web/WebLocalFrame.h" |
+#include "web/WebLocalFrameImpl.h" |
+#include "wtf/text/WTFString.h" |
+ |
+namespace blink { |
+ |
+static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) |
+{ |
+ Document* document = frame->document(); |
+ if (!document) |
+ return; |
+ |
+ if (!frame->view()) |
+ return; |
+ |
+ // Select the document body. |
+ if (document->body()) { |
+ const EphemeralRange range = EphemeralRange::rangeOfContents(*document->body()); |
+ |
+ // The text iterator will walk nodes giving us text. This is similar to |
+ // the plainText() function in core/editing/TextIterator.h, but we implement the maximum |
+ // size and also copy the results directly into a wstring, avoiding the |
+ // string conversion. |
+ for (TextIterator it(range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) { |
+ it.text().appendTextToStringBuilder(output, 0, maxChars - output.length()); |
+ if (output.length() >= maxChars) |
+ return; // Filled up the buffer. |
+ } |
+ } |
+ |
+ // The separator between frames when the frames are converted to plain text. |
+ const LChar frameSeparator[] = { '\n', '\n' }; |
+ const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator); |
+ |
+ // Recursively walk the children. |
+ const FrameTree& frameTree = frame->tree(); |
+ for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) { |
+ if (!curChild->isLocalFrame()) |
+ continue; |
+ LocalFrame* curLocalChild = toLocalFrame(curChild); |
+ // Ignore the text of non-visible frames. |
+ LayoutView* contentLayoutObject = curLocalChild->contentLayoutObject(); |
+ LayoutPart* ownerLayoutObject = curLocalChild->ownerLayoutObject(); |
+ if (!contentLayoutObject || !contentLayoutObject->size().width() || !contentLayoutObject->size().height() |
+ || (contentLayoutObject->location().x() + contentLayoutObject->size().width() <= 0) || (contentLayoutObject->location().y() + contentLayoutObject->size().height() <= 0) |
+ || (ownerLayoutObject && ownerLayoutObject->style() && ownerLayoutObject->style()->visibility() != VISIBLE)) { |
+ continue; |
+ } |
+ |
+ // Make sure the frame separator won't fill up the buffer, and give up if |
+ // it will. The danger is if the separator will make the buffer longer than |
+ // maxChars. This will cause the computation above: |
+ // maxChars - output->size() |
+ // to be a negative number which will crash when the subframe is added. |
+ if (output.length() >= maxChars - frameSeparatorLength) |
+ return; |
+ |
+ output.append(frameSeparator, frameSeparatorLength); |
+ frameContentAsPlainText(maxChars, curLocalChild, output); |
+ if (output.length() >= maxChars) |
+ return; // Filled up the buffer. |
+ } |
+} |
+ |
+WebString WebFrameContentDumper::dumpFrameTreeAsText(WebLocalFrame* frame, size_t maxChars) |
+{ |
+ if (!frame) |
+ return WebString(); |
+ StringBuilder text; |
+ frameContentAsPlainText(maxChars, toWebLocalFrameImpl(frame)->frame(), text); |
+ return text.toString(); |
+} |
+ |
+WebString WebFrameContentDumper::dumpAsMarkup(WebLocalFrame* frame) |
+{ |
+ if (!frame) |
+ return WebString(); |
+ return createMarkup(toWebLocalFrameImpl(frame)->frame()->document()); |
+} |
+ |
+WebString WebFrameContentDumper::dumpLayoutTreeAsText(WebLocalFrame* frame, LayoutAsTextControls toShow) |
+{ |
+ if (!frame) |
+ return WebString(); |
+ LayoutAsTextBehavior behavior = LayoutAsTextShowAllLayers; |
+ |
+ if (toShow & LayoutAsTextWithLineTrees) |
+ behavior |= LayoutAsTextShowLineTrees; |
+ |
+ if (toShow & LayoutAsTextDebug) |
+ behavior |= LayoutAsTextShowCompositedLayers | LayoutAsTextShowAddresses | LayoutAsTextShowIDAndClass | LayoutAsTextShowLayerNesting; |
+ |
+ if (toShow & LayoutAsTextPrinting) |
+ behavior |= LayoutAsTextPrintingMode; |
+ |
+ return externalRepresentation(toWebLocalFrameImpl(frame)->frame(), behavior); |
+} |
+} |