Changeset 272928 in webkit
- Timestamp:
- Feb 16, 2021 2:05:09 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r272927 r272928 1 2021-02-16 Ryosuke Niwa <rniwa@webkit.org> 2 3 EventHandler::updateSelectionForMouseDownDispatchingSelectStart should not use an orphaned selection 4 https://bugs.webkit.org/show_bug.cgi?id=221942 5 6 Reviewed by Wenson Hsieh. 7 8 Added a regression test for the bug 221786 / r272777. 9 10 Also updated a test imported from blink to expect rangeCount of 0 instead of 1 11 since we no longer update the selection when the target node has been removed 12 during selectstart. 13 14 * editing/selection/click-selection-with-selectstart-node-removal-expected.txt: Added. 15 * editing/selection/click-selection-with-selectstart-node-removal.html: Added. 16 * imported/blink/editing/selection/selectstart-event-crash.html: 17 1 18 2021-02-16 Antoine Quint <graouts@webkit.org> 2 19 -
trunk/LayoutTests/imported/blink/editing/selection/selectstart-event-crash.html
r194917 r272928 15 15 eventSender.mouseDown(); 16 16 var selection = getSelection(); 17 assert_equals(selection.rangeCount, 1);17 assert_equals(selection.rangeCount, 0); 18 18 }); 19 19 </script> -
trunk/Source/WebCore/ChangeLog
r272927 r272928 1 2021-02-16 Ryosuke Niwa <rniwa@webkit.org> 2 3 EventHandler::updateSelectionForMouseDownDispatchingSelectStart should not use an orphaned selection 4 https://bugs.webkit.org/show_bug.cgi?id=221942 5 6 Reviewed by Wenson Hsieh. 7 8 In r272777, we re-introduced a nullptr check in DOMSelection::getRangeAt as we were getting crash reports 9 in this code but we weren't sure of the root cause. Since then we've identified that one of the root causes 10 is that EventHandler::updateSelectionForMouseDownDispatchingSelectStart doesn't check if VisibleSelection 11 is still in a good state after dispatching selectstart event. This results in FrameSelection's 12 setSelectionWithoutUpdatingAppearance getting called with a selection with end points already being orphaned. 13 14 This patch fixes this bug in setSelectionWithoutUpdatingAppearance and also adds an additional check in 15 FrameSelection::setSelectionWithoutUpdatingAppearance itself to avoid using an orphaned selection. It also 16 introduces a number of release and debug assertions in a number of places to help catch similar bugs. 17 18 Test: editing/selection/click-selection-with-selectstart-node-removal.html 19 20 * dom/ContainerNode.cpp: 21 (WebCore::ContainerNode::removeAllChildrenWithScriptAssertion): Added a debug-only assertion. 22 (WebCore::ContainerNode::removeNodeWithScriptAssertion): Ditto. 23 * dom/Document.cpp: 24 (WebCore::Document::removedLastRef): Disallow script execution in this code entirely. Also release assert 25 that the selection had already been cleared by this point. 26 (WebCore::Document::willBeRemovedFromFrame): Disallow script execution once we've unloaded subframes. 27 * editing/FrameSelection.cpp: 28 (WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance): Return early if the new selection's 29 end points had been orphaned, and disallow script execution between that and until we update the selection. 30 * editing/VisibleSelection.cpp: 31 (WebCore::VisibleSelection::isOrphan const): Added. 32 * editing/VisibleSelection.h: 33 * page/DOMSelection.cpp: 34 (WebCore::DOMSelection::getRangeAt): Removed nullptr check added in r272777. 35 * page/EventHandler.cpp: 36 (WebCore::EventHandler::updateSelectionForMouseDownDispatchingSelectStart): Fixed what is now believed to be 37 the root cause of the bug 221786. 38 1 39 2021-02-16 Antoine Quint <graouts@webkit.org> 2 40 -
trunk/Source/WebCore/dom/ContainerNode.cpp
r272703 r272928 127 127 } 128 128 129 ASSERT_WITH_SECURITY_IMPLICATION(!document().selection().selection().isOrphan()); 130 129 131 if (deferChildrenChanged == DeferChildrenChanged::No) 130 132 childrenChanged(ContainerNode::ChildChange { ChildChange::Type::AllChildrenRemoved, nullptr, nullptr, source }); … … 192 194 if (source == ChildChange::Source::API && subtreeObservability == RemovedSubtreeObservability::MaybeObservableByRefPtr) 193 195 willCreatePossiblyOrphanedTreeByRemoval(&childToRemove); 196 197 ASSERT_WITH_SECURITY_IMPLICATION(!document().selection().selection().isOrphan()); 194 198 195 199 // FIXME: Move childrenChanged into ScriptDisallowedScope block. -
trunk/Source/WebCore/dom/Document.cpp
r272805 r272928 782 782 void Document::removedLastRef() 783 783 { 784 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 784 785 ASSERT(!m_deletionHasBegun); 785 786 if (m_referencingNodeCount) { … … 811 812 812 813 detachParser(); 814 815 RELEASE_ASSERT(m_selection->isNone()); 813 816 814 817 // removeDetachedChildren() doesn't always unregister IDs, … … 2594 2597 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_frame || !m_frame->tree().childCount()); 2595 2598 2599 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 2600 2596 2601 if (m_domWindow && m_frame) 2597 2602 m_domWindow->willDetachDocumentFromFrame(); -
trunk/Source/WebCore/editing/FrameSelection.cpp
r271814 r272928 66 66 #include "RenderWidget.h" 67 67 #include "RenderedPosition.h" 68 #include "ScriptDisallowedScope.h" 68 69 #include "Settings.h" 69 70 #include "SimpleRange.h" … … 334 335 newSelection.setIsDirectional(true); 335 336 336 if (!m_document || !m_document->frame()) {337 m_selection = newSelection;338 updateAssociatedLiveRange();339 return false;340 }341 342 337 // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection 343 338 // if document->frame() == m_document->frame() we can get into an infinite loop 344 339 if (Document* newSelectionDocument = newSelection.base().document()) { 345 340 if (RefPtr<Frame> newSelectionFrame = newSelectionDocument->frame()) { 346 if ( newSelectionFrame != m_document->frame() && newSelectionDocument != m_document) {341 if (m_document && newSelectionFrame != m_document->frame() && newSelectionDocument != m_document) { 347 342 newSelectionDocument->selection().setSelection(newSelection, options, AXTextStateChangeIntent(), align, granularity); 348 343 // It's possible that during the above set selection, this FrameSelection has been modified by … … 356 351 } 357 352 358 m_granularity = granularity;359 360 if (closeTyping)361 TypingCommand::closeTyping(*m_document);362 363 if (shouldClearTypingStyle)364 clearTypingStyle();365 366 353 VisibleSelection oldSelection = m_selection; 367 bool didMutateSelection = oldSelection != newSelection;368 if ( didMutateSelection)354 bool willMutateSelection = oldSelection != newSelection; 355 if (willMutateSelection && m_document) 369 356 m_document->editor().selectionWillChange(); 370 357 371 m_selection = newSelection; 372 updateAssociatedLiveRange(); 358 { 359 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 360 if (newSelection.isOrphan()) { 361 ASSERT_NOT_REACHED(); 362 clear(); 363 return false; 364 } 365 366 if (!m_document || !m_document->frame()) { 367 m_selection = newSelection; 368 updateAssociatedLiveRange(); 369 return false; 370 } 371 372 if (closeTyping) 373 TypingCommand::closeTyping(*m_document); 374 375 if (shouldClearTypingStyle) 376 clearTypingStyle(); 377 378 m_granularity = granularity; 379 m_selection = newSelection; 380 updateAssociatedLiveRange(); 381 } 373 382 374 383 // Selection offsets should increase when LF is inserted before the caret in InsertLineBreakCommand. See <https://webkit.org/b/56061>. … … 376 385 textControl->selectionChanged(options.contains(FireSelectEvent)); 377 386 378 if (! didMutateSelection)387 if (!willMutateSelection) 379 388 return false; 380 389 -
trunk/Source/WebCore/editing/VisibleSelection.cpp
r269136 r272928 132 132 { 133 133 setExtent(visiblePosition.deepEquivalent()); 134 } 135 136 bool VisibleSelection::isOrphan() const 137 { 138 if (m_base.isOrphan() || m_extent.isOrphan() || m_start.isOrphan() || m_end.isOrphan()) 139 return true; 140 if (m_anchor.isOrphan() && m_anchor.document()->settings().liveRangeSelectionEnabled()) 141 return true; 142 if (m_focus.isOrphan() && m_focus.document()->settings().liveRangeSelectionEnabled()) 143 return true; 144 return false; 134 145 } 135 146 -
trunk/Source/WebCore/editing/VisibleSelection.h
r267362 r272928 87 87 bool isNonOrphanedRange() const { return isRange() && !start().isOrphan() && !end().isOrphan(); } 88 88 bool isNoneOrOrphaned() const { return isNone() || start().isOrphan() || end().isOrphan(); } 89 bool isOrphan() const; 89 90 90 91 bool isBaseFirst() const { return m_anchorIsFirst; } -
trunk/Source/WebCore/page/DOMSelection.cpp
r272777 r272928 368 368 if (auto shadowAncestor = selectionShadowAncestor(frame)) 369 369 return createLiveRange(makeSimpleRange(*makeBoundaryPointBeforeNode(*shadowAncestor))); 370 auto simpleRange = frame->selection().selection().firstRange(); 371 ASSERT(simpleRange); // selection is orphaned but this shouldn't happen. 372 if (!simpleRange) 373 return Exception { IndexSizeError }; 374 return createLiveRange(*simpleRange); 370 return createLiveRange(*frame->selection().selection().firstRange()); 375 371 } 376 372 -
trunk/Source/WebCore/page/EventHandler.cpp
r272503 r272928 467 467 } 468 468 469 if (selection.isOrphan()) { 470 m_mouseDownMayStartSelect = false; 471 return false; 472 } 473 469 474 if (selection.isRange()) 470 475 m_selectionInitiationState = ExtendedSelection;
Note: See TracChangeset
for help on using the changeset viewer.