Commit 090ef923 authored by Yoichi Osato's avatar Yoichi Osato Committed by Commit Bot

Reset SelectionState w/o propagation when clear old SeletionState.

We clear old selected but not selected LayoutObject's SelectionState
to kNone using LayoutObject::SetSelectionStateIfNeeded().
However the function calls virtual LayoutObject::SetSelectionState(),
which change containing blocks' SelectionState.
This causes inconsistency that marked not kNone LayoutObject can
accidentally marked kNone.

This patch changes it to call non virtual
LayoutObject::SetSelectionState() and assign kNone SelectionState
to only target old selected LayoutObjects.

Bug: 739062

Change-Id: I9ca736de43a2a982b1e29a1607325a1b77e3c35f
Reviewed-on: https://chromium-review.googlesource.com/748841
Commit-Queue: Yoichi Osato <yoichio@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513096}
parent d01da0dd
...@@ -258,7 +258,7 @@ static void SetShouldInvalidateSelection( ...@@ -258,7 +258,7 @@ static void SetShouldInvalidateSelection(
// above. // above.
for (LayoutObject* layout_object : old_invalidation_set) { for (LayoutObject* layout_object : old_invalidation_set) {
const SelectionState old_state = layout_object->GetSelectionState(); const SelectionState old_state = layout_object->GetSelectionState();
layout_object->SetSelectionStateIfNeeded(SelectionState::kNone); layout_object->LayoutObject::SetSelectionState(SelectionState::kNone);
if (layout_object->GetSelectionState() == old_state) if (layout_object->GetSelectionState() == old_state)
continue; continue;
SetShouldInvalidateIfNeeds(layout_object); SetShouldInvalidateIfNeeds(layout_object);
...@@ -593,43 +593,15 @@ void LayoutSelection::Commit() { ...@@ -593,43 +593,15 @@ void LayoutSelection::Commit() {
DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView());
SetShouldInvalidateSelection(new_range, paint_range_); SetShouldInvalidateSelection(new_range, paint_range_);
paint_range_ = new_paint_range; paint_range_ = new_paint_range;
// TODO(yoichio): Remove this if state. if (paint_range_.StartLayoutObject() == paint_range_.EndLayoutObject()) {
// This SelectionState reassignment is ad-hoc patch for DCHECK_EQ(paint_range_.StartLayoutObject()->GetSelectionState(),
// prohibiting use-after-free(crbug.com/752715). SelectionState::kStartAndEnd);
// LayoutText::setSelectionState(state) propergates |state| to ancestor return;
// LayoutObjects, which can accidentally change start/end LayoutObject state
// then LayoutObject::IsSelectionBorder() returns false although we should
// clear selection at LayoutObject::WillBeRemoved().
// We should make LayoutObject::setSelectionState() trivial and remove
// such propagation or at least do it in LayoutSelection.
if ((paint_range_.StartLayoutObject()->GetSelectionState() !=
SelectionState::kStart &&
paint_range_.StartLayoutObject()->GetSelectionState() !=
SelectionState::kStartAndEnd) ||
(paint_range_.EndLayoutObject()->GetSelectionState() !=
SelectionState::kEnd &&
paint_range_.EndLayoutObject()->GetSelectionState() !=
SelectionState::kStartAndEnd)) {
if (paint_range_.StartLayoutObject() == paint_range_.EndLayoutObject()) {
paint_range_.StartLayoutObject()->SetSelectionStateIfNeeded(
SelectionState::kStartAndEnd);
} else {
paint_range_.StartLayoutObject()->SetSelectionStateIfNeeded(
SelectionState::kStart);
paint_range_.EndLayoutObject()->SetSelectionStateIfNeeded(
SelectionState::kEnd);
}
} }
// TODO(yoichio): If start == end, they should be kStartAndEnd. DCHECK_EQ(paint_range_.StartLayoutObject()->GetSelectionState(),
// If not, start.SelectionState == kStart and vice versa. SelectionState::kStart);
DCHECK(paint_range_.StartLayoutObject()->GetSelectionState() == DCHECK_EQ(paint_range_.EndLayoutObject()->GetSelectionState(),
SelectionState::kStart || SelectionState::kEnd);
paint_range_.StartLayoutObject()->GetSelectionState() ==
SelectionState::kStartAndEnd);
DCHECK(paint_range_.EndLayoutObject()->GetSelectionState() ==
SelectionState::kEnd ||
paint_range_.EndLayoutObject()->GetSelectionState() ==
SelectionState::kStartAndEnd);
} }
void LayoutSelection::OnDocumentShutdown() { void LayoutSelection::OnDocumentShutdown() {
......
...@@ -266,10 +266,10 @@ TEST_F(LayoutSelectionTest, ...@@ -266,10 +266,10 @@ TEST_F(LayoutSelectionTest,
.Build()); .Build());
// This commit should not crash. // This commit should not crash.
Selection().CommitAppearanceIfNeeded(); Selection().CommitAppearanceIfNeeded();
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate); TEST_NEXT(IsLayoutBlock, kStartAndEnd, NotInvalidate);
TEST_NEXT(IsLayoutBlockFlow, kStartAndEnd, NotInvalidate); TEST_NEXT(IsLayoutBlockFlow, kStartAndEnd, NotInvalidate);
TEST_NEXT("div1", kStartAndEnd, ShouldInvalidate); TEST_NEXT("div1", kStartAndEnd, ShouldInvalidate);
TEST_NEXT(IsLayoutBlockFlow, kNone, NotInvalidate); TEST_NEXT(IsLayoutBlockFlow, kStartAndEnd, NotInvalidate);
TEST_NEXT("foo", kNone, NotInvalidate); TEST_NEXT("foo", kNone, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate); TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kNone, ShouldInvalidate); TEST_NEXT("bar", kNone, ShouldInvalidate);
...@@ -364,8 +364,8 @@ TEST_F(LayoutSelectionTest, FirstLetterUpdateSeletion) { ...@@ -364,8 +364,8 @@ TEST_F(LayoutSelectionTest, FirstLetterUpdateSeletion) {
.SetBaseAndExtent({baz, 2}, {baz, 3}) .SetBaseAndExtent({baz, 2}, {baz, 3})
.Build()); .Build());
Selection().CommitAppearanceIfNeeded(); Selection().CommitAppearanceIfNeeded();
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate); TEST_NEXT(IsLayoutBlock, kStartAndEnd, NotInvalidate);
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate); TEST_NEXT(IsLayoutBlock, kStart, NotInvalidate);
TEST_NEXT("foo", kNone, ShouldInvalidate); TEST_NEXT("foo", kNone, ShouldInvalidate);
// TODO(yoichio): Invalidating next LayoutBlock is flaky but it doesn't // TODO(yoichio): Invalidating next LayoutBlock is flaky but it doesn't
// matter in wild because we don't paint selection gap. I will update // matter in wild because we don't paint selection gap. I will update
......
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