[WK2] Extend processDidCrash delegate to let the client know the reason for the crash
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 May 2017 18:54:37 +0000 (18:54 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 May 2017 18:54:37 +0000 (18:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171565
<rdar://problem/31204417>

Reviewed by Sam Weinig.

Source/WebKit2:

Extend processDidCrash delegate to let the client know the reason for the crash. This
is needed by some clients to distinguish actual crashes from terminations due to
resource limits.

* Shared/ProcessCrashReason.h: Added.
* UIProcess/API/APINavigationClient.h:
(API::NavigationClient::processDidCrash):
* UIProcess/API/C/WKAPICast.h:
(WebKit::toAPI):
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageNavigationClient):
* UIProcess/API/C/WKPageNavigationClient.h:
* UIProcess/API/C/WKProcessCrashReason.h: Added.
* UIProcess/Cocoa/NavigationState.h:
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::NavigationClient::processDidCrash):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::processDidCrash):
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::didClose):
(WebKit::WebProcessProxy::requestTermination):
(WebKit::diagnosticLoggingKeyForTerminationReason):
(WebKit::toProcessCrashReason):
(WebKit::WebProcessProxy::terminateProcessDueToResourceLimits):
(WebKit::WebProcessProxy::didExceedActiveMemoryLimit):
(WebKit::WebProcessProxy::didExceedInactiveMemoryLimit):
(WebKit::WebProcessProxy::didExceedBackgroundCPULimit):
* UIProcess/WebProcessProxy.h:
* WebKit2.xcodeproj/project.pbxproj:

Tools:

Add API test coverage.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2/ProcessDidCrashWithReason.cpp: Added.
(TestWebKitAPI::didFinishNavigation):
(TestWebKitAPI::didCrashWithReason):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216129 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/ProcessCrashReason.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/APINavigationClient.h
Source/WebKit2/UIProcess/API/C/WKAPICast.h
Source/WebKit2/UIProcess/API/C/WKPage.cpp
Source/WebKit2/UIProcess/API/C/WKPageNavigationClient.h
Source/WebKit2/UIProcess/API/C/WKProcessCrashReason.h [new file with mode: 0644]
Source/WebKit2/UIProcess/Cocoa/NavigationState.h
Source/WebKit2/UIProcess/Cocoa/NavigationState.mm
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebProcessProxy.cpp
Source/WebKit2/UIProcess/WebProcessProxy.h
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2/ProcessDidCrashWithReason.cpp [new file with mode: 0644]

index 169601d..ff40924 100644 (file)
@@ -1,3 +1,42 @@
+2017-05-03  Chris Dumez  <cdumez@apple.com>
+
+        [WK2] Extend processDidCrash delegate to let the client know the reason for the crash
+        https://bugs.webkit.org/show_bug.cgi?id=171565
+        <rdar://problem/31204417>
+
+        Reviewed by Sam Weinig.
+
+        Extend processDidCrash delegate to let the client know the reason for the crash. This
+        is needed by some clients to distinguish actual crashes from terminations due to
+        resource limits.
+
+        * Shared/ProcessCrashReason.h: Added.
+        * UIProcess/API/APINavigationClient.h:
+        (API::NavigationClient::processDidCrash):
+        * UIProcess/API/C/WKAPICast.h:
+        (WebKit::toAPI):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageNavigationClient):
+        * UIProcess/API/C/WKPageNavigationClient.h:
+        * UIProcess/API/C/WKProcessCrashReason.h: Added.
+        * UIProcess/Cocoa/NavigationState.h:
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::NavigationClient::processDidCrash):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::processDidCrash):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::didClose):
+        (WebKit::WebProcessProxy::requestTermination):
+        (WebKit::diagnosticLoggingKeyForTerminationReason):
+        (WebKit::toProcessCrashReason):
+        (WebKit::WebProcessProxy::terminateProcessDueToResourceLimits):
+        (WebKit::WebProcessProxy::didExceedActiveMemoryLimit):
+        (WebKit::WebProcessProxy::didExceedInactiveMemoryLimit):
+        (WebKit::WebProcessProxy::didExceedBackgroundCPULimit):
+        * UIProcess/WebProcessProxy.h:
+        * WebKit2.xcodeproj/project.pbxproj:
+
 2017-05-03  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Add GTK+ implementation of WebAutomationSession
