Commit d5e6cca8 authored by Gayane Petrosyan's avatar Gayane Petrosyan Committed by Commit Bot

[Sh-Blink] Autocomplete first and last words.

Update user selection range so that first and last words are complete
words, otherwise TextFragmentFinder will not find a match.
For example, where '[' and ']' indicates user selection.
"samp[le text that user sel]ected"
will be changed to
"[sample text that user selected]"

Bug: 1129647
Change-Id: I5e2274b0e1ed0cc240fcea39ffcc369ab29ce171
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2424541
Commit-Queue: Gayane Petrosyan <gayane@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810591}
parent aa642304
......@@ -182,6 +182,36 @@ void TextFragmentSelectorGenerator::BindTextFragmentSelectorProducer(
selection_frame_->GetTaskRunner(blink::TaskType::kInternalDefault));
}
void TextFragmentSelectorGenerator::CompleteSelection() {
if (!selection_range_)
return;
EphemeralRangeInFlatTree ephemeral_range(selection_range_);
Node* start_container =
ephemeral_range.StartPosition().ComputeContainerNode();
Node* end_container = ephemeral_range.EndPosition().ComputeContainerNode();
String start_text = start_container->textContent();
int selection_start_pos =
ephemeral_range.StartPosition().ComputeOffsetInContainerNode();
start_text.Ensure16Bit();
int word_start = FindWordStartBoundary(
start_text.Characters16(), start_text.length(), selection_start_pos);
String end_text = end_container->textContent();
int selection_end_pos =
ephemeral_range.EndPosition().ComputeOffsetInContainerNode();
end_text.Ensure16Bit();
int word_end = FindWordEndBoundary(end_text.Characters16(), end_text.length(),
selection_end_pos);
if (word_start != selection_start_pos || word_end != selection_end_pos) {
selection_range_ =
MakeGarbageCollected<Range>(selection_range_->OwnerDocument(),
Position(start_container, word_start),
Position(end_container, word_end));
}
}
void TextFragmentSelectorGenerator::GenerateSelector(
GenerateSelectorCallback callback) {
DCHECK(selection_range_);
......@@ -195,6 +225,7 @@ void TextFragmentSelectorGenerator::GenerateSelector(
num_prefix_words_ = 0;
num_suffix_words_ = 0;
CompleteSelection();
GenerateSelectorCandidate();
}
......@@ -283,13 +314,14 @@ void TextFragmentSelectorGenerator::GenerateExactSelector() {
DCHECK_EQ(kNeedsNewCandidate, state_);
EphemeralRangeInFlatTree ephemeral_range(selection_range_);
Node* start_container =
ephemeral_range.StartPosition().ComputeContainerNode();
Node* end_container = ephemeral_range.EndPosition().ComputeContainerNode();
Node& start_first_block_ancestor =
FindBuffer::GetFirstBlockLevelAncestorInclusive(
*ephemeral_range.StartPosition().ComputeContainerNode());
FindBuffer::GetFirstBlockLevelAncestorInclusive(*start_container);
Node& end_first_block_ancestor =
FindBuffer::GetFirstBlockLevelAncestorInclusive(
*ephemeral_range.EndPosition().ComputeContainerNode());
FindBuffer::GetFirstBlockLevelAncestorInclusive(*end_container);
// If not in same node, should use ranges.
if (!start_first_block_ancestor.isSameNode(&end_first_block_ancestor)) {
......@@ -301,8 +333,6 @@ void TextFragmentSelectorGenerator::GenerateExactSelector() {
// by a block. Example: <div>start of the selection <div> sub block </div>end
// of the selection</div>.
// TODO(gayane): Move selection start and end to contain full words.
String selected_text = PlainText(ephemeral_range);
// If too long should use ranges.
......@@ -397,11 +427,7 @@ void TextFragmentSelectorGenerator::ExtendRangeSelector() {
void TextFragmentSelectorGenerator::ExtendContext() {
DCHECK_EQ(kContext, step_);
DCHECK_EQ(kNeedsNewCandidate, state_);
// TODO(gayane): Change this to DCHECK after |ExtendRangeSelector| is
// implemented.
if (!selector_)
return;
DCHECK(selector_);
// Give up if context is already too long.
if (num_prefix_words_ == kMaxContextWords ||
......
......@@ -41,6 +41,9 @@ class CORE_EXPORT TextFragmentSelectorGenerator final
void UpdateSelection(LocalFrame* selection_frame,
const EphemeralRangeInFlatTree& selection_range);
// Extend the selection from start and end to contain full words.
void CompleteSelection();
// blink::mojom::blink::TextFragmentSelectorProducer interface
// Generates selector for current selection.
void GenerateSelector(GenerateSelectorCallback callback) override;
......
......@@ -547,6 +547,47 @@ text_text_text_text_text_text_text_text_text_and_last_text",
GenerateAndVerifySelector(selected_start, selected_end, "");
}
// Selection should be autocompleted to contain full words.
TEST_F(TextFragmentSelectorGeneratorTest, WordLimit) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
<!DOCTYPE html>
<div>Test page</div>
<p id='first'>First paragraph text that is longer than 20 chars</p>
)HTML");
Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
const auto& selected_start = Position(first_paragraph, 7);
const auto& selected_end = Position(first_paragraph, 33);
ASSERT_EQ("aragraph text that is long",
PlainText(EphemeralRange(selected_start, selected_end)));
GenerateAndVerifySelector(selected_start, selected_end,
"paragraph%20text%20that%20is%20longer");
}
// Selection should be autocompleted to contain full words. The autocompletion
// should work with extra spaces.
TEST_F(TextFragmentSelectorGeneratorTest, WordLimit_ExtraSpaces) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
request.Complete(R"HTML(
<!DOCTYPE html>
<div>Test page</div>
<p id='first'>First
paragraph text
that is longer than 20 chars</p>
)HTML");
Node* first_paragraph = GetDocument().getElementById("first")->firstChild();
const auto& selected_start = Position(first_paragraph, 11);
const auto& selected_end = Position(first_paragraph, 41);
ASSERT_EQ("aragraph text that is long",
PlainText(EphemeralRange(selected_start, selected_end)));
GenerateAndVerifySelector(selected_start, selected_end,
"paragraph%20text%20that%20is%20longer");
}
// Basic test case for |GetNextTextBlock|.
TEST_F(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock) {
SimRequest request("https://example.com/test.html", "text/html");
......
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