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

Changeset 282229 in webkit


Ignore:
Timestamp:
Sep 9, 2021, 11:04:35 AM (5 years ago)
Author:
Russell Epstein
Message:

Cherry-pick r282218. rdar://problem/82931375

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

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

Location:
branches/safari-612-branch
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-612-branch/Source/WebKit/ChangeLog

    r282228 r282229  
     12021-09-09  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r282218. rdar://problem/82931375
     4
     5    Implement a WebProcess cap
     6    https://bugs.webkit.org/show_bug.cgi?id=230067
     7    <rdar://79479244>
     8   
     9    Reviewed by Geoffrey Garen.
     10   
     11    Source/WebKit:
     12   
     13    Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways.
     14    The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool).
     15    When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used
     16    WebProcess to avoid going over the limit.
     17   
     18    * Shared/ProcessTerminationReason.h:
     19    * UIProcess/API/C/WKAPICast.h:
     20    (WebKit::toAPI):
     21    * UIProcess/API/Cocoa/WKProcessPool.mm:
     22    (+[WKProcessPool _setWebProcessCountLimit:]):
     23    * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
     24    * UIProcess/Cocoa/NavigationState.mm:
     25    (WebKit::wkProcessTerminationReason):
     26    * UIProcess/WebPageProxy.cpp:
     27    (WebKit::WebPageProxy::loadRequestWithNavigationShared):
     28    (WebKit::WebPageProxy::loadFile):
     29    (WebKit::WebPageProxy::loadDataWithNavigationShared):
     30    (WebKit::WebPageProxy::loadSimulatedRequest):
     31    (WebKit::WebPageProxy::loadAlternateHTML):
     32    (WebKit::WebPageProxy::loadWebArchiveData):
     33    (WebKit::WebPageProxy::reload):
     34    (WebKit::WebPageProxy::goToBackForwardItem):
     35    (WebKit::shouldReloadAfterProcessTermination):
     36    * UIProcess/WebProcessProxy.cpp:
     37    (WebKit::WebProcessProxy::setProcessCountLimit):
     38    (WebKit::WebProcessProxy::create):
     39    (WebKit::WebProcessProxy::~WebProcessProxy):
     40    (WebKit::WebProcessProxy::addProvisionalPageProxy):
     41    (WebKit::WebProcessProxy::addExistingWebPage):
     42    (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
     43    (WebKit::WebProcessProxy::establishServiceWorkerContext):
     44    (WebKit::WebProcessProxy::markProcessAsRecentlyUsed):
     45    * UIProcess/WebProcessProxy.h:
     46   
     47    Tools:
     48   
     49    Add API test coverage.
     50   
     51    * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm:
     52    (TEST):
     53   
     54    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282218 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     55
     56    2021-09-09  Chris Dumez  <cdumez@apple.com>
     57
     58            Implement a WebProcess cap
     59            https://bugs.webkit.org/show_bug.cgi?id=230067
     60            <rdar://79479244>
     61
     62            Reviewed by Geoffrey Garen.
     63
     64            Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways.
     65            The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool).
     66            When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used
     67            WebProcess to avoid going over the limit.
     68
     69            * Shared/ProcessTerminationReason.h:
     70            * UIProcess/API/C/WKAPICast.h:
     71            (WebKit::toAPI):
     72            * UIProcess/API/Cocoa/WKProcessPool.mm:
     73            (+[WKProcessPool _setWebProcessCountLimit:]):
     74            * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
     75            * UIProcess/Cocoa/NavigationState.mm:
     76            (WebKit::wkProcessTerminationReason):
     77            * UIProcess/WebPageProxy.cpp:
     78            (WebKit::WebPageProxy::loadRequestWithNavigationShared):
     79            (WebKit::WebPageProxy::loadFile):
     80            (WebKit::WebPageProxy::loadDataWithNavigationShared):
     81            (WebKit::WebPageProxy::loadSimulatedRequest):
     82            (WebKit::WebPageProxy::loadAlternateHTML):
     83            (WebKit::WebPageProxy::loadWebArchiveData):
     84            (WebKit::WebPageProxy::reload):
     85            (WebKit::WebPageProxy::goToBackForwardItem):
     86            (WebKit::shouldReloadAfterProcessTermination):
     87            * UIProcess/WebProcessProxy.cpp:
     88            (WebKit::WebProcessProxy::setProcessCountLimit):
     89            (WebKit::WebProcessProxy::create):
     90            (WebKit::WebProcessProxy::~WebProcessProxy):
     91            (WebKit::WebProcessProxy::addProvisionalPageProxy):
     92            (WebKit::WebProcessProxy::addExistingWebPage):
     93            (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
     94            (WebKit::WebProcessProxy::establishServiceWorkerContext):
     95            (WebKit::WebProcessProxy::markProcessAsRecentlyUsed):
     96            * UIProcess/WebProcessProxy.h:
     97
    1982021-09-09  Russell Epstein  <repstein@apple.com>
    299
  • branches/safari-612-branch/Source/WebKit/Shared/ProcessTerminationReason.h

    r278895 r282229  
    3131    ExceededMemoryLimit,
    3232    ExceededCPULimit,
     33    ExceededProcessCountLimit,
    3334    RequestedByClient,
    3435    Crash,
  • branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKAPICast.h

    r274815 r282229  
    244244    case ProcessTerminationReason::RequestedByClient:
    245245        return kWKProcessTerminationReasonRequestedByClient;
     246    case ProcessTerminationReason::ExceededProcessCountLimit:
    246247    case ProcessTerminationReason::RequestedByNetworkProcess:
    247248    case ProcessTerminationReason::RequestedByGPUProcess:
  • branches/safari-612-branch/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm

    r282152 r282229  
    566566}
    567567
     568+ (void)_setWebProcessCountLimit:(unsigned)limit
     569{
     570    WebKit::WebProcessProxy::setProcessCountLimit(limit);
     571}
     572
    568573- (void)_garbageCollectJavaScriptObjectsForTesting
    569574{
  • branches/safari-612-branch/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h

    r282152 r282229  
    7474+ (pid_t)_webAuthnProcessIdentifier WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    7575
     76+ (void)_setWebProcessCountLimit:(unsigned)limit WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     77
    7678- (void)_warmInitialProcess WK_API_AVAILABLE(macos(10.12), ios(10.0));
    7779- (void)_automationCapabilitiesDidChange WK_API_AVAILABLE(macos(10.12), ios(10.0));
  • branches/safari-612-branch/Source/WebKit/UIProcess/Cocoa/NavigationState.mm

    r278315 r282229  
    10611061    case ProcessTerminationReason::RequestedByClient:
    10621062        return _WKProcessTerminationReasonRequestedByClient;
     1063    case ProcessTerminationReason::ExceededProcessCountLimit:
    10631064    case ProcessTerminationReason::RequestedByNetworkProcess:
    10641065    case ProcessTerminationReason::RequestedByGPUProcess:
  • branches/safari-612-branch/Source/WebKit/UIProcess/WebPageProxy.cpp

    r281904 r282229  
    14131413    navigation.setIsLoadedWithNavigationShared(true);
    14141414
     1415    process->markProcessAsRecentlyUsed();
     1416
    14151417    if (!process->isLaunching() || !url.isLocalFile())
    14161418        process->send(Messages::WebPage::LoadRequest(loadParameters), webPageID);
    … …  
    14741476    addPlatformLoadParameters(m_process, loadParameters);
    14751477
     1478    m_process->markProcessAsRecentlyUsed();
    14761479    if (m_process->isLaunching())
    14771480        send(Messages::WebPage::LoadRequestWaitingForProcessLaunch(loadParameters, resourceDirectoryURL, m_identifier, checkAssumedReadAccessToResourceURL));
    … …  
    15331536    addPlatformLoadParameters(process, loadParameters);
    15341537
     1538    process->markProcessAsRecentlyUsed();
    15351539    process->assumeReadAccessToBaseURL(*this, baseURL);
    15361540    process->send(Messages::WebPage::LoadData(loadParameters), webPageID);
    … …  
    15901594    addPlatformLoadParameters(m_process, loadParameters);
    15911595
     1596    m_process->markProcessAsRecentlyUsed();
    15921597    m_process->assumeReadAccessToBaseURL(*this, baseURL);
    15931598    m_process->send(Messages::WebPage::LoadSimulatedRequestAndResponse(loadParameters, simulatedResponse), m_webPageID);
    … …  
    16331638    addPlatformLoadParameters(process(), loadParameters);
    16341639
     1640    m_process->markProcessAsRecentlyUsed();
    16351641    m_process->assumeReadAccessToBaseURL(*this, baseURL.string());
    16361642    m_process->assumeReadAccessToBaseURL(*this, unreachableURL.string());
    … …  
    16621668    addPlatformLoadParameters(process(), loadParameters);
    16631669
     1670    m_process->markProcessAsRecentlyUsed();
    16641671    send(Messages::WebPage::LoadData(loadParameters));
    16651672    m_process->startResponsivenessTimer();
    … …  
    17371744        navigation->setUserContentExtensionsEnabled(false);
    17381745
     1746    m_process->markProcessAsRecentlyUsed();
    17391747    send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle));
    17401748    m_process->startResponsivenessTimer();
    … …  
    18151823    m_pageLoadState.setPendingAPIRequest(transaction, { navigation ? navigation->navigationID() : 0, item.url() });
    18161824
     1825    m_process->markProcessAsRecentlyUsed();
    18171826    send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated));
    18181827    m_process->startResponsivenessTimer();
    … …  
    51735182void WebPageProxy::viewIsBecomingVisible()
    51745183{
     5184    m_process->markProcessAsRecentlyUsed();
    51755185#if ENABLE(MEDIA_STREAM)
    51765186    if (m_userMediaPermissionRequestManager)
    … …  
    77117721    case ProcessTerminationReason::Crash:
    77127722        return true;
     7723    case ProcessTerminationReason::ExceededProcessCountLimit:
    77137724    case ProcessTerminationReason::NavigationSwap:
    77147725    case ProcessTerminationReason::RequestedByClient:
  • branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessPool.cpp

    r281032 r282229  
    867867        return;
    868868
     869    if (WebProcessProxy::hasReachedProcessCountLimit())
     870        return;
     871
    869872    WEBPROCESSPOOL_RELEASE_LOG(PerformanceLogging, "prewarmProcess: Prewarming a WebProcess for performance");
    870873    createNewWebProcess(nullptr, WebProcessProxy::IsPrewarmed::Yes);
  • branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessProxy.cpp

    r281007 r282229  
    109109using namespace WebCore;
    110110
     111static unsigned s_maxProcessCount { 400 };
     112
     113static ListHashSet<WebProcessProxy*>& liveProcessesLRU()
     114{
     115    ASSERT(RunLoop::isMain());
     116    static NeverDestroyed<ListHashSet<WebProcessProxy*>> processes;
     117    return processes;
     118}
     119
     120void WebProcessProxy::setProcessCountLimit(unsigned limit)
     121{
     122    s_maxProcessCount = limit;
     123}
     124
     125bool WebProcessProxy::hasReachedProcessCountLimit()
     126{
     127    return liveProcessesLRU().size() >= s_maxProcessCount;
     128}
     129
    111130static bool isMainThreadOrCheckDisabled()
    112131{
    … …  
    151170{
    152171    auto proxy = adoptRef(*new WebProcessProxy(processPool, websiteDataStore, isPrewarmed));
    153     if (shouldLaunchProcess == ShouldLaunchProcess::Yes)
     172    if (shouldLaunchProcess == ShouldLaunchProcess::Yes) {
     173        if (liveProcessesLRU().size() >= s_maxProcessCount) {
     174            for (auto& processPool : WebProcessPool::allProcessPools())
     175                processPool->webProcessCache().clear();
     176            if (liveProcessesLRU().size() >= s_maxProcessCount)
     177                liveProcessesLRU().first()->requestTermination(ProcessTerminationReason::ExceededProcessCountLimit);
     178        }
     179        ASSERT(liveProcessesLRU().size() < s_maxProcessCount);
     180        liveProcessesLRU().add(proxy.ptr());
    154181        proxy->connect();
     182    }
    155183    return proxy;
    156184}
    … …  
    237265    WEBPROCESSPROXY_RELEASE_LOG(Process, "destructor:");
    238266
     267    liveProcessesLRU().remove(this);
     268
    239269    for (auto identifier : m_speechRecognitionServerMap.keys())
    240270        removeMessageReceiver(Messages::SpeechRecognitionServer::messageReceiverName(), identifier);
    … …  
    337367    ASSERT(!m_isInProcessCache);
    338368    ASSERT(!m_provisionalPages.contains(&provisionalPage));
     369    markProcessAsRecentlyUsed();
    339370    m_provisionalPages.add(&provisionalPage);
    340371    updateRegistrationWithDataStore();
    … …  
    558589    }
    559590
     591    markProcessAsRecentlyUsed();
    560592    m_pageMap.set(webPage.identifier(), &webPage);
    561593    globalPageMap().set(webPage.identifier(), &webPage);
    … …  
    888920    // to be deleted before we can finish our work.
    889921    auto protectedThis = makeRef(*this);
     922
     923    liveProcessesLRU().remove(this);
    890924
    891925#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
    … …  
    18511885{
    18521886    WEBPROCESSPROXY_RELEASE_LOG(Loading, "establishServiceWorkerContext: Started");
     1887    markProcessAsRecentlyUsed();
    18531888    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 {
    18541889        if (weakThis)
    … …  
    20012036}
    20022037
     2038void WebProcessProxy::markProcessAsRecentlyUsed()
     2039{
     2040    if (liveProcessesLRU().contains(this))
     2041        liveProcessesLRU().appendOrMoveToLast(this);
     2042}
     2043
    20032044void WebProcessProxy::systemBeep()
    20042045{
  • branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessProxy.h

    r280451 r282229  
    165165    PAL::SessionID sessionID() const;
    166166
     167    static bool hasReachedProcessCountLimit();
     168    static void setProcessCountLimit(unsigned);
     169
    167170    static WebProcessProxy* processForIdentifier(WebCore::ProcessIdentifier);
    168171    static WebPageProxy* webPage(WebPageProxyIdentifier);
    … …  
    409412#endif
    410413
     414    void markProcessAsRecentlyUsed();
     415
    411416#if PLATFORM(MAC)
    412417    void platformSuspendProcess();
  • branches/safari-612-branch/Tools/ChangeLog

    r282152 r282229  
     12021-09-09  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r282218. rdar://problem/82931375
     4
     5    Implement a WebProcess cap
     6    https://bugs.webkit.org/show_bug.cgi?id=230067
     7    <rdar://79479244>
     8   
     9    Reviewed by Geoffrey Garen.
     10   
     11    Source/WebKit:
     12   
     13    Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways.
     14    The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool).
     15    When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used
     16    WebProcess to avoid going over the limit.
     17   
     18    * Shared/ProcessTerminationReason.h:
     19    * UIProcess/API/C/WKAPICast.h:
     20    (WebKit::toAPI):
     21    * UIProcess/API/Cocoa/WKProcessPool.mm:
     22    (+[WKProcessPool _setWebProcessCountLimit:]):
     23    * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
     24    * UIProcess/Cocoa/NavigationState.mm:
     25    (WebKit::wkProcessTerminationReason):
     26    * UIProcess/WebPageProxy.cpp:
     27    (WebKit::WebPageProxy::loadRequestWithNavigationShared):
     28    (WebKit::WebPageProxy::loadFile):
     29    (WebKit::WebPageProxy::loadDataWithNavigationShared):
     30    (WebKit::WebPageProxy::loadSimulatedRequest):
     31    (WebKit::WebPageProxy::loadAlternateHTML):
     32    (WebKit::WebPageProxy::loadWebArchiveData):
     33    (WebKit::WebPageProxy::reload):
     34    (WebKit::WebPageProxy::goToBackForwardItem):
     35    (WebKit::shouldReloadAfterProcessTermination):
     36    * UIProcess/WebProcessProxy.cpp:
     37    (WebKit::WebProcessProxy::setProcessCountLimit):
     38    (WebKit::WebProcessProxy::create):
     39    (WebKit::WebProcessProxy::~WebProcessProxy):
     40    (WebKit::WebProcessProxy::addProvisionalPageProxy):
     41    (WebKit::WebProcessProxy::addExistingWebPage):
     42    (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
     43    (WebKit::WebProcessProxy::establishServiceWorkerContext):
     44    (WebKit::WebProcessProxy::markProcessAsRecentlyUsed):
     45    * UIProcess/WebProcessProxy.h:
     46   
     47    Tools:
     48   
     49    Add API test coverage.
     50   
     51    * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm:
     52    (TEST):
     53   
     54    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282218 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     55
     56    2021-09-09  Chris Dumez  <cdumez@apple.com>
     57
     58            Implement a WebProcess cap
     59            https://bugs.webkit.org/show_bug.cgi?id=230067
     60            <rdar://79479244>
     61
     62            Reviewed by Geoffrey Garen.
     63
     64            Add API test coverage.
     65
     66            * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm:
     67            (TEST):
     68
    1692021-09-08  Alan Coon  <alancoon@apple.com>
    270
  • branches/safari-612-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm

    r273997 r282229  
    377377    TestWebKitAPI::Util::run(&done);
    378378}
     379
     380TEST(WKNavigation, WebProcessLimit)
     381{
     382    constexpr unsigned maxProcessCount = 10;
     383    [WKProcessPool _setWebProcessCountLimit:maxProcessCount];
     384
     385    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
     386    [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) {
     387        finishedLoad = true;
     388    }];
     389    auto createWebView = [&] {
     390        auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     391        auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
     392        [webView setNavigationDelegate:navigationDelegate.get()];
     393        finishedLoad = false;
     394        [webView loadTestPageNamed:@"simple"];
     395        TestWebKitAPI::Util::run(&finishedLoad);
     396        return webView;
     397    };
     398
     399    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView *) {
     400        didCrash = true;
     401    }];
     402
     403    Vector<RetainPtr<WKWebView>> views;
     404    for (unsigned i = 0; i < maxProcessCount; ++i)
     405        views.append(createWebView());
     406    EXPECT_FALSE(didCrash);
     407    for (auto& view : views)
     408        EXPECT_NE([view _webProcessIdentifier], 0);
     409
     410    // We have now reached the WebProcess cap, let's try and launch a new one.
     411    __block unsigned crashCount = 0;
     412    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) {
     413        EXPECT_EQ(views[0], view);
     414        ++crashCount;
     415    }];
     416    views.append(createWebView());
     417
     418    EXPECT_EQ(crashCount, 1U);
     419    for (unsigned i = 0; i < views.size(); ++i) {
     420        if (!i)
     421            EXPECT_EQ([views[i] _webProcessIdentifier], 0);
     422        else
     423            EXPECT_NE([views[i] _webProcessIdentifier], 0);
     424    }
     425
     426    crashCount = 0;
     427    [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) {
     428        EXPECT_EQ(views[1], view);
     429        ++crashCount;
     430    }];
     431    views.append(createWebView());
     432
     433    EXPECT_EQ(crashCount, 1U);
     434    for (unsigned i = 0; i < views.size(); ++i) {
     435        if (i < 2)
     436            EXPECT_EQ([views[i] _webProcessIdentifier], 0);
     437        else
     438            EXPECT_NE([views[i] _webProcessIdentifier], 0);
     439    }
     440
     441    [WKProcessPool _setWebProcessCountLimit:400];
     442}
Note: See TracChangeset for help on using the changeset viewer.