diff --git a/Source/WebKit2/Shared/ProcessCrashReason.h b/Source/WebKit2/Shared/ProcessCrashReason.h
new file mode 100644 (file)
index 0000000..3417f70
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+namespace WebKit {
+
+enum class ProcessCrashReason {
+    TerminationDueToMemoryUsage,
+    TerminationDueToCPUUsage,
+    TerminationRequestedByClient,
+    Other
+};
+
+}
index a6332f7..8a3e1a7 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "APIData.h"
 #include "PluginModuleInfo.h"
+#include "ProcessCrashReason.h"
 #include "SameDocumentNavigationType.h"
 #include "WebEvent.h"
 #include "WebFramePolicyListenerProxy.h"
@@ -82,7 +83,7 @@ public:
     virtual void didReceiveAuthenticationChallenge(WebKit::WebPageProxy&, WebKit::AuthenticationChallengeProxy*) { }
 
     // FIXME: These function should not be part of this client.
-    virtual void processDidCrash(WebKit::WebPageProxy&) { }
+    virtual void processDidCrash(WebKit::WebPageProxy&, WebKit::ProcessCrashReason) { }
     virtual void processDidBecomeResponsive(WebKit::WebPageProxy&) { }
     virtual void processDidBecomeUnresponsive(WebKit::WebPageProxy&) { }
 
index 78a3804..d94a9e9 100644 (file)
@@ -32,6 +32,7 @@
 #include "HTTPCookieAcceptPolicy.h"
 #include "InjectedBundleHitTestResultMediaType.h"
 #include "PluginModuleInfo.h"
+#include "ProcessCrashReason.h"
 #include "ResourceCachesToClear.h"
 #include "WKBundleHitTestResult.h"
 #include "WKContext.h"
@@ -40,6 +41,7 @@
 #include "WKPage.h"
 #include "WKPreferencesRef.h"
 #include "WKPreferencesRefPrivate.h"
+#include "WKProcessCrashReason.h"
 #include "WKProtectionSpaceTypes.h"
 #include "WKResourceCacheManager.h"
 #include "WKSharedAPICast.h"
@@ -233,6 +235,22 @@ inline WKCacheModel toAPI(CacheModel cacheModel)
     return kWKCacheModelDocumentViewer;
 }
 
