Skip to content

Commit ef2e9b1

Browse files
pxlcoderrobert-jenner
authored andcommitted
[iOS] File picker dialog remains after opening a new tab in 3rd-party browsers
https://bugs.webkit.org/show_bug.cgi?id=265602 rdar://119001046 Reviewed by Abrar Rahman Protyasha. The file upload panel does not dismiss itself after a new tab is opened, and can end up displayed over a site that's unrelated to the one requesting the upload. The panel itself is a modal view controller that is presented from an appropriate view controller containing the `WKWebView`. Safari has explicit logic to dismiss presented modal view controllers on tab switch, but it is not reasonable to expect other clients to guarantee this behavior. Fix by dismissing all pickers if the `WKWebView` is removed from the hierarchy. * LayoutTests/fast/forms/ios/file-upload-panel-dismiss-when-view-removed-from-window-expected.txt: Added. * LayoutTests/fast/forms/ios/file-upload-panel-dismiss-when-view-removed-from-window.html: Added. * Source/WebKit/UIProcess/Cocoa/WKContactPicker.h: * Source/WebKit/UIProcess/Cocoa/WKContactPicker.mm: (-[WKContactPicker dismiss]): Add a new hook to dismiss the contact picker. * Source/WebKit/UIProcess/ios/WKContentView.mm: (-[WKContentView willMoveToWindow:]): If the content view has moved to a `nil` window, it has been removed from the view hierarchy, and presented pickers should be dismissed. * Source/WebKit/UIProcess/ios/WKContentViewInteraction.h: * Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm: (-[WKContentView cleanUpInteraction]): Factor out logic into `-[WKContentView dismissPickers]`. (-[WKContentView dismissPickers]): Dismiss all pickers that the content view is aware of. Originally-landed-as: 272448.703@safari-7618-branch (a3524e3). rdar://128089287 Canonical link: https://commits.webkit.org/278816@main
1 parent 775bac3 commit ef2e9b1

7 files changed

+81
-13
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Test that the file upload panel is dismissed when its presenting view is removed from the window on iOS.
2+
3+
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4+
5+
6+
Present file picker
7+
PASS areArraysEqual(typeIdentifiers, ['public.plain-text']) is true
8+
9+
Remove view from window
10+
PASS areArraysEqual(typeIdentifiers, []) is true
11+
PASS successfullyParsed is true
12+
13+
TEST COMPLETE
14+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true shouldHandleRunOpenPanel=false shouldPresentPopovers=false ] -->
2+
<html>
3+
<head>
4+
<meta name="viewport" content="width=device-width">
5+
<script src="../../../resources/js-test.js"></script>
6+
<script src="../../../resources/ui-helper.js"></script>
7+
</head>
8+
<body>
9+
<input id="fileInput" type="file" accept=".txt">
10+
<script>
11+
description("Test that the file upload panel is dismissed when its presenting view is removed from the window on iOS.");
12+
jsTestIsAsync = true;
13+
14+
addEventListener("load", async () => {
15+
debug("Present file picker");
16+
await UIHelper.activateElement(fileInput);
17+
typeIdentifiers = await UIHelper.filePickerAcceptedTypeIdentifiers();
18+
shouldBeTrue("areArraysEqual(typeIdentifiers, ['public.plain-text'])");
19+
20+
debug("\nRemove view from window");
21+
await UIHelper.removeViewFromWindow();
22+
typeIdentifiers = await UIHelper.filePickerAcceptedTypeIdentifiers();
23+
shouldBeTrue("areArraysEqual(typeIdentifiers, [])");
24+
25+
finishJSTest();
26+
});
27+
</script>
28+
</body>
29+
</html>

Source/WebKit/UIProcess/Cocoa/WKContactPicker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct ContactsRequestData;
4444

4545
- (void)presentWithRequestData:(const WebCore::ContactsRequestData&)requestData completionHandler:(WTF::CompletionHandler<void(std::optional<Vector<WebCore::ContactInfo>>&&)>&&)completionHandler;
4646

47+
- (void)dismiss;
48+
4749
@property (nonatomic, weak) id<WKContactPickerDelegate> delegate;
4850

4951
@end

Source/WebKit/UIProcess/Cocoa/WKContactPicker.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ - (void)presentWithRequestData:(const WebCore::ContactsRequestData&)requestData
179179
#endif
180180
}
181181

182+
- (void)dismiss
183+
{
184+
[self dismissWithContacts:nil];
185+
}
186+
182187
#pragma mark - Completion
183188

184189
#if HAVE(CNCONTACTPICKERVIEWCONTROLLER)

Source/WebKit/UIProcess/ios/WKContentView.mm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ - (void)willMoveToWindow:(UIWindow *)newWindow
522522

523523
[self _updateForScreen:newWindow.screen];
524524
}
525+
526+
if (window && !newWindow)
527+
[self dismissPickers];
525528
}
526529

527530
- (void)didMoveToWindow

Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,8 @@ struct ImageAnalysisContextMenuActionData {
681681
- (void)cleanUpInteraction;
682682
- (void)cleanUpInteractionPreviewContainers;
683683

684+
- (void)dismissPickers;
685+
684686
- (void)scrollViewWillStartPanOrPinchGesture;
685687

686688
- (void)buildMenuForWebViewWithBuilder:(id <UIMenuBuilder>)builder;

Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,19 +1561,7 @@ - (void)cleanUpInteraction
15611561
[self _unregisterPreview];
15621562
#endif
15631563

1564-
if (_fileUploadPanel) {
1565-
[_fileUploadPanel setDelegate:nil];
1566-
[_fileUploadPanel dismiss];
1567-
_fileUploadPanel = nil;
1568-
}
1569-
1570-
#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
1571-
if (_shareSheet) {
1572-
[_shareSheet setDelegate:nil];
1573-
[_shareSheet dismiss];
1574-
_shareSheet = nil;
1575-
}
1576-
#endif
1564+
[self dismissPickers];
15771565

15781566
[self stopDeferringInputViewUpdatesForAllSources];
15791567
_focusedElementInformation = { };
@@ -9099,6 +9087,31 @@ - (void)contactPickerDidDismiss:(WKContactPicker *)contactPicker
90999087
}
91009088
#endif
91019089

9090+
- (void)dismissPickers
9091+
{
9092+
if (_fileUploadPanel) {
9093+
[_fileUploadPanel setDelegate:nil];
9094+
[_fileUploadPanel dismiss];
9095+
_fileUploadPanel = nil;
9096+
}
9097+
9098+
#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
9099+
if (_shareSheet) {
9100+
[_shareSheet setDelegate:nil];
9101+
[_shareSheet dismiss];
9102+
_shareSheet = nil;
9103+
}
9104+
#endif
9105+
9106+
#if HAVE(CONTACTSUI)
9107+
if (_contactPicker) {
9108+
[_contactPicker setDelegate:nil];
9109+
[_contactPicker dismiss];
9110+
_contactPicker = nil;
9111+
}
9112+
#endif
9113+
}
9114+
91029115
- (NSString *)inputLabelText
91039116
{
91049117
if (!_focusedElementInformation.label.isEmpty())

0 commit comments

Comments
 (0)