Commit 9696438d authored by Ryan Landay's avatar Ryan Landay Committed by Commit Bot

Fix bug entering text into table cell using IME

My CL https://chromium-review.googlesource.com/801979 exposed a bug with
PlainTextRange::CreateRange() when passed a collapsed range at the beginning of
a table cell. TextIterator outputs a tab character ('\t') when iterating over a
table cell boundary; PlainTextRange() is currently counting the tab character
in its character count for this case, but returning a start/end position
(they're the same since it's a collapsed range) before the <td> element, causing
an off-by-one error.

xiaochengh@ found a fix for this issue, so CreateRange() now returns a position
inside the text node, instead of before the <td> element.

Bug: 826615
Change-Id: Ief427ea6aeb0b93cf82bae3b6901cf1b2a8cb4c7
Reviewed-on: https://chromium-review.googlesource.com/987385Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Ryan Landay <rlanday@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547447}
parent 1b3fbb49
......@@ -339,6 +339,7 @@ jumbo_source_set("unit_tests") {
"LayoutSelectionTest.cpp",
"LocalCaretRectBiDiTest.cpp",
"LocalCaretRectTest.cpp",
"PlainTextRangeTest.cpp",
"PositionIteratorTest.cpp",
"PositionTest.cpp",
"PositionWithAffinityTest.cpp",
......
......@@ -121,8 +121,8 @@ EphemeralRange PlainTextRange::CreateRangeFor(
// FIXME: This is a workaround for the fact that the end of a run
// is often at the wrong position for emitted '\n's or if the
// layoutObject of the current node is a replaced element.
if (len == 1 &&
(it.CharacterAt(0) == '\n' || it.IsInsideAtomicInlineElement())) {
if (len == 1 && (it.CharacterAt(0) == '\n' || it.CharacterAt(0) == '\t' ||
it.IsInsideAtomicInlineElement())) {
it.Advance();
if (!it.AtEnd()) {
text_run_end_position = it.StartPositionInCurrentContainer();
......
// Copyright 2018 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 "core/editing/PlainTextRange.h"
#include "core/editing/EphemeralRange.h"
#include "core/editing/testing/EditingTestBase.h"
namespace blink {
class PlainTextRangeTest : public EditingTestBase {
protected:
Element* InsertHTMLElement(const char* element_code, const char* element_id);
};
TEST_F(PlainTextRangeTest, RangeContainingTableCellBoundary) {
SetBodyInnerHTML(
"<table id='sample' contenteditable><tr><td>a</td><td "
"id='td2'>b</td></tr></table>");
Element* table = GetElementById("sample");
PlainTextRange plain_text_range(2, 2);
const EphemeralRange& range = plain_text_range.CreateRange(*table);
EXPECT_EQ(
"<table contenteditable id=\"sample\"><tbody><tr><td>a</td><td "
"id=\"td2\">|b</td></tr></tbody></table>",
GetCaretTextFromBody(range.StartPosition()));
EXPECT_TRUE(range.IsCollapsed());
}
} // namespace blink
......@@ -7,6 +7,7 @@
#include <memory>
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/NodeList.h"
#include "core/dom/Range.h"
#include "core/editing/Editor.h"
#include "core/editing/EphemeralRange.h"
......@@ -3208,4 +3209,26 @@ TEST_F(InputMethodControllerTest, SetCompositionAfterNonEditableElement) {
.Build()));
}
TEST_F(InputMethodControllerTest, SetCompositionInTableCell) {
GetFrame().Selection().SetSelection(
SetSelectionTextToBody(
"<table id='sample' contenteditable><tr><td>a</td><td "
"id='td2'>|</td></tr></table>"),
SetSelectionOptions());
Element* const table = GetDocument().getElementById("sample");
table->focus();
Controller().SetComposition(String::FromUTF8("c"), Vector<ImeTextSpan>(), 1,
1);
Element* const td2 = GetDocument().getElementById("td2");
const Node* const text_node = td2->firstChild();
Range* range = GetCompositionRange();
EXPECT_EQ(text_node, range->startContainer());
EXPECT_EQ(0u, range->startOffset());
EXPECT_EQ(text_node, range->endContainer());
EXPECT_EQ(1u, range->endOffset());
}
} // namespace blink
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