+inline WKProcessCrashReason toAPI(ProcessCrashReason reason)
+{
+    switch (reason) {
+    case ProcessCrashReason::TerminationDueToMemoryUsage:
+        return kWKProcessCrashReasonTerminationDueToMemoryUsage;
+    case ProcessCrashReason::TerminationDueToCPUUsage:
+        return kWKProcessCrashReasonTerminationDueToCPUUsage;
+    case ProcessCrashReason::TerminationRequestedByClient:
+        return kWKProcessCrashReasonTerminationRequestedByClient;
+    case ProcessCrashReason::Other:
+        return kWKProcessCrashReasonOther;
+    }
+
+    return kWKProcessCrashReasonOther;
+}
+
 inline FontSmoothingLevel toFontSmoothingLevel(WKFontSmoothingLevel wkLevel)
 {
     switch (wkLevel) {
index 07b94cf..4ae752b 100644 (file)
@@ -106,7 +106,7 @@ template<> struct ClientTraits<WKPageLoaderClientBase> {
 };
 
 template<> struct ClientTraits<WKPageNavigationClientBase> {
-    typedef std::tuple<WKPageNavigationClientV0> Versions;
+    typedef std::tuple<WKPageNavigationClientV0, WKPageNavigationClientV1> Versions;
 };
 
 template<> struct ClientTraits<WKPagePolicyClientBase> {
@@ -2400,11 +2400,13 @@ void WKPageSetPageNavigationClient(WKPageRef pageRef, const WKPageNavigationClie
             m_client.didReceiveAuthenticationChallenge(toAPI(&page), toAPI(authenticationChallenge), m_client.base.clientInfo);
         }
 
-        void processDidCrash(WebPageProxy& page) override
+        void processDidCrash(WebPageProxy& page, WebKit::ProcessCrashReason reason) override
         {
-            if (!m_client.webProcessDidCrash)
-                return;
-            m_client.webProcessDidCrash(toAPI(&page), m_client.base.clientInfo);
+            if (m_client.webProcessDidCrash)
+                m_client.webProcessDidCrash(toAPI(&page), m_client.base.clientInfo);
+
+            if (m_client.webProcessDidCrashWithReason)
+                m_client.webProcessDidCrashWithReason(toAPI(&page), toAPI(reason), m_client.base.clientInfo);
         }
 
         RefPtr<API::Data> webCryptoMasterKey(WebPageProxy& page) override
index e19cf97..d71d4eb 100644 (file)
@@ -30,6 +30,7 @@
 #include <WebKit/WKPageLoadTypes.h>
 #include <WebKit/WKPageRenderingProgressEvents.h>
 #include <WebKit/WKPluginLoadPolicy.h>
+#include <WebKit/WKProcessCrashReason.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -65,6 +66,8 @@ typedef void (*WKPageNavigationDidReceiveAuthenticationChallengeCallback)(WKPage
 
 typedef void (*WKPageNavigationWebProcessDidCrashCallback)(WKPageRef page, const void* clientInfo);
 
+typedef void (*WKPageNavigationWebProcessDidCrashWithReasonCallback)(WKPageRef page, WKProcessCrashReason reason, const void* clientInfo);
+
 typedef WKDataRef (*WKPageNavigationCopyWebCryptoMasterKeyCallback)(WKPageRef page, const void* clientInfo);
     
 typedef WKPluginLoadPolicy (*WKPageNavigationDecidePolicyForPluginLoadCallback)(WKPageRef page, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInfoDictionary, WKStringRef* unavailabilityDescription, const void* clientInfo);
@@ -104,13 +107,42 @@ typedef struct WKPageNavigationClientV0 {
     WKPageNavigationDidReceiveAuthenticationChallengeCallback didReceiveAuthenticationChallenge;
     WKPageNavigationWebProcessDidCrashCallback webProcessDidCrash;
     WKPageNavigationCopyWebCryptoMasterKeyCallback copyWebCryptoMasterKey;
-
     WKPageNavigationDidBeginNavigationGesture didBeginNavigationGesture;
     WKPageNavigationWillEndNavigationGesture willEndNavigationGesture;
     WKPageNavigationDidEndNavigationGesture didEndNavigationGesture;
     WKPageNavigationDidRemoveNavigationGestureSnapshot didRemoveNavigationGestureSnapshot;
 } WKPageNavigationClientV0;
 
+typedef struct WKPageNavigationClientV1 {
+    WKPageNavigationClientBase base;
+
+    // Version 0.
+    WKPageNavigationDecidePolicyForNavigationActionCallback decidePolicyForNavigationAction;
+    WKPageNavigationDecidePolicyForNavigationResponseCallback decidePolicyForNavigationResponse;
+    WKPageNavigationDecidePolicyForPluginLoadCallback decidePolicyForPluginLoad;
+    WKPageNavigationDidStartProvisionalNavigationCallback didStartProvisionalNavigation;
+    WKPageNavigationDidReceiveServerRedirectForProvisionalNavigationCallback didReceiveServerRedirectForProvisionalNavigation;
+    WKPageNavigationDidFailProvisionalNavigationCallback didFailProvisionalNavigation;
+    WKPageNavigationDidCommitNavigationCallback didCommitNavigation;
+    WKPageNavigationDidFinishNavigationCallback didFinishNavigation;
+    WKPageNavigationDidFailNavigationCallback didFailNavigation;
+    WKPageNavigationDidFailProvisionalLoadInSubframeCallback didFailProvisionalLoadInSubframe;
+    WKPageNavigationDidFinishDocumentLoadCallback didFinishDocumentLoad;
+    WKPageNavigationDidSameDocumentNavigationCallback didSameDocumentNavigation;
+    WKPageNavigationRenderingProgressDidChangeCallback renderingProgressDidChange;
+    WKPageNavigationCanAuthenticateAgainstProtectionSpaceCallback canAuthenticateAgainstProtectionSpace;
+    WKPageNavigationDidReceiveAuthenticationChallengeCallback didReceiveAuthenticationChallenge;
+    WKPageNavigationWebProcessDidCrashCallback webProcessDidCrash;
+    WKPageNavigationCopyWebCryptoMasterKeyCallback copyWebCryptoMasterKey;
+    WKPageNavigationDidBeginNavigationGesture didBeginNavigationGesture;
+    WKPageNavigationWillEndNavigationGesture willEndNavigationGesture;
+    WKPageNavigationDidEndNavigationGesture didEndNavigationGesture;
+    WKPageNavigationDidRemoveNavigationGestureSnapshot didRemoveNavigationGestureSnapshot;
+
+    // Version 1.
+    WKPageNavigationWebProcessDidCrashWithReasonCallback webProcessDidCrashWithReason;
+} WKPageNavigationClientV1;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Source/WebKit2/UIProcess/API/C/WKProcessCrashReason.h b/Source/WebKit2/UIProcess/API/C/WKProcessCrashReason.h
new file mode 100644 (file)
index 0000000..b476203
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    kWKProcessCrashReasonTerminationDueToMemoryUsage = 0,
+    kWKProcessCrashReasonTerminationDueToCPUUsage,
+    kWKProcessCrashReasonTerminationRequestedByClient,
+    kWKProcessCrashReasonOther,
+};
+typedef uint32_t WKProcessCrashReason;
+
+#ifdef __cplusplus
+}
+#endif
index 46a9ee1..0ad3478 100644 (file)
@@ -32,6 +32,7 @@
 #import "APIHistoryClient.h"
 #import "APINavigationClient.h"
 #import "PageLoadState.h"
+#import "ProcessCrashReason.h"
 #import "ProcessThrottler.h"
 #import "WeakObjCPtr.h"
 #import <wtf/RetainPtr.h>
@@ -102,7 +103,7 @@ private:
 
         bool canAuthenticateAgainstProtectionSpace(WebPageProxy&, WebProtectionSpace*) override;
         void didReceiveAuthenticationChallenge(WebPageProxy&, AuthenticationChallengeProxy*) override;
-        void processDidCrash(WebPageProxy&) override;
+        void processDidCrash(WebPageProxy&, ProcessCrashReason) override;
         void processDidBecomeResponsive(WebPageProxy&) override;
         void processDidBecomeUnresponsive(WebPageProxy&) override;
 
index b66e1a1..a459829 100644 (file)
@@ -710,7 +710,7 @@ void NavigationState::NavigationClient::didReceiveAuthenticationChallenge(WebPag
     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView didReceiveAuthenticationChallenge:wrapper(*authenticationChallenge)];
 }
 
