Title: [282218] trunk
Revision
282218
Author
[email protected]
Date
2021-09-09 09:40:46 -0700 (Thu, 09 Sep 2021)

Log Message

Implement a WebProcess cap
https://bugs.webkit.org/show_bug.cgi?id=230067
<rdar://79479244>

Reviewed by Geoffrey Garen.

Source/WebKit:

Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways.
The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool).
When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used
WebProcess to avoid going over the limit.

* Shared/ProcessTerminationReason.h:
* UIProcess/API/C/WKAPICast.h:
(WebKit::toAPI):
* UIProcess/API/Cocoa/WKProcessPool.mm:
(+[WKProcessPool _setWebProcessCountLimit:]):
* UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::wkProcessTerminationReason):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::loadRequestWithNavigationShared):
(WebKit::WebPageProxy::loadFile):
(WebKit::WebPageProxy::loadDataWithNavigationShared):
(WebKit::WebPageProxy::loadSimulatedRequest):
(WebKit::WebPageProxy::loadAlternateHTML):
(WebKit::WebPageProxy::loadWebArchiveData):
(WebKit::WebPageProxy::reload):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::shouldReloadAfterProcessTermination):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::setProcessCountLimit):
(WebKit::WebProcessProxy::create):
(WebKit::WebProcessProxy::~WebProcessProxy):
(WebKit::WebProcessProxy::addProvisionalPageProxy):
(WebKit::WebProcessProxy::addExistingWebPage):
(WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
(WebKit::WebProcessProxy::establishServiceWorkerContext):
(WebKit::WebProcessProxy::markProcessAsRecentlyUsed):
* UIProcess/WebProcessProxy.h:

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (282217 => 282218)


--- trunk/Source/WebKit/ChangeLog	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/ChangeLog	2021-09-09 16:40:46 UTC (rev 282218)
@@ -1,3 +1,45 @@
+2021-09-09  Chris Dumez  <[email protected]>
+
+        Implement a WebProcess cap
+        https://bugs.webkit.org/show_bug.cgi?id=230067
+        <rdar://79479244>
+
+        Reviewed by Geoffrey Garen.
+
+        Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways.
+        The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool).
+        When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used
+        WebProcess to avoid going over the limit.
+
+        * Shared/ProcessTerminationReason.h:
+        * UIProcess/API/C/WKAPICast.h:
+        (WebKit::toAPI):
+        * UIProcess/API/Cocoa/WKProcessPool.mm:
+        (+[WKProcessPool _setWebProcessCountLimit:]):
+        * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::wkProcessTerminationReason):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::loadRequestWithNavigationShared):
+        (WebKit::WebPageProxy::loadFile):
+        (WebKit::WebPageProxy::loadDataWithNavigationShared):
+        (WebKit::WebPageProxy::loadSimulatedRequest):
+        (WebKit::WebPageProxy::loadAlternateHTML):
+        (WebKit::WebPageProxy::loadWebArchiveData):
+        (WebKit::WebPageProxy::reload):
+        (WebKit::WebPageProxy::goToBackForwardItem):
+        (WebKit::shouldReloadAfterProcessTermination):
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::setProcessCountLimit):
+        (WebKit::WebProcessProxy::create):
+        (WebKit::WebProcessProxy::~WebProcessProxy):
+        (WebKit::WebProcessProxy::addProvisionalPageProxy):
+        (WebKit::WebProcessProxy::addExistingWebPage):
+        (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
+        (WebKit::WebProcessProxy::establishServiceWorkerContext):
+        (WebKit::WebProcessProxy::markProcessAsRecentlyUsed):
+        * UIProcess/WebProcessProxy.h:
+
 2021-09-09  Wenson Hsieh  <[email protected]>
 
         Unreviewed, fix the Mac Catalyst build after r282191

Modified: trunk/Source/WebKit/Shared/ProcessTerminationReason.h (282217 => 282218)


--- trunk/Source/WebKit/Shared/ProcessTerminationReason.h	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/Shared/ProcessTerminationReason.h	2021-09-09 16:40:46 UTC (rev 282218)
@@ -30,6 +30,7 @@
 enum class ProcessTerminationReason {
     ExceededMemoryLimit,
     ExceededCPULimit,
+    ExceededProcessCountLimit,
     RequestedByClient,
     Crash,
     NavigationSwap,

Modified: trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h	2021-09-09 16:40:46 UTC (rev 282218)
@@ -243,6 +243,7 @@
         FALLTHROUGH;
     case ProcessTerminationReason::RequestedByClient:
         return kWKProcessTerminationReasonRequestedByClient;
+    case ProcessTerminationReason::ExceededProcessCountLimit:
     case ProcessTerminationReason::RequestedByNetworkProcess:
     case ProcessTerminationReason::RequestedByGPUProcess:
     case ProcessTerminationReason::Crash:

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


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm	2021-09-09 16:40:46 UTC (rev 282218)
@@ -565,6 +565,11 @@
 #endif
 }
 
++ (void)_setWebProcessCountLimit:(unsigned)limit
+{
+    WebKit::WebProcessProxy::setProcessCountLimit(limit);
+}
+
 - (void)_garbageCollectJavaScriptObjectsForTesting
 {
     _processPool->garbageCollectJavaScriptObjects();

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


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h	2021-09-09 16:40:46 UTC (rev 282218)
@@ -73,6 +73,8 @@
 + (NSURL *)_websiteDataURLForContainerWithURL:(NSURL *)containerURL bundleIdentifierIfNotInContainer:(NSString *)bundleIdentifier;
 + (pid_t)_webAuthnProcessIdentifier WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
++ (void)_setWebProcessCountLimit:(unsigned)limit WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 - (void)_warmInitialProcess WK_API_AVAILABLE(macos(10.12), ios(10.0));
 - (void)_automationCapabilitiesDidChange WK_API_AVAILABLE(macos(10.12), ios(10.0));
 - (void)_setAutomationSession:(_WKAutomationSession *)automationSession WK_API_AVAILABLE(macos(10.12), ios(10.0));

Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm	2021-09-09 16:40:46 UTC (rev 282218)
@@ -1060,6 +1060,7 @@
         FALLTHROUGH;
     case ProcessTerminationReason::RequestedByClient:
         return _WKProcessTerminationReasonRequestedByClient;
+    case ProcessTerminationReason::ExceededProcessCountLimit:
     case ProcessTerminationReason::RequestedByNetworkProcess:
     case ProcessTerminationReason::RequestedByGPUProcess:
     case ProcessTerminationReason::Crash:

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-09-09 16:40:46 UTC (rev 282218)
@@ -1413,6 +1413,8 @@
 
     navigation.setIsLoadedWithNavigationShared(true);
 
+    process->markProcessAsRecentlyUsed();
+
     if (!process->isLaunching() || !url.isLocalFile())
         process->send(Messages::WebPage::LoadRequest(loadParameters), webPageID);
     else
@@ -1474,6 +1476,7 @@
     maybeInitializeSandboxExtensionHandle(m_process, fileURL, resourceDirectoryURL, loadParameters.sandboxExtensionHandle, checkAssumedReadAccessToResourceURL);
     addPlatformLoadParameters(m_process, loadParameters);
 
+    m_process->markProcessAsRecentlyUsed();
     if (m_process->isLaunching())
         send(Messages::WebPage::LoadRequestWaitingForProcessLaunch(loadParameters, resourceDirectoryURL, m_identifier, checkAssumedReadAccessToResourceURL));
     else
@@ -1533,6 +1536,7 @@
     loadParameters.isNavigatingToAppBoundDomain = isNavigatingToAppBoundDomain;
     addPlatformLoadParameters(process, loadParameters);
 
+    process->markProcessAsRecentlyUsed();
     process->assumeReadAccessToBaseURL(*this, baseURL);
     process->send(Messages::WebPage::LoadData(loadParameters), webPageID);
     process->startResponsivenessTimer();
@@ -1590,6 +1594,7 @@
 
     addPlatformLoadParameters(m_process, loadParameters);
 
+    m_process->markProcessAsRecentlyUsed();
     m_process->assumeReadAccessToBaseURL(*this, baseURL);
     m_process->send(Messages::WebPage::LoadSimulatedRequestAndResponse(loadParameters, simulatedResponse), m_webPageID);
     m_process->startResponsivenessTimer();
@@ -1633,6 +1638,7 @@
     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
     addPlatformLoadParameters(process(), loadParameters);
 
+    m_process->markProcessAsRecentlyUsed();
     m_process->assumeReadAccessToBaseURL(*this, baseURL.string());
     m_process->assumeReadAccessToBaseURL(*this, unreachableURL.string());
     send(Messages::WebPage::LoadAlternateHTML(loadParameters));
@@ -1662,6 +1668,7 @@
     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
     addPlatformLoadParameters(process(), loadParameters);
 
+    m_process->markProcessAsRecentlyUsed();
     send(Messages::WebPage::LoadData(loadParameters));
     m_process->startResponsivenessTimer();
 }
@@ -1737,6 +1744,7 @@
     if (options.contains(WebCore::ReloadOption::DisableContentBlockers))
         navigation->setUserContentExtensionsEnabled(false);
 
+    m_process->markProcessAsRecentlyUsed();
     send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle));
     m_process->startResponsivenessTimer();
 
