Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[iOS] Crash when tapping <select> element and calling window.open()
https://bugs.webkit.org/show_bug.cgi?id=229468
rdar://82122972

Reviewed by Wenson Hsieh.

Source/WebKit:

UIKit throws an exception when attempting to present a context menu
for a view that is not in a window.

One instance where this can occur in Safari is when a call to
window.open() is made in response to a touch on a select element.
In this scenario, the call to window.open() opens a new tab, unparenting
the current webview. However, the touch also focuses the element, and
WebKit attempts to present a context menu in an unparented view.

To fix, guard against the case where the view is not parented, and do
not attempt to present a context menu.

Test: fast/forms/ios/show-select-menu-in-unparented-view-crash.html

* UIProcess/ios/WKActionSheetAssistant.mm:

Note that the helper method used in other classes is not used in
WKActionSheetAssistant, since the hosting view is not always a
WKContentView.

(-[WKActionSheetAssistant showDataDetectorsUIForPositionInformation:]):
(-[WKActionSheetAssistant showMediaControlsContextMenu:items:completionHandler:]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView presentContextMenu:atLocation:]):

Added a helper method to ensure the view is parented prior to presenting
a context menu.

(-[WKContentView imageAnalysisGestureDidTimeOut:]):
* UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm:
(-[WKDataListSuggestionsDropdown _showSuggestions]):
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker showDateTimePicker]):
* UIProcess/ios/forms/WKFileUploadPanel.mm:
(-[WKFileUploadPanel showDocumentPickerMenu]):
* UIProcess/ios/forms/WKFormSelectPicker.mm:
(-[WKSelectPicker showSelectPicker]):

LayoutTests:

Added a test to verify a crash does not occur when tapping a <select>
element and unparenting the webview.

* fast/forms/ios/show-select-menu-in-unparented-view-crash-expected.txt: Added.
* fast/forms/ios/show-select-menu-in-unparented-view-crash.html: Added.


Canonical link: https://commits.webkit.org/240943@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@281579 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
pxlcoder committed Aug 25, 2021
1 parent 6d48c91 commit 026dfa3
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 7 deletions.
14 changes: 14 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
2021-08-25 Aditya Keerthi <akeerthi@apple.com>

[iOS] Crash when tapping <select> element and calling window.open()
https://bugs.webkit.org/show_bug.cgi?id=229468
rdar://82122972

Reviewed by Wenson Hsieh.

Added a test to verify a crash does not occur when tapping a <select>
element and unparenting the webview.

* fast/forms/ios/show-select-menu-in-unparented-view-crash-expected.txt: Added.
* fast/forms/ios/show-select-menu-in-unparented-view-crash.html: Added.

2021-08-25 Alan Bujtas <zalan@apple.com>

Unreviewed test gardening after r228617.
Expand Down
@@ -0,0 +1,9 @@
This test verifies that tapping on a select element and then unparenting the webview does not result in a crash.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,42 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<script src="../../../resources/js-test.js"></script>
<script src="../../../resources/ui-helper.js"></script>
</head>
<body>
<select id="select">
<option>January</option>
<option>February</option>
<option>March</option>
<option>April</option>
<option>May</option>
<option>June</option>
<option>July</option>
<option>August</option>
<option>September</option>
<option>October</option>
<option>November</option>
<option>December</option>
</select>
</body>
<script>
jsTestIsAsync = true;

addEventListener("load", async () => {
description("This test verifies that tapping on a select element and then unparenting the webview does not result in a crash.");

select.addEventListener("touchstart", () => {
UIHelper.removeViewFromWindow();
});

select.addEventListener("focus", async () => {
await UIHelper.ensurePresentationUpdate();
finishJSTest();
});

UIHelper.activateElement(select);
});
</script>
</html>
47 changes: 47 additions & 0 deletions Source/WebKit/ChangeLog
@@ -1,3 +1,50 @@
2021-08-25 Aditya Keerthi <akeerthi@apple.com>

[iOS] Crash when tapping <select> element and calling window.open()
https://bugs.webkit.org/show_bug.cgi?id=229468
rdar://82122972

Reviewed by Wenson Hsieh.

UIKit throws an exception when attempting to present a context menu
for a view that is not in a window.

One instance where this can occur in Safari is when a call to
window.open() is made in response to a touch on a select element.
In this scenario, the call to window.open() opens a new tab, unparenting
the current webview. However, the touch also focuses the element, and
WebKit attempts to present a context menu in an unparented view.

To fix, guard against the case where the view is not parented, and do
not attempt to present a context menu.

Test: fast/forms/ios/show-select-menu-in-unparented-view-crash.html

* UIProcess/ios/WKActionSheetAssistant.mm:

Note that the helper method used in other classes is not used in
WKActionSheetAssistant, since the hosting view is not always a
WKContentView.

(-[WKActionSheetAssistant showDataDetectorsUIForPositionInformation:]):
(-[WKActionSheetAssistant showMediaControlsContextMenu:items:completionHandler:]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView presentContextMenu:atLocation:]):

Added a helper method to ensure the view is parented prior to presenting
a context menu.

(-[WKContentView imageAnalysisGestureDidTimeOut:]):
* UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm:
(-[WKDataListSuggestionsDropdown _showSuggestions]):
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker showDateTimePicker]):
* UIProcess/ios/forms/WKFileUploadPanel.mm:
(-[WKFileUploadPanel showDocumentPickerMenu]):
* UIProcess/ios/forms/WKFormSelectPicker.mm:
(-[WKSelectPicker showSelectPicker]):