-void NavigationState::NavigationClient::processDidCrash(WebKit::WebPageProxy& page)
+void NavigationState::NavigationClient::processDidCrash(WebKit::WebPageProxy& page, WebKit::ProcessCrashReason)
 {
     if (!m_navigationState.m_navigationDelegateMethods.webViewWebContentProcessDidTerminate && !m_navigationState.m_navigationDelegateMethods.webViewWebProcessDidCrash)
         return;
index 1f0cc9d..b65b619 100644 (file)
@@ -5293,7 +5293,7 @@ void WebPageProxy::didChangeProcessIsResponsive()
     m_pageLoadState.didChangeProcessIsResponsive();
 }
 
-void WebPageProxy::processDidCrash()
+void WebPageProxy::processDidCrash(ProcessCrashReason reason)
 {
     ASSERT(m_isValid);
 
@@ -5316,7 +5316,7 @@ void WebPageProxy::processDidCrash()
     navigationState().clearAllNavigations();
 
     if (m_navigationClient)
-        m_navigationClient->processDidCrash(*this);
+        m_navigationClient->processDidCrash(*this, reason);
     else
         m_loaderClient->processDidCrash(*this);
 
index a4d7477..b48d646 100644 (file)
@@ -40,6 +40,7 @@
 #include "MessageSender.h"
 #include "NotificationPermissionRequestManagerProxy.h"
 #include "PageLoadState.h"
+#include "ProcessCrashReason.h"
 #include "ProcessThrottler.h"
 #include "SandboxExtension.h"
 #include "ShareableBitmap.h"
@@ -857,7 +858,7 @@ public:
 
     void processDidBecomeUnresponsive();
     void processDidBecomeResponsive();
-    void processDidCrash();
+    void processDidCrash(ProcessCrashReason);
     void willChangeProcessIsResponsive();
     void didChangeProcessIsResponsive();
 
index 8eabeb3..95b74cc 100644 (file)
@@ -600,7 +600,7 @@ void WebProcessProxy::didClose(IPC::Connection&)
     shutDown();
 
     for (size_t i = 0, size = pages.size(); i < size; ++i)
-        pages[i]->processDidCrash();
+        pages[i]->processDidCrash(ProcessCrashReason::Other);
 
 }
 
