From 8a45da39c3a57dbc3b5a8d04e9445357b67e4000 Mon Sep 17 00:00:00 2001 From: yoichio Date: Sun, 10 Sep 2017 01:34:52 +0000 Subject: [PATCH] Check PositionInFlatTree validity in LayoutSelection. |ToPositionInFlatTree(pos_in_dom)| returned invalid PositionInFlatTree when |pos_in_dom| is not settled in flat tree. This patch checks validity of returned PositionInFlatTree. Bug: 759364 Change-Id: I859e5cfb57a40a9b1f7c1e39a911707a4959f60c Reviewed-on: https://chromium-review.googlesource.com/656778 Commit-Queue: Yoichi Osato Reviewed-by: Yoshifumi Inoue Cr-Commit-Position: refs/heads/master@{#500806} --- .../Source/core/editing/LayoutSelection.cpp | 14 ++++++++++++- .../core/editing/LayoutSelectionTest.cpp | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp index 2ce20826e2348..2bfd67199ebc2 100644 --- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp +++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp @@ -119,6 +119,16 @@ static SelectionMode ComputeSelectionMode( return SelectionMode::kBlockCursor; } +// TODO(yoichio): Once we have Position::IsValidFor, use it. +static bool IsPositionValidFor(const PositionInFlatTree& position, + const Document& document) { + DCHECK(position.IsNotNull()); + if (position.GetDocument() != document) + return false; + + return FlatTreeTraversal::Contains(document, *position.AnchorNode()); +} + static EphemeralRangeInFlatTree CalcSelectionInFlatTree( const FrameSelection& frame_selection) { const SelectionInDOMTree& selection_in_dom = @@ -131,7 +141,9 @@ static EphemeralRangeInFlatTree CalcSelectionInFlatTree( ToPositionInFlatTree(selection_in_dom.Base()); const PositionInFlatTree& extent = ToPositionInFlatTree(selection_in_dom.Extent()); - if (base.IsNull() || extent.IsNull() || base == extent) + if (base.IsNull() || extent.IsNull() || base == extent || + !IsPositionValidFor(base, frame_selection.GetDocument()) || + !IsPositionValidFor(extent, frame_selection.GetDocument())) return {}; return base <= extent ? EphemeralRangeInFlatTree(base, extent) : EphemeralRangeInFlatTree(extent, base); diff --git a/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp b/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp index efa0ed2a50f17..8400ccdfce654 100644 --- a/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/LayoutSelectionTest.cpp @@ -372,4 +372,25 @@ TEST_F(LayoutSelectionTest, FirstLetterUpdateSeletion) { TEST_NO_NEXT_LAYOUT_OBJECT(); } +TEST_F(LayoutSelectionTest, CommitAppearanceIfNeededNotCrash) { + SetBodyContent("
bar
baz
"); + SetShadowContent("foo", "host"); + UpdateAllLifecyclePhases(); + //
+ // #shadow-root + // foo + // |bar + //
+ //
baz^
+ // |span| is not in flat tree. + Node* const span = + ToElement(GetDocument().QuerySelector("#host")->firstChild()); + DCHECK(span); + Node* const baz = GetDocument().body()->firstChild()->nextSibling(); + DCHECK(baz); + Selection().SetSelection(SelectionInDOMTree::Builder() + .SetBaseAndExtent({baz, 1}, {span, 0}) + .Build()); + Selection().CommitAppearanceIfNeeded(); +} } // namespace blink