HTMLDocument& document() const;
Vector<String> iterate(TextIteratorBehavior = TextIteratorDefaultBehavior);
+ Vector<String> iteratePartial(const Position& start, const Position& end, TextIteratorBehavior = TextIteratorDefaultBehavior);
void setBodyInnerHTML(const char*);
- PassRefPtr<Range> getBodyRange() const;
+ PassRefPtrWillBeRawPtr<Range> getBodyRange() const;
private:
+ Vector<String> iterateWithIterator(TextIterator&);
+
OwnPtr<DummyPageHolder> m_dummyPageHolder;
HTMLDocument* m_document;
Vector<String> TextIteratorTest::iterate(TextIteratorBehavior iteratorBehavior)
{
document().view()->updateLayoutAndStyleIfNeededRecursive(); // Force renderers to be created; TextIterator needs them.
+ RefPtrWillBeRawPtr<Range> range = getBodyRange();
+ TextIterator iterator(range.get(), iteratorBehavior);
+ return iterateWithIterator(iterator);
+}
+
+Vector<String> TextIteratorTest::iteratePartial(const Position& start, const Position& end, TextIteratorBehavior iteratorBehavior)
+{
+ document().view()->updateLayoutAndStyleIfNeededRecursive();
+ TextIterator iterator(start, end, iteratorBehavior);
+ return iterateWithIterator(iterator);
+}
- RefPtr<Range> range = getBodyRange();
- TextIterator textIterator(range.get(), iteratorBehavior);
+Vector<String> TextIteratorTest::iterateWithIterator(TextIterator& iterator)
+{
Vector<String> textChunks;
- while (!textIterator.atEnd()) {
- textChunks.append(textIterator.substring(0, textIterator.length()));
- textIterator.advance();
+ while (!iterator.atEnd()) {
+ textChunks.append(iterator.substring(0, iterator.length()));
+ iterator.advance();
}
return textChunks;
}
document().body()->setInnerHTML(String::fromUTF8(bodyContent), ASSERT_NO_EXCEPTION);
}
-PassRefPtr<Range> TextIteratorTest::getBodyRange() const
+PassRefPtrWillBeRawPtr<Range> TextIteratorTest::getBodyRange() const
{
- RefPtr<Range> range(Range::create(document()));
+ RefPtrWillBeRawPtr<Range> range(Range::create(document()));
range->selectNode(document().body());
return range.release();
}
EXPECT_EQ(expectedTextChunks, iterate(TextIteratorEntersAuthorShadowRoots));
}
+TEST_F(TextIteratorTest, StartingAtNodeInShadowRoot)
+{
+ static const char* bodyContent = "<div id=\"outer\">Hello, <span id=\"host\">text</span> iterator.</div>";
+ static const char* shadowContent = "<span><content>content</content> shadow</span>";
+ static const char* expectedTextChunksRawString[] = {
+ " shadow",
+ "text",
+ " iterator."
+ };
+ Vector<String> expectedTextChunks = createVectorString(expectedTextChunksRawString, WTF_ARRAY_LENGTH(expectedTextChunksRawString));
+
+ setBodyInnerHTML(bodyContent);
+ RefPtr<ShadowRoot> shadowRoot = createShadowRootForElementWithIDAndSetInnerHTML(document(), "host", shadowContent);
+ Node* outerDiv = document().getElementById("outer");
+ Node* spanInShadow = shadowRoot->firstChild();
+ Position start(spanInShadow, Position::PositionIsBeforeChildren);
+ Position end(outerDiv, Position::PositionIsAfterChildren);
+
+ EXPECT_EQ(expectedTextChunks, iteratePartial(start, end, TextIteratorEntersAuthorShadowRoots));
+}
+
+TEST_F(TextIteratorTest, FinishingAtNodeInShadowRoot)
+{
+ static const char* bodyContent = "<div id=\"outer\">Hello, <span id=\"host\">text</span> iterator.</div>";
+ static const char* shadowContent = "<span><content>content</content> shadow</span>";
+ static const char* expectedTextChunksRawString[] = {
+ "Hello, ",
+ " shadow"
+ };
+ Vector<String> expectedTextChunks = createVectorString(expectedTextChunksRawString, WTF_ARRAY_LENGTH(expectedTextChunksRawString));
+
+ setBodyInnerHTML(bodyContent);
+ RefPtr<ShadowRoot> shadowRoot = createShadowRootForElementWithIDAndSetInnerHTML(document(), "host", shadowContent);
+ Node* outerDiv = document().getElementById("outer");
+ Node* spanInShadow = shadowRoot->firstChild();
+ Position start(outerDiv, Position::PositionIsBeforeChildren);
+ Position end(spanInShadow, Position::PositionIsAfterChildren);
+
+ EXPECT_EQ(expectedTextChunks, iteratePartial(start, end, TextIteratorEntersAuthorShadowRoots));
+}
+
TEST_F(TextIteratorTest, FullyClipsContents)
{
static const char* bodyContent =
EXPECT_EQ(expectedTextChunks, iterate(TextIteratorEntersAuthorShadowRoots));
}
+TEST_F(TextIteratorTest, FindPlainTextInvalidTarget)
+{
+ static const char* bodyContent = "<div>foo bar test</div>";
+ setBodyInnerHTML(bodyContent);
+ RefPtrWillBeRawPtr<Range> range = getBodyRange();
+
+ RefPtrWillBeRawPtr<Range> expectedRange = range->cloneRange();
+ expectedRange->collapse(false);
+
+ // A lone lead surrogate (0xDA0A) example taken from fuzz-58.
+ static const UChar invalid1[] = {
+ 0x1461u, 0x2130u, 0x129bu, 0xd711u, 0xd6feu, 0xccadu, 0x7064u,
+ 0xd6a0u, 0x4e3bu, 0x03abu, 0x17dcu, 0xb8b7u, 0xbf55u, 0xfca0u,
+ 0x07fau, 0x0427u, 0xda0au, 0
+ };
+
+ // A lone trailing surrogate (U+DC01).
+ static const UChar invalid2[] = {
+ 0x1461u, 0x2130u, 0x129bu, 0xdc01u, 0xd6feu, 0xccadu, 0
+ };
+ // A trailing surrogate followed by a lead surrogate (U+DC03 U+D901).
+ static const UChar invalid3[] = {
+ 0xd800u, 0xdc00u, 0x0061u, 0xdc03u, 0xd901u, 0xccadu, 0
+ };
+
+ static const UChar* invalidUStrings[] = { invalid1, invalid2, invalid3 };
+
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(invalidUStrings); ++i) {
+ String invalidTarget(invalidUStrings[i]);
+ RefPtrWillBeRawPtr<Range> actualRange = findPlainText(range.get(), invalidTarget, 0);
+ EXPECT_TRUE(areRangesEqual(expectedRange.get(), actualRange.get()));
+ }
+}
+
}