@@ -857,7 +857,13 @@ void WebProcessProxy::requestTermination()
     if (webConnection())
         webConnection()->didClose();
 
+    Vector<RefPtr<WebPageProxy>> pages;
+    copyValuesToVector(m_pageMap, pages);
+
     shutDown();
+
+    for (size_t i = 0, size = pages.size(); i < size; ++i)
+        pages[i]->processDidCrash(ProcessCrashReason::TerminationRequestedByClient);
 }
 
 void WebProcessProxy::enableSuddenTermination()
@@ -1129,39 +1135,51 @@ static Vector<RefPtr<WebPageProxy>> pagesCopy(WTF::IteratorRange<WebProcessProxy
     return vector;
 }
 
-static String diagnosticLoggingKeyForSimulatedCrashReason(SimulatedCrashReason reason)
+static String diagnosticLoggingKeyForTerminationReason(TerminationReason reason)
 {
     switch (reason) {
-    case SimulatedCrashReason::ExceededActiveMemoryLimit:
+    case TerminationReason::ExceededActiveMemoryLimit:
         return DiagnosticLoggingKeys::exceededActiveMemoryLimitKey();
-    case SimulatedCrashReason::ExceededInactiveMemoryLimit:
+    case TerminationReason::ExceededInactiveMemoryLimit:
         return DiagnosticLoggingKeys::exceededInactiveMemoryLimitKey();
-    case SimulatedCrashReason::ExceededBackgroundCPULimit:
+    case TerminationReason::ExceededBackgroundCPULimit:
         return DiagnosticLoggingKeys::exceededBackgroundCPULimitKey();
     default:
         RELEASE_ASSERT_NOT_REACHED();
     }
 }
 
-void WebProcessProxy::simulateProcessCrash(SimulatedCrashReason reason)
+static ProcessCrashReason toProcessCrashReason(TerminationReason reason)
+{
+    switch (reason) {
+    case TerminationReason::ExceededActiveMemoryLimit:
+    case TerminationReason::ExceededInactiveMemoryLimit:
+        return ProcessCrashReason::TerminationDueToMemoryUsage;
+    case TerminationReason::ExceededBackgroundCPULimit:
+        return ProcessCrashReason::TerminationDueToCPUUsage;
+    }
+    return ProcessCrashReason::Other;
+}
+
+void WebProcessProxy::terminateProcessDueToResourceLimits(TerminationReason reason)
 {
     for (auto& page : pagesCopy(pages())) {
-        page->logDiagnosticMessage(DiagnosticLoggingKeys::simulatedPageCrashKey(), diagnosticLoggingKeyForSimulatedCrashReason(reason), ShouldSample::No);
+        page->logDiagnosticMessage(DiagnosticLoggingKeys::simulatedPageCrashKey(), diagnosticLoggingKeyForTerminationReason(reason), ShouldSample::No);
         page->terminateProcess();
-        page->processDidCrash();
+        page->processDidCrash(toProcessCrashReason(reason));
     }
 }
 
 void WebProcessProxy::didExceedActiveMemoryLimit()
 {
     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedActiveMemoryLimit() Terminating WebProcess that has exceeded the active memory limit", this);
-    simulateProcessCrash(SimulatedCrashReason::ExceededActiveMemoryLimit);
+    terminateProcessDueToResourceLimits(TerminationReason::ExceededActiveMemoryLimit);
 }
 
 void WebProcessProxy::didExceedInactiveMemoryLimit()
 {
     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedInactiveMemoryLimit() Terminating WebProcess that has exceeded the inactive memory limit", this);
-    simulateProcessCrash(SimulatedCrashReason::ExceededInactiveMemoryLimit);
+    terminateProcessDueToResourceLimits(TerminationReason::ExceededInactiveMemoryLimit);
 }
 
 void WebProcessProxy::didExceedBackgroundCPULimit()
