Title: [282483] trunk
Revision
282483
Author
[email protected]
Date
2021-09-15 18:02:18 -0700 (Wed, 15 Sep 2021)

Log Message

Implement network process crash recovery for BroadcastChannel
https://bugs.webkit.org/show_bug.cgi?id=230236

Reviewed by Alex Christensen.

Source/WebKit:

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):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm:
(-[BroadcastChannelMessageHandler userContentController:didReceiveScriptMessage:]):
(TEST):

Modified Paths

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]);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to