Diff
Modified: trunk/Source/WebKit/ChangeLog (282482 => 282483)
--- trunk/Source/WebKit/ChangeLog 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Source/WebKit/ChangeLog 2021-09-16 01:02:18 UTC (rev 282483)
@@ -1,3 +1,21 @@
+2021-09-15 Chris Dumez <[email protected]>
+
+ Implement network process crash recovery for BroadcastChannel
+ https://bugs.webkit.org/show_bug.cgi?id=230236
+
+ Reviewed by Alex Christensen.
+
+ Have the WebBroadcastChannelRegistry register its BroadcastChannels with the network
+ process after a network process crash. This is useful so that cross-WebProcess
+ communication can keep happening via existing BroadcastChannel after a network process
+ crash.
+
+ * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+ (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+ * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::networkProcessConnectionClosed):
+
2021-09-15 Devin Rousso <[email protected]>
[Payment Request] Clean up some WKA hooks
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp (282482 => 282483)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp 2021-09-16 01:02:18 UTC (rev 282483)
@@ -106,4 +106,12 @@
postMessageLocally(origin, name, std::nullopt, *message.message, callbackAggregator.copyRef());
}
+void WebBroadcastChannelRegistry::networkProcessCrashed()
+{
+ for (auto& [origin, channelsForOrigin] : m_channelsPerOrigin) {
+ for (auto& name : channelsForOrigin.keys())
+ networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { origin, name }, 0);
+ }
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h (282482 => 282483)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h 2021-09-16 01:02:18 UTC (rev 282483)
@@ -52,6 +52,8 @@
void unregisterChannel(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
void postMessage(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
+ void networkProcessCrashed();
+
void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
private:
Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (282482 => 282483)
--- trunk/Source/WebKit/WebProcess/WebProcess.cpp 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp 2021-09-16 01:02:18 UTC (rev 282483)
@@ -1195,6 +1195,7 @@
m_webLoaderStrategy.networkProcessCrashed();
WebSocketStream::networkProcessCrashed();
m_webSocketChannelManager.networkProcessCrashed();
+ m_broadcastChannelRegistry->networkProcessCrashed();
if (m_libWebRTCNetwork)
m_libWebRTCNetwork->networkProcessCrashed();
Modified: trunk/Tools/ChangeLog (282482 => 282483)
--- trunk/Tools/ChangeLog 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Tools/ChangeLog 2021-09-16 01:02:18 UTC (rev 282483)
@@ -1,3 +1,16 @@
+2021-09-15 Chris Dumez <[email protected]>
+
+ Implement network process crash recovery for BroadcastChannel
+ https://bugs.webkit.org/show_bug.cgi?id=230236
+
+ Reviewed by Alex Christensen.
+
+ Add API test coverage.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm:
+ (-[BroadcastChannelMessageHandler userContentController:didReceiveScriptMessage:]):
+ (TEST):
+
2021-09-15 Tim Horton <[email protected]>
Remove the "core.webKitBranchBuild" prompt from setup-git-clone
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm (282482 => 282483)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm 2021-09-16 00:26:33 UTC (rev 282482)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm 2021-09-16 01:02:18 UTC (rev 282483)
@@ -26,9 +26,11 @@
#import "config.h"
#import "HTTPServer.h"
+#import "PlatformUtilities.h"
#import "TestWKWebView.h"
#import "Utilities.h"
#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKScriptMessageHandler.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
@@ -192,3 +194,129 @@
while (preflightRequestsReceived != 2)
TestWebKitAPI::Util::spinRunLoop();
}
+
+
+static Vector<RetainPtr<WKScriptMessage>> receivedMessages;
+static bool receivedMessage = false;
+
+@interface BroadcastChannelMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation BroadcastChannelMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+ receivedMessages.append(message);
+ receivedMessage = true;
+}
+@end
+
+TEST(NetworkProcess, BroadcastChannelCrashRecovery)
+{
+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto messageHandler = adoptNS([[BroadcastChannelMessageHandler alloc] init]);
+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"test"];
+
+ auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+ auto webView2 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+
+ receivedMessage = false;
+ receivedMessages.clear();
+
+ NSString *html = [NSString stringWithFormat:@"<script>let bc = new BroadcastChannel('test'); bc._onmessage_ = (msg) => { webkit.messageHandlers.test.postMessage(msg.data); };</script>"];
+ NSURL *baseURL = [NSURL URLWithString:@"http://example.com/"];
+
+ [webView1 synchronouslyLoadHTMLString:html baseURL:baseURL];
+ [webView2 synchronouslyLoadHTMLString:html baseURL:baseURL];
+
+ auto webPID1 = [webView1 _webProcessIdentifier];
+ auto webPID2 = [webView2 _webProcessIdentifier];
+ EXPECT_NE(webPID1, 0);
+ EXPECT_NE(webPID2, 0);
+ EXPECT_NE(webPID1, webPID2);
+
+ auto networkPID = [[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier];
+ EXPECT_NE(networkPID, 0);
+
+ EXPECT_FALSE(receivedMessage);
+ EXPECT_TRUE(receivedMessages.isEmpty());
+
+ // Test that initial communication from webView1 to webView2 works.
+ receivedMessage = false;
+ receivedMessages.clear();
+ bool finishedRunningScript = false;
+ [webView1 evaluateJavaScript:@"bc.postMessage('foo')" completionHandler: [&] (id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ finishedRunningScript = true;
+ }];
+ TestWebKitAPI::Util::run(&finishedRunningScript);
+
+ TestWebKitAPI::Util::run(&receivedMessage);
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ EXPECT_EQ(receivedMessages.size(), 1U);
+ EXPECT_EQ([receivedMessages[0] webView], webView2);
+ EXPECT_WK_STREQ([receivedMessages[0] body], @"foo");
+
+ // Test that initial communication from webView2 to webView1 works.
+ receivedMessage = false;
+ receivedMessages.clear();
+ finishedRunningScript = false;
+ [webView2 evaluateJavaScript:@"bc.postMessage('bar')" completionHandler: [&] (id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ finishedRunningScript = true;
+ }];
+ TestWebKitAPI::Util::run(&finishedRunningScript);
+
+ TestWebKitAPI::Util::run(&receivedMessage);
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ EXPECT_EQ(receivedMessages.size(), 1U);
+ EXPECT_EQ([receivedMessages[0] webView], webView1);
+ EXPECT_WK_STREQ([receivedMessages[0] body], @"bar");
+
+ // Kill the network process.
+ kill(networkPID, 9);
+ while ([[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier] == networkPID)
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ // Test that initial communication from webView1 to webView2 works.
+ receivedMessage = false;
+ receivedMessages.clear();
+ finishedRunningScript = false;
+ [webView1 evaluateJavaScript:@"bc.postMessage('foo2')" completionHandler: [&] (id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ finishedRunningScript = true;
+ }];
+ TestWebKitAPI::Util::run(&finishedRunningScript);
+
+ TestWebKitAPI::Util::run(&receivedMessage);
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ EXPECT_EQ(receivedMessages.size(), 1U);
+ EXPECT_EQ([receivedMessages[0] webView], webView2);
+ EXPECT_WK_STREQ([receivedMessages[0] body], @"foo2");
+
+ // Test that initial communication from webView2 to webView1 works.
+ receivedMessage = false;
+ receivedMessages.clear();
+ finishedRunningScript = false;
+ [webView2 evaluateJavaScript:@"bc.postMessage('bar2')" completionHandler: [&] (id result, NSError *error) {
+ EXPECT_TRUE(!error);
+ finishedRunningScript = true;
+ }];
+ TestWebKitAPI::Util::run(&finishedRunningScript);
+
+ TestWebKitAPI::Util::run(&receivedMessage);
+ TestWebKitAPI::Util::spinRunLoop(10);
+
+ EXPECT_EQ(receivedMessages.size(), 1U);
+ EXPECT_EQ([receivedMessages[0] webView], webView1);
+ EXPECT_WK_STREQ([receivedMessages[0] body], @"bar2");
+
+ auto networkPID2 = [[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier];
+ EXPECT_NE(networkPID2, 0);
+ EXPECT_NE(networkPID, networkPID2);
+
+ EXPECT_EQ(webPID1, [webView1 _webProcessIdentifier]);
+ EXPECT_EQ(webPID2, [webView2 _webProcessIdentifier]);
+}