@@ -1182,7 +1200,7 @@ void WebProcessProxy::didExceedBackgroundCPULimit()
     }
 
     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedBackgroundCPULimit() Terminating background WebProcess that has exceeded the background CPU limit", this);
-    simulateProcessCrash(SimulatedCrashReason::ExceededBackgroundCPULimit);
+    terminateProcessDueToResourceLimits(TerminationReason::ExceededBackgroundCPULimit);
 }
 
 void WebProcessProxy::updateBackgroundResponsivenessTimer()
index 96316cd..154a6fd 100644 (file)
@@ -55,7 +55,7 @@ struct PluginInfo;
 
 namespace WebKit {
 
-enum class SimulatedCrashReason {
+enum class TerminationReason {
     ExceededActiveMemoryLimit,
     ExceededInactiveMemoryLimit,
     ExceededBackgroundCPULimit,
@@ -247,7 +247,7 @@ private:
 
     bool canTerminateChildProcess();
 
-    void simulateProcessCrash(SimulatedCrashReason);
+    void terminateProcessDueToResourceLimits(TerminationReason);
 
     ResponsivenessTimer m_responsivenessTimer;
     BackgroundProcessResponsivenessTimer m_backgroundResponsivenessTimer;
index 72b0c5c..d53b99a 100644 (file)
                41FAF5F81E3C1021001AE678 /* LibWebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */; };
                41FAF5F91E3C1025001AE678 /* LibWebRTCResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */; };
                4450AEC01DC3FAE5009943F2 /* SharedMemoryCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */; };
+               463FD4801EB9459600A2982C /* WKProcessCrashReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD47F1EB9458400A2982C /* WKProcessCrashReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               463FD4821EB94EC000A2982C /* ProcessCrashReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD4811EB94EAD00A2982C /* ProcessCrashReason.h */; };
                46A2B6081E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */; };
                46A2B6091E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */; };
                4A3CC18A19B063E700D14AEF /* UserMediaPermissionRequestManagerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */; };
                41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCResolver.h; path = Network/webrtc/LibWebRTCResolver.h; sourceTree = "<group>"; };
                41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCResolver.cpp; path = Network/webrtc/LibWebRTCResolver.cpp; sourceTree = "<group>"; };
                4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharedMemoryCocoa.cpp; path = cocoa/SharedMemoryCocoa.cpp; sourceTree = "<group>"; };
+               463FD47F1EB9458400A2982C /* WKProcessCrashReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKProcessCrashReason.h; sourceTree = "<group>"; };
+               463FD4811EB94EAD00A2982C /* ProcessCrashReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessCrashReason.h; sourceTree = "<group>"; };
                46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundProcessResponsivenessTimer.cpp; sourceTree = "<group>"; };
                46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackgroundProcessResponsivenessTimer.h; sourceTree = "<group>"; };
                4A410F3519AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKUserMediaPermissionRequest.cpp; sourceTree = "<group>"; };
                                BCC43AB9127B95DC00317F16 /* PlatformPopupMenuData.h */,
                                E18C92F312DB9E7100CF2AEB /* PrintInfo.cpp */,
                                E1CC1B8E12D7EADF00625838 /* PrintInfo.h */,