2021-08-25 Per Arne Vollan <pvollan@apple.com>

Build error preprocessing sandbox
Expand Down
5 changes: 3 additions & 2 deletions Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm
Expand Up @@ -770,7 +770,8 @@ - (void)showDataDetectorsUIForPositionInformation:(const WebKit::InteractionInfo
return;

#if USE(UICONTEXTMENU) && HAVE(UICONTEXTMENU_LOCATION)
[self._ensureDataDetectorContextMenuInteraction _presentMenuAtLocation:_positionInformation->request.point];
if ([_view window])
[self._ensureDataDetectorContextMenuInteraction _presentMenuAtLocation:_positionInformation->request.point];
#else
NSMutableArray *elementActions = [NSMutableArray array];
for (NSUInteger actionNumber = 0; actionNumber < [dataDetectorsActions count]; actionNumber++) {
Expand Down Expand Up @@ -831,7 +832,7 @@ - (void)showMediaControlsContextMenu:(WebCore::FloatRect&&)targetFrame items:(Ve
items = WTFMove(items[0].children);
}

if (items.isEmpty()) {
if (![_view window] || items.isEmpty()) {
completionHandler(WebCore::MediaControlsContextMenuItem::invalidID);
return;
}
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Expand Up @@ -730,6 +730,8 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
#if USE(UICONTEXTMENU)
- (UIView *)textEffectsWindow;

- (void)presentContextMenu:(UIContextMenuInteraction *)contextMenuInteraction atLocation:(CGPoint)location;

- (UITargetedPreview *)_createTargetedContextMenuHintPreviewForFocusedElement;
- (UITargetedPreview *)_createTargetedContextMenuHintPreviewIfPossible;
- (void)_removeContextMenuHintContainerIfPossible;
Expand Down
10 changes: 9 additions & 1 deletion Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Expand Up @@ -8761,6 +8761,14 @@ - (void)_removeContextMenuHintContainerIfPossible
[self _removeContainerForContextMenuHintPreviews];
}

- (void)presentContextMenu:(UIContextMenuInteraction *)contextMenuInteraction atLocation:(CGPoint) location
{
if (!self.window)
return;

[contextMenuInteraction _presentMenuAtLocation:location];
}

#endif // USE(UICONTEXTMENU)

#if HAVE(UI_WK_DOCUMENT_CONTEXT)
Expand Down Expand Up @@ -10453,7 +10461,7 @@ - (void)imageAnalysisGestureDidTimeOut:(WKImageAnalysisGestureRecognizer *)gestu
[strongSelf _updateContextMenuForMachineReadableCodeForImageAnalysis:result];
#endif // ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES)
strongSelf->_contextMenuWasTriggeredByImageAnalysisTimeout = YES;
[strongSelf->_contextMenuInteraction _presentMenuAtLocation:location];
[strongSelf presentContextMenu:strongSelf->_contextMenuInteraction.get() atLocation:location];
#else
UNUSED_PARAM(location);
#endif // USE(UICONTEXTMENU)
Expand Down
Expand Up @@ -473,7 +473,8 @@ - (void)_showSuggestions
if (!strongSelf)
return;

[strongSelf->_suggestionsContextMenuInteraction _presentMenuAtLocation:[[strongSelf view] lastInteractionLocation]];
auto view = [strongSelf view];
[view presentContextMenu:strongSelf->_suggestionsContextMenuInteraction.get() atLocation:[view lastInteractionLocation]];
}];
} else {
[_suggestionsContextMenuInteraction updateVisibleMenuWithBlock:[&](UIMenu *visibleMenu) -> UIMenu * {
Expand Down
Expand Up @@ -511,7 +511,7 @@ - (void)showDateTimePicker
[_view.webView _didShowContextMenu];
#elif USE(UICONTEXTMENU) && HAVE(UICONTEXTMENU_LOCATION)
[self ensureContextMenuInteraction];
[_dateTimeContextMenuInteraction _presentMenuAtLocation:_interactionPoint];
[_view presentContextMenu:_dateTimeContextMenuInteraction.get() atLocation:_interactionPoint];
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/UIProcess/ios/forms/WKFileUploadPanel.mm
Expand Up @@ -531,7 +531,7 @@ - (void)showDocumentPickerMenu
#if HAVE(UICONTEXTMENU_LOCATION)
if (_allowedImagePickerTypes.containsAny({ WKFileUploadPanelImagePickerType::Image, WKFileUploadPanelImagePickerType::Video })) {
[self ensureContextMenuInteraction];
[_documentContextMenuInteraction _presentMenuAtLocation:_interactionPoint];
[_view presentContextMenu:_documentContextMenuInteraction.get() atLocation:_interactionPoint];
} else // Image and Video types are not accepted so bypass the menu and open the file picker directly.
#endif
[self showFilePickerMenu];
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/UIProcess/ios/forms/WKFormSelectPicker.mm
Expand Up @@ -717,7 +717,7 @@ - (void)ensureContextMenuInteraction
- (void)showSelectPicker
{
[self ensureContextMenuInteraction];
[_selectContextMenuInteraction _presentMenuAtLocation:_interactionPoint];
[_view presentContextMenu:_selectContextMenuInteraction.get() atLocation:_interactionPoint];
}

#endif // USE(UICONTEXTMENU)
Expand Down

0 comments on commit 026dfa3

Please sign in to comment.