@@ -1815,6 +1823,7 @@
     auto transaction = m_pageLoadState.transaction();
     m_pageLoadState.setPendingAPIRequest(transaction, { navigation ? navigation->navigationID() : 0, item.url() });
 
+    m_process->markProcessAsRecentlyUsed();
     send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated));
     m_process->startResponsivenessTimer();
 
@@ -5176,6 +5185,7 @@
 
 void WebPageProxy::viewIsBecomingVisible()
 {
+    m_process->markProcessAsRecentlyUsed();
 #if ENABLE(MEDIA_STREAM)
     if (m_userMediaPermissionRequestManager)
         m_userMediaPermissionRequestManager->viewIsBecomingVisible();
@@ -7739,6 +7749,7 @@
     case ProcessTerminationReason::RequestedByGPUProcess:
     case ProcessTerminationReason::Crash:
         return true;
+    case ProcessTerminationReason::ExceededProcessCountLimit:
     case ProcessTerminationReason::NavigationSwap:
     case ProcessTerminationReason::RequestedByClient:
         break;

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2021-09-09 16:40:46 UTC (rev 282218)
@@ -866,6 +866,9 @@
     if (m_prewarmedProcess)
         return;
 
+    if (WebProcessProxy::hasReachedProcessCountLimit())
+        return;
+
     WEBPROCESSPOOL_RELEASE_LOG(PerformanceLogging, "prewarmProcess: Prewarming a WebProcess for performance");
     createNewWebProcess(nullptr, WebProcessProxy::IsPrewarmed::Yes);
 }

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-09-09 16:40:46 UTC (rev 282218)
@@ -108,6 +108,25 @@
 namespace WebKit {
 using namespace WebCore;
 
+static unsigned s_maxProcessCount { 400 };
+
+static ListHashSet<WebProcessProxy*>& liveProcessesLRU()
+{
+    ASSERT(RunLoop::isMain());
+    static NeverDestroyed<ListHashSet<WebProcessProxy*>> processes;
+    return processes;
+}
+
+void WebProcessProxy::setProcessCountLimit(unsigned limit)
+{
+    s_maxProcessCount = limit;
+}
+
+bool WebProcessProxy::hasReachedProcessCountLimit()
+{
+    return liveProcessesLRU().size() >= s_maxProcessCount;
+}
+
 static bool isMainThreadOrCheckDisabled()
 {
 #if PLATFORM(IOS_FAMILY)
@@ -150,8 +169,17 @@
 Ref<WebProcessProxy> WebProcessProxy::create(WebProcessPool& processPool, WebsiteDataStore* websiteDataStore, IsPrewarmed isPrewarmed, CrossOriginMode crossOriginMode, ShouldLaunchProcess shouldLaunchProcess)
 {
     auto proxy = adoptRef(*new WebProcessProxy(processPool, websiteDataStore, isPrewarmed, crossOriginMode));
-    if (shouldLaunchProcess == ShouldLaunchProcess::Yes)
+    if (shouldLaunchProcess == ShouldLaunchProcess::Yes) {
+        if (liveProcessesLRU().size() >= s_maxProcessCount) {
+            for (auto& processPool : WebProcessPool::allProcessPools())
+                processPool->webProcessCache().clear();
+            if (liveProcessesLRU().size() >= s_maxProcessCount)
+                liveProcessesLRU().first()->requestTermination(ProcessTerminationReason::ExceededProcessCountLimit);
+        }
+        ASSERT(liveProcessesLRU().size() < s_maxProcessCount);
+        liveProcessesLRU().add(proxy.ptr());
         proxy->connect();
+    }
     return proxy;
 }
 
@@ -237,6 +265,8 @@
     ASSERT(m_pageURLRetainCountMap.isEmpty());
     WEBPROCESSPROXY_RELEASE_LOG(Process, "destructor:");
 
+    liveProcessesLRU().remove(this);
+
     for (auto identifier : m_speechRecognitionServerMap.keys())
         removeMessageReceiver(Messages::SpeechRecognitionServer::messageReceiverName(), identifier);
 
@@ -337,6 +367,7 @@
 
     ASSERT(!m_isInProcessCache);
     ASSERT(!m_provisionalPages.contains(&provisionalPage));
+    markProcessAsRecentlyUsed();
     m_provisionalPages.add(&provisionalPage);
     updateRegistrationWithDataStore();
 }
@@ -558,6 +589,7 @@
         m_processPool->pageBeginUsingWebsiteDataStore(webPage.identifier(), webPage.websiteDataStore());
     }
 
