Title: [231321] trunk
Revision
231321
Author
[email protected]
Date
2018-05-03 12:59:05 -0700 (Thu, 03 May 2018)

Log Message

Load hangs if the WebProcess fails to launch
https://bugs.webkit.org/show_bug.cgi?id=185225
<rdar://problem/38249058>

Reviewed by Geoff Garen.

Source/WebKit:

When a process fails to launch, ChildProcessProxy::didFinishLaunching() gets called with an
invalid connection identifier. While NetworkProcessProxy::didFinishLaunching() properly deals with
this situation, WebProcessProxy::didFinishLaunching() does not. As a result, we do not attempt to
relaunch the process, we do not notify the client and WebPageProxy::m_isValid stays true.

This patch thus updates WebProcessProxy::didFinishLaunching() to check if the connection identifier
is valid and treats it as a crash. As a result, the WebPageProxies properly reset their state and
the client gets notified of the crash so that it can attempt to reload.

* UIProcess/API/Cocoa/WKProcessPool.mm:
(-[WKProcessPool _makeNextWebProcessLaunchFailForTesting]):
* UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
* UIProcess/Launcher/ProcessLauncher.h:
* UIProcess/Launcher/mac/ProcessLauncherMac.mm:
(WebKit::ProcessLauncher::launchProcess):
Add SPI to make the next WebProcess launch fail, for the purpose of API testing.

* UIProcess/WebProcessPool.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::getLaunchOptions):
(WebKit::WebProcessProxy::didClose):
(WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
(WebKit::WebProcessProxy::didFinishLaunching):
* UIProcess/WebProcessProxy.h:

Tools:

Add API test coverage.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm: Added.
(-[CrashOnStartNavigationDelegate _webView:webContentProcessDidTerminateWithReason:]):
(-[CrashOnStartNavigationDelegate webView:didFinishNavigation:]):
(-[CrashRecoveryScriptMessageHandler userContentController:didReceiveScriptMessage:]):
(TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (231320 => 231321)


--- trunk/Source/WebKit/ChangeLog	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/ChangeLog	2018-05-03 19:59:05 UTC (rev 231321)
@@ -1,3 +1,36 @@
+2018-05-03  Chris Dumez  <[email protected]>
+
+        Load hangs if the WebProcess fails to launch
+        https://bugs.webkit.org/show_bug.cgi?id=185225
+        <rdar://problem/38249058>
+
+        Reviewed by Geoff Garen.
+
+        When a process fails to launch, ChildProcessProxy::didFinishLaunching() gets called with an
+        invalid connection identifier. While NetworkProcessProxy::didFinishLaunching() properly deals with
+        this situation, WebProcessProxy::didFinishLaunching() does not. As a result, we do not attempt to
+        relaunch the process, we do not notify the client and WebPageProxy::m_isValid stays true.
+
+        This patch thus updates WebProcessProxy::didFinishLaunching() to check if the connection identifier
+        is valid and treats it as a crash. As a result, the WebPageProxies properly reset their state and
+        the client gets notified of the crash so that it can attempt to reload.
+
+        * UIProcess/API/Cocoa/WKProcessPool.mm:
+        (-[WKProcessPool _makeNextWebProcessLaunchFailForTesting]):
+        * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
+        * UIProcess/Launcher/ProcessLauncher.h:
+        * UIProcess/Launcher/mac/ProcessLauncherMac.mm:
+        (WebKit::ProcessLauncher::launchProcess):
+        Add SPI to make the next WebProcess launch fail, for the purpose of API testing.
+
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::getLaunchOptions):
+        (WebKit::WebProcessProxy::didClose):
+        (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
+        (WebKit::WebProcessProxy::didFinishLaunching):
+        * UIProcess/WebProcessProxy.h:
+
 2018-05-03  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r231223 and r231288.

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2018-05-03 19:59:05 UTC (rev 231321)
@@ -459,6 +459,11 @@
     return _processPool->processes().size();
 }
 
+- (void)_makeNextWebProcessLaunchFailForTesting
+{
+    _processPool->setShouldMakeNextWebProcessLaunchFailForTesting(true);
+}
+
 - (size_t)_prewarmedWebProcessCount
 {
     size_t result = 0;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2018-05-03 19:59:05 UTC (rev 231321)
@@ -94,6 +94,7 @@
 - (size_t)_pluginProcessCount WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));
 - (size_t)_serviceWorkerProcessCount WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_syncNetworkProcessCookies WK_API_AVAILABLE(macosx(10.13), ios(11.0));
+- (void)_makeNextWebProcessLaunchFailForTesting WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 // Test only. Returns web processes running web pages (does not include web processes running service workers)
 - (size_t)_webPageContentProcessCount WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));