+                               463FD4811EB94EAD00A2982C /* ProcessCrashReason.h */,
                                F6A0C13F13281E6E0070430F /* ResourceCachesToClear.h */,
                                410482CB1DDD2FB500F006D0 /* RTCNetwork.cpp */,
                                410482CC1DDD2FB500F006D0 /* RTCNetwork.h */,
                                BCD597CF112B56AC00EC8C23 /* WKPreferences.cpp */,
                                BCD597CE112B56AC00EC8C23 /* WKPreferencesRef.h */,
                                762B7484120BBA2D00819339 /* WKPreferencesRefPrivate.h */,
+                               463FD47F1EB9458400A2982C /* WKProcessCrashReason.h */,
                                512F58F312A88A5400629530 /* WKProtectionSpace.cpp */,
                                512F58F412A88A5400629530 /* WKProtectionSpace.h */,
                                518ACAE912AEE6BB00B04B83 /* WKProtectionSpaceTypes.h */,
                                1AC1338618590C4600F3EC05 /* RemoteObjectRegistryMessages.h in Headers */,
                                0F594790187B3B3A00437857 /* RemoteScrollingCoordinator.h in Headers */,
                                0F5947A8187B517600437857 /* RemoteScrollingCoordinatorMessages.h in Headers */,
+                               463FD4821EB94EC000A2982C /* ProcessCrashReason.h in Headers */,
                                0F59479B187B3B6000437857 /* RemoteScrollingCoordinatorProxy.h in Headers */,
                                0F5947A4187B3B7D00437857 /* RemoteScrollingCoordinatorTransaction.h in Headers */,
                                0F59479D187B3B6000437857 /* RemoteScrollingTree.h in Headers */,
                                1C8E2A361277852400BC7BD0 /* WebInspectorMessages.h in Headers */,
                                1C8E28341275D73800BC7BD0 /* WebInspectorProxy.h in Headers */,
                                1CA8B946127C882A00576C2B /* WebInspectorProxyMessages.h in Headers */,
+                               463FD4801EB9459600A2982C /* WKProcessCrashReason.h in Headers */,
                                1C891D6619B124FF00BA79DD /* WebInspectorUI.h in Headers */,
                                1CBBE4A119B66C53006B7D81 /* WebInspectorUIMessages.h in Headers */,
                                A55BA82B1BA38E61007CD33D /* WebInspectorUtilities.h in Headers */,
index 4b1841e..e111a29 100644 (file)
@@ -1,3 +1,19 @@
+2017-05-03  Chris Dumez  <cdumez@apple.com>
+
+        [WK2] Extend processDidCrash delegate to let the client know the reason for the crash
+        https://bugs.webkit.org/show_bug.cgi?id=171565
+        <rdar://problem/31204417>
+
+        Reviewed by Sam Weinig.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2/ProcessDidCrashWithReason.cpp: Added.
+        (TestWebKitAPI::didFinishNavigation):
+        (TestWebKitAPI::didCrashWithReason):
+        (TestWebKitAPI::TEST):
+
 2017-05-02  David Kilzer  <ddkilzer@apple.com>
 
         check-webkit-style should also keep js-test-post[-async].js in sync
index 5b64692..e2a66f3 100644 (file)
                3FBD1B4A1D3D66AB00E6D6FA /* FullscreenLayoutConstraints.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 3FBD1B491D39D1DB00E6D6FA /* FullscreenLayoutConstraints.html */; };
                448D7E471EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448D7E451EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp */; };
                46397B951DC2C850009A78AE /* DOMNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46397B941DC2C850009A78AE /* DOMNode.mm */; };
