⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 282483 in webkit


Ignore:
Timestamp:
Sep 15, 2021, 6:02:18 PM (5 years ago)
Author:
Chris Dumez
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):

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r282464 r282483  
     12021-09-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement network process crash recovery for BroadcastChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=230236
     5
     6        Reviewed by Alex Christensen.
     7
     8        Have the WebBroadcastChannelRegistry register its BroadcastChannels with the network
     9        process after a network process crash. This is useful so that cross-WebProcess
     10        communication can keep happening via existing BroadcastChannel after a network process
     11        crash.
     12
     13        * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
     14        (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
     15        * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
     16        * WebProcess/WebProcess.cpp:
     17        (WebKit::WebProcess::networkProcessConnectionClosed):
     18
    1192021-09-15  Devin Rousso  <drousso@apple.com>
    220
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp

    r282377 r282483  
    107107}
    108108
     109void WebBroadcastChannelRegistry::networkProcessCrashed()
     110{
     111    for (auto& [origin, channelsForOrigin] : m_channelsPerOrigin) {
     112        for (auto& name : channelsForOrigin.keys())
     113            networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { origin, name }, 0);
     114    }
     115}
     116
    109117} // namespace WebKit
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h

    r282377 r282483  
    5353    void postMessage(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
    5454
     55    void networkProcessCrashed();
     56
    5557    void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
    5658
  • trunk/Source/WebKit/WebProcess/WebProcess.cpp

    r282429 r282483  
    11961196    WebSocketStream::networkProcessCrashed();
    11971197    m_webSocketChannelManager.networkProcessCrashed();
     1198    m_broadcastChannelRegistry->networkProcessCrashed();
    11981199
    11991200    if (m_libWebRTCNetwork)
  • trunk/Tools/ChangeLog

    r282482 r282483  
     12021-09-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement network process crash recovery for BroadcastChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=230236
     5
     6        Reviewed by Alex Christensen.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm:
     11        (-[BroadcastChannelMessageHandler userContentController:didReceiveScriptMessage:]):
     12        (TEST):
     13
    1142021-09-15  Tim Horton  <timothy_horton@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm

    r280081 r282483  
    2727
    2828#import "HTTPServer.h"
     29#import "PlatformUtilities.h"
    2930#import "TestWKWebView.h"
    3031#import "Utilities.h"
    3132#import <WebKit/WKProcessPoolPrivate.h>
     33#import <WebKit/WKScriptMessageHandler.h>
    3234#import <WebKit/WKWebViewPrivate.h>
    3335#import <WebKit/WKWebsiteDataStorePrivate.h>
    … …  
    193195        TestWebKitAPI::Util::spinRunLoop();
    194196}
     197
     198
     199static Vector<RetainPtr<WKScriptMessage>> receivedMessages;
     200static bool receivedMessage = false;
     201
     202@interface BroadcastChannelMessageHandler : NSObject <WKScriptMessageHandler>
     203@end
     204
     205@implementation BroadcastChannelMessageHandler
     206- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
     207{
     208    receivedMessages.append(message);
     209    receivedMessage = true;
     210}
     211@end
     212
     213TEST(NetworkProcess, BroadcastChannelCrashRecovery)
     214{
     215    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     216    auto messageHandler = adoptNS([[BroadcastChannelMessageHandler alloc] init]);
     217    [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"test"];
     218
     219    auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     220    auto webView2 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     221
     222    receivedMessage = false;
     223    receivedMessages.clear();
     224
     225    NSString *html = [NSString stringWithFormat:@"<script>let bc = new BroadcastChannel('test'); bc.onmessage = (msg) => { webkit.messageHandlers.test.postMessage(msg.data); };</script>"];
     226    NSURL *baseURL = [NSURL URLWithString:@"http://example.com/"];
     227
     228    [webView1 synchronouslyLoadHTMLString:html baseURL:baseURL];
     229    [webView2 synchronouslyLoadHTMLString:html baseURL:baseURL];
     230
     231    auto webPID1 = [webView1 _webProcessIdentifier];
     232    auto webPID2 = [webView2 _webProcessIdentifier];
     233    EXPECT_NE(webPID1, 0);
     234    EXPECT_NE(webPID2, 0);
     235    EXPECT_NE(webPID1, webPID2);
     236
     237    auto networkPID = [[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier];
     238    EXPECT_NE(networkPID, 0);
     239
     240    EXPECT_FALSE(receivedMessage);
     241    EXPECT_TRUE(receivedMessages.isEmpty());
     242
     243    // Test that initial communication from webView1 to webView2 works.
     244    receivedMessage = false;
     245    receivedMessages.clear();
     246    bool finishedRunningScript = false;
     247    [webView1 evaluateJavaScript:@"bc.postMessage('foo')" completionHandler: [&] (id result, NSError *error) {
     248        EXPECT_TRUE(!error);
     249        finishedRunningScript = true;
     250    }];
     251    TestWebKitAPI::Util::run(&finishedRunningScript);
     252
     253    TestWebKitAPI::Util::run(&receivedMessage);
     254    TestWebKitAPI::Util::spinRunLoop(10);
     255
     256    EXPECT_EQ(receivedMessages.size(), 1U);
     257    EXPECT_EQ([receivedMessages[0] webView], webView2);
     258    EXPECT_WK_STREQ([receivedMessages[0] body], @"foo");
     259
     260    // Test that initial communication from webView2 to webView1 works.
     261    receivedMessage = false;
     262    receivedMessages.clear();
     263    finishedRunningScript = false;
     264    [webView2 evaluateJavaScript:@"bc.postMessage('bar')" completionHandler: [&] (id result, NSError *error) {
     265        EXPECT_TRUE(!error);
     266        finishedRunningScript = true;
     267    }];
     268    TestWebKitAPI::Util::run(&finishedRunningScript);
     269
     270    TestWebKitAPI::Util::run(&receivedMessage);
     271    TestWebKitAPI::Util::spinRunLoop(10);
     272
     273    EXPECT_EQ(receivedMessages.size(), 1U);
     274    EXPECT_EQ([receivedMessages[0] webView], webView1);
     275    EXPECT_WK_STREQ([receivedMessages[0] body], @"bar");
     276
     277    // Kill the network process.
     278    kill(networkPID, 9);
     279    while ([[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier] == networkPID)
     280        TestWebKitAPI::Util::spinRunLoop(10);
     281
     282    // Test that initial communication from webView1 to webView2 works.
     283    receivedMessage = false;
     284    receivedMessages.clear();
     285    finishedRunningScript = false;
     286    [webView1 evaluateJavaScript:@"bc.postMessage('foo2')" completionHandler: [&] (id result, NSError *error) {
     287        EXPECT_TRUE(!error);
     288        finishedRunningScript = true;
     289    }];
     290    TestWebKitAPI::Util::run(&finishedRunningScript);
     291
     292    TestWebKitAPI::Util::run(&receivedMessage);
     293    TestWebKitAPI::Util::spinRunLoop(10);
     294
     295    EXPECT_EQ(receivedMessages.size(), 1U);
     296    EXPECT_EQ([receivedMessages[0] webView], webView2);
     297    EXPECT_WK_STREQ([receivedMessages[0] body], @"foo2");
     298
     299    // Test that initial communication from webView2 to webView1 works.
     300    receivedMessage = false;
     301    receivedMessages.clear();
     302    finishedRunningScript = false;
     303    [webView2 evaluateJavaScript:@"bc.postMessage('bar2')" completionHandler: [&] (id result, NSError *error) {
     304        EXPECT_TRUE(!error);
     305        finishedRunningScript = true;
     306    }];
     307    TestWebKitAPI::Util::run(&finishedRunningScript);
     308
     309    TestWebKitAPI::Util::run(&receivedMessage);
     310    TestWebKitAPI::Util::spinRunLoop(10);
     311
     312    EXPECT_EQ(receivedMessages.size(), 1U);
     313    EXPECT_EQ([receivedMessages[0] webView], webView1);
     314    EXPECT_WK_STREQ([receivedMessages[0] body], @"bar2");
     315
     316    auto networkPID2 = [[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier];
     317    EXPECT_NE(networkPID2, 0);
     318    EXPECT_NE(networkPID, networkPID2);
     319
     320    EXPECT_EQ(webPID1, [webView1 _webProcessIdentifier]);
     321    EXPECT_EQ(webPID2, [webView2 _webProcessIdentifier]);
     322}
Note: See TracChangeset for help on using the changeset viewer.