Modified: trunk/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/Launcher/ProcessLauncher.h	2018-05-03 19:59:05 UTC (rev 231321)
@@ -65,6 +65,7 @@
         WebCore::ProcessIdentifier processIdentifier;
         HashMap<String, String> extraInitializationData;
         bool nonValidInjectedCodeAllowed { false };
+        bool shouldMakeProcessLaunchFailForTesting { false };
 
 #if ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE))
         String processCmdPrefix;

Modified: trunk/Source/WebKit/UIProcess/Launcher/mac/ProcessLauncherMac.mm (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/Launcher/mac/ProcessLauncherMac.mm	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/Launcher/mac/ProcessLauncherMac.mm	2018-05-03 19:59:05 UTC (rev 231321)
@@ -202,8 +202,8 @@
     xpc_dictionary_set_value(bootstrapMessage.get(), "extra-initialization-data", extraInitializationData.get());
 
     auto weakProcessLauncher = m_weakPtrFactory.createWeakPtr(*this);
-    xpc_connection_set_event_handler(m_xpcConnection.get(), [weakProcessLauncher, listeningPort](xpc_object_t event) {
-        ASSERT(xpc_get_type(event) == XPC_TYPE_ERROR);
+    auto errorHandler = [weakProcessLauncher, listeningPort](xpc_object_t event) {
+        ASSERT(!event || xpc_get_type(event) == XPC_TYPE_ERROR);
 
         auto processLauncher = weakProcessLauncher.get();
         if (!processLauncher)
@@ -229,10 +229,19 @@
         processLauncher->m_xpcConnection = nullptr;
 
         processLauncher->didFinishLaunchingProcess(0, IPC::Connection::Identifier());
-    });
+    };
 
+    xpc_connection_set_event_handler(m_xpcConnection.get(), errorHandler);
+
     xpc_connection_resume(m_xpcConnection.get());
 
+    if (UNLIKELY(m_launchOptions.shouldMakeProcessLaunchFailForTesting)) {
+        RunLoop::main().dispatch([errorHandler = WTFMove(errorHandler)] {
+            errorHandler(nullptr);
+        });
+        return;
+    }
+
     ref();
     xpc_connection_send_message_with_reply(m_xpcConnection.get(), bootstrapMessage.get(), dispatch_get_main_queue(), ^(xpc_object_t reply) {
         // Errors are handled in the event handler.

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2018-05-03 19:59:05 UTC (rev 231321)
@@ -276,6 +276,9 @@
 
     void syncNetworkProcessCookies();
 
+    void setShouldMakeNextWebProcessLaunchFailForTesting(bool value) { m_shouldMakeNextWebProcessLaunchFailForTesting = value; }
+    bool shouldMakeNextWebProcessLaunchFailForTesting() const { return m_shouldMakeNextWebProcessLaunchFailForTesting; }
+
     void reportWebContentCPUTime(Seconds cpuTime, uint64_t activityState);
 
     void allowSpecificHTTPSCertificateForHost(const WebCertificateInfo*, const String& host);
@@ -631,6 +634,7 @@
     bool m_javaScriptConfigurationFileEnabled { false };
     bool m_alwaysRunsAtBackgroundPriority;
     bool m_shouldTakeUIBackgroundAssertion;
+    bool m_shouldMakeNextWebProcessLaunchFailForTesting { false };
 
     UserObservablePageCounter m_userObservablePageCounter;
     ProcessSuppressionDisabledCounter m_processSuppressionDisabledForPageCounter;

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2018-05-03 19:59:05 UTC (rev 231321)
@@ -174,6 +174,11 @@
     }
 
     launchOptions.nonValidInjectedCodeAllowed = shouldAllowNonValidInjectedCode();
+
+    if (processPool().shouldMakeNextWebProcessLaunchFailForTesting()) {
+        processPool().setShouldMakeNextWebProcessLaunchFailForTesting(false);
+        launchOptions.shouldMakeProcessLaunchFailForTesting = true;
+    }
 }
 
 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
@@ -652,11 +657,17 @@
 
 void WebProcessProxy::didClose(IPC::Connection&)
 {
+    processDidTerminateOrFailedToLaunch();
+}
+
+void WebProcessProxy::processDidTerminateOrFailedToLaunch()
+{
     // Protect ourselves, as the call to disconnect() below may otherwise cause us
     // to be deleted before we can finish our work.
     Ref<WebProcessProxy> protect(*this);
 
-    webConnection()->didClose();
+    if (auto* webConnection = this->webConnection())
+        webConnection->didClose();
 
     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
 
@@ -671,13 +682,13 @@
     }
 #endif
 
-    for (auto& page : pages)
-        page->processDidTerminate(ProcessTerminationReason::Crash);
-
     for (auto* suspendedPage : copyToVectorOf<SuspendedPageProxy*>(m_suspendedPageMap.values()))
         suspendedPage->webProcessDidClose(*this);
 
     m_suspendedPageMap.clear();
+
+    for (auto& page : pages)
+        page->processDidTerminate(ProcessTerminationReason::Crash);
 }
 
 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
