Changeset 258989 in webkit
- Timestamp:
- Mar 25, 2020 9:50:27 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r258985 r258989 1 2020-03-24 Daniel Bates <dabates@apple.com> 2 3 [iOS] ASSERTION FAILURE: !isMissingPostLayoutData in WebKit::EditorState::postLayoutData() 4 https://bugs.webkit.org/show_bug.cgi?id=199960 5 <rdar://problem/53323966> 6 7 Reviewed by Simon Fraser. 8 9 Add a test to ensure we do not assert when using the software keyboard to type a character 10 into a <textarea> and then delete it. 11 12 * TestExpectations: Skip tests in editing/deleting/ios on all platforms. 13 * editing/deleting/ios/backspace-last-character-expected.txt: Added. 14 * editing/deleting/ios/backspace-last-character.html: Added. 15 * platform/ios/TestExpectations: Unskip tests in editing/deleting/ios on iOS. 16 1 17 2020-03-25 Simon Fraser <simon.fraser@apple.com> 2 18 -
trunk/LayoutTests/TestExpectations
r258661 r258989 22 22 editing/pasteboard/gtk [ Skip ] 23 23 editing/selection/ios [ Skip ] 24 editing/deleting/ios [ Skip ] 24 25 editing/undo-manager [ Skip ] 25 26 tiled-drawing [ Skip ] -
trunk/LayoutTests/platform/ios/TestExpectations
r258930 r258989 9 9 accessibility/ios-simulator [ Pass ] 10 10 displaylists [ Pass ] 11 editing/deleting/ios [ Pass ] 11 12 http/tests/quicklook [ Pass ] 12 13 media/ios [ Pass ] -
trunk/Source/WebKit/ChangeLog
r258986 r258989 1 2020-03-24 Daniel Bates <dabates@apple.com> 2 3 [iOS] ASSERTION FAILURE: !isMissingPostLayoutData in WebKit::EditorState::postLayoutData() 4 https://bugs.webkit.org/show_bug.cgi?id=199960 5 <rdar://problem/53323966> 6 7 Reviewed by Simon Fraser. 8 9 Refactor the computation of editor state so that we can request that a layout be performed 10 each time we compute the editor state as part of asking the UI process to interpret a key 11 event. The full (read: after layout) editor state is needed for UIKit to perform a deletion 12 because UIKit wants to know how many characters are before the selection. Otherwise, we hit 13 an assert due to the fact the last editor state sent (when the Web process asked the UI process 14 to interpret the key) is missing layout data. 15 16 The refactoring also moves the Cocoa-common code out of the platform-independent WebPage.cpp 17 file into WebPageCocoa.mm. 18 19 One side effect of the refactoring is that we no longer allow the platformEditorState() function 20 to override the isMissingPostLayoutData bit. Currently it can even though the calling code, the 21 platform independent code (PIE) in WebPage, may have attached layout data. Now the PIE code sets 22 this bit if it attached layout data and the platformEditorState() function only attaches more 23 layout data if that bit is set. platformEditorState() never unsets that bit (i.e. sets isMissingPostLayoutData 24 to true). 25 26 The patch also removes m_isEditorStateMissingPostLayoutData in WebPage.h. This instance variable 27 has been unused since <https://trac.webkit.org/changeset/221064/webkit>. Also we haven't been using 28 IncludePostLayoutDataHint::No since the last reference to it was removed in <https://trac.webkit.org/changeset/244494/webkit>. 29 30 I also renamed platformEditorState() to getPlatformEditorState() since it has an out argument. 31 32 Test: editing/deleting/ios/backspace-last-character.html 33 34 * Shared/EditorState.h: 35 * UIProcess/API/glib/WebKitEditorState.cpp: 36 (webkitEditorStateCreate): Initialize _WebKitEditorStatePrivate::typingAttributes to WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE. 37 * WebProcess/WebPage/Cocoa/WebPageCocoa.mm: 38 (WebKit::WebPage::getPlatformEditorStateCommon const): Added. Moved Cocoa-common code from WebPage.cpp to here. 39 * WebProcess/WebPage/WebPage.cpp: 40 (WebKit::WebPage::editorState const): Move Cocoa-common code to WebPageCocoa.mm. Change enum to 41 track whether a layout should be performed. Keep the current behavior of only including post layout 42 data if the frame view does not need a layout. This behavior is encoded in the enumerator ShouldPerformLayout::Default. 43 which is the default argument value for the argument shouldPerformLayout. 44 * WebProcess/WebPage/WebPage.h: 45 (WebKit::WebPage::platformNeedsLayoutForEditorState const): Added. Non-Cocoa port implementation 46 that returns false. 47 * WebProcess/WebPage/glib/WebPageGLib.cpp: 48 (WebKit::WebPage::getPlatformEditorState const): Early return if isMissingPostLayoutData is true. 49 (WebKit::WebPage::platformEditorState const): Deleted. 50 * WebProcess/WebPage/ios/WebPageIOS.mm: 51 (WebKit::WebPage::platformNeedsLayoutForEditorState const): Added. Keep the current behavior of 52 performing a layout if we have a composition or a hardware keyboard is attached. 53 (WebKit::WebPage::getPlatformEditorState const): Call platformEditorStateCommon(). Bail out early 54 if isMissingPostLayoutData is true. 55 (WebKit::WebPage::handleEditingKeyboardEvent): The important part of this patch. Request a layout 56 when computing the editor state that we will send to the UI process. 57 (WebKit::WebPage::platformEditorState const): Deleted. 58 * WebProcess/WebPage/mac/WebPageMac.mm: 59 (WebKit::WebPage::getPlatformEditorState const): Call platformEditorStateCommon(). Bail out early 60 if isMissingPostLayoutData is true. 61 (WebKit::WebPage::platformEditorState const): Deleted. 62 * WebProcess/WebPage/playstation/WebPagePlayStation.cpp: 63 (WebKit::WebPage::getPlatformEditorState const): Update as needed. 64 (WebKit::WebPage::platformEditorState const): Deleted. 65 * WebProcess/WebPage/win/WebPageWin.cpp: 66 (WebKit::WebPage::getPlatformEditorState const): Update as needed. 67 (WebKit::WebPage::platformEditorState const): Deleted. 68 1 69 2020-03-25 Kate Cheney <katherine_cheney@apple.com> 2 70 -
trunk/Source/WebKit/Shared/EditorState.h
r258131 r258989 75 75 bool isInPlugin { false }; 76 76 bool hasComposition { false }; 77 bool isMissingPostLayoutData { false };77 bool isMissingPostLayoutData { true }; 78 78 79 79 #if PLATFORM(IOS_FAMILY) -
trunk/Source/WebKit/UIProcess/API/glib/WebKitEditorState.cpp
r224945 r258989 110 110 WebKitEditorState* editorState = WEBKIT_EDITOR_STATE(g_object_new(WEBKIT_TYPE_EDITOR_STATE, nullptr)); 111 111 editorState->priv->page = &page; 112 editorState->priv->typingAttributes = WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE; 112 113 webkitEditorStateChanged(editorState, page.editorState()); 113 114 return editorState; -
trunk/Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm
r258873 r258989 37 37 #import <pal/spi/cocoa/LaunchServicesSPI.h> 38 38 #import <WebCore/DictionaryLookup.h> 39 #import <WebCore/Editing.h> 39 40 #import <WebCore/Editor.h> 40 41 #import <WebCore/EventHandler.h> … … 43 44 #import <WebCore/FrameView.h> 44 45 #import <WebCore/HTMLConverter.h> 46 #import <WebCore/HTMLOListElement.h> 47 #import <WebCore/HTMLUListElement.h> 45 48 #import <WebCore/HitTestResult.h> 46 49 #import <WebCore/NodeRenderStyle.h> … … 312 315 } 313 316 317 314 318 void WebPage::getProcessDisplayName(CompletionHandler<void(String&&)>&& completionHandler) 315 319 { … … 321 325 } 322 326 327 void WebPage::getPlatformEditorStateCommon(const Frame& frame, EditorState& result) const 328 { 329 if (result.isMissingPostLayoutData) 330 return; 331 332 const auto& selection = frame.selection().selection(); 333 334 if (!result.isContentEditable || selection.isNone()) 335 return; 336 337 auto& postLayoutData = result.postLayoutData(); 338 if (auto editingStyle = EditingStyle::styleAtSelectionStart(selection)) { 339 if (editingStyle->hasStyle(CSSPropertyFontWeight, "bold"_s)) 340 postLayoutData.typingAttributes |= AttributeBold; 341 342 if (editingStyle->hasStyle(CSSPropertyFontStyle, "italic"_s) || editingStyle->hasStyle(CSSPropertyFontStyle, "oblique"_s)) 343 postLayoutData.typingAttributes |= AttributeItalics; 344 345 if (editingStyle->hasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline"_s)) 346 postLayoutData.typingAttributes |= AttributeUnderline; 347 348 if (auto* styleProperties = editingStyle->style()) { 349 bool isLeftToRight = styleProperties->propertyAsValueID(CSSPropertyDirection) == CSSValueLtr; 350 switch (styleProperties->propertyAsValueID(CSSPropertyTextAlign)) { 351 case CSSValueRight: 352 case CSSValueWebkitRight: 353 postLayoutData.textAlignment = RightAlignment; 354 break; 355 case CSSValueLeft: 356 case CSSValueWebkitLeft: 357 postLayoutData.textAlignment = LeftAlignment; 358 break; 359 case CSSValueCenter: 360 case CSSValueWebkitCenter: 361 postLayoutData.textAlignment = CenterAlignment; 362 break; 363 case CSSValueJustify: 364 postLayoutData.textAlignment = JustifiedAlignment; 365 break; 366 case CSSValueStart: 367 postLayoutData.textAlignment = isLeftToRight ? LeftAlignment : RightAlignment; 368 break; 369 case CSSValueEnd: 370 postLayoutData.textAlignment = isLeftToRight ? RightAlignment : LeftAlignment; 371 break; 372 default: 373 break; 374 } 375 if (auto textColor = styleProperties->propertyAsColor(CSSPropertyColor)) 376 postLayoutData.textColor = *textColor; 377 } 378 } 379 380 if (auto* enclosingListElement = enclosingList(selection.start().containerNode())) { 381 if (is<HTMLUListElement>(*enclosingListElement)) 382 postLayoutData.enclosingListType = UnorderedList; 383 else if (is<HTMLOListElement>(*enclosingListElement)) 384 postLayoutData.enclosingListType = OrderedList; 385 else 386 ASSERT_NOT_REACHED(); 387 } 388 389 postLayoutData.baseWritingDirection = frame.editor().baseWritingDirectionForSelectionStart(); 390 } 391 323 392 } // namespace WebKit 324 393 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r258986 r258989 179 179 #include <WebCore/HTMLMenuElement.h> 180 180 #include <WebCore/HTMLMenuItemElement.h> 181 #include <WebCore/HTMLOListElement.h>182 181 #include <WebCore/HTMLPlugInElement.h> 183 182 #include <WebCore/HTMLPlugInImageElement.h> 184 183 #include <WebCore/HTMLSelectElement.h> 185 184 #include <WebCore/HTMLTextFormControlElement.h> 186 #include <WebCore/HTMLUListElement.h>187 185 #include <WebCore/HistoryController.h> 188 186 #include <WebCore/HistoryItem.h> … … 1037 1035 #endif 1038 1036 1039 EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayoutData) const 1040 { 1041 Frame& frame = m_page->focusController().focusedOrMainFrame(); 1037 EditorState WebPage::editorState(ShouldPerformLayout shouldPerformLayout) const 1038 { 1039 // Ref the frame because this function may perform layout, which may cause frame destruction. 1040 Ref<Frame> frame = m_page->focusController().focusedOrMainFrame(); 1042 1041 1043 1042 EditorState result; … … 1052 1051 } 1053 1052 1054 const VisibleSelection& selection = frame .selection().selection();1055 const Editor& editor = frame .editor();1053 const VisibleSelection& selection = frame->selection().selection(); 1054 const Editor& editor = frame->editor(); 1056 1055 1057 1056 result.selectionIsNone = selection.isNone(); … … 1063 1062 result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges() || (editor.client() && !editor.client()->shouldRevealCurrentSelectionAfterInsertion()); 1064 1063 1065 if (auto* document = frame.document()) 1066 result.originIdentifierForPasteboard = document->originIdentifierForPasteboard(); 1067 1068 bool canIncludePostLayoutData = frame.view() && !frame.view()->needsLayout(); 1069 if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::Yes && canIncludePostLayoutData) { 1064 Ref<Document> document = *frame->document(); 1065 result.originIdentifierForPasteboard = document->originIdentifierForPasteboard(); 1066 1067 if (shouldPerformLayout == ShouldPerformLayout::Yes || platformNeedsLayoutForEditorState(frame)) 1068 document->updateLayout(); // May cause document destruction 1069 1070 if (auto* frameView = document->view(); frameView && !frameView->needsLayout()) { 1071 result.isMissingPostLayoutData = false; 1072 1070 1073 auto& postLayoutData = result.postLayoutData(); 1071 1074 postLayoutData.canCut = editor.canCut(); … … 1075 1078 if (m_needsFontAttributes) 1076 1079 postLayoutData.fontAttributes = editor.fontAttributesAtSelectionStart(); 1077 1078 #if PLATFORM(COCOA) 1079 if (result.isContentEditable && !selection.isNone()) { 1080 if (auto editingStyle = EditingStyle::styleAtSelectionStart(selection)) { 1081 if (editingStyle->hasStyle(CSSPropertyFontWeight, "bold")) 1082 postLayoutData.typingAttributes |= AttributeBold; 1083 1084 if (editingStyle->hasStyle(CSSPropertyFontStyle, "italic") || editingStyle->hasStyle(CSSPropertyFontStyle, "oblique")) 1085 postLayoutData.typingAttributes |= AttributeItalics; 1086 1087 if (editingStyle->hasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline")) 1088 postLayoutData.typingAttributes |= AttributeUnderline; 1089 1090 if (auto* styleProperties = editingStyle->style()) { 1091 bool isLeftToRight = styleProperties->propertyAsValueID(CSSPropertyDirection) == CSSValueLtr; 1092 switch (styleProperties->propertyAsValueID(CSSPropertyTextAlign)) { 1093 case CSSValueRight: 1094 case CSSValueWebkitRight: 1095 postLayoutData.textAlignment = RightAlignment; 1096 break; 1097 case CSSValueLeft: 1098 case CSSValueWebkitLeft: 1099 postLayoutData.textAlignment = LeftAlignment; 1100 break; 1101 case CSSValueCenter: 1102 case CSSValueWebkitCenter: 1103 postLayoutData.textAlignment = CenterAlignment; 1104 break; 1105 case CSSValueJustify: 1106 postLayoutData.textAlignment = JustifiedAlignment; 1107 break; 1108 case CSSValueStart: 1109 postLayoutData.textAlignment = isLeftToRight ? LeftAlignment : RightAlignment; 1110 break; 1111 case CSSValueEnd: 1112 postLayoutData.textAlignment = isLeftToRight ? RightAlignment : LeftAlignment; 1113 break; 1114 default: 1115 break; 1116 } 1117 if (auto textColor = styleProperties->propertyAsColor(CSSPropertyColor)) 1118 postLayoutData.textColor = *textColor; 1119 } 1120 } 1121 1122 if (auto* enclosingListElement = enclosingList(selection.start().containerNode())) { 1123 if (is<HTMLUListElement>(*enclosingListElement)) 1124 postLayoutData.enclosingListType = UnorderedList; 1125 else if (is<HTMLOListElement>(*enclosingListElement)) 1126 postLayoutData.enclosingListType = OrderedList; 1127 else 1128 ASSERT_NOT_REACHED(); 1129 } 1130 1131 postLayoutData.baseWritingDirection = editor.baseWritingDirectionForSelectionStart(); 1132 } 1133 #endif 1134 } 1135 1136 platformEditorState(frame, result, shouldIncludePostLayoutData); 1080 } 1081 1082 getPlatformEditorState(frame, result); 1137 1083 1138 1084 m_lastEditorStateWasContentEditable = result.isContentEditable ? EditorStateIsContentEditable::Yes : EditorStateIsContentEditable::No; -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.h
r258804 r258989 479 479 #endif 480 480 481 enum class IncludePostLayoutDataHint { No, Yes };482 EditorState editorState( IncludePostLayoutDataHint = IncludePostLayoutDataHint::Yes) const;481 enum class ShouldPerformLayout { Default, Yes }; 482 EditorState editorState(ShouldPerformLayout = ShouldPerformLayout::Default) const; 483 483 void updateEditorStateAfterLayoutIfEditabilityChanged(); 484 484 … … 1317 1317 void platformReinitialize(); 1318 1318 void platformDetach(); 1319 void platformEditorState(WebCore::Frame&, EditorState& result, IncludePostLayoutDataHint) const; 1319 void getPlatformEditorState(WebCore::Frame&, EditorState&) const; 1320 bool platformNeedsLayoutForEditorState(const WebCore::Frame&) const; 1320 1321 void platformWillPerformEditingCommand(); 1321 1322 void sendEditorStateUpdate(); 1323 void getPlatformEditorStateCommon(const WebCore::Frame&, EditorState&) const; 1322 1324 1323 1325 #if HAVE(TOUCH_BAR) … … 2010 2012 bool m_mainFrameProgressCompleted { false }; 2011 2013 bool m_shouldDispatchFakeMouseMoveEvents { true }; 2012 bool m_isEditorStateMissingPostLayoutData { false };2013 2014 bool m_isSelectingTextWhileInsertingAsynchronously { false }; 2014 2015 … … 2082 2083 #if !PLATFORM(IOS_FAMILY) 2083 2084 inline void WebPage::platformWillPerformEditingCommand() { } 2085 inline bool WebPage::platformNeedsLayoutForEditorState(const WebCore::Frame&) const { return false; } 2084 2086 #endif 2085 2087 -
trunk/Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp
r258918 r258989 69 69 } 70 70 71 void WebPage:: platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const71 void WebPage::getPlatformEditorState(Frame& frame, EditorState& result) const 72 72 { 73 if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No || !frame.view() || frame.view()->needsLayout()) { 74 result.isMissingPostLayoutData = true; 73 if (result.isMissingPostLayoutData || !frame.view() || frame.view()->needsLayout()) 75 74 return; 76 }77 75 78 76 auto& postLayoutData = result.postLayoutData(); -
trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r258974 r258989 224 224 } 225 225 226 void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const 227 { 226 bool WebPage::platformNeedsLayoutForEditorState(const Frame& frame) const 227 { 228 // If we have a composition or are using a hardware keyboard then we need to send the full 229 // editor so that the UIProcess can update UI, including the position of the caret. 230 bool needsLayout = frame.editor().hasComposition(); 231 #if !PLATFORM(MACCATALYST) 232 needsLayout |= m_keyboardIsAttached; 233 #endif 234 return needsLayout; 235 } 236 237 void WebPage::getPlatformEditorState(Frame& frame, EditorState& result) const 238 { 239 getPlatformEditorStateCommon(frame, result); 240 228 241 FrameView* view = frame.view(); 229 242 if (!view) { … … 256 269 requiresPostLayoutData |= m_keyboardIsAttached; 257 270 #endif 258 if ((shouldIncludePostLayoutData == IncludePostLayoutDataHint::No || needsLayout) && !requiresPostLayoutData) { 259 result.isMissingPostLayoutData = true; 260 return; 261 } 271 if (needsLayout || result.isMissingPostLayoutData) 272 return; 262 273 263 274 auto& postLayoutData = result.postLayoutData(); 264 265 const VisibleSelection& selection = frame.selection().selection(); 275 const auto& selection = frame.selection().selection(); 266 276 postLayoutData.isStableStateUpdate = m_isInStableState; 267 277 bool startNodeIsInsideFixedPosition = false; … … 480 490 // FIXME: Interpret the event immediately upon receiving it in UI process, without sending to WebProcess first. 481 491 bool eventWasHandled = false; 482 bool sendResult = WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::InterpretKeyEvent(editorState( ), platformEvent->type() == PlatformKeyboardEvent::Char),492 bool sendResult = WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::InterpretKeyEvent(editorState(ShouldPerformLayout::Yes), platformEvent->type() == PlatformKeyboardEvent::Char), 483 493 Messages::WebPageProxy::InterpretKeyEvent::Reply(eventWasHandled), m_identifier); 484 494 return sendResult && eventWasHandled; -
trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
r258871 r258989 134 134 } 135 135 136 void WebPage:: platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const137 { 138 if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No || !frame.view() || frame.view()->needsLayout() || !result.isContentEditable) {139 result.isMissingPostLayoutData = true; 140 return;141 }136 void WebPage::getPlatformEditorState(Frame& frame, EditorState& result) const 137 { 138 getPlatformEditorStateCommon(frame, result); 139 140 if (result.isMissingPostLayoutData) 141 return; 142 142 143 143 auto& selection = frame.selection().selection(); -
trunk/Source/WebKit/WebProcess/WebPage/playstation/WebPagePlayStation.cpp
r254713 r258989 72 72 } 73 73 74 void WebPage:: platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const74 void WebPage::getPlatformEditorState(Frame& frame, EditorState& result) const 75 75 { 76 76 notImplemented(); -
trunk/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp
r254897 r258989 64 64 } 65 65 66 void WebPage:: platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const66 void WebPage::getPlatformEditorState(Frame&, EditorState&) const 67 67 { 68 68 }
Note: See TracChangeset
for help on using the changeset viewer.