Process swapping on navigation needs to handle server redirects.
[WebKit-https.git] / Source / WebKit / UIProcess / WebProcessPool.cpp
1 /*
2  * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebProcessPool.h"
28
29 #include "APIArray.h"
30 #include "APIAutomationClient.h"
31 #include "APICustomProtocolManagerClient.h"
32 #include "APIDownloadClient.h"
33 #include "APIHTTPCookieStore.h"
34 #include "APIInjectedBundleClient.h"
35 #include "APILegacyContextHistoryClient.h"
36 #include "APIPageConfiguration.h"
37 #include "APIProcessPoolConfiguration.h"
38 #include "ChildProcessMessages.h"
39 #include "DownloadProxy.h"
40 #include "DownloadProxyMessages.h"
41 #include "GamepadData.h"
42 #include "HighPerformanceGraphicsUsageSampler.h"
43 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
44 #include "LegacyCustomProtocolManagerMessages.h"
45 #endif
46 #include "LogInitialization.h"
47 #include "NetworkProcessCreationParameters.h"
48 #include "NetworkProcessMessages.h"
49 #include "NetworkProcessProxy.h"
50 #include "PerActivityStateCPUUsageSampler.h"
51 #include "SandboxExtension.h"
52 #include "ServiceWorkerProcessProxy.h"
53 #include "StatisticsData.h"
54 #include "StorageProcessCreationParameters.h"
55 #include "StorageProcessMessages.h"
56 #include "TextChecker.h"
57 #include "UIGamepad.h"
58 #include "UIGamepadProvider.h"
59 #include "WKContextPrivate.h"
60 #include "WebAutomationSession.h"
61 #include "WebCertificateInfo.h"
62 #include "WebContextSupplement.h"
63 #include "WebCookieManagerProxy.h"
64 #include "WebCoreArgumentCoders.h"
65 #include "WebGeolocationManagerProxy.h"
66 #include "WebKit2Initialize.h"
67 #include "WebMemorySampler.h"
68 #include "WebNotificationManagerProxy.h"
69 #include "WebPageGroup.h"
70 #include "WebPreferences.h"
71 #include "WebPreferencesKeys.h"
72 #include "WebProcessCreationParameters.h"
73 #include "WebProcessMessages.h"
74 #include "WebProcessPoolMessages.h"
75 #include "WebProcessProxy.h"
76 #include "WebsiteDataStore.h"
77 #include "WebsiteDataStoreParameters.h"
78 #include <JavaScriptCore/JSCInlines.h>
79 #include <WebCore/ApplicationCacheStorage.h>
80 #include <WebCore/LogInitialization.h>
81 #include <WebCore/NetworkStorageSession.h>
82 #include <WebCore/PlatformScreen.h>
83 #include <WebCore/ResourceRequest.h>
84 #include <WebCore/URLParser.h>
85 #include <pal/SessionID.h>
86 #include <wtf/Language.h>
87 #include <wtf/MainThread.h>
88 #include <wtf/NeverDestroyed.h>
89 #include <wtf/ProcessPrivilege.h>
90 #include <wtf/RunLoop.h>
91 #include <wtf/WallTime.h>
92 #include <wtf/text/StringBuilder.h>
93
94 #if ENABLE(SERVICE_CONTROLS)
95 #include "ServicesController.h"
96 #endif
97
98 #if ENABLE(REMOTE_INSPECTOR)
99 #include <JavaScriptCore/RemoteInspector.h>
100 #endif
101
102 #if OS(LINUX)
103 #include "MemoryPressureMonitor.h"
104 #endif
105
106 #if PLATFORM(WAYLAND)
107 #include "WaylandCompositor.h"
108 #include <WebCore/PlatformDisplay.h>
109 #endif
110
111 #ifndef NDEBUG
112 #include <wtf/RefCountedLeakCounter.h>
113 #endif
114
115 using namespace WebCore;
116 using namespace WebKit;
117
118 namespace WebKit {
119
120 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, processPoolCounter, ("WebProcessPool"));
121
122 static const Seconds serviceWorkerTerminationDelay { 5_s };
123
124 static uint64_t generateListenerIdentifier()
125 {
126     static uint64_t nextIdentifier = 1;
127     return nextIdentifier++;
128 }
129
130 static HashMap<uint64_t, Function<void(WebProcessPool&)>>& processPoolCreationListenerFunctionMap()
131 {
132     static NeverDestroyed<HashMap<uint64_t, Function<void(WebProcessPool&)>>> map;
133     return map;
134 }
135
136 uint64_t WebProcessPool::registerProcessPoolCreationListener(Function<void(WebProcessPool&)>&& function)
137 {
138     ASSERT(function);
139
140     auto identifier = generateListenerIdentifier();
141     processPoolCreationListenerFunctionMap().set(identifier, WTFMove(function));
142     return identifier;
143 }
144
145 void WebProcessPool::unregisterProcessPoolCreationListener(uint64_t identifier)
146 {
147     processPoolCreationListenerFunctionMap().remove(identifier);
148 }
149
150 Ref<WebProcessPool> WebProcessPool::create(API::ProcessPoolConfiguration& configuration)
151 {
152     InitializeWebKit2();
153     return adoptRef(*new WebProcessPool(configuration));
154 }
155
156 void WebProcessPool::notifyThisWebProcessPoolWasCreated()
157 {
158     auto& listenerMap = processPoolCreationListenerFunctionMap();
159
160     Vector<uint64_t> identifiers;
161     identifiers.reserveInitialCapacity(listenerMap.size());
162     for (auto identifier : listenerMap.keys())
163         identifiers.uncheckedAppend(identifier);
164
165     for (auto identifier : identifiers) {
166         auto iterator = listenerMap.find(identifier);
167         if (iterator == listenerMap.end())
168             continue;
169
170         // To make sure the Function object stays alive until after the function call has been made,
171         // we temporarily move it out of the map.
172         // This protects it from the Function calling unregisterProcessPoolCreationListener thereby
173         // removing itself from the map of listeners.
174         // If the identifier still exists in the map later, we move it back in.
175         Function<void(WebProcessPool&)> function = WTFMove(iterator->value);
176         function(*this);
177
178         iterator = listenerMap.find(identifier);
179         if (iterator != listenerMap.end()) {
180             ASSERT(!iterator->value);
181             iterator->value = WTFMove(function);
182         }
183     }
184 }
185
186 static Vector<WebProcessPool*>& processPools()
187 {
188     static NeverDestroyed<Vector<WebProcessPool*>> processPools;
189     return processPools;
190 }
191
192 const Vector<WebProcessPool*>& WebProcessPool::allProcessPools()
193 {
194     return processPools();
195 }
196
197 static WebsiteDataStore::Configuration legacyWebsiteDataStoreConfiguration(API::ProcessPoolConfiguration& processPoolConfiguration)
198 {
199     WebsiteDataStore::Configuration configuration;
200
201     configuration.cacheStorageDirectory = API::WebsiteDataStore::defaultCacheStorageDirectory();
202     configuration.serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory();
203     configuration.localStorageDirectory = processPoolConfiguration.localStorageDirectory();
204     configuration.webSQLDatabaseDirectory = processPoolConfiguration.webSQLDatabaseDirectory();
205     configuration.applicationCacheDirectory = processPoolConfiguration.applicationCacheDirectory();
206     configuration.applicationCacheFlatFileSubdirectoryName = processPoolConfiguration.applicationCacheFlatFileSubdirectoryName();
207     configuration.mediaCacheDirectory = processPoolConfiguration.mediaCacheDirectory();
208     configuration.mediaKeysStorageDirectory = processPoolConfiguration.mediaKeysStorageDirectory();
209     configuration.resourceLoadStatisticsDirectory = processPoolConfiguration.resourceLoadStatisticsDirectory();
210     configuration.networkCacheDirectory = processPoolConfiguration.diskCacheDirectory();
211     configuration.javaScriptConfigurationDirectory = processPoolConfiguration.javaScriptConfigurationDirectory();
212
213     return configuration;
214 }
215
216 static HashSet<String, ASCIICaseInsensitiveHash>& globalURLSchemesWithCustomProtocolHandlers()
217 {
218     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> set;
219     return set;
220 }
221
222 WebProcessPool::WebProcessPool(API::ProcessPoolConfiguration& configuration)
223     : m_configuration(configuration.copy())
224     , m_defaultPageGroup(WebPageGroup::create())
225     , m_injectedBundleClient(std::make_unique<API::InjectedBundleClient>())
226     , m_automationClient(std::make_unique<API::AutomationClient>())
227     , m_downloadClient(std::make_unique<API::DownloadClient>())
228     , m_historyClient(std::make_unique<API::LegacyContextHistoryClient>())
229     , m_customProtocolManagerClient(std::make_unique<API::CustomProtocolManagerClient>())
230     , m_visitedLinkStore(VisitedLinkStore::create())
231 #if PLATFORM(MAC)
232     , m_highPerformanceGraphicsUsageSampler(std::make_unique<HighPerformanceGraphicsUsageSampler>(*this))
233     , m_perActivityStateCPUUsageSampler(std::make_unique<PerActivityStateCPUUsageSampler>(*this))
234 #endif
235     , m_alwaysRunsAtBackgroundPriority(m_configuration->alwaysRunsAtBackgroundPriority())
236     , m_shouldTakeUIBackgroundAssertion(m_configuration->shouldTakeUIBackgroundAssertion())
237     , m_userObservablePageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
238     , m_processSuppressionDisabledForPageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
239     , m_hiddenPageThrottlingAutoIncreasesCounter([this](RefCounterEvent) { m_hiddenPageThrottlingTimer.startOneShot(0_s); })
240     , m_hiddenPageThrottlingTimer(RunLoop::main(), this, &WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit)
241     , m_serviceWorkerProcessesTerminationTimer(RunLoop::main(), this, &WebProcessPool::terminateServiceWorkerProcesses)
242 #if PLATFORM(IOS)
243     , m_foregroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
244     , m_backgroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
245 #endif
246 {
247     static std::once_flag onceFlag;
248     std::call_once(onceFlag, [] {
249         WTF::setProcessPrivileges(allPrivileges());
250         WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
251     });
252
253     if (m_configuration->shouldHaveLegacyDataStore())
254         m_websiteDataStore = API::WebsiteDataStore::createLegacy(legacyWebsiteDataStoreConfiguration(m_configuration));
255
256     if (!m_websiteDataStore && API::WebsiteDataStore::defaultDataStoreExists())
257         m_websiteDataStore = API::WebsiteDataStore::defaultDataStore();
258
259     for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
260         m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
261
262     for (const auto& urlScheme : m_configuration->cachePartitionedURLSchemes())
263         m_schemesToRegisterAsCachePartitioned.add(urlScheme);
264
265     platformInitialize();
266
267     addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
268
269     // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
270     addSupplement<WebCookieManagerProxy>();
271     addSupplement<WebGeolocationManagerProxy>();
272     addSupplement<WebNotificationManagerProxy>();
273 #if ENABLE(MEDIA_SESSION)
274     addSupplement<WebMediaSessionFocusManager>();
275 #endif
276
277     processPools().append(this);
278
279     addLanguageChangeObserver(this, languageChanged);
280
281     resolvePathsForSandboxExtensions();
282
283 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
284     WebCore::initializeLogChannelsIfNecessary();
285     WebKit::initializeLogChannelsIfNecessary();
286 #endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
287
288 #ifndef NDEBUG
289     processPoolCounter.increment();
290 #endif
291
292     notifyThisWebProcessPoolWasCreated();
293 }
294
295 WebProcessPool::~WebProcessPool()
296 {
297     bool removed = processPools().removeFirst(this);
298     ASSERT_UNUSED(removed, removed);
299
300     removeLanguageChangeObserver(this);
301
302     m_messageReceiverMap.invalidate();
303
304     for (auto& supplement : m_supplements.values()) {
305         supplement->processPoolDestroyed();
306         supplement->clearProcessPool();
307     }
308
309     invalidateCallbackMap(m_dictionaryCallbacks, CallbackBase::Error::OwnerWasInvalidated);
310
311     platformInvalidateContext();
312
313 #ifndef NDEBUG
314     processPoolCounter.decrement();
315 #endif
316
317     if (m_networkProcess)
318         m_networkProcess->shutDownProcess();
319
320 #if ENABLE(GAMEPAD)
321     if (!m_processesUsingGamepads.isEmpty())
322         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
323 #endif
324 }
325
326 void WebProcessPool::initializeClient(const WKContextClientBase* client)
327 {
328     m_client.initialize(client);
329 }
330
331 void WebProcessPool::setInjectedBundleClient(std::unique_ptr<API::InjectedBundleClient>&& client)
332 {
333     if (!client)
334         m_injectedBundleClient = std::make_unique<API::InjectedBundleClient>();
335     else
336         m_injectedBundleClient = WTFMove(client);
337 }
338
339 void WebProcessPool::initializeConnectionClient(const WKContextConnectionClientBase* client)
340 {
341     m_connectionClient.initialize(client);
342 }
343
344 void WebProcessPool::setHistoryClient(std::unique_ptr<API::LegacyContextHistoryClient>&& historyClient)
345 {
346     if (!historyClient)
347         m_historyClient = std::make_unique<API::LegacyContextHistoryClient>();
348     else
349         m_historyClient = WTFMove(historyClient);
350 }
351
352 void WebProcessPool::setDownloadClient(std::unique_ptr<API::DownloadClient>&& downloadClient)
353 {
354     if (!downloadClient)
355         m_downloadClient = std::make_unique<API::DownloadClient>();
356     else
357         m_downloadClient = WTFMove(downloadClient);
358 }
359
360 void WebProcessPool::setAutomationClient(std::unique_ptr<API::AutomationClient>&& automationClient)
361 {
362     if (!automationClient)
363         m_automationClient = std::make_unique<API::AutomationClient>();
364     else
365         m_automationClient = WTFMove(automationClient);
366 }
367
368 void WebProcessPool::setLegacyCustomProtocolManagerClient(std::unique_ptr<API::CustomProtocolManagerClient>&& customProtocolManagerClient)
369 {
370 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
371     if (!customProtocolManagerClient)
372         m_customProtocolManagerClient = std::make_unique<API::CustomProtocolManagerClient>();
373     else
374         m_customProtocolManagerClient = WTFMove(customProtocolManagerClient);
375 #endif
376 }
377
378 void WebProcessPool::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
379 {
380     // Guard against API misuse.
381     if (!m_processes.isEmpty())
382         CRASH();
383
384     m_configuration->setMaximumProcessCount(maximumNumberOfProcesses);
385 }
386
387 IPC::Connection* WebProcessPool::networkingProcessConnection()
388 {
389     return m_networkProcess->connection();
390 }
391
392 void WebProcessPool::languageChanged(void* context)
393 {
394     static_cast<WebProcessPool*>(context)->languageChanged();
395 }
396
397 void WebProcessPool::languageChanged()
398 {
399     sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
400 #if USE(SOUP)
401     if (m_networkProcess)
402         m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
403 #endif
404 }
405
406 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
407 {
408     sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
409 }
410
411 void WebProcessPool::textCheckerStateChanged()
412 {
413     sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
414 }
415
416 NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* withWebsiteDataStore)
417 {
418     if (m_networkProcess) {
419         if (withWebsiteDataStore)
420             m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(withWebsiteDataStore->parameters()), 0);
421         return *m_networkProcess;
422     }
423
424     if (m_websiteDataStore)
425         m_websiteDataStore->websiteDataStore().resolveDirectoriesIfNecessary();
426
427     m_networkProcess = NetworkProcessProxy::create(*this);
428
429     NetworkProcessCreationParameters parameters;
430
431     if (withWebsiteDataStore) {
432         auto websiteDataStoreParameters = withWebsiteDataStore->parameters();
433         parameters.defaultSessionParameters = websiteDataStoreParameters.networkSessionParameters;
434
435         // FIXME: This isn't conceptually correct, but it's needed to preserve behavior introduced in r213241.
436         // We should separate the concept of the default session from the currently used persistent session.
437         parameters.defaultSessionParameters.sessionID = PAL::SessionID::defaultSessionID();
438     }
439     
440     parameters.privateBrowsingEnabled = WebPreferences::anyPagesAreUsingPrivateBrowsing();
441
442     parameters.cacheModel = cacheModel();
443     parameters.diskCacheSizeOverride = m_configuration->diskCacheSizeOverride();
444     parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
445
446     for (auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
447         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
448
449     for (auto& scheme : m_urlSchemesRegisteredForCustomProtocols)
450         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
451
452     parameters.cacheStorageDirectory = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().cacheStorageDirectory() : API::WebsiteDataStore::defaultCacheStorageDirectory();
453     if (!parameters.cacheStorageDirectory.isEmpty())
454         SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
455     parameters.cacheStoragePerOriginQuota = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().cacheStoragePerOriginQuota() : WebsiteDataStore::defaultCacheStoragePerOriginQuota;
456
457     parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
458     if (!parameters.diskCacheDirectory.isEmpty())
459         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
460 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
461     parameters.shouldEnableNetworkCacheSpeculativeRevalidation = m_configuration->diskCacheSpeculativeValidationEnabled();
462 #endif
463
464 #if PLATFORM(IOS)
465     String cookieStorageDirectory = this->cookieStorageDirectory();
466     if (!cookieStorageDirectory.isEmpty())
467         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
468
469     String containerCachesDirectory = this->networkingCachesDirectory();
470     if (!containerCachesDirectory.isEmpty())
471         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
472
473     String parentBundleDirectory = this->parentBundleDirectory();
474     if (!parentBundleDirectory.isEmpty())
475         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::Type::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
476 #endif
477
478 #if OS(LINUX)
479     if (MemoryPressureMonitor::isEnabled())
480         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
481 #endif
482
483     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
484     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
485
486     parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
487     parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
488     parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
489     parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
490     parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
491     parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
492     parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
493
494     // Add any platform specific parameters
495     platformInitializeNetworkProcess(parameters);
496
497     // Initialize the network process.
498     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
499
500 #if PLATFORM(COCOA)
501     m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
502 #endif
503
504     if (m_didNetworkProcessCrash) {
505         m_didNetworkProcessCrash = false;
506         reinstateNetworkProcessAssertionState(*m_networkProcess);
507         if (m_websiteDataStore)
508             m_websiteDataStore->websiteDataStore().networkProcessDidCrash();
509     }
510
511     if (withWebsiteDataStore)
512         m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(withWebsiteDataStore->parameters()), 0);
513
514     return *m_networkProcess;
515 }
516
517 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy& networkProcessProxy, Vector<Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>>&& pendingReplies)
518 {
519     networkProcessFailedToLaunch(networkProcessProxy);
520     ASSERT(!m_networkProcess);
521     if (pendingReplies.isEmpty())
522         return;
523     auto& newNetworkProcess = ensureNetworkProcess();
524     for (auto& reply : pendingReplies)
525         newNetworkProcess.getNetworkProcessConnection(WTFMove(reply));
526 }
527
528 void WebProcessPool::networkProcessFailedToLaunch(NetworkProcessProxy& networkProcessProxy)
529 {
530     ASSERT(m_networkProcess);
531     ASSERT(&networkProcessProxy == m_networkProcess.get());
532     m_didNetworkProcessCrash = true;
533
534     for (auto& supplement : m_supplements.values())
535         supplement->processDidClose(&networkProcessProxy);
536
537     m_client.networkProcessDidCrash(this);
538
539     // Leave the process proxy around during client call, so that the client could query the process identifier.
540     m_networkProcess = nullptr;
541 }
542
543 void WebProcessPool::getNetworkProcessConnection(Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>&& reply)
544 {
545     ensureNetworkProcess();
546     ASSERT(m_networkProcess);
547
548     m_networkProcess->getNetworkProcessConnection(WTFMove(reply));
549 }
550
551 void WebProcessPool::ensureStorageProcessAndWebsiteDataStore(WebsiteDataStore* relevantDataStore)
552 {
553     // *********
554     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
555     // *********
556
557     if (!m_storageProcess) {
558         auto parameters = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().storageProcessParameters() : (relevantDataStore ? relevantDataStore->storageProcessParameters() : API::WebsiteDataStore::defaultDataStore()->websiteDataStore().storageProcessParameters());
559
560         ASSERT(parameters.sessionID.isValid());
561
562 #if ENABLE(INDEXED_DATABASE)
563         if (parameters.indexedDatabaseDirectory.isEmpty()) {
564             parameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
565             SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
566         }
567 #endif
568 #if ENABLE(SERVICE_WORKER)
569         if (parameters.serviceWorkerRegistrationDirectory.isEmpty()) {
570             parameters.serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory();
571             SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
572         }
573
574         if (!m_schemesServiceWorkersCanHandle.isEmpty())
575             parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
576
577         parameters.shouldDisableServiceWorkerProcessTerminationDelay = m_shouldDisableServiceWorkerProcessTerminationDelay;
578 #endif
579
580         m_storageProcess = StorageProcessProxy::create(*this);
581         m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(parameters), 0);
582     }
583
584     if (!relevantDataStore || !m_websiteDataStore || relevantDataStore == &m_websiteDataStore->websiteDataStore())
585         return;
586
587     m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(relevantDataStore->storageProcessParameters()), 0);
588 }
589
590 void WebProcessPool::getStorageProcessConnection(WebProcessProxy& webProcessProxy, PAL::SessionID initialSessionID, Ref<Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply>&& reply)
591 {
592     ensureStorageProcessAndWebsiteDataStore(WebsiteDataStore::existingNonDefaultDataStoreForSessionID(initialSessionID));
593
594     m_storageProcess->getStorageProcessConnection(webProcessProxy, WTFMove(reply));
595 }
596
597 void WebProcessPool::storageProcessCrashed(StorageProcessProxy* storageProcessProxy)
598 {
599     ASSERT(m_storageProcess);
600     ASSERT(storageProcessProxy == m_storageProcess.get());
601
602     for (auto& supplement : m_supplements.values())
603         supplement->processDidClose(storageProcessProxy);
604
605     m_client.storageProcessDidCrash(this);
606     m_storageProcess = nullptr;
607 }
608
609 #if ENABLE(SERVICE_WORKER)
610 void WebProcessPool::establishWorkerContextConnectionToStorageProcess(StorageProcessProxy& proxy, SecurityOriginData&& securityOrigin, std::optional<PAL::SessionID> sessionID)
611 {
612     ASSERT_UNUSED(proxy, &proxy == m_storageProcess);
613
614     if (m_serviceWorkerProcesses.contains(securityOrigin))
615         return;
616
617     m_mayHaveRegisteredServiceWorkers.clear();
618
619     WebsiteDataStore* websiteDataStore = nullptr;
620     if (sessionID)
621         websiteDataStore = WebsiteDataStore::existingNonDefaultDataStoreForSessionID(*sessionID);
622
623     if (!websiteDataStore) {
624         if (!m_websiteDataStore)
625             m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
626         websiteDataStore = &m_websiteDataStore->websiteDataStore();
627     }
628
629     if (m_serviceWorkerProcesses.isEmpty())
630         sendToAllProcesses(Messages::WebProcess::RegisterServiceWorkerClients { });
631
632     auto serviceWorkerProcessProxy = ServiceWorkerProcessProxy::create(*this, securityOrigin, *websiteDataStore);
633     m_serviceWorkerProcesses.add(WTFMove(securityOrigin), serviceWorkerProcessProxy.ptr());
634
635     updateProcessAssertions();
636     initializeNewWebProcess(serviceWorkerProcessProxy, *websiteDataStore);
637
638     auto* serviceWorkerProcessProxyPtr = serviceWorkerProcessProxy.ptr();
639     m_processes.append(WTFMove(serviceWorkerProcessProxy));
640
641     serviceWorkerProcessProxyPtr->start(m_serviceWorkerPreferences ? m_serviceWorkerPreferences.value() : m_defaultPageGroup->preferences().store(), sessionID);
642     if (!m_serviceWorkerUserAgent.isNull())
643         serviceWorkerProcessProxyPtr->setUserAgent(m_serviceWorkerUserAgent);
644 }
645 #endif
646
647 void WebProcessPool::disableServiceWorkerProcessTerminationDelay()
648 {
649 #if ENABLE(SERVICE_WORKER)
650     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
651         return;
652
653     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
654     if (m_storageProcess)
655         m_storageProcess->send(Messages::StorageProcess::DisableServiceWorkerProcessTerminationDelay(), 0);
656 #endif
657 }
658
659 void WebProcessPool::willStartUsingPrivateBrowsing()
660 {
661     for (auto* processPool : allProcessPools())
662         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
663 }
664
665 void WebProcessPool::willStopUsingPrivateBrowsing()
666 {
667     for (auto* processPool : allProcessPools())
668         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
669 }
670
671 void WebProcessPool::windowServerConnectionStateChanged()
672 {
673     size_t processCount = m_processes.size();
674     for (size_t i = 0; i < processCount; ++i)
675         m_processes[i]->windowServerConnectionStateChanged();
676 }
677
678 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
679 {
680     if (networkProcess()) {
681         if (privateBrowsingEnabled)
682             networkProcess()->send(Messages::NetworkProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()), 0);
683         else
684             networkProcess()->send(Messages::NetworkProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()), 0);
685     }
686
687     if (privateBrowsingEnabled)
688         sendToAllProcesses(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()));
689     else
690         sendToAllProcesses(Messages::WebProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()));
691 }
692
693 void (*s_invalidMessageCallback)(WKStringRef messageName);
694
695 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
696 {
697     s_invalidMessageCallback = invalidMessageCallback;
698 }
699
700 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
701 {
702     if (!s_invalidMessageCallback)
703         return;
704
705     StringBuilder messageNameStringBuilder;
706     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
707     messageNameStringBuilder.append('.');
708     messageNameStringBuilder.append(messageName.data(), messageName.size());
709
710     s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
711 }
712
713 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
714 {
715     if (m_processWithPageCache && m_processWithPageCache != process)
716         m_processWithPageCache->releasePageCache();
717     m_processWithPageCache = process;
718 }
719
720 void WebProcessPool::resolvePathsForSandboxExtensions()
721 {
722     m_resolvedPaths.injectedBundlePath = resolvePathForSandboxExtension(injectedBundlePath());
723     m_resolvedPaths.applicationCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory());
724     m_resolvedPaths.webSQLDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory());
725     m_resolvedPaths.mediaCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory());
726     m_resolvedPaths.mediaKeyStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory());
727     m_resolvedPaths.indexedDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory());
728
729     m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.reserveCapacity(m_configuration->additionalReadAccessAllowedPaths().size());
730     for (const auto& path : m_configuration->additionalReadAccessAllowedPaths())
731         m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.uncheckedAppend(resolvePathForSandboxExtension(path.data()));
732
733     platformResolvePathsForSandboxExtensions();
734 }
735
736 WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDataStore)
737 {
738     auto processProxy = WebProcessProxy::create(*this, websiteDataStore);
739     auto& process = processProxy.get();
740     initializeNewWebProcess(process, websiteDataStore);
741     m_processes.append(WTFMove(processProxy));
742
743     if (m_serviceWorkerProcessesTerminationTimer.isActive())
744         m_serviceWorkerProcessesTerminationTimer.stop();
745
746     return process;
747 }
748
749 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
750 static void displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
751 {
752     HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
753     WebCore::getScreenProperties(screenProperties);
754
755     for (auto& processPool : WebProcessPool::allProcessPools())
756         processPool->sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
757 }
758
759 static void registerDisplayConfigurationCallback()
760 {
761     static std::once_flag onceFlag;
762     std::call_once(
763         onceFlag,
764         [] {
765             CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, nullptr);
766         });
767 }
768 #endif
769
770 void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDataStore& websiteDataStore)
771 {
772     ensureNetworkProcess();
773
774     WebProcessCreationParameters parameters;
775
776     websiteDataStore.resolveDirectoriesIfNecessary();
777
778     parameters.injectedBundlePath = m_resolvedPaths.injectedBundlePath;
779     if (!parameters.injectedBundlePath.isEmpty())
780         SandboxExtension::createHandleWithoutResolvingPath(parameters.injectedBundlePath, SandboxExtension::Type::ReadOnly, parameters.injectedBundlePathExtensionHandle);
781
782     parameters.additionalSandboxExtensionHandles.allocate(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size());
783     for (size_t i = 0, size = m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size(); i < size; ++i)
784         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths[i], SandboxExtension::Type::ReadOnly, parameters.additionalSandboxExtensionHandles[i]);
785
786     parameters.applicationCacheDirectory = websiteDataStore.resolvedApplicationCacheDirectory();
787     if (parameters.applicationCacheDirectory.isEmpty())
788         parameters.applicationCacheDirectory = m_resolvedPaths.applicationCacheDirectory;
789     if (!parameters.applicationCacheDirectory.isEmpty())
790         SandboxExtension::createHandleWithoutResolvingPath(parameters.applicationCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.applicationCacheDirectoryExtensionHandle);
791
792     parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName();
793
794     parameters.webSQLDatabaseDirectory = websiteDataStore.resolvedDatabaseDirectory();
795     if (parameters.webSQLDatabaseDirectory.isEmpty())
796         parameters.webSQLDatabaseDirectory = m_resolvedPaths.webSQLDatabaseDirectory;
797     if (!parameters.webSQLDatabaseDirectory.isEmpty())
798         SandboxExtension::createHandleWithoutResolvingPath(parameters.webSQLDatabaseDirectory, SandboxExtension::Type::ReadWrite, parameters.webSQLDatabaseDirectoryExtensionHandle);
799
800     parameters.mediaCacheDirectory = websiteDataStore.resolvedMediaCacheDirectory();
801     if (parameters.mediaCacheDirectory.isEmpty())
802         parameters.mediaCacheDirectory = m_resolvedPaths.mediaCacheDirectory;
803     if (!parameters.mediaCacheDirectory.isEmpty())
804         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaCacheDirectoryExtensionHandle);
805
806     parameters.mediaKeyStorageDirectory = websiteDataStore.resolvedMediaKeysDirectory();
807     if (parameters.mediaKeyStorageDirectory.isEmpty())
808         parameters.mediaKeyStorageDirectory = m_resolvedPaths.mediaKeyStorageDirectory;
809     if (!parameters.mediaKeyStorageDirectory.isEmpty())
810         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaKeyStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaKeyStorageDirectoryExtensionHandle);
811
812 #if PLATFORM(IOS)
813     setJavaScriptConfigurationFileEnabledFromDefaults();
814 #endif
815
816     if (javaScriptConfigurationFileEnabled()) {
817         parameters.javaScriptConfigurationDirectory = websiteDataStore.resolvedJavaScriptConfigurationDirectory();
818         if (!parameters.javaScriptConfigurationDirectory.isEmpty())
819             SandboxExtension::createHandleWithoutResolvingPath(parameters.javaScriptConfigurationDirectory, SandboxExtension::Type::ReadWrite, parameters.javaScriptConfigurationDirectoryExtensionHandle);
820     }
821
822     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
823
824     parameters.cacheModel = cacheModel();
825     parameters.languages = userPreferredLanguages();
826
827     parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
828     parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
829     parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
830     parameters.urlSchemesForWhichDomainRelaxationIsForbidden = copyToVector(m_schemesToSetDomainRelaxationForbiddenFor);
831     parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
832     parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
833     parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
834     parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
835     parameters.urlSchemesRegisteredAsAlwaysRevalidated = copyToVector(m_schemesToRegisterAsAlwaysRevalidated);
836     parameters.urlSchemesRegisteredAsCachePartitioned = copyToVector(m_schemesToRegisterAsCachePartitioned);
837     parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
838     parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
839
840     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
841     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
842
843     parameters.terminationTimeout = 0_s;
844
845     parameters.textCheckerState = TextChecker::state();
846
847     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
848
849     parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
850
851 #if ENABLE(NOTIFICATIONS)
852     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
853     parameters.notificationPermissions = supplement<WebNotificationManagerProxy>()->notificationPermissions();
854 #endif
855
856     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
857     parameters.plugInAutoStartOrigins = copyToVector(m_plugInAutoStartProvider.autoStartOrigins());
858
859     parameters.memoryCacheDisabled = m_memoryCacheDisabled;
860
861 #if ENABLE(SERVICE_CONTROLS)
862     auto& serviceController = ServicesController::singleton();
863     parameters.hasImageServices = serviceController.hasImageServices();
864     parameters.hasSelectionServices = serviceController.hasSelectionServices();
865     parameters.hasRichContentServices = serviceController.hasRichContentServices();
866     serviceController.refreshExistingServices();
867 #endif
868
869 #if ENABLE(NETSCAPE_PLUGIN_API)
870     parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
871 #endif
872
873 #if OS(LINUX)
874     parameters.shouldEnableMemoryPressureReliefLogging = true;
875     if (MemoryPressureMonitor::isEnabled())
876         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
877 #endif
878
879 #if PLATFORM(WAYLAND) && USE(EGL)
880     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
881         parameters.waylandCompositorDisplayName = WaylandCompositor::singleton().displayName();
882 #endif
883
884     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
885 #if ENABLE(MEDIA_STREAM)
886     parameters.shouldCaptureAudioInUIProcess = m_configuration->shouldCaptureAudioInUIProcess();
887 #endif
888
889     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
890
891     // Add any platform specific parameters
892     platformInitializeWebProcess(parameters);
893
894     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient->getInjectedBundleInitializationUserData(*this);
895     if (!injectedBundleInitializationUserData)
896         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
897     parameters.initializationUserData = UserData(process.transformObjectsToHandles(injectedBundleInitializationUserData.get()));
898
899     process.send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
900
901 #if PLATFORM(COCOA)
902     process.send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
903 #endif
904
905     if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
906         process.send(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()), 0);
907
908     if (m_automationSession)
909         process.send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0);
910
911     ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
912
913 #if ENABLE(REMOTE_INSPECTOR)
914     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
915     Inspector::RemoteInspector::singleton(); 
916 #endif
917
918 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
919     registerDisplayConfigurationCallback();
920
921     HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
922     WebCore::getScreenProperties(screenProperties);
923     process.send(Messages::WebProcess::SetScreenProperties(screenProperties), 0);
924 #endif
925 }
926
927 void WebProcessPool::warmInitialProcess()
928 {
929     if (m_haveInitialEmptyProcess) {
930         ASSERT(!m_processes.isEmpty());
931         return;
932     }
933
934     if (m_processes.size() >= maximumNumberOfProcesses())
935         return;
936
937     if (!m_websiteDataStore)
938         m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
939     createNewWebProcess(m_websiteDataStore->websiteDataStore());
940
941     m_haveInitialEmptyProcess = true;
942 }
943
944 void WebProcessPool::enableProcessTermination()
945 {
946     m_processTerminationEnabled = true;
947     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
948     for (size_t i = 0; i < processes.size(); ++i) {
949         if (shouldTerminate(processes[i].get()))
950             processes[i]->terminate();
951     }
952 }
953
954 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
955 {
956     ASSERT(m_processes.contains(process));
957
958     if (!m_processTerminationEnabled)
959         return false;
960
961     return true;
962 }
963
964 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
965 {
966     ASSERT(m_processes.contains(process));
967
968     if (!m_visitedLinksPopulated) {
969         populateVisitedLinks();
970         m_visitedLinksPopulated = true;
971     }
972
973     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
974     // so check if it needs to be started here
975     if (m_memorySamplerEnabled) {
976         SandboxExtension::Handle sampleLogSandboxHandle;        
977         WallTime now = WallTime::now();
978         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()), process->processIdentifier());
979         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
980         
981         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
982     }
983
984     if (m_configuration->fullySynchronousModeIsAllowedForTesting())
985         process->connection()->allowFullySynchronousModeForTesting();
986
987     if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
988         process->connection()->ignoreTimeoutsForTesting();
989
990     m_connectionClient.didCreateConnection(this, process->webConnection());
991 }
992
993 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
994 {
995     ASSERT(m_processes.contains(process));
996
997     if (m_haveInitialEmptyProcess && process == m_processes.last())
998         m_haveInitialEmptyProcess = false;
999
1000     // FIXME (Multi-WebProcess): <rdar://problem/12239765> Some of the invalidation calls of the other supplements are still necessary in multi-process mode, but they should only affect data structures pertaining to the process being disconnected.
1001     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
1002     RefPtr<WebProcessProxy> protect(process);
1003     if (m_processWithPageCache == process)
1004         m_processWithPageCache = nullptr;
1005
1006 #if ENABLE(SERVICE_WORKER)
1007     if (is<ServiceWorkerProcessProxy>(*process)) {
1008         auto* removedProcess = m_serviceWorkerProcesses.take(downcast<ServiceWorkerProcessProxy>(*process).securityOrigin());
1009         ASSERT_UNUSED(removedProcess, removedProcess == process);
1010         updateProcessAssertions();
1011     }
1012 #endif
1013
1014     static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
1015
1016     m_processes.removeFirst(process);
1017
1018 #if ENABLE(GAMEPAD)
1019     if (m_processesUsingGamepads.contains(process))
1020         processStoppedUsingGamepads(*process);
1021 #endif
1022
1023 #if ENABLE(SERVICE_WORKER)
1024     // FIXME: We should do better than this. For now, we just destroy the ServiceWorker process
1025     // whenever there is no regular WebContent process remaining.
1026     if (m_processes.size() == m_serviceWorkerProcesses.size()) {
1027         if (!m_serviceWorkerProcessesTerminationTimer.isActive())
1028             m_serviceWorkerProcessesTerminationTimer.startOneShot(serviceWorkerTerminationDelay);
1029     }
1030 #endif
1031 }
1032
1033 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebsiteDataStore& websiteDataStore)
1034 {
1035     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=168676
1036     // Once WebsiteDataStores are truly per-view instead of per-process, remove this nonsense.
1037
1038 #if PLATFORM(COCOA)
1039     bool mustMatchDataStore = API::WebsiteDataStore::defaultDataStoreExists() && &websiteDataStore != &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
1040 #else
1041     bool mustMatchDataStore = false;
1042 #endif
1043
1044     if (m_processes.size() < maximumNumberOfProcesses())
1045         return createNewWebProcess(websiteDataStore);
1046
1047     WebProcessProxy* processToReuse = nullptr;
1048     for (auto& process : m_processes) {
1049         if (mustMatchDataStore && &process->websiteDataStore() != &websiteDataStore)
1050             continue;
1051 #if ENABLE(SERVICE_WORKER)
1052         if (is<ServiceWorkerProcessProxy>(*process))
1053             continue;
1054 #endif
1055         // Choose the process with fewest pages.
1056         if (!processToReuse || processToReuse->pageCount() > process->pageCount())
1057             processToReuse = process.get();
1058     }
1059     return processToReuse ? *processToReuse : createNewWebProcess(websiteDataStore);
1060 }
1061
1062 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
1063 {
1064     if (!pageConfiguration->pageGroup())
1065         pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
1066     if (!pageConfiguration->preferences())
1067         pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
1068     if (!pageConfiguration->userContentController())
1069         pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
1070     if (!pageConfiguration->visitedLinkStore())
1071         pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
1072
1073     if (!pageConfiguration->websiteDataStore()) {
1074         // We try to avoid creating the default data store as long as possible.
1075         // But if there is an attempt to create a web page without any specified data store, then we have to create it.
1076         if (!m_websiteDataStore)
1077             m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
1078
1079         ASSERT(!pageConfiguration->sessionID().isValid());
1080         pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
1081         pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? PAL::SessionID::legacyPrivateSessionID() : m_websiteDataStore->websiteDataStore().sessionID());
1082     }
1083
1084     RefPtr<WebProcessProxy> process;
1085     if (m_haveInitialEmptyProcess) {
1086         process = m_processes.last();
1087         m_haveInitialEmptyProcess = false;
1088     } else if (pageConfiguration->relatedPage()) {
1089         // Sharing processes, e.g. when creating the page via window.open().
1090         process = &pageConfiguration->relatedPage()->process();
1091     } else
1092         process = &createNewWebProcessRespectingProcessCountLimit(pageConfiguration->websiteDataStore()->websiteDataStore());
1093
1094 #if ENABLE(SERVICE_WORKER)
1095     ASSERT(!is<ServiceWorkerProcessProxy>(*process));
1096 #endif
1097
1098     return process->createWebPage(pageClient, WTFMove(pageConfiguration));
1099 }
1100
1101 #if ENABLE(SERVICE_WORKER)
1102 void WebProcessPool::updateServiceWorkerUserAgent(const String& userAgent)
1103 {
1104     if (m_serviceWorkerUserAgent == userAgent)
1105         return;
1106     m_serviceWorkerUserAgent = userAgent;
1107     for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1108         serviceWorkerProcess->setUserAgent(m_serviceWorkerUserAgent);
1109 }
1110
1111 bool WebProcessPool::mayHaveRegisteredServiceWorkers(const WebsiteDataStore& store)
1112 {
1113     if (!m_serviceWorkerProcesses.isEmpty())
1114         return true;
1115
1116     String serviceWorkerRegistrationDirectory = store.resolvedServiceWorkerRegistrationDirectory();
1117     if (serviceWorkerRegistrationDirectory.isEmpty())
1118         serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultDataStoreConfiguration().serviceWorkerRegistrationDirectory;
1119
1120     return m_mayHaveRegisteredServiceWorkers.ensure(serviceWorkerRegistrationDirectory, [&] {
1121         // FIXME: Make this computation on a background thread.
1122         return ServiceWorkerProcessProxy::hasRegisteredServiceWorkers(serviceWorkerRegistrationDirectory);
1123     }).iterator->value;
1124 }
1125 #endif
1126
1127 void WebProcessPool::pageBeginUsingWebsiteDataStore(WebPageProxy& page)
1128 {
1129     auto result = m_sessionToPagesMap.add(page.sessionID(), HashSet<WebPageProxy*>()).iterator->value.add(&page);
1130     ASSERT_UNUSED(result, result.isNewEntry);
1131
1132     auto sessionID = page.sessionID();
1133     if (sessionID.isEphemeral()) {
1134         ASSERT(page.websiteDataStore().parameters().networkSessionParameters.sessionID == sessionID);
1135         sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
1136         page.process().send(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::privateSessionParameters(sessionID)), 0);
1137     } else if (sessionID != PAL::SessionID::defaultSessionID()) {
1138         sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
1139         page.process().send(Messages::WebProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()), 0);
1140
1141 #if ENABLE(INDEXED_DATABASE)
1142         if (!page.websiteDataStore().resolvedIndexedDatabaseDirectory().isEmpty())
1143             ensureStorageProcessAndWebsiteDataStore(&page.websiteDataStore());
1144 #endif
1145     }
1146
1147 #if ENABLE(SERVICE_WORKER)
1148     if (!m_serviceWorkerPreferences) {
1149         m_serviceWorkerPreferences = page.preferencesStore();
1150         for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1151             serviceWorkerProcess->updatePreferencesStore(*m_serviceWorkerPreferences);
1152     }
1153 #endif
1154 }
1155
1156 void WebProcessPool::pageEndUsingWebsiteDataStore(WebPageProxy& page)
1157 {
1158     auto sessionID = page.sessionID();
1159     auto iterator = m_sessionToPagesMap.find(sessionID);
1160     ASSERT(iterator != m_sessionToPagesMap.end());
1161
1162     auto takenPage = iterator->value.take(&page);
1163     ASSERT_UNUSED(takenPage, takenPage == &page);
1164
1165     if (iterator->value.isEmpty()) {
1166         m_sessionToPagesMap.remove(iterator);
1167
1168         if (sessionID == PAL::SessionID::defaultSessionID())
1169             return;
1170
1171         // The last user of this non-default PAL::SessionID is gone, so clean it up in the child processes.
1172         if (networkProcess())
1173             networkProcess()->send(Messages::NetworkProcess::DestroySession(sessionID), 0);
1174         page.process().send(Messages::WebProcess::DestroySession(sessionID), 0);
1175     }
1176 }
1177
1178 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
1179 {
1180     auto* downloadProxy = createDownloadProxy(request, initiatingPage);
1181     PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
1182
1183     if (initiatingPage)
1184         initiatingPage->handleDownloadRequest(downloadProxy);
1185
1186     if (networkProcess()) {
1187         ResourceRequest updatedRequest(request);
1188         // Request's firstPartyForCookies will be used as Original URL of the download request.
1189         // We set the value to top level document's URL.
1190         if (initiatingPage)
1191             updatedRequest.setFirstPartyForCookies(URL(URL(), initiatingPage->pageLoadState().url()));
1192         else
1193             updatedRequest.setFirstPartyForCookies(URL());
1194         networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest, suggestedFilename), 0);
1195         return downloadProxy;
1196     }
1197
1198     return downloadProxy;
1199 }
1200
1201 DownloadProxy* WebProcessPool::resumeDownload(const API::Data* resumeData, const String& path)
1202 {
1203     auto* downloadProxy = createDownloadProxy(ResourceRequest(), nullptr);
1204
1205     SandboxExtension::Handle sandboxExtensionHandle;
1206     if (!path.isEmpty())
1207         SandboxExtension::createHandle(path, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
1208
1209     if (networkProcess()) {
1210         // FIXME: If we started a download in an ephemeral session and that session still exists, we should find a way to use that same session.
1211         networkProcess()->send(Messages::NetworkProcess::ResumeDownload(PAL::SessionID::defaultSessionID(), downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
1212         return downloadProxy;
1213     }
1214
1215     return downloadProxy;
1216 }
1217
1218 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
1219 {
1220     for (auto& process : m_processes) {
1221         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
1222         process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
1223     }
1224 }
1225
1226 void WebProcessPool::populateVisitedLinks()
1227 {
1228     m_historyClient->populateVisitedLinks(*this);
1229 }
1230
1231 WebProcessPool::Statistics& WebProcessPool::statistics()
1232 {
1233     static Statistics statistics = Statistics();
1234
1235     return statistics;
1236 }
1237
1238 #if ENABLE(NETSCAPE_PLUGIN_API)
1239 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
1240 {
1241     Vector<String> directories;
1242     directories.append(directory);
1243
1244     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
1245 }
1246
1247 void WebProcessPool::refreshPlugins()
1248 {
1249     m_pluginInfoStore.refresh();
1250     sendToAllProcesses(Messages::WebProcess::RefreshPlugins());
1251 }
1252
1253 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1254
1255 ProcessID WebProcessPool::networkProcessIdentifier()
1256 {
1257     if (!m_networkProcess)
1258         return 0;
1259
1260     return m_networkProcess->processIdentifier();
1261 }
1262
1263 ProcessID WebProcessPool::storageProcessIdentifier()
1264 {
1265     if (!m_storageProcess)
1266         return 0;
1267
1268     return m_storageProcess->processIdentifier();
1269 }
1270
1271 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
1272 {
1273     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
1274     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
1275 }
1276
1277 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
1278 {
1279     m_shouldUseFontSmoothing = useFontSmoothing;
1280     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
1281 }
1282
1283 void WebProcessPool::setResourceLoadStatisticsEnabled(bool enabled)
1284 {
1285     m_resourceLoadStatisticsEnabled = enabled;
1286     sendToAllProcesses(Messages::WebProcess::SetResourceLoadStatisticsEnabled(enabled));
1287 }
1288
1289 void WebProcessPool::clearResourceLoadStatistics()
1290 {
1291     sendToAllProcesses(Messages::WebProcess::ClearResourceLoadStatistics());
1292 }
1293
1294 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
1295 {
1296     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
1297     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
1298 }
1299
1300 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
1301 {
1302     m_schemesToRegisterAsSecure.add(urlScheme);
1303     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
1304     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsSecure(urlScheme));
1305 }
1306
1307 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
1308 {
1309     m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
1310     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1311     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1312 }
1313
1314 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
1315 {
1316     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
1317     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
1318 }
1319
1320 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
1321 {
1322     m_canHandleHTTPSServerTrustEvaluation = value;
1323     if (m_networkProcess) {
1324         m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
1325         return;
1326     }
1327 }
1328
1329 void WebProcessPool::preconnectToServer(const URL& url)
1330 {
1331     if (!url.isValid() || !url.protocolIsInHTTPFamily())
1332         return;
1333
1334     ensureNetworkProcess().send(Messages::NetworkProcess::PreconnectTo(url, StoredCredentialsPolicy::Use), 0);
1335 }
1336
1337 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
1338 {
1339     m_schemesToRegisterAsLocal.add(urlScheme);
1340     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
1341     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsLocal(urlScheme));
1342 }
1343
1344 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
1345 {
1346     m_schemesToRegisterAsNoAccess.add(urlScheme);
1347     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1348     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1349 }
1350
1351 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
1352 {
1353     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
1354     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1355     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1356 }
1357
1358 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
1359 {
1360     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
1361     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1362     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1363 }
1364
1365 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1366 {
1367     if (!urlScheme)
1368         return;
1369
1370     globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
1371     for (auto* processPool : allProcessPools())
1372         processPool->registerSchemeForCustomProtocol(urlScheme);
1373 }
1374
1375 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1376 {
1377     if (!urlScheme)
1378         return;
1379
1380     globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
1381     for (auto* processPool : allProcessPools())
1382         processPool->unregisterSchemeForCustomProtocol(urlScheme);
1383 }
1384
1385 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
1386 {
1387     m_schemesToRegisterAsCachePartitioned.add(urlScheme);
1388     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
1389 }
1390
1391 void WebProcessPool::registerURLSchemeServiceWorkersCanHandle(const String& urlScheme)
1392 {
1393     m_schemesServiceWorkersCanHandle.add(urlScheme);
1394     sendToAllProcesses(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme));
1395     if (m_storageProcess)
1396         m_storageProcess->send(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme), 0);
1397 }
1398
1399 void WebProcessPool::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& urlScheme)
1400 {
1401     m_schemesToRegisterAsCanDisplayOnlyIfCanRequest.add(urlScheme);
1402     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1403     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1404 }
1405
1406 void WebProcessPool::setCacheModel(CacheModel cacheModel)
1407 {
1408     m_configuration->setCacheModel(cacheModel);
1409     sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
1410
1411     if (m_networkProcess)
1412         m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
1413 }
1414
1415 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
1416 {
1417     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
1418 }
1419
1420 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
1421 {
1422     auto downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
1423     downloadProxy->setOriginatingPage(originatingPage);
1424     return downloadProxy;
1425 }
1426
1427 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
1428 {
1429     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
1430 }
1431
1432 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
1433 {
1434     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
1435 }
1436
1437 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName)
1438 {
1439     m_messageReceiverMap.removeMessageReceiver(messageReceiverName);
1440 }
1441
1442 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
1443 {
1444     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
1445 }
1446
1447 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
1448 {
1449     return m_messageReceiverMap.dispatchMessage(connection, decoder);
1450 }
1451
1452 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
1453 {
1454     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1455 }
1456
1457 void WebProcessPool::setEnhancedAccessibility(bool flag)
1458 {
1459     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1460 }
1461     
1462 void WebProcessPool::startMemorySampler(const double interval)
1463 {    
1464     // For new WebProcesses we will also want to start the Memory Sampler
1465     m_memorySamplerEnabled = true;
1466     m_memorySamplerInterval = interval;
1467     
1468     // For UIProcess
1469 #if ENABLE(MEMORY_SAMPLER)
1470     WebMemorySampler::singleton()->start(interval);
1471 #endif
1472     
1473     // For WebProcess
1474     SandboxExtension::Handle sampleLogSandboxHandle;    
1475     WallTime now = WallTime::now();
1476     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()));
1477     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
1478     
1479     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1480 }
1481
1482 void WebProcessPool::stopMemorySampler()
1483 {    
1484     // For WebProcess
1485     m_memorySamplerEnabled = false;
1486     
1487     // For UIProcess
1488 #if ENABLE(MEMORY_SAMPLER)
1489     WebMemorySampler::singleton()->stop();
1490 #endif
1491
1492     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1493 }
1494
1495 void WebProcessPool::useTestingNetworkSession()
1496 {
1497     ASSERT(m_processes.isEmpty());
1498     ASSERT(!m_networkProcess);
1499
1500     if (m_networkProcess)
1501         return;
1502
1503     if (!m_processes.isEmpty())
1504         return;
1505
1506     m_shouldUseTestingNetworkSession = true;
1507 }
1508
1509 template<typename T, typename U>
1510 void WebProcessPool::sendSyncToNetworkingProcess(T&& message, U&& reply)
1511 {
1512     if (m_networkProcess && m_networkProcess->canSendMessage())
1513         m_networkProcess->sendSync(std::forward<T>(message), std::forward<U>(reply), 0);
1514 }
1515
1516 void WebProcessPool::setAllowsAnySSLCertificateForWebSocket(bool allows)
1517 {
1518     sendSyncToNetworkingProcess(Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket(allows), Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket::Reply());
1519 }
1520
1521 void WebProcessPool::clearCachedCredentials()
1522 {
1523     sendToAllProcesses(Messages::WebProcess::ClearCachedCredentials());
1524     if (m_networkProcess)
1525         m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1526 }
1527
1528 void WebProcessPool::terminateStorageProcess()
1529 {
1530     if (!m_storageProcess)
1531         return;
1532
1533     m_storageProcess->terminate();
1534     m_storageProcess = nullptr;
1535 }
1536
1537 void WebProcessPool::terminateNetworkProcess()
1538 {
1539     if (!m_networkProcess)
1540         return;
1541     
1542     m_networkProcess->terminate();
1543     m_networkProcess = nullptr;
1544     m_didNetworkProcessCrash = true;
1545 }
1546
1547 void WebProcessPool::terminateServiceWorkerProcesses()
1548 {
1549 #if ENABLE(SERVICE_WORKER)
1550     auto protectedThis = makeRef(*this);
1551     while (!m_serviceWorkerProcesses.isEmpty())
1552         m_serviceWorkerProcesses.begin()->value->requestTermination(ProcessTerminationReason::RequestedByClient);
1553 #endif
1554 }
1555
1556 void WebProcessPool::syncNetworkProcessCookies()
1557 {
1558     sendSyncToNetworkingProcess(Messages::NetworkProcess::SyncAllCookies(), Messages::NetworkProcess::SyncAllCookies::Reply());
1559 }
1560
1561 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1562 {
1563     ensureNetworkProcess();
1564     m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1565 }
1566
1567 void WebProcessPool::updateAutomationCapabilities() const
1568 {
1569 #if ENABLE(REMOTE_INSPECTOR)
1570     Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1571 #endif
1572 }
1573
1574 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1575 {
1576     if (m_automationSession)
1577         m_automationSession->setProcessPool(nullptr);
1578     
1579     m_automationSession = WTFMove(automationSession);
1580
1581 #if ENABLE(REMOTE_INSPECTOR)
1582     if (m_automationSession) {
1583         m_automationSession->init();
1584         m_automationSession->setProcessPool(this);
1585
1586         sendToAllProcesses(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()));
1587     } else
1588         sendToAllProcesses(Messages::WebProcess::DestroyAutomationSessionProxy());
1589 #endif
1590 }
1591
1592 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1593 {
1594 #if PLATFORM(COCOA)
1595     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1596 #else
1597     UNUSED_PARAM(enabled);
1598 #endif
1599 }
1600
1601 bool WebProcessPool::httpPipeliningEnabled() const
1602 {
1603 #if PLATFORM(COCOA)
1604     return ResourceRequest::httpPipeliningEnabled();
1605 #else
1606     return false;
1607 #endif
1608 }
1609
1610 void WebProcessPool::getStatistics(uint32_t statisticsMask, Function<void (API::Dictionary*, CallbackBase::Error)>&& callbackFunction)
1611 {
1612     if (!statisticsMask) {
1613         callbackFunction(nullptr, CallbackBase::Error::Unknown);
1614         return;
1615     }
1616
1617     RefPtr<StatisticsRequest> request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1618
1619     if (statisticsMask & StatisticsRequestTypeWebContent)
1620         requestWebContentStatistics(request.get());
1621     
1622     if (statisticsMask & StatisticsRequestTypeNetworking)
1623         requestNetworkingStatistics(request.get());
1624 }
1625
1626 void WebProcessPool::requestWebContentStatistics(StatisticsRequest* request)
1627 {
1628     // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1629 }
1630
1631 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest* request)
1632 {
1633     if (!m_networkProcess) {
1634         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1635         return;
1636     }
1637
1638     uint64_t requestID = request->addOutstandingRequest();
1639     m_statisticsRequests.set(requestID, request);
1640     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1641 }
1642
1643 static WebProcessProxy* webProcessProxyFromConnection(IPC::Connection& connection, const Vector<RefPtr<WebProcessProxy>>& processes)
1644 {
1645     for (auto& process : processes) {
1646         if (process->hasConnection(connection))
1647             return process.get();
1648     }
1649
1650     ASSERT_NOT_REACHED();
1651     return nullptr;
1652 }
1653
1654 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1655 {
1656     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1657     if (!webProcessProxy)
1658         return;
1659     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1660 }
1661
1662 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1663 {
1664     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1665     if (!webProcessProxy)
1666         return;
1667
1668     RefPtr<API::Object> returnData;
1669     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1670     returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1671 }
1672
1673 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1674 {
1675     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1676     if (!request) {
1677         LOG_ERROR("Cannot report networking statistics.");
1678         return;
1679     }
1680
1681     request->completedRequest(requestID, statisticsData);
1682 }
1683
1684 #if ENABLE(GAMEPAD)
1685
1686 void WebProcessPool::startedUsingGamepads(IPC::Connection& connection)
1687 {
1688     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1689     if (!proxy)
1690         return;
1691
1692     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1693
1694     ASSERT(!m_processesUsingGamepads.contains(proxy));
1695     m_processesUsingGamepads.add(proxy);
1696
1697     if (!wereAnyProcessesUsingGamepads)
1698         UIGamepadProvider::singleton().processPoolStartedUsingGamepads(*this);
1699
1700     proxy->send(Messages::WebProcess::SetInitialGamepads(UIGamepadProvider::singleton().snapshotGamepads()), 0);
1701 }
1702
1703 void WebProcessPool::stoppedUsingGamepads(IPC::Connection& connection)
1704 {
1705     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1706     if (!proxy)
1707         return;
1708
1709     ASSERT(m_processesUsingGamepads.contains(proxy));
1710     processStoppedUsingGamepads(*proxy);
1711 }
1712
1713 void WebProcessPool::processStoppedUsingGamepads(WebProcessProxy& process)
1714 {
1715     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1716
1717     ASSERT(m_processesUsingGamepads.contains(&process));
1718     m_processesUsingGamepads.remove(&process);
1719
1720     if (wereAnyProcessesUsingGamepads && m_processesUsingGamepads.isEmpty())
1721         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
1722 }
1723
1724 void WebProcessPool::gamepadConnected(const UIGamepad& gamepad)
1725 {
1726     for (auto& process : m_processesUsingGamepads)
1727         process->send(Messages::WebProcess::GamepadConnected(gamepad.fullGamepadData()), 0);
1728 }
1729
1730 void WebProcessPool::gamepadDisconnected(const UIGamepad& gamepad)
1731 {
1732     for (auto& process : m_processesUsingGamepads)
1733         process->send(Messages::WebProcess::GamepadDisconnected(gamepad.index()), 0);
1734 }
1735
1736 void WebProcessPool::setInitialConnectedGamepads(const Vector<std::unique_ptr<UIGamepad>>& gamepads)
1737 {
1738     Vector<GamepadData> gamepadDatas;
1739     gamepadDatas.grow(gamepads.size());
1740     for (size_t i = 0; i < gamepads.size(); ++i) {
1741         if (!gamepads[i])
1742             continue;
1743         gamepadDatas[i] = gamepads[i]->fullGamepadData();
1744     }
1745
1746     for (auto& process : m_processesUsingGamepads)
1747         process->send(Messages::WebProcess::SetInitialGamepads(gamepadDatas), 0);
1748 }
1749
1750 #endif // ENABLE(GAMEPAD)
1751
1752 void WebProcessPool::setJavaScriptConfigurationFileEnabled(bool flag)
1753 {
1754     m_javaScriptConfigurationFileEnabled = flag;
1755 }
1756
1757 void WebProcessPool::garbageCollectJavaScriptObjects()
1758 {
1759     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1760 }
1761
1762 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1763 {
1764     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1765 }
1766
1767 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, PAL::SessionID sessionID)
1768 {
1769     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1770 }
1771
1772 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, PAL::SessionID sessionID)
1773 {
1774     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1775 }
1776
1777 Ref<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1778 {
1779     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1780 }
1781
1782 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1783 {
1784     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1785 }
1786
1787 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1788 {
1789     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1790 }
1791
1792 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, WallTime time)
1793 {
1794     m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1795 }
1796
1797 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1798 {
1799 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1800     if (!globalURLSchemesWithCustomProtocolHandlers().contains(scheme))
1801         m_urlSchemesRegisteredForCustomProtocols.add(scheme);
1802     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::RegisterScheme(scheme));
1803 #endif
1804 }
1805
1806 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1807 {
1808 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1809     m_urlSchemesRegisteredForCustomProtocols.remove(scheme);
1810     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::UnregisterScheme(scheme));
1811 #endif
1812 }
1813
1814 #if ENABLE(NETSCAPE_PLUGIN_API)
1815 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1816 {
1817     auto& policiesForHost = m_pluginLoadClientPolicies.ensure(host, [] { return HashMap<String, HashMap<String, uint8_t>>(); }).iterator->value;
1818     auto& versionsToPolicies = policiesForHost.ensure(bundleIdentifier, [] { return HashMap<String, uint8_t>(); }).iterator->value;
1819     versionsToPolicies.set(versionString, policy);
1820
1821     sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1822 }
1823
1824 void WebProcessPool::resetPluginLoadClientPolicies(HashMap<String, HashMap<String, HashMap<String, uint8_t>>>&& pluginLoadClientPolicies)
1825 {
1826     m_pluginLoadClientPolicies = WTFMove(pluginLoadClientPolicies);
1827     sendToAllProcesses(Messages::WebProcess::ResetPluginLoadClientPolicies(m_pluginLoadClientPolicies));
1828 }
1829
1830 void WebProcessPool::clearPluginClientPolicies()
1831 {
1832     m_pluginLoadClientPolicies.clear();
1833     sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1834 }
1835 #endif
1836
1837 void WebProcessPool::addSupportedPlugin(String&& matchingDomain, String&& name, HashSet<String>&& mimeTypes, HashSet<String> extensions)
1838 {
1839 #if ENABLE(NETSCAPE_PLUGIN_API)
1840     m_pluginInfoStore.addSupportedPlugin(WTFMove(matchingDomain), WTFMove(name), WTFMove(mimeTypes), WTFMove(extensions));
1841 #else
1842     UNUSED_PARAM(matchingDomain);
1843     UNUSED_PARAM(name);
1844     UNUSED_PARAM(mimeTypes);
1845     UNUSED_PARAM(extensions);
1846 #endif
1847 }
1848
1849 void WebProcessPool::clearSupportedPlugins()
1850 {
1851 #if ENABLE(NETSCAPE_PLUGIN_API)
1852     m_pluginInfoStore.clearSupportedPlugins();
1853 #endif
1854 }
1855
1856 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1857 {
1858     m_memoryCacheDisabled = disabled;
1859     sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1860 }
1861
1862 void WebProcessPool::setFontWhitelist(API::Array* array)
1863 {
1864     m_fontWhitelist.clear();
1865     if (array) {
1866         for (size_t i = 0; i < array->size(); ++i) {
1867             if (API::String* font = array->at<API::String>(i))
1868                 m_fontWhitelist.append(font->string());
1869         }
1870     }
1871 }
1872
1873 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1874 {
1875     // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1876     // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1877     // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1878     static int maximumTimerThrottlePerPageInMS = 200 * 100;
1879
1880     int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1881     sendToAllProcesses(Messages::WebProcess::SetHiddenPageDOMTimerThrottlingIncreaseLimit(limitInMilliseconds));
1882 }
1883
1884 void WebProcessPool::reportWebContentCPUTime(Seconds cpuTime, uint64_t activityState)
1885 {
1886 #if PLATFORM(MAC)
1887     if (m_perActivityStateCPUUsageSampler)
1888         m_perActivityStateCPUUsageSampler->reportWebContentCPUTime(cpuTime, static_cast<WebCore::ActivityStateForCPUSampling>(activityState));
1889 #else
1890     UNUSED_PARAM(cpuTime);
1891     UNUSED_PARAM(activityState);
1892 #endif
1893 }
1894
1895 void WebProcessPool::updateProcessAssertions()
1896 {
1897 #if PLATFORM(IOS)
1898 #if ENABLE(SERVICE_WORKER)
1899     auto updateServiceWorkerProcessAssertion = [&] {
1900         if (!m_serviceWorkerProcesses.isEmpty() && m_foregroundWebProcessCounter.value()) {
1901             // FIXME: We can do better than this once we have process per origin.
1902             for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1903                 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
1904                 if (!m_foregroundTokensForServiceWorkerProcesses.contains(securityOrigin))
1905                     m_foregroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().foregroundActivityToken());
1906             }
1907             m_backgroundTokensForServiceWorkerProcesses.clear();
1908             return;
1909         }
1910         if (!m_serviceWorkerProcesses.isEmpty() && m_backgroundWebProcessCounter.value()) {
1911             // FIXME: We can do better than this once we have process per origin.
1912             for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1913                 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
1914                 if (!m_backgroundTokensForServiceWorkerProcesses.contains(securityOrigin))
1915                     m_backgroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().backgroundActivityToken());
1916             }
1917             m_foregroundTokensForServiceWorkerProcesses.clear();
1918             return;
1919         }
1920         m_foregroundTokensForServiceWorkerProcesses.clear();
1921         m_backgroundTokensForServiceWorkerProcesses.clear();
1922     };
1923     updateServiceWorkerProcessAssertion();
1924 #endif
1925
1926     auto updateNetworkProcessAssertion = [&] {
1927         if (m_foregroundWebProcessCounter.value()) {
1928             if (!m_foregroundTokenForNetworkProcess)
1929                 m_foregroundTokenForNetworkProcess = ensureNetworkProcess().throttler().foregroundActivityToken();
1930             m_backgroundTokenForNetworkProcess = nullptr;
1931             return;
1932         }
1933         if (m_backgroundWebProcessCounter.value()) {
1934             if (!m_backgroundTokenForNetworkProcess)
1935                 m_backgroundTokenForNetworkProcess = ensureNetworkProcess().throttler().backgroundActivityToken();
1936             m_foregroundTokenForNetworkProcess = nullptr;
1937             return;
1938         }
1939         m_foregroundTokenForNetworkProcess = nullptr;
1940         m_backgroundTokenForNetworkProcess = nullptr;
1941     };
1942     updateNetworkProcessAssertion();
1943 #endif
1944 }
1945
1946 #if ENABLE(SERVICE_WORKER)
1947 void WebProcessPool::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destination, MessageWithMessagePorts&& message, ServiceWorkerIdentifier source, const String& sourceOrigin)
1948 {
1949     sendToStorageProcessRelaunchingIfNecessary(Messages::StorageProcess::PostMessageToServiceWorkerClient(destination, WTFMove(message), source, sourceOrigin));
1950 }
1951
1952 void WebProcessPool::postMessageToServiceWorker(ServiceWorkerIdentifier destination, MessageWithMessagePorts&& message, const ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
1953 {
1954     sendToStorageProcessRelaunchingIfNecessary(Messages::StorageProcess::PostMessageToServiceWorker(destination, WTFMove(message), source, connectionIdentifier));
1955 }
1956 #endif
1957
1958 void WebProcessPool::reinstateNetworkProcessAssertionState(NetworkProcessProxy& newNetworkProcessProxy)
1959 {
1960 #if PLATFORM(IOS)
1961     // The network process crashed; take new tokens for the new network process.
1962     if (m_backgroundTokenForNetworkProcess)
1963         m_backgroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().backgroundActivityToken();
1964     else if (m_foregroundTokenForNetworkProcess)
1965         m_foregroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().foregroundActivityToken();
1966 #else
1967     UNUSED_PARAM(newNetworkProcessProxy);
1968 #endif
1969 }
1970
1971 #if ENABLE(SERVICE_WORKER)
1972 ServiceWorkerProcessProxy* WebProcessPool::serviceWorkerProcessProxyFromPageID(uint64_t pageID) const
1973 {
1974     // FIXME: This is inefficient.
1975     for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1976         if (serviceWorkerProcess->pageID() == pageID)
1977             return serviceWorkerProcess;
1978     }
1979     return nullptr;
1980 }
1981 #endif
1982
1983 Ref<WebProcessProxy> WebProcessPool::processForNavigation(WebPageProxy& page, const API::Navigation& navigation, PolicyAction& action)
1984 {
1985     if (!m_configuration->processSwapsOnNavigation())
1986         return page.process();
1987
1988     if (!page.process().hasCommittedAnyProvisionalLoads())
1989         return page.process();
1990
1991     // FIXME: We should support process swap when a window has an opener.
1992     if (navigation.opener())
1993         return page.process();
1994
1995     if (navigation.isCrossOriginWindowOpenNavigation()) {
1996         action = PolicyAction::Ignore;
1997         return createNewWebProcess(page.websiteDataStore());
1998     }
1999
2000     auto targetURL = navigation.currentRequest().url();
2001     auto url = URL { ParsedURLString, page.pageLoadState().url() };
2002     if (!url.isValid() || url.isEmpty() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL))
2003         return page.process();
2004
2005     action = PolicyAction::Suspend;
2006     return createNewWebProcess(page.websiteDataStore());
2007 }
2008
2009 } // namespace WebKit