@@ -737,6 +748,11 @@
 {
     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
 
+    if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
+        processDidTerminateOrFailedToLaunch();
+        return;
+    }
+
     for (WebPageProxy* page : m_pageMap.values()) {
         ASSERT(this == &page->process());
         page->processDidFinishLaunching();

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (231320 => 231321)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2018-05-03 19:59:05 UTC (rev 231321)
@@ -270,6 +270,8 @@
 
     void updateBackgroundResponsivenessTimer();
 
+    void processDidTerminateOrFailedToLaunch();
+
     // IPC::Connection::Client
     friend class WebConnectionToWebProcess;
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;

Modified: trunk/Tools/ChangeLog (231320 => 231321)


--- trunk/Tools/ChangeLog	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Tools/ChangeLog	2018-05-03 19:59:05 UTC (rev 231321)
@@ -1,3 +1,20 @@
+2018-05-03  Chris Dumez  <[email protected]>
+
+        Load hangs if the WebProcess fails to launch
+        https://bugs.webkit.org/show_bug.cgi?id=185225
+        <rdar://problem/38249058>
+
+        Reviewed by Geoff Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm: Added.
+        (-[CrashOnStartNavigationDelegate _webView:webContentProcessDidTerminateWithReason:]):
+        (-[CrashOnStartNavigationDelegate webView:didFinishNavigation:]):
+        (-[CrashRecoveryScriptMessageHandler userContentController:didReceiveScriptMessage:]):
+        (TEST):
+
 2018-05-03  Don Olmstead  <[email protected]>
 
         [WinCairo] Add JSC test bots

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (231320 => 231321)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-05-03 19:42:21 UTC (rev 231320)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-05-03 19:59:05 UTC (rev 231321)
@@ -545,6 +545,7 @@
 		7CD4C26E1E2C0E6E00929470 /* StringConcatenate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CD4C26C1E2C0E6E00929470 /* StringConcatenate.cpp */; };
 		7CEFA9661AC0B9E200B910FD /* _WKUserContentExtensionStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */; };
 		7CFBCAE51743238F00B2BFCF /* WillLoad_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CFBCAE31743238E00B2BFCF /* WillLoad_Bundle.cpp */; };
+		830F2E0C209A6A8E00D36FF1 /* WebContentProcessDidTerminate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 830F2E0B209A6A7400D36FF1 /* WebContentProcessDidTerminate.mm */; };
 		83148B06202AC6A400BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83148B05202AC68200BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior.cpp */; };
 		83148B07202AC6AD00BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83148B04202AC68200BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior_Bundle.cpp */; };
 		83148B09202AC78D00BADE99 /* override-builtins-test.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 83148B08202AC76800BADE99 /* override-builtins-test.html */; };
@@ -1575,6 +1576,7 @@
 		7CFBCADD1743234F00B2BFCF /* WillLoad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillLoad.cpp; sourceTree = "<group>"; };
 		7CFBCAE31743238E00B2BFCF /* WillLoad_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillLoad_Bundle.cpp; sourceTree = "<group>"; };
 		81B50192140F232300D9EB58 /* StringBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringBuilder.cpp; sourceTree = "<group>"; };
+		830F2E0B209A6A7400D36FF1 /* WebContentProcessDidTerminate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebContentProcessDidTerminate.mm; sourceTree = "<group>"; };
 		83148B04202AC68200BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleDisableOverrideBuiltinsBehavior_Bundle.cpp; sourceTree = "<group>"; };
 		83148B05202AC68200BADE99 /* InjectedBundleDisableOverrideBuiltinsBehavior.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleDisableOverrideBuiltinsBehavior.cpp; sourceTree = "<group>"; };
 		83148B08202AC76800BADE99 /* override-builtins-test.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "override-builtins-test.html"; sourceTree = "<group>"; };
@@ -2245,6 +2247,7 @@
 				93E943F11CD3E87E00AC08C2 /* VideoControlsManager.mm */,
 				6356FB211EC4E0BA0044BF18 /* VisibleContentRect.mm */,
 				83779C371F82FEB0007CDA8A /* VisitedLinkStore.mm */,
+				830F2E0B209A6A7400D36FF1 /* WebContentProcessDidTerminate.mm */,
 				5C973F5B1F58EF0A00359C27 /* WebGLPolicy.mm */,
 				51714EB61CF8C7A4004723C4 /* WebProcessKillIDBCleanup.mm */,
 				C1D8EE212028E8E3008EB141 /* WebProcessTerminate.mm */,
