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. } }
void PaintPropertyTreeBuilder::buildTreeNodes( FrameView& frameView, PaintPropertyTreeBuilderContext& context) { if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { LayoutView* layoutView = frameView.layoutView(); if (!layoutView) return; TransformationMatrix frameTranslate; frameTranslate.translate(frameView.x() + layoutView->location().x() + context.current.paintOffset.x(), frameView.y() + layoutView->location().y() + context.current.paintOffset.y()); context.current.transform = layoutView->getMutableForPainting() .ensurePaintProperties() .updatePaintOffsetTranslation(context.current.transform, frameTranslate, FloatPoint3D()); context.current.paintOffset = LayoutPoint(); context.current.renderingContextID = 0; context.current.shouldFlattenInheritedTransform = true; context.absolutePosition = context.current; context.containerForAbsolutePosition = nullptr; // This will get set in updateOutOfFlowContext(). context.fixedPosition = context.current; return; } TransformationMatrix frameTranslate; frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), frameView.y() + context.current.paintOffset.y()); context.current.transform = updateFrameViewPreTranslation( frameView, context.current.transform, frameTranslate, FloatPoint3D()); FloatRoundedRect contentClip( IntRect(IntPoint(), frameView.visibleContentSize())); context.current.clip = updateFrameViewContentClip( frameView, context.current.clip, frameView.preTranslation(), contentClip); // Record the fixed properties before any scrolling occurs. const auto* fixedTransformNode = context.current.transform; auto* fixedScrollNode = context.current.scroll; ScrollOffset scrollOffset = frameView.scrollOffset(); if (frameView.isScrollable() || !scrollOffset.isZero()) { TransformationMatrix frameScroll; frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); context.current.transform = updateFrameViewScrollTranslation( frameView, frameView.preTranslation(), frameScroll, FloatPoint3D()); IntSize scrollClip = frameView.visibleContentSize(); IntSize scrollBounds = frameView.contentsSize(); bool userScrollableHorizontal = frameView.userInputScrollable(HorizontalScrollbar); bool userScrollableVertical = frameView.userInputScrollable(VerticalScrollbar); context.current.scroll = updateFrameViewScroll( frameView, context.current.scroll, frameView.scrollTranslation(), scrollClip, scrollBounds, userScrollableHorizontal, userScrollableVertical); } else { // Ensure pre-existing properties are cleared when there is no scrolling. frameView.setScrollTranslation(nullptr); frameView.setScroll(nullptr); } // Initialize the context for current, absolute and fixed position cases. // They are the same, except that scroll translation does not apply to // fixed position descendants. context.current.paintOffset = LayoutPoint(); context.current.renderingContextID = 0; context.current.shouldFlattenInheritedTransform = true; context.absolutePosition = context.current; context.containerForAbsolutePosition = nullptr; context.fixedPosition = context.current; context.fixedPosition.transform = fixedTransformNode; context.fixedPosition.scroll = fixedScrollNode; std::unique_ptr<PropertyTreeState> contentsState( new PropertyTreeState(context.current.transform, context.current.clip, context.currentEffect, context.current.scroll)); frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); }