+    markProcessAsRecentlyUsed();
     m_pageMap.set(webPage.identifier(), &webPage);
     globalPageMap().set(webPage.identifier(), &webPage);
 
@@ -889,6 +921,8 @@
     // to be deleted before we can finish our work.
     auto protectedThis = makeRef(*this);
 
+    liveProcessesLRU().remove(this);
+
 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
     m_userMediaCaptureManagerProxy->clear();
 #endif
@@ -1856,6 +1890,7 @@
 void WebProcessProxy::establishServiceWorkerContext(const WebPreferencesStore& store, CompletionHandler<void()>&& completionHandler)
 {
     WEBPROCESSPROXY_RELEASE_LOG(Loading, "establishServiceWorkerContext: Started");
+    markProcessAsRecentlyUsed();
     sendWithAsyncReply(Messages::WebProcess::EstablishWorkerContextConnectionToNetworkProcess { processPool().defaultPageGroup().pageGroupID(), m_serviceWorkerInformation->serviceWorkerPageProxyID, m_serviceWorkerInformation->serviceWorkerPageID, store, *m_registrableDomain, m_serviceWorkerInformation->initializationData }, [this, weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)]() mutable {
         if (weakThis)
             WEBPROCESSPROXY_RELEASE_LOG(Loading, "establishServiceWorkerContext: Finished");
@@ -2006,6 +2041,12 @@
     return !m_sleepDisablers.isEmpty();
 }
 
+void WebProcessProxy::markProcessAsRecentlyUsed()
+{
+    if (liveProcessesLRU().contains(this))
+        liveProcessesLRU().appendOrMoveToLast(this);
+}
+
 void WebProcessProxy::systemBeep()
 {
     PAL::systemBeep();

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (282217 => 282218)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-09-09 16:40:46 UTC (rev 282218)
@@ -166,6 +166,9 @@
     
     PAL::SessionID sessionID() const;
 
+    static bool hasReachedProcessCountLimit();
+    static void setProcessCountLimit(unsigned);
+
     static WebProcessProxy* processForIdentifier(WebCore::ProcessIdentifier);
     static WebPageProxy* webPage(WebPageProxyIdentifier);
     Ref<WebPageProxy> createWebPage(PageClient&, Ref<API::PageConfiguration>&&);
@@ -410,6 +413,8 @@
     static bool shouldEnableRemoteInspector();
 #endif
 
+    void markProcessAsRecentlyUsed();
+
 #if PLATFORM(MAC)
     void platformSuspendProcess();
     void platformResumeProcess();

Modified: trunk/Tools/ChangeLog (282217 => 282218)


--- trunk/Tools/ChangeLog	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Tools/ChangeLog	2021-09-09 16:40:46 UTC (rev 282218)
@@ -1,3 +1,16 @@
+2021-09-09  Chris Dumez  <[email protected]>
+
+        Implement a WebProcess cap
+        https://bugs.webkit.org/show_bug.cgi?id=230067
+        <rdar://79479244>
+
+        Reviewed by Geoffrey Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm:
+        (TEST):
+
 2021-09-09  Aakash Jain  <[email protected]>
 
         Run check-github-mirror-integrity more frequently

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm (282217 => 282218)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm	2021-09-09 16:08:51 UTC (rev 282217)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm	2021-09-09 16:40:46 UTC (rev 282218)
@@ -376,3 +376,67 @@
     kill([webView _webProcessIdentifier], 9);
     TestWebKitAPI::Util::run(&done);
 }
+
+TEST(WKNavigation, WebProcessLimit)
+{
+    constexpr unsigned maxProcessCount = 10;
+    [WKProcessPool _setWebProcessCountLimit:maxProcessCount];
+
+    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
+    [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) {
+        finishedLoad = true;
+    }];
+    auto createWebView = [&] {
+        auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+        auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
+        [webView setNavigationDelegate:navigationDelegate.get()];
+        finishedLoad = false;
+        [webView loadTestPageNamed:@"simple"];
+        TestWebKitAPI::Util::run(&finishedLoad);
+        return webView;
+    };
+
+    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView *) {
+        didCrash = true;
+    }];
+
+    Vector<RetainPtr<WKWebView>> views;
+    for (unsigned i = 0; i < maxProcessCount; ++i)
+        views.append(createWebView());
+    EXPECT_FALSE(didCrash);
+    for (auto& view : views)
+        EXPECT_NE([view _webProcessIdentifier], 0);
+
+    // We have now reached the WebProcess cap, let's try and launch a new one.
+    __block unsigned crashCount = 0;
+    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) {
+        EXPECT_EQ(views[0], view);
+        ++crashCount;
+    }];
+    views.append(createWebView());
+
+    EXPECT_EQ(crashCount, 1U);
+    for (unsigned i = 0; i < views.size(); ++i) {
+        if (!i)
+            EXPECT_EQ([views[i] _webProcessIdentifier], 0);
+        else
+            EXPECT_NE([views[i] _webProcessIdentifier], 0);
+    }
+
+    crashCount = 0;
+    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) {
+        EXPECT_EQ(views[1], view);
+        ++crashCount;
+    }];
+    views.append(createWebView());
+
+    EXPECT_EQ(crashCount, 1U);
+    for (unsigned i = 0; i < views.size(); ++i) {
+        if (i < 2)
+            EXPECT_EQ([views[i] _webProcessIdentifier], 0);
+        else
+            EXPECT_NE([views[i] _webProcessIdentifier], 0);
+    }
+
+    [WKProcessPool _setWebProcessCountLimit:400];
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to