Title: [269983] trunk
- Revision
- 269983
- Author
- [email protected]
- Date
- 2020-11-18 13:57:01 -0800 (Wed, 18 Nov 2020)
Log Message
[iOS] beforeunload event does not fire in MobileSafari
https://bugs.webkit.org/show_bug.cgi?id=219102
<rdar://problem/70550655>
Reviewed by Geoff Garen.
Source/WebCore:
MobileSafari on iOS does not implement WKUIDelegate's runJavaScriptAlertPanelWithMessage because
it never shows any before unload prompt. When the client does not implement this delegate,
Chrome::canRunBeforeUnloadConfirmPanel() returns false and this was causing
FrameLoader::shouldClose() to return early, before even firing the beforeunload event in each
frame. I updated our logic so that we now fire the beforeunload events no matter what and we
merely do not attempt to show the beforeunload prompt when Chrome::canRunBeforeUnloadConfirmPanel()
return false, similarly to what we do when the document does not have a user gesture.
Note that we already fire the pagehide and unload events on iOS so this is not a significant
change in policy.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::shouldClose):
(WebCore::FrameLoader::dispatchBeforeUnloadEvent):
Tools:
Add API test coverage.
* TestWebKitAPI/Tests/WebKit/beforeunload.html:
* TestWebKitAPI/Tests/WebKitCocoa/ModalAlerts.mm:
(-[UIDelegateWithoutRunBeforeUnload webViewDidClose:]):
(-[BeforeUnloadMessageHandler userContentController:didReceiveScriptMessage:]):
(TEST):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (269982 => 269983)
--- trunk/Source/WebCore/ChangeLog 2020-11-18 21:47:20 UTC (rev 269982)
+++ trunk/Source/WebCore/ChangeLog 2020-11-18 21:57:01 UTC (rev 269983)
@@ -1,3 +1,26 @@
+2020-11-18 Chris Dumez <[email protected]>
+
+ [iOS] beforeunload event does not fire in MobileSafari
+ https://bugs.webkit.org/show_bug.cgi?id=219102
+ <rdar://problem/70550655>
+
+ Reviewed by Geoff Garen.
+
+ MobileSafari on iOS does not implement WKUIDelegate's runJavaScriptAlertPanelWithMessage because
+ it never shows any before unload prompt. When the client does not implement this delegate,
+ Chrome::canRunBeforeUnloadConfirmPanel() returns false and this was causing
+ FrameLoader::shouldClose() to return early, before even firing the beforeunload event in each
+ frame. I updated our logic so that we now fire the beforeunload events no matter what and we
+ merely do not attempt to show the beforeunload prompt when Chrome::canRunBeforeUnloadConfirmPanel()
+ return false, similarly to what we do when the document does not have a user gesture.
+
+ Note that we already fire the pagehide and unload events on iOS so this is not a significant
+ change in policy.
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::shouldClose):
+ (WebCore::FrameLoader::dispatchBeforeUnloadEvent):
+
2020-11-18 Aditya Keerthi <[email protected]>
[iOS][FCR] Use new glyph for -webkit-list-button
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (269982 => 269983)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2020-11-18 21:47:20 UTC (rev 269982)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2020-11-18 21:57:01 UTC (rev 269983)
@@ -3234,8 +3234,6 @@
Page* page = m_frame.page();
if (!page)
return true;
- if (!page->chrome().canRunBeforeUnloadConfirmPanel())
- return true;
// Store all references to each subframe in advance since beforeunload's event handler may modify frame
Vector<Ref<Frame>, 16> targetFrames;
@@ -3365,7 +3363,7 @@
if (!beforeUnloadEvent->defaultPrevented())
document->defaultEventHandler(beforeUnloadEvent.get());
- if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
+ if (!chrome.canRunBeforeUnloadConfirmPanel() || !shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
return true;
// If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
Modified: trunk/Tools/ChangeLog (269982 => 269983)
--- trunk/Tools/ChangeLog 2020-11-18 21:47:20 UTC (rev 269982)
+++ trunk/Tools/ChangeLog 2020-11-18 21:57:01 UTC (rev 269983)
@@ -1,5 +1,21 @@
2020-11-18 Chris Dumez <[email protected]>
+ [iOS] beforeunload event does not fire in MobileSafari
+ https://bugs.webkit.org/show_bug.cgi?id=219102
+ <rdar://problem/70550655>
+
+ Reviewed by Geoff Garen.
+
+ Add API test coverage.
+
+ * TestWebKitAPI/Tests/WebKit/beforeunload.html:
+ * TestWebKitAPI/Tests/WebKitCocoa/ModalAlerts.mm:
+ (-[UIDelegateWithoutRunBeforeUnload webViewDidClose:]):
+ (-[BeforeUnloadMessageHandler userContentController:didReceiveScriptMessage:]):
+ (TEST):
+
+2020-11-18 Chris Dumez <[email protected]>
+
navigator.clipboard is not exposed on *.localhost pages
https://bugs.webkit.org/show_bug.cgi?id=219020
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/beforeunload.html (269982 => 269983)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/beforeunload.html 2020-11-18 21:47:20 UTC (rev 269982)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/beforeunload.html 2020-11-18 21:57:01 UTC (rev 269983)
@@ -3,6 +3,8 @@
<head>
<script>
_onbeforeunload_ = (ev) => {
+ if (window.webkit && webkit.messageHandlers.testHandler)
+ webkit.messageHandlers.testHandler.postMessage("beforeunload called");
ev.preventDefault();
return "foo";
}
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalAlerts.mm (269982 => 269983)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalAlerts.mm 2020-11-18 21:47:20 UTC (rev 269982)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalAlerts.mm 2020-11-18 21:57:01 UTC (rev 269983)
@@ -313,3 +313,54 @@
}
#endif
+
+static bool wasBeforeUnloadEventHandlerCalled = false;
+
+@interface UIDelegateWithoutRunBeforeUnload : NSObject <WKUIDelegate>
+@end
+
+@implementation UIDelegateWithoutRunBeforeUnload
+
+- (void)webViewDidClose:(WKWebView *)webView
+{
+ [webView _close];
+}
+
+@end
+
+@interface BeforeUnloadMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation BeforeUnloadMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+ NSString *scriptMessage = [message body];
+ EXPECT_WK_STREQ(@"beforeunload called", scriptMessage);
+ wasBeforeUnloadEventHandlerCalled = true;
+}
+@end
+
+TEST(WebKit, BeforeUnloadEventWithoutRunBeforeUnloadConfirmPanelUIDelegate)
+{
+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto messageHandler = adoptNS([[BeforeUnloadMessageHandler alloc] init]);
+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
+
+ auto uiDelegate = adoptNS([[UIDelegateWithoutRunBeforeUnload alloc] init]);
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+ [webView setUIDelegate:uiDelegate.get()];
+
+ [webView synchronouslyLoadTestPageNamed:@"beforeunload"];
+
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ [webView _tryClose];
+
+ // The beforeunload event handler should get called even if the client application does not
+ // have a UIDelegate that can show the before unload prompt.
+ TestWebKitAPI::Util::run(&wasBeforeUnloadEventHandlerCalled);
+
+ // The view should get closed.
+ while (![webView _isClosed])
+ TestWebKitAPI::Util::sleep(0.1);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes