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