+               4647B1261EBA3B850041D7EF /* ProcessDidCrashWithReason.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4647B1251EBA3B730041D7EF /* ProcessDidCrashWithReason.cpp */; };
                46C519DA1D355AB200DAA51A /* LocalStorageNullEntries.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46C519D81D355A7300DAA51A /* LocalStorageNullEntries.mm */; };
                46C519E61D3563FD00DAA51A /* LocalStorageNullEntries.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 46C519E21D35629600DAA51A /* LocalStorageNullEntries.html */; };
                46C519E71D3563FD00DAA51A /* LocalStorageNullEntries.localstorage in Copy Resources */ = {isa = PBXBuildFile; fileRef = 46C519E31D35629600DAA51A /* LocalStorageNullEntries.localstorage */; };
                448D7E451EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnvironmentUtilitiesTest.cpp; sourceTree = "<group>"; };
                44A622C114A0E2B60048515B /* WTFStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFStringUtilities.h; sourceTree = "<group>"; };
                46397B941DC2C850009A78AE /* DOMNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMNode.mm; sourceTree = "<group>"; };
+               4647B1251EBA3B730041D7EF /* ProcessDidCrashWithReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessDidCrashWithReason.cpp; sourceTree = "<group>"; };
                46C519D81D355A7300DAA51A /* LocalStorageNullEntries.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalStorageNullEntries.mm; sourceTree = "<group>"; };
                46C519E21D35629600DAA51A /* LocalStorageNullEntries.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LocalStorageNullEntries.html; sourceTree = "<group>"; };
                46C519E31D35629600DAA51A /* LocalStorageNullEntries.localstorage */ = {isa = PBXFileReference; lastKnownFileType = file; path = LocalStorageNullEntries.localstorage; sourceTree = "<group>"; };
                                0766DD1F1A5AD5200023E3BB /* PendingAPIRequestURL.cpp */,
                                333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */,
                                F6FDDDD214241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp */,
+                               4647B1251EBA3B730041D7EF /* ProcessDidCrashWithReason.cpp */,
                                8A3AF93A16C9ED2700D248C1 /* ReloadPageAfterCrash.cpp */,
                                2DD7D3A9178205D00026E1E3 /* ResizeReversePaginatedWebView.cpp */,
                                8A2C750D16CED9550024F352 /* ResizeWindowAfterCrash.cpp */,
                                7CCE7EEE1A411AE600447C4C /* DownloadDecideDestinationCrash.cpp in Sources */,
                                F4BFA68E1E4AD08000154298 /* DragAndDropPasteboardTests.mm in Sources */,
                                A155022A1E05020B00A24C57 /* DuplicateCompletionHandlerCalls.mm in Sources */,
+                               4647B1261EBA3B850041D7EF /* ProcessDidCrashWithReason.cpp in Sources */,
                                7CCE7EBE1A411A7E00447C4C /* DynamicDeviceScaleFactor.mm in Sources */,
                                5C0BF8921DD599B600B00328 /* EarlyKVOCrash.mm in Sources */,
                                7CCE7EE01A411A9A00447C4C /* EditorCommands.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ProcessDidCrashWithReason.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ProcessDidCrashWithReason.cpp
new file mode 100644 (file)
index 0000000..e7aea5e
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool loadBeforeCrash = false;
+static bool crashHandlerCalled = false;
+
+static void didFinishNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef userData, const void* clientInfo)
+{
+    if (!loadBeforeCrash) {
+        loadBeforeCrash = true;
+        return;
+    }
+
+    EXPECT_TRUE(false);
+}
+
+static void didCrashWithReason(WKPageRef page, WKProcessCrashReason reason, const void* clientInfo)
+{
+    // Test if first load actually worked.
+    EXPECT_TRUE(loadBeforeCrash);
+
+    // Should only be called once.
+    EXPECT_FALSE(crashHandlerCalled);
+
+    EXPECT_EQ(kWKProcessCrashReasonTerminationRequestedByClient, reason);
+
+    crashHandlerCalled = true;
+}
+
+TEST(WebKit2, ProcessDidCrashWithReasonRequestedByClient)
+{
+    WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+    PlatformWebView webView(context.get());
+
+    WKPageNavigationClientV1 navigationClient;
+    memset(&navigationClient, 0, sizeof(navigationClient));
+    navigationClient.base.version = 1;
+    navigationClient.didFinishNavigation = didFinishNavigation;
+    navigationClient.webProcessDidCrashWithReason = didCrashWithReason;
+
+    WKPageSetPageNavigationClient(webView.page(), &navigationClient.base);
+
+    WKRetainPtr<WKURLRef> url = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
+    // Load a blank page and next kills WebProcess.
+    WKPageLoadURL(webView.page(), url.get());
+    Util::run(&loadBeforeCrash);
+    WKPageTerminate(webView.page());
+
+    Util::run(&crashHandlerCalled);
+}
+
+} // namespace TestWebKitAPI
+
+#endif