@@ -3769,6 +3772,7 @@
 				83779C381F82FECE007CDA8A /* VisitedLinkStore.mm in Sources */,
 				0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */,
 				7CCE7F191A411AE600447C4C /* WebArchive.cpp in Sources */,
+				830F2E0C209A6A8E00D36FF1 /* WebContentProcessDidTerminate.mm in Sources */,
 				7C83E04C1D0A641800FEBCF3 /* WebCoreNSURLSession.mm in Sources */,
 				7CCE7F1A1A411AE600447C4C /* WebCoreStatisticsWithNoWebProcess.cpp in Sources */,
 				5C973F5C1F58EF8B00359C27 /* WebGLPolicy.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm (0 => 231321)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm	2018-05-03 19:59:05 UTC (rev 231321)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_API_ENABLED
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import <WebKit/WKNavigationDelegatePrivate.h>
+#import <WebKit/WKNavigationPrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKWebView.h>
+#import <wtf/RetainPtr.h>
+
+static bool didCrash;
+static _WKProcessTerminationReason expectedCrashReason;
+static bool finishedLoad;
+static bool shouldLoadAgainOnCrash;
+static bool receivedScriptMessage;
+
+static NSString *testHTML = @"<script>window.webkit.messageHandlers.testHandler.postMessage('LOADED');</script>";
+
+@interface CrashOnStartNavigationDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation CrashOnStartNavigationDelegate
+
+- (void)_webView:(WKWebView *)webView webContentProcessDidTerminateWithReason:(_WKProcessTerminationReason)reason
+{
+    EXPECT_FALSE(didCrash);
+    didCrash = true;
+    EXPECT_EQ(expectedCrashReason, reason);
+    EXPECT_EQ(0, webView._webProcessIdentifier);
+
+    // Attempt the load again.
+    if (shouldLoadAgainOnCrash)
+        [webView loadHTMLString:testHTML baseURL:nil];
+}
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+    finishedLoad = true;
+}
+
+@end
+
+@interface CrashRecoveryScriptMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation CrashRecoveryScriptMessageHandler
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    EXPECT_STREQ([(NSString *)[message body] UTF8String], "LOADED");
+    receivedScriptMessage = true;
+}
+
+@end
+
+TEST(WKNavigation, FailureToStartWebProcessRecovery)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[CrashRecoveryScriptMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+
+    [configuration.get().processPool _makeNextWebProcessLaunchFailForTesting];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    auto delegate = adoptNS([[CrashOnStartNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    finishedLoad = false;
+    didCrash = false;
+    receivedScriptMessage = false;
+    expectedCrashReason = _WKProcessTerminationReasonCrash;
+    shouldLoadAgainOnCrash = true;
+
+    [webView loadHTMLString:testHTML baseURL:nil];
+    TestWebKitAPI::Util::run(&finishedLoad);
+
+    EXPECT_TRUE(didCrash);
+    EXPECT_TRUE(!!webView.get()._webProcessIdentifier);
+    EXPECT_TRUE(receivedScriptMessage);
+}
+
+TEST(WKNavigation, FailureToStartWebProcessAfterCrashRecovery)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[CrashRecoveryScriptMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    auto delegate = adoptNS([[CrashOnStartNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    receivedScriptMessage = false;
+    finishedLoad = false;
+    didCrash = false;
+
+    [webView loadHTMLString:testHTML baseURL:nil];
+    TestWebKitAPI::Util::run(&finishedLoad);
+
+    EXPECT_FALSE(didCrash);
+    EXPECT_TRUE(!!webView.get()._webProcessIdentifier);
+    EXPECT_TRUE(receivedScriptMessage);
+
+    receivedScriptMessage = false;
+    shouldLoadAgainOnCrash = false;
+    expectedCrashReason = _WKProcessTerminationReasonRequestedByClient;
+    [webView _killWebContentProcessAndResetState];
+
+    TestWebKitAPI::Util::run(&didCrash);
+    EXPECT_TRUE(!webView.get()._webProcessIdentifier);
+    EXPECT_FALSE(receivedScriptMessage);
+
+    expectedCrashReason = _WKProcessTerminationReasonCrash;
+    didCrash = false;
+    finishedLoad = false;
+    receivedScriptMessage = false;
+    shouldLoadAgainOnCrash = true;
+
+    [configuration.get().processPool _makeNextWebProcessLaunchFailForTesting];
+    [webView loadHTMLString:testHTML baseURL:nil];
+
+    TestWebKitAPI::Util::run(&finishedLoad);
+
+    EXPECT_TRUE(didCrash);
+    EXPECT_TRUE(!!webView.get()._webProcessIdentifier);
+    EXPECT_TRUE(receivedScriptMessage);
+}
+
+#endif // WK_API_ENABLED
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to