Commit 41baf87e authored by Rakina Zata Amni's avatar Rakina Zata Amni Committed by Commit Bot

Fix crashes due to matching max codepoint by skipping invalid matches

We should check each ICU match to make sure they are valid (aren't
empty or start/end in non-offset-in-anchor positions).

Bug: 1028152
Change-Id: I1e99075a65e474cb7bf7fc14b08730f801df6541
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1939159
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720425}
parent bd94f94a
......@@ -34,20 +34,27 @@ FindBuffer::Results::Results() {
empty_result_ = true;
}
FindBuffer::Results::Results(const Vector<UChar>& buffer,
String search_text,
FindBuffer::Results::Results(const FindBuffer& find_buffer,
TextSearcherICU* text_searcher,
const Vector<UChar>& buffer,
const String& search_text,
const blink::FindOptions options) {
// We need to own the |search_text| because |text_searcher_| only has a
// StringView (doesn't own the search text).
search_text_ = search_text;
text_searcher_.SetPattern(search_text_, options);
text_searcher_.SetText(buffer.data(), buffer.size());
text_searcher_.SetOffset(0);
find_buffer_ = &find_buffer;
text_searcher_ = text_searcher;
text_searcher_->SetPattern(search_text_, options);
text_searcher_->SetText(buffer.data(), buffer.size());
text_searcher_->SetOffset(0);
}
FindBuffer::Results::Iterator::Iterator(TextSearcherICU* text_searcher,
String search_text)
: text_searcher_(text_searcher), has_match_(true) {
FindBuffer::Results::Iterator::Iterator(const FindBuffer& find_buffer,
TextSearcherICU* text_searcher,
const String& search_text)
: find_buffer_(&find_buffer),
text_searcher_(text_searcher),
has_match_(true) {
operator++();
}
......@@ -60,28 +67,50 @@ const FindBuffer::BufferMatchResult FindBuffer::Results::Iterator::operator*()
void FindBuffer::Results::Iterator::operator++() {
DCHECK(has_match_);
has_match_ = text_searcher_->NextMatchResult(match_);
if (has_match_ && find_buffer_ && find_buffer_->IsInvalidMatch(match_))
operator++();
}
FindBuffer::Results::Iterator FindBuffer::Results::begin() {
bool FindBuffer::IsInvalidMatch(MatchResultICU match) const {
// Invalid matches are a result of accidentally matching elements that are
// replaced with the max code point, and may lead to crashes. To avoid
// crashing, we should skip the matches that are invalid - they would have
// either an empty position or a non-offset-in-anchor position.
const unsigned start_index = match.start;
PositionInFlatTree start_position =
PositionAtStartOfCharacterAtIndex(start_index);
if (start_position.IsNull() || !start_position.IsOffsetInAnchor())
return true;
const unsigned end_index = match.start + match.length;
DCHECK_LE(start_index, end_index);
PositionInFlatTree end_position =
PositionAtEndOfCharacterAtIndex(end_index - 1);
if (end_position.IsNull() || !end_position.IsOffsetInAnchor())
return true;
return false;
}
FindBuffer::Results::Iterator FindBuffer::Results::begin() const {
if (empty_result_)
return end();
text_searcher_.SetOffset(0);
return Iterator(&text_searcher_, search_text_);
text_searcher_->SetOffset(0);
return Iterator(*find_buffer_, text_searcher_, search_text_);
}
FindBuffer::Results::Iterator FindBuffer::Results::end() const {
return Iterator();
}
bool FindBuffer::Results::IsEmpty() {
bool FindBuffer::Results::IsEmpty() const {
return begin() == end();
}
FindBuffer::BufferMatchResult FindBuffer::Results::front() {
FindBuffer::BufferMatchResult FindBuffer::Results::front() const {
return *begin();
}
FindBuffer::BufferMatchResult FindBuffer::Results::back() {
FindBuffer::BufferMatchResult FindBuffer::Results::back() const {
Iterator last_result;
for (Iterator it = begin(); it != end(); ++it) {
last_result = it;
......@@ -89,7 +118,7 @@ FindBuffer::BufferMatchResult FindBuffer::Results::back() {
return *last_result;
}
unsigned FindBuffer::Results::CountForTesting() {
unsigned FindBuffer::Results::CountForTesting() const {
unsigned result = 0;
for (Iterator it = begin(); it != end(); ++it) {
++result;
......@@ -205,15 +234,14 @@ EphemeralRangeInFlatTree FindBuffer::FindMatchInRange(
FindBuffer buffer(
EphemeralRangeInFlatTree(start_position, range.EndPosition()));
std::unique_ptr<Results> match_results =
buffer.FindMatches(search_text, options);
if (!match_results->IsEmpty()) {
Results match_results = buffer.FindMatches(search_text, options);
if (!match_results.IsEmpty()) {
if (!(options & kBackwards)) {
BufferMatchResult match = match_results->front();
BufferMatchResult match = match_results.front();
return buffer.RangeFromBufferIndex(match.start,
match.start + match.length);
}
BufferMatchResult match = match_results->back();
BufferMatchResult match = match_results.back();
last_match_range =
buffer.RangeFromBufferIndex(match.start, match.start + match.length);
}
......@@ -222,19 +250,18 @@ EphemeralRangeInFlatTree FindBuffer::FindMatchInRange(
return last_match_range;
}
std::unique_ptr<FindBuffer::Results> FindBuffer::FindMatches(
const WebString& search_text,
const blink::FindOptions options) const {
FindBuffer::Results FindBuffer::FindMatches(const WebString& search_text,
const blink::FindOptions options) {
// We should return empty result if it's impossible to get a match (buffer is
// empty or too short), or when something went wrong in layout, in which case
// |offset_mapping_| is null.
if (buffer_.IsEmpty() || search_text.length() > buffer_.size() ||
!offset_mapping_)
return std::make_unique<Results>();
return Results();
String search_text_16_bit = search_text;
search_text_16_bit.Ensure16Bit();
FoldQuoteMarksAndSoftHyphens(search_text_16_bit);
return std::make_unique<Results>(buffer_, search_text_16_bit, options);
return Results(*this, &text_searcher_, buffer_, search_text_16_bit, options);
}
bool FindBuffer::PushScopedForcedUpdateIfNeeded(const Element& element) {
......@@ -388,7 +415,7 @@ EphemeralRangeInFlatTree FindBuffer::RangeFromBufferIndex(
return EphemeralRangeInFlatTree(start_position, end_position);
}
FindBuffer::BufferNodeMapping FindBuffer::MappingForIndex(
const FindBuffer::BufferNodeMapping* FindBuffer::MappingForIndex(
unsigned index) const {
// Get the first entry that starts at a position higher than offset, and
// move back one entry.
......@@ -397,27 +424,32 @@ FindBuffer::BufferNodeMapping FindBuffer::MappingForIndex(
[](const unsigned offset, const BufferNodeMapping& entry) {
return offset < entry.offset_in_buffer;
});
DCHECK_NE(it, buffer_node_mappings_.begin());
auto* const entry = std::prev(it);
return *entry;
if (it == buffer_node_mappings_.begin())
return nullptr;
auto* entry = std::prev(it);
return entry;
}
PositionInFlatTree FindBuffer::PositionAtStartOfCharacterAtIndex(
unsigned index) const {
DCHECK_LT(index, buffer_.size());
DCHECK(offset_mapping_);
BufferNodeMapping entry = MappingForIndex(index);
const BufferNodeMapping* entry = MappingForIndex(index);
if (!entry)
return PositionInFlatTree();
return ToPositionInFlatTree(offset_mapping_->GetLastPosition(
index - entry.offset_in_buffer + entry.offset_in_mapping));
index - entry->offset_in_buffer + entry->offset_in_mapping));
}
PositionInFlatTree FindBuffer::PositionAtEndOfCharacterAtIndex(
unsigned index) const {
DCHECK_LT(index, buffer_.size());
DCHECK(offset_mapping_);
BufferNodeMapping entry = MappingForIndex(index);
const BufferNodeMapping* entry = MappingForIndex(index);
if (!entry)
return PositionInFlatTree();
return ToPositionInFlatTree(offset_mapping_->GetFirstPosition(
index - entry.offset_in_buffer + entry.offset_in_mapping + 1));
index - entry->offset_in_buffer + entry->offset_in_mapping + 1));
}
void FindBuffer::AddTextToBuffer(const Text& text_node,
......
......@@ -49,18 +49,26 @@ class CORE_EXPORT FindBuffer {
// All match results for this buffer. We can iterate through the
// BufferMatchResults one by one using the Iterator.
class CORE_EXPORT Results {
STACK_ALLOCATED();
public:
Results();
Results(const Vector<UChar>& buffer,
String search_text,
Results(const FindBuffer& find_buffer,
TextSearcherICU* text_searcher,
const Vector<UChar>& buffer,
const String& search_text,
const blink::FindOptions options);
class CORE_EXPORT Iterator
: public std::iterator<std::forward_iterator_tag, BufferMatchResult> {
STACK_ALLOCATED();
public:
Iterator() = default;
Iterator(TextSearcherICU* text_searcher, String search_text_);
Iterator(const FindBuffer& find_buffer,
TextSearcherICU* text_searcher,
const String& search_text);
bool operator==(const Iterator& other) {
return has_match_ == other.has_match_;
......@@ -75,32 +83,34 @@ class CORE_EXPORT FindBuffer {
void operator++();
private:
const FindBuffer* find_buffer_;
TextSearcherICU* text_searcher_;
MatchResultICU match_;
bool has_match_ = false;
};
Iterator begin();
Iterator begin() const;
Iterator end() const;
bool IsEmpty();
bool IsEmpty() const;
BufferMatchResult front();
BufferMatchResult front() const;
BufferMatchResult back();
BufferMatchResult back() const;
unsigned CountForTesting();
unsigned CountForTesting() const;
private:
String search_text_;
TextSearcherICU text_searcher_;
const FindBuffer* find_buffer_;
TextSearcherICU* text_searcher_;
bool empty_result_ = false;
};
// Finds all the match for |search_text| in |buffer_|.
std::unique_ptr<Results> FindMatches(const WebString& search_text,
const blink::FindOptions options) const;
Results FindMatches(const WebString& search_text,
const blink::FindOptions options);
// Gets a flat tree range corresponding to text in the [start_index,
// end_index) of |buffer|.
......@@ -113,6 +123,8 @@ class CORE_EXPORT FindBuffer {
return PositionInFlatTree::FirstPositionInNode(*node_after_block_);
}
bool IsInvalidMatch(MatchResultICU match) const;
private:
// Collects text for one LayoutBlockFlow located within |range| to |buffer_|,
// might be stopped without finishing one full LayoutBlockFlow if we
......@@ -164,7 +176,7 @@ class CORE_EXPORT FindBuffer {
const unsigned offset_in_mapping;
};
BufferNodeMapping MappingForIndex(unsigned index) const;
const BufferNodeMapping* MappingForIndex(unsigned index) const;
PositionInFlatTree PositionAtStartOfCharacterAtIndex(unsigned index) const;
......@@ -179,6 +191,7 @@ class CORE_EXPORT FindBuffer {
Vector<UChar> buffer_;
Vector<BufferNodeMapping> buffer_node_mappings_;
Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_;
TextSearcherICU text_searcher_;
const NGOffsetMapping* offset_mapping_ = nullptr;
};
......
......@@ -44,10 +44,9 @@ TEST_F(FindBufferTest, FindInline) {
"style='display: inline;'>e</div></div>");
FindBuffer buffer(WholeDocumentRange());
EXPECT_TRUE(buffer.PositionAfterBlock().IsNull());
std::unique_ptr<FindBuffer::Results> results =
buffer.FindMatches("abce", kCaseInsensitive);
EXPECT_EQ(1u, results->CountForTesting());
FindBuffer::BufferMatchResult match = *results->begin();
FindBuffer::Results results = buffer.FindMatches("abce", kCaseInsensitive);
EXPECT_EQ(1u, results.CountForTesting());
FindBuffer::BufferMatchResult match = *results.begin();
EXPECT_EQ(0u, match.start);
EXPECT_EQ(4u, match.length);
EXPECT_EQ(
......@@ -143,20 +142,26 @@ TEST_F(FindBufferTest, FindBetweenPositionsSameNode) {
// |end_position| = foofoo| (end of text).
PositionInFlatTree end_position =
PositionInFlatTree::LastPositionInNode(*node);
FindBuffer buffer(EphemeralRangeInFlatTree(start_position, end_position));
EXPECT_EQ(1u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(4u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(EphemeralRangeInFlatTree(start_position, end_position));
EXPECT_EQ(1u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(4u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// |start_position| = fo|ofoo
// |end_position| = foof|oo
start_position = PositionInFlatTree(*node, 2u);
end_position = PositionInFlatTree(*node, 4u);
buffer = FindBuffer(EphemeralRangeInFlatTree(start_position, end_position));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(EphemeralRangeInFlatTree(start_position, end_position));
EXPECT_EQ(0u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
}
TEST_F(FindBufferTest, FindBetweenPositionsDifferentNodes) {
......@@ -167,48 +172,60 @@ TEST_F(FindBufferTest, FindBetweenPositionsDifferentNodes) {
Element* b = GetElementById("b");
// <div>^foo<span>foof|<b>oo</b></span></div>
// So buffer = "foofoof"
FindBuffer buffer(EphemeralRangeInFlatTree(
PositionInFlatTree::FirstPositionInNode(*div->firstChild()),
PositionInFlatTree::LastPositionInNode(*span->firstChild())));
EXPECT_EQ(2u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("fo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oof", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(4u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(3u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(EphemeralRangeInFlatTree(
PositionInFlatTree::FirstPositionInNode(*div->firstChild()),
PositionInFlatTree::LastPositionInNode(*span->firstChild())));
EXPECT_EQ(2u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("fo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u,
buffer.FindMatches("oof", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(4u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(3u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>f^oo<span>foof<b>o|o</b></span></div>
// So buffer = "oofoofo"
buffer = FindBuffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*div->firstChild(), 1),
PositionInFlatTree(*b->firstChild(), 1)));
EXPECT_EQ(1u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oof", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("fo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(5u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*div->firstChild(), 1),
PositionInFlatTree(*b->firstChild(), 1)));
EXPECT_EQ(1u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u,
buffer.FindMatches("oof", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("fo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(5u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>foo<span>f^oof|<b>oo</b></span></div>
// So buffer = "oof"
buffer = FindBuffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*span->firstChild(), 4)));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oof", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("fo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*span->firstChild(), 4)));
EXPECT_EQ(0u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("oof", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("fo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>foo<span>foof^<b>oo|</b></span></div>
// So buffer = "oo"
buffer = FindBuffer(
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 4),
PositionInFlatTree(*b->firstChild(), 2)));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oof", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("fo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oof", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("fo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, FindBetweenPositionsSkippedNodes) {
......@@ -224,45 +241,58 @@ TEST_F(FindBufferTest, FindBetweenPositionsSkippedNodes) {
// <div>^foo<span style='display:none;'>foo|f</span><b>oo</b>
// <script>fo</script><a>o</a></div>
// So buffer = "foo"
FindBuffer buffer(EphemeralRangeInFlatTree(
PositionInFlatTree::FirstPositionInNode(*div->firstChild()),
PositionInFlatTree(*span->firstChild(), 3)));
EXPECT_EQ(1u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oof", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("fo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(EphemeralRangeInFlatTree(
PositionInFlatTree::FirstPositionInNode(*div->firstChild()),
PositionInFlatTree(*span->firstChild(), 3)));
EXPECT_EQ(1u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("oof", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("fo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>foo<span style='display:none;'>f^oof</span><b>oo|</b>
// <script>fo</script><a>o</a></div>
// So buffer = "oo"
buffer = FindBuffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*b->firstChild(), 2)));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*b->firstChild(), 2)));
EXPECT_EQ(0u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>foo<span style='display:none;'>f^oof</span><b>oo|</b>
// <script>f|o</script><a>o</a></div>
// So buffer = "oo"
buffer = FindBuffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*script->firstChild(), 2)));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*span->firstChild(), 1),
PositionInFlatTree(*script->firstChild(), 2)));
EXPECT_EQ(0u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
// <div>foo<span style='display:none;'>foof</span><b>oo|</b>
// <script>f^o</script><a>o|</a></div>
// So buffer = "o"
buffer = FindBuffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*script->firstChild(), 1),
PositionInFlatTree(*a->firstChild(), 1)));
EXPECT_EQ(0u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("o", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive)->CountForTesting());
{
FindBuffer buffer(
EphemeralRangeInFlatTree(PositionInFlatTree(*script->firstChild(), 1),
PositionInFlatTree(*a->firstChild(), 1)));
EXPECT_EQ(0u,
buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("oo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("o", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("f", kCaseInsensitive).CountForTesting());
}
}
TEST_F(FindBufferTest, FindMatchInRange) {
......@@ -355,41 +385,50 @@ INSTANTIATE_TEST_SUITE_P(Blocks,
TEST_P(FindBufferBlockTest, FindBlock) {
SetBodyContent("text<div id='block' style='display: " + GetParam() +
";'>block</div><span id='span'>span</span>");
FindBuffer text_buffer(WholeDocumentRange());
EXPECT_EQ(GetElementById("block"),
*text_buffer.PositionAfterBlock().ComputeContainerNode());
EXPECT_EQ(
1u, text_buffer.FindMatches("text", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, text_buffer.FindMatches("textblock", kCaseInsensitive)
->CountForTesting());
EXPECT_EQ(0u, text_buffer.FindMatches("text block", kCaseInsensitive)
->CountForTesting());
FindBuffer block_buffer(EphemeralRangeInFlatTree(
text_buffer.PositionAfterBlock(), LastPositionInDocument()));
EXPECT_EQ(GetElementById("span"),
*block_buffer.PositionAfterBlock().ComputeContainerNode());
EXPECT_EQ(
1u,
block_buffer.FindMatches("block", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("textblock", kCaseInsensitive)
->CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("text block", kCaseInsensitive)
->CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("blockspan", kCaseInsensitive)
->CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("block span", kCaseInsensitive)
->CountForTesting());
FindBuffer span_buffer(EphemeralRangeInFlatTree(
block_buffer.PositionAfterBlock(), LastPositionInDocument()));
EXPECT_TRUE(span_buffer.PositionAfterBlock().IsNull());
EXPECT_EQ(
1u, span_buffer.FindMatches("span", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, span_buffer.FindMatches("blockspan", kCaseInsensitive)
->CountForTesting());
EXPECT_EQ(0u, span_buffer.FindMatches("block span", kCaseInsensitive)
->CountForTesting());
PositionInFlatTree position_after_block;
{
FindBuffer text_buffer(WholeDocumentRange());
EXPECT_EQ(GetElementById("block"),
*text_buffer.PositionAfterBlock().ComputeContainerNode());
EXPECT_EQ(
1u,
text_buffer.FindMatches("text", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, text_buffer.FindMatches("textblock", kCaseInsensitive)
.CountForTesting());
EXPECT_EQ(0u, text_buffer.FindMatches("text block", kCaseInsensitive)
.CountForTesting());
position_after_block = text_buffer.PositionAfterBlock();
}
{
FindBuffer block_buffer(EphemeralRangeInFlatTree(position_after_block,
LastPositionInDocument()));
EXPECT_EQ(GetElementById("span"),
*block_buffer.PositionAfterBlock().ComputeContainerNode());
EXPECT_EQ(
1u,
block_buffer.FindMatches("block", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("textblock", kCaseInsensitive)
.CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("text block", kCaseInsensitive)
.CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("blockspan", kCaseInsensitive)
.CountForTesting());
EXPECT_EQ(0u, block_buffer.FindMatches("block span", kCaseInsensitive)
.CountForTesting());
position_after_block = block_buffer.PositionAfterBlock();
}
{
FindBuffer span_buffer(EphemeralRangeInFlatTree(position_after_block,
LastPositionInDocument()));
EXPECT_TRUE(span_buffer.PositionAfterBlock().IsNull());
EXPECT_EQ(
1u,
span_buffer.FindMatches("span", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, span_buffer.FindMatches("blockspan", kCaseInsensitive)
.CountForTesting());
EXPECT_EQ(0u, span_buffer.FindMatches("block span", kCaseInsensitive)
.CountForTesting());
}
}
class FindBufferSeparatorTest
......@@ -409,7 +448,7 @@ INSTANTIATE_TEST_SUITE_P(Separators,
TEST_P(FindBufferSeparatorTest, FindSeparatedElements) {
SetBodyContent("a<" + GetParam() + ">a</" + GetParam() + ">a");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(0u, buffer.FindMatches("aa", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("aa", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, WhiteSpaceCollapsingPreWrap) {
......@@ -419,79 +458,75 @@ TEST_F(FindBufferTest, WhiteSpaceCollapsingPreWrap) {
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(
1u,
buffer.FindMatches("a b c d e ", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a b c d e ", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, WhiteSpaceCollapsingPre) {
SetBodyContent("<div style='white-space: pre;'>a \n b</div>");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(1u, buffer.FindMatches("a", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ab", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("a", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ab", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a\n b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a\n b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a \nb", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a \nb", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("a \n b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a \n b", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, WhiteSpaceCollapsingPreLine) {
SetBodyContent("<div style='white-space: pre-line;'>a \n b</div>");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(1u, buffer.FindMatches("a", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ab", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("a", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ab", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a \n b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a \n b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a\n b", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a\n b", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u,
buffer.FindMatches("a \nb", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("a\nb", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("a \nb", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("a\nb", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, BidiTest) {
SetBodyContent("<bdo dir=rtl id=bdo>foo<span>bar</span></bdo>");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(1u,
buffer.FindMatches("foobar", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("foobar", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, KanaSmallVsNormal) {
SetBodyContent("や"); // Normal-sized や
FindBuffer buffer(WholeDocumentRange());
// Should find normal-sized や
EXPECT_EQ(1u, buffer.FindMatches("や", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("や", kCaseInsensitive).CountForTesting());
// Should not find smalll-sized ゃ
EXPECT_EQ(0u, buffer.FindMatches("ゃ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ゃ", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, KanaDakuten) {
SetBodyContent("びゃ"); // Hiragana bya
FindBuffer buffer(WholeDocumentRange());
// Should find bi
EXPECT_EQ(1u, buffer.FindMatches("び", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("び", kCaseInsensitive).CountForTesting());
// Should find smalll-sized ゃ
EXPECT_EQ(1u, buffer.FindMatches("ゃ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ゃ", kCaseInsensitive).CountForTesting());
// Should find bya
EXPECT_EQ(1u,
buffer.FindMatches("びゃ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("びゃ", kCaseInsensitive).CountForTesting());
// Should not find hi
EXPECT_EQ(0u, buffer.FindMatches("ひ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ひ", kCaseInsensitive).CountForTesting());
// Should not find pi
EXPECT_EQ(0u, buffer.FindMatches("ぴ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ぴ", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, KanaHalfFull) {
......@@ -500,49 +535,48 @@ TEST_F(FindBufferTest, KanaHalfFull) {
SetBodyContent("らキナ");
FindBuffer buffer(WholeDocumentRange());
// Should find katakana ra
EXPECT_EQ(1u, buffer.FindMatches("ラ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ラ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ラ", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ラ", kCaseInsensitive).CountForTesting());
// Should find hiragana & katakana ki
EXPECT_EQ(1u, buffer.FindMatches("き", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("キ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("き", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("キ", kCaseInsensitive).CountForTesting());
// Should find hiragana & katakana na
EXPECT_EQ(1u, buffer.FindMatches("な", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ナ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("な", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ナ", kCaseInsensitive).CountForTesting());
// Should find whole word
EXPECT_EQ(1u,
buffer.FindMatches("らきな", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ラキナ", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("らきな", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ラキナ", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("ラキナ", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("ラキナ", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, WholeWordTest) {
SetBodyContent("foo bar foobar 六本木");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(2u, buffer.FindMatches("foo", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("foo", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("foo", kCaseInsensitive | kWholeWord)
->CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("bar", kCaseInsensitive)->CountForTesting());
.CountForTesting());
EXPECT_EQ(2u, buffer.FindMatches("bar", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("bar", kCaseInsensitive | kWholeWord)
->CountForTesting());
.CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("六", kCaseInsensitive | kWholeWord)
->CountForTesting());
.CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("本木", kCaseInsensitive | kWholeWord)
->CountForTesting());
.CountForTesting());
}
TEST_F(FindBufferTest, KanaDecomposed) {
SetBodyContent("は ゛");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(0u, buffer.FindMatches("ば", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("は ゛", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("バ ", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("ば", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("ハ ゛", kCaseInsensitive)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ハ ゙", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("は ゛", kCaseInsensitive).CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("バ ", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u,
buffer.FindMatches("ハ ゛", kCaseInsensitive)->CountForTesting());
buffer.FindMatches("ハ ゛", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ハ ゙", kCaseInsensitive).CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("ハ ゛", kCaseInsensitive).CountForTesting());
}
TEST_F(FindBufferTest, FindPlainTextInvalidTarget1) {
......@@ -557,7 +591,7 @@ TEST_F(FindBufferTest, FindPlainTextInvalidTarget1) {
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches(String(kInvalid1), 0);
EXPECT_TRUE(results->IsEmpty());
EXPECT_TRUE(results.IsEmpty());
}
TEST_F(FindBufferTest, FindPlainTextInvalidTarget2) {
......@@ -570,7 +604,7 @@ TEST_F(FindBufferTest, FindPlainTextInvalidTarget2) {
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches(String(kInvalid2), 0);
EXPECT_TRUE(results->IsEmpty());
EXPECT_TRUE(results.IsEmpty());
}
TEST_F(FindBufferTest, FindPlainTextInvalidTarget3) {
......@@ -582,22 +616,22 @@ TEST_F(FindBufferTest, FindPlainTextInvalidTarget3) {
0xd901u, 0xccadu, 0};
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches(String(kInvalid3), 0);
EXPECT_TRUE(results->IsEmpty());
EXPECT_TRUE(results.IsEmpty());
}
TEST_F(FindBufferTest, DisplayInline) {
SetBodyContent("<span>fi</span>nd");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("find", 0);
ASSERT_EQ(1u, results->CountForTesting());
EXPECT_EQ(FindBuffer::BufferMatchResult({0, 4}), results->front());
ASSERT_EQ(1u, results.CountForTesting());
EXPECT_EQ(FindBuffer::BufferMatchResult({0, 4}), results.front());
}
TEST_F(FindBufferTest, DisplayBlock) {
SetBodyContent("<div>fi</div>nd");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("find", 0);
ASSERT_EQ(0u, results->CountForTesting())
ASSERT_EQ(0u, results.CountForTesting())
<< "We should not match across block.";
}
......@@ -605,48 +639,54 @@ TEST_F(FindBufferTest, DisplayContents) {
SetBodyContent("<div style='display: contents'>fi</div>nd");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("find", 0);
ASSERT_EQ(1u, results->CountForTesting());
EXPECT_EQ(FindBuffer::BufferMatchResult({0, 4}), results->front());
ASSERT_EQ(1u, results.CountForTesting());
EXPECT_EQ(FindBuffer::BufferMatchResult({0, 4}), results.front());
}
TEST_F(FindBufferTest, WBRTest) {
SetBodyContent("fi<wbr>nd and fin<wbr>d");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("find", 0);
ASSERT_EQ(2u, results->CountForTesting());
ASSERT_EQ(2u, results.CountForTesting());
}
TEST_F(FindBufferTest, InputTest) {
SetBodyContent("fi<input type='text'>nd and fin<input type='text'>d");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("find", 0);
ASSERT_EQ(0u, results->CountForTesting());
ASSERT_EQ(0u, results.CountForTesting());
}
TEST_F(FindBufferTest, SelectMultipleTest) {
SetBodyContent("<select multiple><option>find me</option></select>");
FindBuffer buffer(WholeDocumentRange());
{
FindBuffer buffer(WholeDocumentRange());
#if defined(OS_ANDROID)
EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("find", 0).CountForTesting());
#else
EXPECT_EQ(1u, buffer.FindMatches("find", 0)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("find", 0).CountForTesting());
#endif // defined(OS_ANDROID)
}
SetBodyContent("<select size=2><option>find me</option></select>");
buffer = FindBuffer(WholeDocumentRange());
{
FindBuffer buffer(WholeDocumentRange());
#if defined(OS_ANDROID)
EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("find", 0).CountForTesting());
#else
EXPECT_EQ(1u, buffer.FindMatches("find", 0)->CountForTesting());
EXPECT_EQ(1u, buffer.FindMatches("find", 0).CountForTesting());
#endif // defined(OS_ANDROID)
}
SetBodyContent("<select size=1><option>find me</option></select>");
buffer = FindBuffer(WholeDocumentRange());
EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
{
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(0u, buffer.FindMatches("find", 0).CountForTesting());
}
}
TEST_F(FindBufferTest, NullRange) {
SetBodyContent("x<div></div>");
FindBuffer buffer(WholeDocumentRange());
EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
EXPECT_EQ(0u, buffer.FindMatches("find", 0).CountForTesting());
}
TEST_F(FindBufferTest, FindObjectReplacementCharacter) {
......@@ -654,27 +694,50 @@ TEST_F(FindBufferTest, FindObjectReplacementCharacter) {
"some text with <br> and \uFFFC (object replacement character)");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\uFFFC", 0);
ASSERT_EQ(1u, results->CountForTesting());
ASSERT_EQ(1u, results.CountForTesting());
}
TEST_F(FindBufferTest, FindMaxCodepointWithReplacedElementAndMaxCodepoint) {
TEST_F(FindBufferTest,
FindMaxCodepointWithReplacedElementAndMaxCodepointUTF32) {
SetBodyContent("some text with <img/> <br> and \U0010FFFF (max codepoint)");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\U0010FFFF", 0);
ASSERT_EQ(1u, results->CountForTesting());
ASSERT_EQ(1u, results.CountForTesting());
}
TEST_F(FindBufferTest, FindMaxCodepointNormalText) {
TEST_F(FindBufferTest, FindMaxCodepointNormalTextUTF32) {
SetBodyContent("some text");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\U0010FFFF", 0);
ASSERT_EQ(0u, results->CountForTesting());
ASSERT_EQ(0u, results.CountForTesting());
}
TEST_F(FindBufferTest, FindMaxCodepointWithReplacedElement) {
TEST_F(FindBufferTest, FindMaxCodepointWithReplacedElementUTF32) {
SetBodyContent("some text with <img/> <br>");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\U0010FFFF", 0);
ASSERT_EQ(0u, results->CountForTesting());
ASSERT_EQ(0u, results.CountForTesting());
}
TEST_F(FindBufferTest,
FindMaxCodepointWithReplacedElementAndMaxCodepointUTF16) {
SetBodyContent("some text with <img/> <br> and \uFFFF (max codepoint)");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\uFFFF", 0);
ASSERT_EQ(1u, results.CountForTesting());
}
TEST_F(FindBufferTest, FindMaxCodepointNormalTextUTF16) {
SetBodyContent("some text");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\uFFFF", 0);
ASSERT_EQ(0u, results.CountForTesting());
}
TEST_F(FindBufferTest, FindMaxCodepointWithReplacedElementUTF16) {
SetBodyContent("some text with <img/> <br>");
FindBuffer buffer(WholeDocumentRange());
const auto results = buffer.FindMatches("\uFFFF", 0);
ASSERT_EQ(0u, results.CountForTesting());
}
} // namespace blink
......@@ -112,9 +112,9 @@ class FindTaskController::IdleFindTask
while (search_start != search_end) {
// Find in the whole block.
FindBuffer buffer(EphemeralRangeInFlatTree(search_start, search_end));
std::unique_ptr<FindBuffer::Results> match_results =
FindBuffer::Results match_results =
buffer.FindMatches(search_text_, find_options);
for (FindBuffer::BufferMatchResult match : *match_results) {
for (FindBuffer::BufferMatchResult match : match_results) {
const EphemeralRangeInFlatTree ephemeral_match_range =
buffer.RangeFromBufferIndex(match.start,
match.start + match.length);
......
......@@ -104,11 +104,11 @@ EphemeralRangeInFlatTree FindImmediateMatch(String search_text,
// TODO(nburris): FindBuffer will search the rest of the document for a match,
// but we only need to check for an immediate match, so we should stop
// searching if there's no immediate match.
std::unique_ptr<FindBuffer::Results> match_results =
FindBuffer::Results match_results =
buffer.FindMatches(search_text, kCaseInsensitive);
if (!match_results->IsEmpty() && match_results->front().start == 0u) {
FindBuffer::BufferMatchResult buffer_match = match_results->front();
if (!match_results.IsEmpty() && match_results.front().start == 0u) {
FindBuffer::BufferMatchResult buffer_match = match_results.front();
EphemeralRangeInFlatTree match = buffer.RangeFromBufferIndex(
buffer_match.start, buffer_match.start + buffer_match.length);
if (IsWholeWordMatch(match))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment