Unreviewed, rolling out r240446.
[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 "APINavigation.h"
37 #include "APIPageConfiguration.h"
38 #include "APIProcessPoolConfiguration.h"
39 #include "ChildProcessMessages.h"
40 #include "DownloadProxy.h"
41 #include "DownloadProxyMessages.h"
42 #include "GamepadData.h"
43 #include "HighPerformanceGraphicsUsageSampler.h"
44 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
45 #include "LegacyCustomProtocolManagerMessages.h"
46 #endif
47 #include "LogInitialization.h"
48 #include "Logging.h"
49 #include "NetworkProcessCreationParameters.h"
50 #include "NetworkProcessMessages.h"
51 #include "NetworkProcessProxy.h"
52 #include "PerActivityStateCPUUsageSampler.h"
53 #include "PluginProcessManager.h"
54 #include "SandboxExtension.h"
55 #include "ServiceWorkerProcessProxy.h"
56 #include "StatisticsData.h"
57 #include "TextChecker.h"
58 #include "UIGamepad.h"
59 #include "UIGamepadProvider.h"
60 #include "WKContextPrivate.h"
61 #include "WebAutomationSession.h"
62 #include "WebBackForwardList.h"
63 #include "WebBackForwardListItem.h"
64 #include "WebCertificateInfo.h"
65 #include "WebContextSupplement.h"
66 #include "WebCookieManagerProxy.h"
67 #include "WebCoreArgumentCoders.h"
68 #include "WebGeolocationManagerProxy.h"
69 #include "WebKit2Initialize.h"
70 #include "WebMemorySampler.h"
71 #include "WebNotificationManagerProxy.h"
72 #include "WebPageGroup.h"
73 #include "WebPreferences.h"
74 #include "WebPreferencesKeys.h"
75 #include "WebProcessCreationParameters.h"
76 #include "WebProcessMessages.h"
77 #include "WebProcessPoolMessages.h"
78 #include "WebProcessProxy.h"
79 #include "WebsiteDataStore.h"
80 #include "WebsiteDataStoreParameters.h"
81 #include <JavaScriptCore/JSCInlines.h>
82 #include <WebCore/ApplicationCacheStorage.h>
83 #include <WebCore/LogInitialization.h>
84 #include <WebCore/MockRealtimeMediaSourceCenter.h>
85 #include <WebCore/NetworkStorageSession.h>
86 #include <WebCore/PlatformScreen.h>
87 #include <WebCore/Process.h>
88 #include <WebCore/ProcessWarming.h>
89 #include <WebCore/ResourceRequest.h>
90 #include <WebCore/RuntimeApplicationChecks.h>
91 #include <pal/SessionID.h>
92 #include <wtf/Language.h>
93 #include <wtf/MainThread.h>
94 #include <wtf/NeverDestroyed.h>
95 #include <wtf/ProcessPrivilege.h>
96 #include <wtf/RunLoop.h>
97 #include <wtf/Scope.h>
98 #include <wtf/URLParser.h>
99 #include <wtf/WallTime.h>
100 #include <wtf/text/StringBuilder.h>
101
102 #if ENABLE(SERVICE_CONTROLS)
103 #include "ServicesController.h"
104 #endif
105
106 #if ENABLE(REMOTE_INSPECTOR)
107 #include <JavaScriptCore/RemoteInspector.h>
108 #endif
109
110 #if OS(LINUX)
111 #include "MemoryPressureMonitor.h"
112 #endif
113
114 #if PLATFORM(WAYLAND)
115 #include "WaylandCompositor.h"
116 #include <WebCore/PlatformDisplay.h>
117 #endif
118
119 #if PLATFORM(COCOA)
120 #include "VersionChecks.h"
121 #endif
122
123 #ifndef NDEBUG
124 #include <wtf/RefCountedLeakCounter.h>
125 #endif
126
127 namespace WebKit {
128 using namespace WebCore;
129
130 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, processPoolCounter, ("WebProcessPool"));
131
132 const Seconds serviceWorkerTerminationDelay { 5_s };
133
134 static uint64_t generateListenerIdentifier()
135 {
136     static uint64_t nextIdentifier = 1;
137     return nextIdentifier++;
138 }
139
140 static HashMap<uint64_t, Function<void(WebProcessPool&)>>& processPoolCreationListenerFunctionMap()
141 {
142     static NeverDestroyed<HashMap<uint64_t, Function<void(WebProcessPool&)>>> map;
143     return map;
144 }
145
146 uint64_t WebProcessPool::registerProcessPoolCreationListener(Function<void(WebProcessPool&)>&& function)
147 {
148     ASSERT(function);
149
150     auto identifier = generateListenerIdentifier();
151     processPoolCreationListenerFunctionMap().set(identifier, WTFMove(function));
152     return identifier;
153 }
154
155 void WebProcessPool::unregisterProcessPoolCreationListener(uint64_t identifier)
156 {
157     processPoolCreationListenerFunctionMap().remove(identifier);
158 }
159
160 Ref<WebProcessPool> WebProcessPool::create(API::ProcessPoolConfiguration& configuration)
161 {
162     InitializeWebKit2();
163     return adoptRef(*new WebProcessPool(configuration));
164 }
165
166 void WebProcessPool::notifyThisWebProcessPoolWasCreated()
167 {
168     auto& listenerMap = processPoolCreationListenerFunctionMap();
169
170     Vector<uint64_t> identifiers;
171     identifiers.reserveInitialCapacity(listenerMap.size());
172     for (auto identifier : listenerMap.keys())
173         identifiers.uncheckedAppend(identifier);
174
175     for (auto identifier : identifiers) {
176         auto iterator = listenerMap.find(identifier);
177         if (iterator == listenerMap.end())
178             continue;
179
180         // To make sure the Function object stays alive until after the function call has been made,
181         // we temporarily move it out of the map.
182         // This protects it from the Function calling unregisterProcessPoolCreationListener thereby
183         // removing itself from the map of listeners.
184         // If the identifier still exists in the map later, we move it back in.
185         Function<void(WebProcessPool&)> function = WTFMove(iterator->value);
186         function(*this);
187
188         iterator = listenerMap.find(identifier);
189         if (iterator != listenerMap.end()) {
190             ASSERT(!iterator->value);
191             iterator->value = WTFMove(function);
192         }
193     }
194 }
195
196 static Vector<WebProcessPool*>& processPools()
197 {
198     static NeverDestroyed<Vector<WebProcessPool*>> processPools;
199     return processPools;
200 }
201
202 const Vector<WebProcessPool*>& WebProcessPool::allProcessPools()
203 {
204     return processPools();
205 }
206
207 static Ref<WebsiteDataStoreConfiguration> legacyWebsiteDataStoreConfiguration(API::ProcessPoolConfiguration& processPoolConfiguration)
208 {
209     auto configuration = WebsiteDataStoreConfiguration::create();
210
211     configuration->setCacheStorageDirectory(String(API::WebsiteDataStore::defaultCacheStorageDirectory()));
212     configuration->setServiceWorkerRegistrationDirectory(String(API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory()));
213     configuration->setLocalStorageDirectory(String(processPoolConfiguration.localStorageDirectory()));
214     configuration->setWebSQLDatabaseDirectory(String(processPoolConfiguration.webSQLDatabaseDirectory()));
215     configuration->setApplicationCacheDirectory(String(processPoolConfiguration.applicationCacheDirectory()));
216     configuration->setApplicationCacheFlatFileSubdirectoryName(String(processPoolConfiguration.applicationCacheFlatFileSubdirectoryName()));
217     configuration->setMediaCacheDirectory(String(processPoolConfiguration.mediaCacheDirectory()));
218     configuration->setMediaKeysStorageDirectory(String(processPoolConfiguration.mediaKeysStorageDirectory()));
219     configuration->setResourceLoadStatisticsDirectory(String(processPoolConfiguration.resourceLoadStatisticsDirectory()));
220     configuration->setNetworkCacheDirectory(String(processPoolConfiguration.diskCacheDirectory()));
221     configuration->setJavaScriptConfigurationDirectory(String(processPoolConfiguration.javaScriptConfigurationDirectory()));
222
223     return configuration;
224 }
225
226 static HashSet<String, ASCIICaseInsensitiveHash>& globalURLSchemesWithCustomProtocolHandlers()
227 {
228     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> set;
229     return set;
230 }
231
232 WebProcessPool::WebProcessPool(API::ProcessPoolConfiguration& configuration)
233     : m_configuration(configuration.copy())
234     , m_defaultPageGroup(WebPageGroup::create())
235     , m_injectedBundleClient(std::make_unique<API::InjectedBundleClient>())
236     , m_automationClient(std::make_unique<API::AutomationClient>())
237     , m_downloadClient(std::make_unique<API::DownloadClient>())
238     , m_historyClient(std::make_unique<API::LegacyContextHistoryClient>())
239     , m_customProtocolManagerClient(std::make_unique<API::CustomProtocolManagerClient>())
240     , m_visitedLinkStore(VisitedLinkStore::create())
241 #if PLATFORM(MAC)
242     , m_highPerformanceGraphicsUsageSampler(std::make_unique<HighPerformanceGraphicsUsageSampler>(*this))
243     , m_perActivityStateCPUUsageSampler(std::make_unique<PerActivityStateCPUUsageSampler>(*this))
244 #endif
245     , m_alwaysRunsAtBackgroundPriority(m_configuration->alwaysRunsAtBackgroundPriority())
246     , m_shouldTakeUIBackgroundAssertion(m_configuration->shouldTakeUIBackgroundAssertion())
247     , m_userObservablePageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
248     , m_processSuppressionDisabledForPageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
249     , m_hiddenPageThrottlingAutoIncreasesCounter([this](RefCounterEvent) { m_hiddenPageThrottlingTimer.startOneShot(0_s); })
250     , m_hiddenPageThrottlingTimer(RunLoop::main(), this, &WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit)
251     , m_serviceWorkerProcessesTerminationTimer(RunLoop::main(), this, &WebProcessPool::terminateServiceWorkerProcesses)
252 #if PLATFORM(IOS_FAMILY)
253     , m_foregroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
254     , m_backgroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
255 #endif
256 {
257     static std::once_flag onceFlag;
258     std::call_once(onceFlag, [] {
259         WTF::setProcessPrivileges(allPrivileges());
260         WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
261         Process::setIdentifier(generateObjectIdentifier<WebCore::ProcessIdentifierType>());
262     });
263
264     if (m_configuration->shouldHaveLegacyDataStore())
265         m_websiteDataStore = API::WebsiteDataStore::createLegacy(legacyWebsiteDataStoreConfiguration(m_configuration));
266
267     if (!m_websiteDataStore && API::WebsiteDataStore::defaultDataStoreExists())
268         m_websiteDataStore = API::WebsiteDataStore::defaultDataStore();
269
270     for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
271         m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
272
273     for (const auto& urlScheme : m_configuration->cachePartitionedURLSchemes())
274         m_schemesToRegisterAsCachePartitioned.add(urlScheme);
275
276     platformInitialize();
277
278 #if OS(LINUX)
279     MemoryPressureMonitor::singleton().start();
280 #endif
281
282     addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
283
284     // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
285     addSupplement<WebCookieManagerProxy>();
286     addSupplement<WebGeolocationManagerProxy>();
287     addSupplement<WebNotificationManagerProxy>();
288 #if ENABLE(MEDIA_SESSION)
289     addSupplement<WebMediaSessionFocusManager>();
290 #endif
291
292     processPools().append(this);
293
294     addLanguageChangeObserver(this, languageChanged);
295
296     resolvePathsForSandboxExtensions();
297
298 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
299     WebCore::initializeLogChannelsIfNecessary();
300     WebKit::initializeLogChannelsIfNecessary();
301 #endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
302
303 #ifndef NDEBUG
304     processPoolCounter.increment();
305 #endif
306
307     notifyThisWebProcessPoolWasCreated();
308
309     updateMaxSuspendedPageCount();
310 }
311
312 WebProcessPool::~WebProcessPool()
313 {
314     bool removed = processPools().removeFirst(this);
315     ASSERT_UNUSED(removed, removed);
316
317     removeLanguageChangeObserver(this);
318
319     m_messageReceiverMap.invalidate();
320
321     for (auto& supplement : m_supplements.values()) {
322         supplement->processPoolDestroyed();
323         supplement->clearProcessPool();
324     }
325
326     invalidateCallbackMap(m_dictionaryCallbacks, CallbackBase::Error::OwnerWasInvalidated);
327
328     platformInvalidateContext();
329
330 #ifndef NDEBUG
331     processPoolCounter.decrement();
332 #endif
333
334     if (m_networkProcess)
335         m_networkProcess->shutDownProcess();
336
337 #if ENABLE(GAMEPAD)
338     if (!m_processesUsingGamepads.isEmpty())
339         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
340 #endif
341
342     // Only remaining processes should be pre-warmed ones as other keep the process pool alive.
343     while (!m_processes.isEmpty()) {
344         auto& process = m_processes.first();
345
346         ASSERT(process->isPrewarmed());
347         // We need to be the only one holding a reference to the pre-warmed process so that it gets destroyed.
348         // WebProcessProxies currently always expect to have a WebProcessPool.
349         ASSERT(process->hasOneRef());
350
351         process->shutDown();
352     }
353 }
354
355 void WebProcessPool::initializeClient(const WKContextClientBase* client)
356 {
357     m_client.initialize(client);
358 }
359
360 void WebProcessPool::setInjectedBundleClient(std::unique_ptr<API::InjectedBundleClient>&& client)
361 {
362     if (!client)
363         m_injectedBundleClient = std::make_unique<API::InjectedBundleClient>();
364     else
365         m_injectedBundleClient = WTFMove(client);
366 }
367
368 void WebProcessPool::initializeConnectionClient(const WKContextConnectionClientBase* client)
369 {
370     m_connectionClient.initialize(client);
371 }
372
373 void WebProcessPool::setHistoryClient(std::unique_ptr<API::LegacyContextHistoryClient>&& historyClient)
374 {
375     if (!historyClient)
376         m_historyClient = std::make_unique<API::LegacyContextHistoryClient>();
377     else
378         m_historyClient = WTFMove(historyClient);
379 }
380
381 void WebProcessPool::setDownloadClient(std::unique_ptr<API::DownloadClient>&& downloadClient)
382 {
383     if (!downloadClient)
384         m_downloadClient = std::make_unique<API::DownloadClient>();
385     else
386         m_downloadClient = WTFMove(downloadClient);
387 }
388
389 void WebProcessPool::setAutomationClient(std::unique_ptr<API::AutomationClient>&& automationClient)
390 {
391     if (!automationClient)
392         m_automationClient = std::make_unique<API::AutomationClient>();
393     else
394         m_automationClient = WTFMove(automationClient);
395 }
396
397 void WebProcessPool::setLegacyCustomProtocolManagerClient(std::unique_ptr<API::CustomProtocolManagerClient>&& customProtocolManagerClient)
398 {
399 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
400     if (!customProtocolManagerClient)
401         m_customProtocolManagerClient = std::make_unique<API::CustomProtocolManagerClient>();
402     else
403         m_customProtocolManagerClient = WTFMove(customProtocolManagerClient);
404 #endif
405 }
406
407 void WebProcessPool::setCustomWebContentServiceBundleIdentifier(const String& customWebContentServiceBundleIdentifier)
408 {
409     // Guard against API misuse.
410     if (!customWebContentServiceBundleIdentifier.isAllASCII())
411         CRASH();
412
413     m_configuration->setCustomWebContentServiceBundleIdentifier(customWebContentServiceBundleIdentifier);
414 }
415
416 IPC::Connection* WebProcessPool::networkingProcessConnection()
417 {
418     return m_networkProcess->connection();
419 }
420
421 void WebProcessPool::languageChanged(void* context)
422 {
423     static_cast<WebProcessPool*>(context)->languageChanged();
424 }
425
426 void WebProcessPool::languageChanged()
427 {
428     sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
429 #if USE(SOUP)
430     if (m_networkProcess)
431         m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
432 #endif
433 }
434
435 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
436 {
437     sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
438 }
439
440 #if OS(LINUX)
441 void WebProcessPool::sendMemoryPressureEvent(bool isCritical)
442 {
443     sendToAllProcesses(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical));
444     sendToNetworkingProcess(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical));
445 #if ENABLE(NETSCAPE_PLUGIN_API)
446     PluginProcessManager::singleton().sendMemoryPressureEvent(isCritical);
447 #endif
448 }
449 #endif
450
451 void WebProcessPool::textCheckerStateChanged()
452 {
453     sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
454 }
455
456 void WebProcessPool::screenPropertiesStateChanged()
457 {
458 #if PLATFORM(MAC)
459     auto screenProperties = WebCore::collectScreenProperties();
460     sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
461 #endif
462 }
463
464 NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* withWebsiteDataStore)
465 {
466     if (m_networkProcess) {
467         if (withWebsiteDataStore) {
468             m_networkProcess->addSession(makeRef(*withWebsiteDataStore));
469             withWebsiteDataStore->clearPendingCookies();
470         }
471         return *m_networkProcess;
472     }
473
474     m_networkProcess = std::make_unique<NetworkProcessProxy>(*this);
475
476     NetworkProcessCreationParameters parameters;
477
478     if (m_websiteDataStore) {
479         parameters.defaultDataStoreParameters.pendingCookies = copyToVector(m_websiteDataStore->websiteDataStore().pendingCookies());
480         m_websiteDataStore->websiteDataStore().clearPendingCookies();
481     }
482
483     parameters.cacheModel = cacheModel();
484     parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
485
486     for (auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
487         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
488
489     for (auto& scheme : m_urlSchemesRegisteredForCustomProtocols)
490         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
491
492     parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
493     if (!parameters.diskCacheDirectory.isEmpty())
494         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
495 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
496     parameters.shouldEnableNetworkCacheSpeculativeRevalidation = m_configuration->diskCacheSpeculativeValidationEnabled();
497 #endif
498
499 #if PLATFORM(IOS_FAMILY)
500     String cookieStorageDirectory = this->cookieStorageDirectory();
501     if (!cookieStorageDirectory.isEmpty())
502         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
503
504     String containerCachesDirectory = this->networkingCachesDirectory();
505     if (!containerCachesDirectory.isEmpty())
506         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
507
508     String parentBundleDirectory = this->parentBundleDirectory();
509     if (!parentBundleDirectory.isEmpty())
510         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::Type::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
511
512 #if ENABLE(INDEXED_DATABASE)
513     SandboxExtension::createHandleForTemporaryFile(emptyString(), SandboxExtension::Type::ReadWrite, parameters.defaultDataStoreParameters.indexedDatabaseTempBlobDirectoryExtensionHandle);
514 #endif
515 #endif
516
517     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
518
519     parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
520     parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
521     parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
522     parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
523     parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
524     parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
525     parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
526
527 #if ENABLE(INDEXED_DATABASE)
528     // *********
529     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
530     // *********
531     parameters.defaultDataStoreParameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
532     if (parameters.defaultDataStoreParameters.indexedDatabaseDirectory.isEmpty())
533         parameters.defaultDataStoreParameters.indexedDatabaseDirectory = API::WebsiteDataStore::defaultDataStore()->websiteDataStore().parameters().indexedDatabaseDirectory;
534     
535     SandboxExtension::createHandleForReadWriteDirectory(parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle);
536 #endif
537
538 #if ENABLE(SERVICE_WORKER)
539     if (m_websiteDataStore)
540         parameters.serviceWorkerRegistrationDirectory = m_websiteDataStore->websiteDataStore().resolvedServiceWorkerRegistrationDirectory();
541     if (!parameters.serviceWorkerRegistrationDirectory)
542         parameters.serviceWorkerRegistrationDirectory =  API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory();
543     SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
544
545     if (!m_schemesServiceWorkersCanHandle.isEmpty())
546         parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
547
548     parameters.shouldDisableServiceWorkerProcessTerminationDelay = m_shouldDisableServiceWorkerProcessTerminationDelay;
549 #endif
550
551     if (m_websiteDataStore)
552         parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = m_websiteDataStore->websiteDataStore().resolvedResourceLoadStatisticsDirectory();
553     if (parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory.isEmpty())
554         parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = API::WebsiteDataStore::defaultResourceLoadStatisticsDirectory();
555
556     SandboxExtension::createHandleForReadWriteDirectory(parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory, parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectoryExtensionHandle);
557
558     parameters.defaultDataStoreParameters.networkSessionParameters.enableResourceLoadStatistics = false; // FIXME(193297): Turn on when the feature is on. (m_configuration->resourceLoadStatisticsEnabled()?)
559
560     // Add any platform specific parameters
561     platformInitializeNetworkProcess(parameters);
562
563     // Initialize the network process.
564     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
565
566     if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
567         m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()), 0);
568
569 #if PLATFORM(COCOA)
570     m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
571 #endif
572
573     if (m_didNetworkProcessCrash) {
574         m_didNetworkProcessCrash = false;
575         reinstateNetworkProcessAssertionState(*m_networkProcess);
576     }
577
578     if (withWebsiteDataStore) {
579         m_networkProcess->addSession(makeRef(*withWebsiteDataStore));
580         withWebsiteDataStore->clearPendingCookies();
581     }
582
583     // Make sure the network process knows about all the sessions that have been registered before it started.
584     for (auto& sessionID : m_sessionToPagesMap.keys()) {
585         if (auto* websiteDataStore = WebsiteDataStore::existingNonDefaultDataStoreForSessionID(sessionID))
586             m_networkProcess->addSession(*websiteDataStore);
587     }
588
589     return *m_networkProcess;
590 }
591
592 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy& networkProcessProxy, Vector<std::pair<RefPtr<WebProcessProxy>, Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>>&& pendingReplies)
593 {
594     ASSERT(m_networkProcess);
595     ASSERT(&networkProcessProxy == m_networkProcess.get());
596     m_didNetworkProcessCrash = true;
597
598     for (auto& supplement : m_supplements.values())
599         supplement->processDidClose(&networkProcessProxy);
600
601     m_client.networkProcessDidCrash(this);
602
603     if (m_automationSession)
604         m_automationSession->terminate();
605
606     // Leave the process proxy around during client call, so that the client could query the process identifier.
607     m_networkProcess = nullptr;
608
609     // Attempt to re-launch.
610     if (pendingReplies.isEmpty())
611         return;
612     auto& newNetworkProcess = ensureNetworkProcess();
613     for (auto& reply : pendingReplies)
614         newNetworkProcess.getNetworkProcessConnection(*reply.first, WTFMove(reply.second));
615 }
616
617 void WebProcessPool::getNetworkProcessConnection(WebProcessProxy& webProcessProxy, Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&& reply)
618 {
619     ensureNetworkProcess();
620     ASSERT(m_networkProcess);
621
622     m_networkProcess->getNetworkProcessConnection(webProcessProxy, WTFMove(reply));
623 }
624
625 #if ENABLE(SERVICE_WORKER)
626 void WebProcessPool::establishWorkerContextConnectionToNetworkProcess(NetworkProcessProxy& proxy, SecurityOriginData&& securityOrigin, Optional<PAL::SessionID> sessionID)
627 {
628     ASSERT_UNUSED(proxy, &proxy == m_networkProcess.get());
629
630     if (m_serviceWorkerProcesses.contains(securityOrigin))
631         return;
632
633     m_mayHaveRegisteredServiceWorkers.clear();
634
635     WebsiteDataStore* websiteDataStore = nullptr;
636     if (sessionID)
637         websiteDataStore = WebsiteDataStore::existingNonDefaultDataStoreForSessionID(*sessionID);
638
639     if (!websiteDataStore) {
640         if (!m_websiteDataStore)
641             m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
642         websiteDataStore = &m_websiteDataStore->websiteDataStore();
643     }
644
645     if (m_serviceWorkerProcesses.isEmpty())
646         sendToAllProcesses(Messages::WebProcess::RegisterServiceWorkerClients { });
647
648     auto serviceWorkerProcessProxy = ServiceWorkerProcessProxy::create(*this, securityOrigin, *websiteDataStore);
649     m_serviceWorkerProcesses.add(WTFMove(securityOrigin), serviceWorkerProcessProxy.ptr());
650
651     updateProcessAssertions();
652     initializeNewWebProcess(serviceWorkerProcessProxy, *websiteDataStore);
653
654     auto* serviceWorkerProcessProxyPtr = serviceWorkerProcessProxy.ptr();
655     m_processes.append(WTFMove(serviceWorkerProcessProxy));
656
657     serviceWorkerProcessProxyPtr->start(m_serviceWorkerPreferences ? m_serviceWorkerPreferences.value() : m_defaultPageGroup->preferences().store(), sessionID);
658     if (!m_serviceWorkerUserAgent.isNull())
659         serviceWorkerProcessProxyPtr->setUserAgent(m_serviceWorkerUserAgent);
660 }
661 #endif
662
663 void WebProcessPool::disableServiceWorkerProcessTerminationDelay()
664 {
665 #if ENABLE(SERVICE_WORKER)
666     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
667         return;
668
669     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
670     if (m_networkProcess)
671         m_networkProcess->send(Messages::NetworkProcess::DisableServiceWorkerProcessTerminationDelay(), 0);
672 #endif
673 }
674
675 void WebProcessPool::willStartUsingPrivateBrowsing()
676 {
677     for (auto* processPool : allProcessPools())
678         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
679 }
680
681 void WebProcessPool::willStopUsingPrivateBrowsing()
682 {
683     for (auto* processPool : allProcessPools())
684         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
685 }
686
687 void WebProcessPool::windowServerConnectionStateChanged()
688 {
689     size_t processCount = m_processes.size();
690     for (size_t i = 0; i < processCount; ++i)
691         m_processes[i]->windowServerConnectionStateChanged();
692 }
693
694 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
695 {
696     if (privateBrowsingEnabled) {
697         sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()));
698     } else {
699         networkProcess()->removeSession(PAL::SessionID::legacyPrivateSessionID());
700     }
701 }
702
703 void (*s_invalidMessageCallback)(WKStringRef messageName);
704
705 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
706 {
707     s_invalidMessageCallback = invalidMessageCallback;
708 }
709
710 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
711 {
712     if (!s_invalidMessageCallback)
713         return;
714
715     StringBuilder messageNameStringBuilder;
716     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
717     messageNameStringBuilder.append('.');
718     messageNameStringBuilder.append(messageName.data(), messageName.size());
719
720     s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
721 }
722
723 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
724 {
725     if (m_processWithPageCache && m_processWithPageCache != process)
726         m_processWithPageCache->releasePageCache();
727     m_processWithPageCache = process;
728 }
729
730 void WebProcessPool::resolvePathsForSandboxExtensions()
731 {
732     m_resolvedPaths.injectedBundlePath = resolvePathForSandboxExtension(injectedBundlePath());
733     m_resolvedPaths.applicationCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory());
734     m_resolvedPaths.webSQLDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory());
735     m_resolvedPaths.mediaCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory());
736     m_resolvedPaths.mediaKeyStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory());
737     m_resolvedPaths.indexedDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory());
738
739     m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.reserveCapacity(m_configuration->additionalReadAccessAllowedPaths().size());
740     for (const auto& path : m_configuration->additionalReadAccessAllowedPaths())
741         m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.uncheckedAppend(resolvePathForSandboxExtension(path.data()));
742
743     platformResolvePathsForSandboxExtensions();
744 }
745
746 WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDataStore, WebProcessProxy::IsPrewarmed isPrewarmed)
747 {
748     auto processProxy = WebProcessProxy::create(*this, websiteDataStore, isPrewarmed);
749     auto& process = processProxy.get();
750     initializeNewWebProcess(process, websiteDataStore);
751     m_processes.append(WTFMove(processProxy));
752     if (isPrewarmed == WebProcessProxy::IsPrewarmed::Yes) {
753         ASSERT(!m_prewarmedProcess);
754         m_prewarmedProcess = &process;
755         
756         m_prewarmedProcess->send(Messages::WebProcess::PrewarmGlobally(), 0);
757     }
758
759     if (m_serviceWorkerProcessesTerminationTimer.isActive())
760         m_serviceWorkerProcessesTerminationTimer.stop();
761
762     return process;
763 }
764
765 RefPtr<WebProcessProxy> WebProcessPool::tryTakePrewarmedProcess(WebsiteDataStore& websiteDataStore)
766 {
767     if (!m_prewarmedProcess)
768         return nullptr;
769
770     ASSERT(m_prewarmedProcess->isPrewarmed());
771     m_prewarmedProcess->markIsNoLongerInPrewarmedPool();
772
773     return std::exchange(m_prewarmedProcess, nullptr);
774 }
775
776 #if PLATFORM(MAC)
777 static void displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
778 {
779     auto screenProperties = WebCore::collectScreenProperties();
780     for (auto& processPool : WebProcessPool::allProcessPools()) {
781         processPool->sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
782 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
783         processPool->sendToAllProcesses(Messages::WebProcess::DisplayConfigurationChanged(display, flags));
784 #endif
785     }
786 }
787
788 static void registerDisplayConfigurationCallback()
789 {
790     static std::once_flag onceFlag;
791     std::call_once(
792         onceFlag,
793         [] {
794             CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, nullptr);
795         });
796 }
797 #endif
798
799 void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDataStore& websiteDataStore)
800 {
801     auto initializationActivityToken = process.throttler().backgroundActivityToken();
802     auto scopeExit = makeScopeExit([&process, initializationActivityToken] {
803         // Round-trip to the Web Content process before releasing the
804         // initialization activity token, so that we're sure that all
805         // messages sent from this function have been handled.
806         process.isResponsive([initializationActivityToken] (bool) { });
807     });
808
809     ensureNetworkProcess();
810
811     WebProcessCreationParameters parameters;
812
813     websiteDataStore.resolveDirectoriesIfNecessary();
814
815     parameters.injectedBundlePath = m_resolvedPaths.injectedBundlePath;
816     if (!parameters.injectedBundlePath.isEmpty())
817         SandboxExtension::createHandleWithoutResolvingPath(parameters.injectedBundlePath, SandboxExtension::Type::ReadOnly, parameters.injectedBundlePathExtensionHandle);
818
819     parameters.additionalSandboxExtensionHandles.allocate(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size());
820     for (size_t i = 0, size = m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size(); i < size; ++i)
821         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths[i], SandboxExtension::Type::ReadOnly, parameters.additionalSandboxExtensionHandles[i]);
822
823     parameters.applicationCacheDirectory = websiteDataStore.resolvedApplicationCacheDirectory();
824     if (parameters.applicationCacheDirectory.isEmpty())
825         parameters.applicationCacheDirectory = m_resolvedPaths.applicationCacheDirectory;
826     if (!parameters.applicationCacheDirectory.isEmpty())
827         SandboxExtension::createHandleWithoutResolvingPath(parameters.applicationCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.applicationCacheDirectoryExtensionHandle);
828
829     parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName();
830
831     parameters.webSQLDatabaseDirectory = websiteDataStore.resolvedDatabaseDirectory();
832     if (parameters.webSQLDatabaseDirectory.isEmpty())
833         parameters.webSQLDatabaseDirectory = m_resolvedPaths.webSQLDatabaseDirectory;
834     if (!parameters.webSQLDatabaseDirectory.isEmpty())
835         SandboxExtension::createHandleWithoutResolvingPath(parameters.webSQLDatabaseDirectory, SandboxExtension::Type::ReadWrite, parameters.webSQLDatabaseDirectoryExtensionHandle);
836
837     parameters.mediaCacheDirectory = websiteDataStore.resolvedMediaCacheDirectory();
838     if (parameters.mediaCacheDirectory.isEmpty())
839         parameters.mediaCacheDirectory = m_resolvedPaths.mediaCacheDirectory;
840     if (!parameters.mediaCacheDirectory.isEmpty())
841         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaCacheDirectoryExtensionHandle);
842
843     parameters.mediaKeyStorageDirectory = websiteDataStore.resolvedMediaKeysDirectory();
844     if (parameters.mediaKeyStorageDirectory.isEmpty())
845         parameters.mediaKeyStorageDirectory = m_resolvedPaths.mediaKeyStorageDirectory;
846     if (!parameters.mediaKeyStorageDirectory.isEmpty())
847         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaKeyStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaKeyStorageDirectoryExtensionHandle);
848
849 #if PLATFORM(IOS_FAMILY)
850     setJavaScriptConfigurationFileEnabledFromDefaults();
851 #endif
852
853     if (javaScriptConfigurationFileEnabled()) {
854         parameters.javaScriptConfigurationDirectory = websiteDataStore.resolvedJavaScriptConfigurationDirectory();
855         if (!parameters.javaScriptConfigurationDirectory.isEmpty())
856             SandboxExtension::createHandleWithoutResolvingPath(parameters.javaScriptConfigurationDirectory, SandboxExtension::Type::ReadWrite, parameters.javaScriptConfigurationDirectoryExtensionHandle);
857     }
858
859     parameters.cacheModel = cacheModel();
860     parameters.languages = userPreferredLanguages();
861
862     parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
863     parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
864     parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
865     parameters.urlSchemesForWhichDomainRelaxationIsForbidden = copyToVector(m_schemesToSetDomainRelaxationForbiddenFor);
866     parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
867     parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
868     parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
869     parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
870     parameters.urlSchemesRegisteredAsAlwaysRevalidated = copyToVector(m_schemesToRegisterAsAlwaysRevalidated);
871     parameters.urlSchemesRegisteredAsCachePartitioned = copyToVector(m_schemesToRegisterAsCachePartitioned);
872     parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
873     parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
874
875     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
876     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
877
878     parameters.terminationTimeout = 0_s;
879
880     parameters.textCheckerState = TextChecker::state();
881
882     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
883
884     parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
885
886 #if ENABLE(NOTIFICATIONS)
887     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
888     parameters.notificationPermissions = supplement<WebNotificationManagerProxy>()->notificationPermissions();
889 #endif
890
891     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
892     parameters.plugInAutoStartOrigins = copyToVector(m_plugInAutoStartProvider.autoStartOrigins());
893
894     parameters.memoryCacheDisabled = m_memoryCacheDisabled;
895     parameters.attrStyleEnabled = m_configuration->attrStyleEnabled();
896
897 #if ENABLE(SERVICE_CONTROLS)
898     auto& serviceController = ServicesController::singleton();
899     parameters.hasImageServices = serviceController.hasImageServices();
900     parameters.hasSelectionServices = serviceController.hasSelectionServices();
901     parameters.hasRichContentServices = serviceController.hasRichContentServices();
902     serviceController.refreshExistingServices();
903 #endif
904
905 #if ENABLE(NETSCAPE_PLUGIN_API)
906     parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
907 #endif
908
909 #if OS(LINUX)
910     parameters.shouldEnableMemoryPressureReliefLogging = true;
911 #endif
912
913 #if PLATFORM(WAYLAND) && USE(EGL)
914     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
915         parameters.waylandCompositorDisplayName = WaylandCompositor::singleton().displayName();
916 #endif
917
918     parameters.resourceLoadStatisticsEnabled = websiteDataStore.resourceLoadStatisticsEnabled();
919 #if ENABLE(MEDIA_STREAM)
920     parameters.shouldCaptureAudioInUIProcess = m_configuration->shouldCaptureAudioInUIProcess();
921     parameters.shouldCaptureVideoInUIProcess = m_configuration->shouldCaptureVideoInUIProcess();
922     parameters.shouldCaptureDisplayInUIProcess = m_configuration->shouldCaptureDisplayInUIProcess();
923 #endif
924
925     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
926
927 #if PLATFORM(COCOA)
928     parameters.mediaMIMETypes = process.mediaMIMETypes();
929 #endif
930
931     // Add any platform specific parameters
932     platformInitializeWebProcess(parameters);
933
934     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient->getInjectedBundleInitializationUserData(*this);
935     if (!injectedBundleInitializationUserData)
936         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
937     parameters.initializationUserData = UserData(process.transformObjectsToHandles(injectedBundleInitializationUserData.get()));
938
939     process.send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
940
941 #if PLATFORM(COCOA)
942     process.send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
943 #endif
944
945     if (m_automationSession)
946         process.send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0);
947
948     ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
949
950 #if ENABLE(REMOTE_INSPECTOR)
951     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
952     Inspector::RemoteInspector::singleton(); 
953 #endif
954
955 #if PLATFORM(MAC)
956     registerDisplayConfigurationCallback();
957 #endif
958 }
959
960 void WebProcessPool::prewarmProcess(MayCreateDefaultDataStore mayCreateDefaultDataStore)
961 {
962     if (m_prewarmedProcess)
963         return;
964
965     auto* websiteDataStore = m_websiteDataStore ? &m_websiteDataStore->websiteDataStore() : nullptr;
966     if (!websiteDataStore) {
967         if (!m_processes.isEmpty())
968             websiteDataStore = &m_processes.last()->websiteDataStore();
969         else if (mayCreateDefaultDataStore == MayCreateDefaultDataStore::Yes || API::WebsiteDataStore::defaultDataStoreExists())
970             websiteDataStore = &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
971         else {
972             RELEASE_LOG(PerformanceLogging, "Unable to prewarming a WebProcess because we could not find a usable data store");
973             return;
974         }
975     }
976     ASSERT(websiteDataStore);
977
978     RELEASE_LOG(PerformanceLogging, "Prewarming a WebProcess for performance");
979     createNewWebProcess(*websiteDataStore, WebProcessProxy::IsPrewarmed::Yes);
980 }
981
982 void WebProcessPool::enableProcessTermination()
983 {
984     m_processTerminationEnabled = true;
985     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
986     for (size_t i = 0; i < processes.size(); ++i) {
987         if (shouldTerminate(processes[i].get()))
988             processes[i]->terminate();
989     }
990 }
991
992 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
993 {
994     ASSERT(m_processes.contains(process));
995
996     if (!m_processTerminationEnabled || m_configuration->alwaysKeepAndReuseSwappedProcesses())
997         return false;
998
999     return true;
1000 }
1001
1002 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
1003 {
1004     ASSERT(m_processes.contains(process));
1005
1006     if (!m_visitedLinksPopulated) {
1007         populateVisitedLinks();
1008         m_visitedLinksPopulated = true;
1009     }
1010
1011     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
1012     // so check if it needs to be started here
1013     if (m_memorySamplerEnabled) {
1014         SandboxExtension::Handle sampleLogSandboxHandle;        
1015         WallTime now = WallTime::now();
1016         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()), process->processIdentifier());
1017         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
1018         
1019         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
1020     }
1021
1022     if (m_configuration->fullySynchronousModeIsAllowedForTesting())
1023         process->connection()->allowFullySynchronousModeForTesting();
1024
1025     if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
1026         process->connection()->ignoreTimeoutsForTesting();
1027
1028     m_connectionClient.didCreateConnection(this, process->webConnection());
1029
1030     if (m_websiteDataStore)
1031         m_websiteDataStore->websiteDataStore().didCreateNetworkProcess();
1032 }
1033
1034 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
1035 {
1036     ASSERT(m_processes.contains(process));
1037
1038     if (m_prewarmedProcess == process) {
1039         ASSERT(m_prewarmedProcess->isPrewarmed());
1040         m_prewarmedProcess = nullptr;
1041     }
1042
1043     // 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.
1044     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
1045     RefPtr<WebProcessProxy> protect(process);
1046     if (m_processWithPageCache == process)
1047         m_processWithPageCache = nullptr;
1048
1049     m_suspendedPages.removeAllMatching([process](auto& suspendedPage) {
1050         return &suspendedPage->process() == process;
1051     });
1052
1053 #if ENABLE(SERVICE_WORKER)
1054     if (is<ServiceWorkerProcessProxy>(*process)) {
1055         auto* removedProcess = m_serviceWorkerProcesses.take(downcast<ServiceWorkerProcessProxy>(*process).securityOrigin());
1056         ASSERT_UNUSED(removedProcess, removedProcess == process);
1057         updateProcessAssertions();
1058     }
1059 #endif
1060
1061     static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
1062
1063     m_processes.removeFirst(process);
1064
1065 #if ENABLE(GAMEPAD)
1066     if (m_processesUsingGamepads.contains(process))
1067         processStoppedUsingGamepads(*process);
1068 #endif
1069
1070     removeProcessFromOriginCacheSet(*process);
1071
1072 #if ENABLE(SERVICE_WORKER)
1073     // FIXME: We should do better than this. For now, we just destroy the ServiceWorker process
1074     // whenever there is no regular WebContent process remaining.
1075     if (m_processes.size() == m_serviceWorkerProcesses.size()) {
1076         if (!m_serviceWorkerProcessesTerminationTimer.isActive())
1077             m_serviceWorkerProcessesTerminationTimer.startOneShot(serviceWorkerTerminationDelay);
1078     }
1079 #endif
1080 }
1081
1082 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebsiteDataStore& websiteDataStore)
1083 {
1084     if (!usesSingleWebProcess())
1085         return createNewWebProcess(websiteDataStore);
1086
1087 #if PLATFORM(COCOA)
1088     bool mustMatchDataStore = API::WebsiteDataStore::defaultDataStoreExists() && &websiteDataStore != &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
1089 #else
1090     bool mustMatchDataStore = false;
1091 #endif
1092
1093     for (auto& process : m_processes) {
1094         if (mustMatchDataStore && &process->websiteDataStore() != &websiteDataStore)
1095             continue;
1096 #if ENABLE(SERVICE_WORKER)
1097         if (is<ServiceWorkerProcessProxy>(*process))
1098             continue;
1099 #endif
1100         return *process;
1101     }
1102     return createNewWebProcess(websiteDataStore);
1103 }
1104
1105 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
1106 {
1107     if (!pageConfiguration->pageGroup())
1108         pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
1109     if (!pageConfiguration->preferences())
1110         pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
1111     if (!pageConfiguration->userContentController())
1112         pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
1113     if (!pageConfiguration->visitedLinkStore())
1114         pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
1115
1116     if (!pageConfiguration->websiteDataStore()) {
1117         // We try to avoid creating the default data store as long as possible.
1118         // But if there is an attempt to create a web page without any specified data store, then we have to create it.
1119         if (!m_websiteDataStore)
1120             m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
1121
1122         ASSERT(!pageConfiguration->sessionID().isValid());
1123         pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
1124         pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? PAL::SessionID::legacyPrivateSessionID() : m_websiteDataStore->websiteDataStore().sessionID());
1125     }
1126
1127     RefPtr<WebProcessProxy> process;
1128     if (pageConfiguration->relatedPage()) {
1129         // Sharing processes, e.g. when creating the page via window.open().
1130         process = &pageConfiguration->relatedPage()->process();
1131     } else {
1132         process = tryTakePrewarmedProcess(pageConfiguration->websiteDataStore()->websiteDataStore());
1133         if (!process)
1134             process = &createNewWebProcessRespectingProcessCountLimit(pageConfiguration->websiteDataStore()->websiteDataStore());
1135     }
1136
1137 #if ENABLE(SERVICE_WORKER)
1138     ASSERT(!is<ServiceWorkerProcessProxy>(*process));
1139 #endif
1140
1141     auto page = process->createWebPage(pageClient, WTFMove(pageConfiguration));
1142
1143     bool enableProcessSwapOnCrossSiteNavigation = page->preferences().processSwapOnCrossSiteNavigationEnabled();
1144 #if PLATFORM(IOS_FAMILY)
1145     if (WebCore::IOSApplication::isFirefox() && !linkedOnOrAfter(WebKit::SDKVersion::FirstWithProcessSwapOnCrossSiteNavigation))
1146         enableProcessSwapOnCrossSiteNavigation = false;
1147 #endif
1148
1149     m_configuration->setProcessSwapsOnNavigationFromExperimentalFeatures(enableProcessSwapOnCrossSiteNavigation);
1150     m_configuration->setShouldCaptureAudioInUIProcess(page->preferences().captureAudioInUIProcessEnabled());
1151     m_configuration->setShouldCaptureVideoInUIProcess(page->preferences().captureVideoInUIProcessEnabled());
1152
1153     return page;
1154 }
1155
1156 #if ENABLE(SERVICE_WORKER)
1157 void WebProcessPool::updateServiceWorkerUserAgent(const String& userAgent)
1158 {
1159     if (m_serviceWorkerUserAgent == userAgent)
1160         return;
1161     m_serviceWorkerUserAgent = userAgent;
1162     for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1163         serviceWorkerProcess->setUserAgent(m_serviceWorkerUserAgent);
1164 }
1165
1166 bool WebProcessPool::mayHaveRegisteredServiceWorkers(const WebsiteDataStore& store)
1167 {
1168     if (!m_serviceWorkerProcesses.isEmpty())
1169         return true;
1170
1171     String serviceWorkerRegistrationDirectory = store.resolvedServiceWorkerRegistrationDirectory();
1172     if (serviceWorkerRegistrationDirectory.isEmpty())
1173         serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultDataStoreConfiguration()->serviceWorkerRegistrationDirectory();
1174
1175     return m_mayHaveRegisteredServiceWorkers.ensure(serviceWorkerRegistrationDirectory, [&] {
1176         // FIXME: Make this computation on a background thread.
1177         return ServiceWorkerProcessProxy::hasRegisteredServiceWorkers(serviceWorkerRegistrationDirectory);
1178     }).iterator->value;
1179 }
1180 #endif
1181
1182 void WebProcessPool::pageBeginUsingWebsiteDataStore(WebPageProxy& page)
1183 {
1184     auto result = m_sessionToPagesMap.add(page.sessionID(), HashSet<WebPageProxy*>()).iterator->value.add(&page);
1185     ASSERT_UNUSED(result, result.isNewEntry);
1186
1187     auto sessionID = page.sessionID();
1188     if (sessionID.isEphemeral()) {
1189         ASSERT(page.websiteDataStore().parameters().networkSessionParameters.sessionID == sessionID);
1190         if (m_networkProcess)
1191             m_networkProcess->addSession(makeRef(page.websiteDataStore()));
1192         page.websiteDataStore().clearPendingCookies();
1193     } else if (sessionID != PAL::SessionID::defaultSessionID()) {
1194         if (m_networkProcess)
1195             m_networkProcess->addSession(makeRef(page.websiteDataStore()));
1196         page.websiteDataStore().clearPendingCookies();
1197     }
1198
1199 #if ENABLE(SERVICE_WORKER)
1200     if (!m_serviceWorkerPreferences) {
1201         m_serviceWorkerPreferences = page.preferencesStore();
1202         for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1203             serviceWorkerProcess->updatePreferencesStore(*m_serviceWorkerPreferences);
1204     }
1205 #endif
1206 }
1207
1208 void WebProcessPool::pageEndUsingWebsiteDataStore(WebPageProxy& page)
1209 {
1210     auto sessionID = page.sessionID();
1211     auto iterator = m_sessionToPagesMap.find(sessionID);
1212     ASSERT(iterator != m_sessionToPagesMap.end());
1213
1214     auto takenPage = iterator->value.take(&page);
1215     ASSERT_UNUSED(takenPage, takenPage == &page);
1216
1217     if (iterator->value.isEmpty()) {
1218         m_sessionToPagesMap.remove(iterator);
1219
1220         if (sessionID == PAL::SessionID::defaultSessionID())
1221             return;
1222
1223         // The last user of this non-default PAL::SessionID is gone, so clean it up in the child processes.
1224         if (networkProcess())
1225             networkProcess()->removeSession(sessionID);
1226     }
1227 }
1228
1229 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
1230 {
1231     auto* downloadProxy = createDownloadProxy(request, initiatingPage);
1232     PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
1233
1234     if (initiatingPage)
1235         initiatingPage->handleDownloadRequest(downloadProxy);
1236
1237     if (networkProcess()) {
1238         ResourceRequest updatedRequest(request);
1239         // Request's firstPartyForCookies will be used as Original URL of the download request.
1240         // We set the value to top level document's URL.
1241         if (initiatingPage) {
1242             URL initiatingPageURL = URL { URL { }, initiatingPage->pageLoadState().url() };
1243             updatedRequest.setFirstPartyForCookies(initiatingPageURL);
1244             updatedRequest.setIsSameSite(registrableDomainsAreEqual(initiatingPageURL, request.url()));
1245             if (!updatedRequest.hasHTTPHeaderField(HTTPHeaderName::UserAgent))
1246                 updatedRequest.setHTTPUserAgent(initiatingPage->userAgent());
1247         } else {
1248             updatedRequest.setFirstPartyForCookies(URL());
1249             updatedRequest.setIsSameSite(false);
1250             if (!updatedRequest.hasHTTPHeaderField(HTTPHeaderName::UserAgent))
1251                 updatedRequest.setHTTPUserAgent(WebPageProxy::standardUserAgent());
1252         }
1253         updatedRequest.setIsTopSite(false);
1254         networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest, suggestedFilename), 0);
1255         return downloadProxy;
1256     }
1257
1258     return downloadProxy;
1259 }
1260
1261 DownloadProxy* WebProcessPool::resumeDownload(WebPageProxy* initiatingPage, const API::Data* resumeData, const String& path)
1262 {
1263     auto* downloadProxy = createDownloadProxy(ResourceRequest(), initiatingPage);
1264     PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
1265
1266     SandboxExtension::Handle sandboxExtensionHandle;
1267     if (!path.isEmpty())
1268         SandboxExtension::createHandle(path, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
1269
1270     if (networkProcess()) {
1271         networkProcess()->send(Messages::NetworkProcess::ResumeDownload(sessionID, downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
1272         return downloadProxy;
1273     }
1274
1275     return downloadProxy;
1276 }
1277
1278 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
1279 {
1280     for (auto& process : m_processes) {
1281         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
1282         process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
1283     }
1284 }
1285
1286 void WebProcessPool::didReachGoodTimeToPrewarm()
1287 {
1288     if (!configuration().isAutomaticProcessWarmingEnabled() || !configuration().processSwapsOnNavigation() || usesSingleWebProcess())
1289         return;
1290
1291     if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
1292         if (!m_prewarmedProcess)
1293             RELEASE_LOG(PerformanceLogging, "Not automatically prewarming a WebProcess due to memory pressure");
1294         return;
1295     }
1296
1297     prewarmProcess(MayCreateDefaultDataStore::No);
1298 }
1299
1300 void WebProcessPool::populateVisitedLinks()
1301 {
1302     m_historyClient->populateVisitedLinks(*this);
1303 }
1304
1305 WebProcessPool::Statistics& WebProcessPool::statistics()
1306 {
1307     static Statistics statistics = Statistics();
1308
1309     return statistics;
1310 }
1311
1312 void WebProcessPool::handleMemoryPressureWarning(Critical)
1313 {
1314     if (m_prewarmedProcess)
1315         m_prewarmedProcess->shutDown();
1316     ASSERT(!m_prewarmedProcess);
1317
1318     m_suspendedPages.clear();
1319 }
1320
1321 #if ENABLE(NETSCAPE_PLUGIN_API)
1322 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
1323 {
1324     Vector<String> directories;
1325     directories.append(directory);
1326
1327     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
1328 }
1329
1330 void WebProcessPool::refreshPlugins()
1331 {
1332     m_pluginInfoStore.refresh();
1333     sendToAllProcesses(Messages::WebProcess::RefreshPlugins());
1334 }
1335
1336 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1337
1338 ProcessID WebProcessPool::networkProcessIdentifier()
1339 {
1340     if (!m_networkProcess)
1341         return 0;
1342
1343     return m_networkProcess->processIdentifier();
1344 }
1345
1346 void WebProcessPool::activePagesOriginsInWebProcessForTesting(ProcessID pid, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
1347 {
1348     for (auto& process : m_processes) {
1349         if (process->processIdentifier() == pid)
1350             return process->activePagesDomainsForTesting(WTFMove(completionHandler));
1351     }
1352     completionHandler({ });
1353 }
1354
1355 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
1356 {
1357     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
1358     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
1359 }
1360
1361 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
1362 {
1363     m_shouldUseFontSmoothing = useFontSmoothing;
1364     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
1365 }
1366
1367 void WebProcessPool::setResourceLoadStatisticsEnabled(bool enabled)
1368 {
1369     sendToAllProcesses(Messages::WebProcess::SetResourceLoadStatisticsEnabled(enabled));
1370 }
1371
1372 void WebProcessPool::clearResourceLoadStatistics()
1373 {
1374     sendToAllProcesses(Messages::WebProcess::ClearResourceLoadStatistics());
1375 }
1376
1377 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
1378 {
1379     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
1380     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
1381 }
1382
1383 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
1384 {
1385     m_schemesToRegisterAsSecure.add(urlScheme);
1386     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
1387     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsSecure(urlScheme));
1388 }
1389
1390 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
1391 {
1392     m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
1393     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1394     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1395 }
1396
1397 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
1398 {
1399     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
1400     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
1401 }
1402
1403 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
1404 {
1405     m_canHandleHTTPSServerTrustEvaluation = value;
1406     if (m_networkProcess) {
1407         m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
1408         return;
1409     }
1410 }
1411
1412 void WebProcessPool::preconnectToServer(const URL& url)
1413 {
1414     if (!url.isValid() || !url.protocolIsInHTTPFamily())
1415         return;
1416
1417     ensureNetworkProcess().send(Messages::NetworkProcess::PreconnectTo(url, StoredCredentialsPolicy::Use), 0);
1418 }
1419
1420 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
1421 {
1422     m_schemesToRegisterAsLocal.add(urlScheme);
1423     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
1424     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsLocal(urlScheme));
1425 }
1426
1427 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
1428 {
1429     m_schemesToRegisterAsNoAccess.add(urlScheme);
1430     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1431     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1432 }
1433
1434 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
1435 {
1436     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
1437     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1438     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1439 }
1440
1441 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
1442 {
1443     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
1444     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1445     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1446 }
1447
1448 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1449 {
1450     if (!urlScheme)
1451         return;
1452
1453     globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
1454     for (auto* processPool : allProcessPools())
1455         processPool->registerSchemeForCustomProtocol(urlScheme);
1456 }
1457
1458 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1459 {
1460     if (!urlScheme)
1461         return;
1462
1463     globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
1464     for (auto* processPool : allProcessPools())
1465         processPool->unregisterSchemeForCustomProtocol(urlScheme);
1466 }
1467
1468 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
1469 {
1470     m_schemesToRegisterAsCachePartitioned.add(urlScheme);
1471     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
1472 }
1473
1474 void WebProcessPool::registerURLSchemeServiceWorkersCanHandle(const String& urlScheme)
1475 {
1476     m_schemesServiceWorkersCanHandle.add(urlScheme);
1477     sendToAllProcesses(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme));
1478     if (m_networkProcess)
1479         m_networkProcess->send(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme), 0);
1480 }
1481
1482 void WebProcessPool::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& urlScheme)
1483 {
1484     m_schemesToRegisterAsCanDisplayOnlyIfCanRequest.add(urlScheme);
1485     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1486     sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1487 }
1488
1489 void WebProcessPool::updateMaxSuspendedPageCount()
1490 {
1491     unsigned dummy = 0;
1492     Seconds dummyInterval;
1493     unsigned pageCacheSize = 0;
1494     calculateMemoryCacheSizes(m_configuration->cacheModel(), dummy, dummy, dummy, dummyInterval, pageCacheSize);
1495
1496     m_maxSuspendedPageCount = pageCacheSize;
1497
1498     while (m_suspendedPages.size() > m_maxSuspendedPageCount)
1499         m_suspendedPages.removeFirst();
1500 }
1501
1502 void WebProcessPool::setCacheModel(CacheModel cacheModel)
1503 {
1504     m_configuration->setCacheModel(cacheModel);
1505     updateMaxSuspendedPageCount();
1506
1507     sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
1508
1509     if (m_networkProcess)
1510         m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
1511 }
1512
1513 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
1514 {
1515     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
1516 }
1517
1518 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
1519 {
1520     auto downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
1521     downloadProxy->setOriginatingPage(originatingPage);
1522     return downloadProxy;
1523 }
1524
1525 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
1526 {
1527     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
1528 }
1529
1530 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
1531 {
1532     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
1533 }
1534
1535 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName)
1536 {
1537     m_messageReceiverMap.removeMessageReceiver(messageReceiverName);
1538 }
1539
1540 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
1541 {
1542     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
1543 }
1544
1545 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
1546 {
1547     return m_messageReceiverMap.dispatchMessage(connection, decoder);
1548 }
1549
1550 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
1551 {
1552     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1553 }
1554
1555 void WebProcessPool::setEnhancedAccessibility(bool flag)
1556 {
1557     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1558 }
1559     
1560 void WebProcessPool::startMemorySampler(const double interval)
1561 {    
1562     // For new WebProcesses we will also want to start the Memory Sampler
1563     m_memorySamplerEnabled = true;
1564     m_memorySamplerInterval = interval;
1565     
1566     // For UIProcess
1567 #if ENABLE(MEMORY_SAMPLER)
1568     WebMemorySampler::singleton()->start(interval);
1569 #endif
1570     
1571     // For WebProcess
1572     SandboxExtension::Handle sampleLogSandboxHandle;    
1573     WallTime now = WallTime::now();
1574     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()));
1575     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
1576     
1577     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1578 }
1579
1580 void WebProcessPool::stopMemorySampler()
1581 {    
1582     // For WebProcess
1583     m_memorySamplerEnabled = false;
1584     
1585     // For UIProcess
1586 #if ENABLE(MEMORY_SAMPLER)
1587     WebMemorySampler::singleton()->stop();
1588 #endif
1589
1590     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1591 }
1592
1593 void WebProcessPool::useTestingNetworkSession()
1594 {
1595     ASSERT(m_processes.isEmpty());
1596     ASSERT(!m_networkProcess);
1597
1598     if (m_networkProcess)
1599         return;
1600
1601     if (!m_processes.isEmpty())
1602         return;
1603
1604     m_shouldUseTestingNetworkSession = true;
1605 }
1606
1607 template<typename T, typename U>
1608 void WebProcessPool::sendSyncToNetworkingProcess(T&& message, U&& reply)
1609 {
1610     if (m_networkProcess && m_networkProcess->canSendMessage())
1611         m_networkProcess->sendSync(std::forward<T>(message), std::forward<U>(reply), 0);
1612 }
1613
1614 void WebProcessPool::setAllowsAnySSLCertificateForWebSocket(bool allows)
1615 {
1616     sendSyncToNetworkingProcess(Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket(allows), Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket::Reply());
1617 }
1618
1619 void WebProcessPool::clearCachedCredentials()
1620 {
1621     if (m_networkProcess)
1622         m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1623 }
1624
1625 void WebProcessPool::terminateNetworkProcess()
1626 {
1627     if (!m_networkProcess)
1628         return;
1629     
1630     m_networkProcess->terminate();
1631     m_networkProcess = nullptr;
1632     m_didNetworkProcessCrash = true;
1633 }
1634
1635 void WebProcessPool::terminateServiceWorkerProcesses()
1636 {
1637 #if ENABLE(SERVICE_WORKER)
1638     auto protectedThis = makeRef(*this);
1639     while (!m_serviceWorkerProcesses.isEmpty())
1640         m_serviceWorkerProcesses.begin()->value->requestTermination(ProcessTerminationReason::RequestedByClient);
1641 #endif
1642 }
1643
1644 void WebProcessPool::syncNetworkProcessCookies()
1645 {
1646     ensureNetworkProcess().syncAllCookies();
1647 }
1648
1649 void WebProcessPool::setIDBPerOriginQuota(uint64_t quota)
1650 {
1651 #if ENABLE(INDEXED_DATABASE)
1652     ensureNetworkProcess().send(Messages::NetworkProcess::SetIDBPerOriginQuota(quota), 0);
1653 #endif
1654 }
1655
1656 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1657 {
1658     ensureNetworkProcess();
1659     m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1660 }
1661
1662 void WebProcessPool::updateAutomationCapabilities() const
1663 {
1664 #if ENABLE(REMOTE_INSPECTOR)
1665     Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1666 #endif
1667 }
1668
1669 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1670 {
1671     if (m_automationSession)
1672         m_automationSession->setProcessPool(nullptr);
1673     
1674     m_automationSession = WTFMove(automationSession);
1675
1676 #if ENABLE(REMOTE_INSPECTOR)
1677     if (m_automationSession) {
1678         m_automationSession->init();
1679         m_automationSession->setProcessPool(this);
1680
1681         sendToAllProcesses(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()));
1682     } else
1683         sendToAllProcesses(Messages::WebProcess::DestroyAutomationSessionProxy());
1684 #endif
1685 }
1686
1687 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1688 {
1689 #if PLATFORM(COCOA)
1690     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1691 #else
1692     UNUSED_PARAM(enabled);
1693 #endif
1694 }
1695
1696 bool WebProcessPool::httpPipeliningEnabled() const
1697 {
1698 #if PLATFORM(COCOA)
1699     return ResourceRequest::httpPipeliningEnabled();
1700 #else
1701     return false;
1702 #endif
1703 }
1704
1705 void WebProcessPool::getStatistics(uint32_t statisticsMask, Function<void (API::Dictionary*, CallbackBase::Error)>&& callbackFunction)
1706 {
1707     if (!statisticsMask) {
1708         callbackFunction(nullptr, CallbackBase::Error::Unknown);
1709         return;
1710     }
1711
1712     auto request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1713
1714     if (statisticsMask & StatisticsRequestTypeWebContent)
1715         requestWebContentStatistics(request.get());
1716     
1717     if (statisticsMask & StatisticsRequestTypeNetworking)
1718         requestNetworkingStatistics(request.get());
1719 }
1720
1721 void WebProcessPool::requestWebContentStatistics(StatisticsRequest& request)
1722 {
1723     // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1724 }
1725
1726 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest& request)
1727 {
1728     if (!m_networkProcess) {
1729         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1730         return;
1731     }
1732
1733     uint64_t requestID = request.addOutstandingRequest();
1734     m_statisticsRequests.set(requestID, &request);
1735     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1736 }
1737
1738 static WebProcessProxy* webProcessProxyFromConnection(IPC::Connection& connection, const Vector<RefPtr<WebProcessProxy>>& processes)
1739 {
1740     for (auto& process : processes) {
1741         if (process->hasConnection(connection))
1742             return process.get();
1743     }
1744
1745     ASSERT_NOT_REACHED();
1746     return nullptr;
1747 }
1748
1749 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1750 {
1751     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1752     if (!webProcessProxy)
1753         return;
1754     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1755 }
1756
1757 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1758 {
1759     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1760     if (!webProcessProxy)
1761         return;
1762
1763     RefPtr<API::Object> returnData;
1764     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1765     returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1766 }
1767
1768 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1769 {
1770     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1771     if (!request) {
1772         LOG_ERROR("Cannot report networking statistics.");
1773         return;
1774     }
1775
1776     request->completedRequest(requestID, statisticsData);
1777 }
1778
1779 #if ENABLE(GAMEPAD)
1780
1781 void WebProcessPool::startedUsingGamepads(IPC::Connection& connection)
1782 {
1783     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1784     if (!proxy)
1785         return;
1786
1787     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1788
1789     ASSERT(!m_processesUsingGamepads.contains(proxy));
1790     m_processesUsingGamepads.add(proxy);
1791
1792     if (!wereAnyProcessesUsingGamepads)
1793         UIGamepadProvider::singleton().processPoolStartedUsingGamepads(*this);
1794
1795     proxy->send(Messages::WebProcess::SetInitialGamepads(UIGamepadProvider::singleton().snapshotGamepads()), 0);
1796 }
1797
1798 void WebProcessPool::stoppedUsingGamepads(IPC::Connection& connection)
1799 {
1800     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1801     if (!proxy)
1802         return;
1803
1804     ASSERT(m_processesUsingGamepads.contains(proxy));
1805     processStoppedUsingGamepads(*proxy);
1806 }
1807
1808 void WebProcessPool::processStoppedUsingGamepads(WebProcessProxy& process)
1809 {
1810     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1811
1812     ASSERT(m_processesUsingGamepads.contains(&process));
1813     m_processesUsingGamepads.remove(&process);
1814
1815     if (wereAnyProcessesUsingGamepads && m_processesUsingGamepads.isEmpty())
1816         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
1817 }
1818
1819 void WebProcessPool::gamepadConnected(const UIGamepad& gamepad)
1820 {
1821     for (auto& process : m_processesUsingGamepads)
1822         process->send(Messages::WebProcess::GamepadConnected(gamepad.fullGamepadData()), 0);
1823 }
1824
1825 void WebProcessPool::gamepadDisconnected(const UIGamepad& gamepad)
1826 {
1827     for (auto& process : m_processesUsingGamepads)
1828         process->send(Messages::WebProcess::GamepadDisconnected(gamepad.index()), 0);
1829 }
1830
1831 void WebProcessPool::setInitialConnectedGamepads(const Vector<std::unique_ptr<UIGamepad>>& gamepads)
1832 {
1833     Vector<GamepadData> gamepadDatas;
1834     gamepadDatas.grow(gamepads.size());
1835     for (size_t i = 0; i < gamepads.size(); ++i) {
1836         if (!gamepads[i])
1837             continue;
1838         gamepadDatas[i] = gamepads[i]->fullGamepadData();
1839     }
1840
1841     for (auto& process : m_processesUsingGamepads)
1842         process->send(Messages::WebProcess::SetInitialGamepads(gamepadDatas), 0);
1843 }
1844
1845 #endif // ENABLE(GAMEPAD)
1846
1847 void WebProcessPool::setJavaScriptConfigurationFileEnabled(bool flag)
1848 {
1849     m_javaScriptConfigurationFileEnabled = flag;
1850 }
1851
1852 void WebProcessPool::garbageCollectJavaScriptObjects()
1853 {
1854     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1855 }
1856
1857 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1858 {
1859     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1860 }
1861
1862 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, PAL::SessionID sessionID)
1863 {
1864     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1865 }
1866
1867 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, PAL::SessionID sessionID)
1868 {
1869     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1870 }
1871
1872 Ref<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1873 {
1874     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1875 }
1876
1877 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1878 {
1879     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1880 }
1881
1882 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1883 {
1884     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1885 }
1886
1887 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, WallTime time)
1888 {
1889     m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1890 }
1891
1892 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1893 {
1894 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1895     if (!globalURLSchemesWithCustomProtocolHandlers().contains(scheme))
1896         m_urlSchemesRegisteredForCustomProtocols.add(scheme);
1897     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::RegisterScheme(scheme));
1898 #endif
1899 }
1900
1901 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1902 {
1903 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1904     m_urlSchemesRegisteredForCustomProtocols.remove(scheme);
1905     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::UnregisterScheme(scheme));
1906 #endif
1907 }
1908
1909 #if ENABLE(NETSCAPE_PLUGIN_API)
1910 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1911 {
1912     auto& policiesForHost = m_pluginLoadClientPolicies.ensure(host, [] { return HashMap<String, HashMap<String, uint8_t>>(); }).iterator->value;
1913     auto& versionsToPolicies = policiesForHost.ensure(bundleIdentifier, [] { return HashMap<String, uint8_t>(); }).iterator->value;
1914     versionsToPolicies.set(versionString, policy);
1915
1916     sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1917 }
1918
1919 void WebProcessPool::resetPluginLoadClientPolicies(HashMap<String, HashMap<String, HashMap<String, uint8_t>>>&& pluginLoadClientPolicies)
1920 {
1921     m_pluginLoadClientPolicies = WTFMove(pluginLoadClientPolicies);
1922     sendToAllProcesses(Messages::WebProcess::ResetPluginLoadClientPolicies(m_pluginLoadClientPolicies));
1923 }
1924
1925 void WebProcessPool::clearPluginClientPolicies()
1926 {
1927     m_pluginLoadClientPolicies.clear();
1928     sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1929 }
1930 #endif
1931
1932 void WebProcessPool::addSupportedPlugin(String&& matchingDomain, String&& name, HashSet<String>&& mimeTypes, HashSet<String> extensions)
1933 {
1934 #if ENABLE(NETSCAPE_PLUGIN_API)
1935     m_pluginInfoStore.addSupportedPlugin(WTFMove(matchingDomain), WTFMove(name), WTFMove(mimeTypes), WTFMove(extensions));
1936 #else
1937     UNUSED_PARAM(matchingDomain);
1938     UNUSED_PARAM(name);
1939     UNUSED_PARAM(mimeTypes);
1940     UNUSED_PARAM(extensions);
1941 #endif
1942 }
1943
1944 void WebProcessPool::clearSupportedPlugins()
1945 {
1946 #if ENABLE(NETSCAPE_PLUGIN_API)
1947     m_pluginInfoStore.clearSupportedPlugins();
1948 #endif
1949 }
1950
1951 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1952 {
1953     m_memoryCacheDisabled = disabled;
1954     sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1955 }
1956
1957 void WebProcessPool::setFontWhitelist(API::Array* array)
1958 {
1959     m_fontWhitelist.clear();
1960     if (array) {
1961         for (size_t i = 0; i < array->size(); ++i) {
1962             if (API::String* font = array->at<API::String>(i))
1963                 m_fontWhitelist.append(font->string());
1964         }
1965     }
1966 }
1967
1968 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1969 {
1970     // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1971     // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1972     // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1973     static int maximumTimerThrottlePerPageInMS = 200 * 100;
1974
1975     int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1976     sendToAllProcesses(Messages::WebProcess::SetHiddenPageDOMTimerThrottlingIncreaseLimit(limitInMilliseconds));
1977 }
1978
1979 void WebProcessPool::reportWebContentCPUTime(Seconds cpuTime, uint64_t activityState)
1980 {
1981 #if PLATFORM(MAC)
1982     if (m_perActivityStateCPUUsageSampler)
1983         m_perActivityStateCPUUsageSampler->reportWebContentCPUTime(cpuTime, static_cast<WebCore::ActivityStateForCPUSampling>(activityState));
1984 #else
1985     UNUSED_PARAM(cpuTime);
1986     UNUSED_PARAM(activityState);
1987 #endif
1988 }
1989
1990 void WebProcessPool::updateProcessAssertions()
1991 {
1992 #if PLATFORM(IOS_FAMILY)
1993 #if ENABLE(SERVICE_WORKER)
1994     auto updateServiceWorkerProcessAssertion = [&] {
1995         if (!m_serviceWorkerProcesses.isEmpty() && m_foregroundWebProcessCounter.value()) {
1996             // FIXME: We can do better than this once we have process per origin.
1997             for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1998                 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
1999                 if (!m_foregroundTokensForServiceWorkerProcesses.contains(securityOrigin))
2000                     m_foregroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().foregroundActivityToken());
2001             }
2002             m_backgroundTokensForServiceWorkerProcesses.clear();
2003             return;
2004         }
2005         if (!m_serviceWorkerProcesses.isEmpty() && m_backgroundWebProcessCounter.value()) {
2006             // FIXME: We can do better than this once we have process per origin.
2007             for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
2008                 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
2009                 if (!m_backgroundTokensForServiceWorkerProcesses.contains(securityOrigin))
2010                     m_backgroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().backgroundActivityToken());
2011             }
2012             m_foregroundTokensForServiceWorkerProcesses.clear();
2013             return;
2014         }
2015         m_foregroundTokensForServiceWorkerProcesses.clear();
2016         m_backgroundTokensForServiceWorkerProcesses.clear();
2017     };
2018     updateServiceWorkerProcessAssertion();
2019 #endif
2020
2021     auto updateNetworkProcessAssertion = [&] {
2022         auto& networkProcess = ensureNetworkProcess();
2023
2024         if (m_foregroundWebProcessCounter.value()) {
2025             if (!m_foregroundTokenForNetworkProcess) {
2026                 m_foregroundTokenForNetworkProcess = networkProcess.throttler().foregroundActivityToken();
2027                 networkProcess.sendProcessDidTransitionToForeground();
2028             }
2029             m_backgroundTokenForNetworkProcess = nullptr;
2030             return;
2031         }
2032         if (m_backgroundWebProcessCounter.value()) {
2033             if (!m_backgroundTokenForNetworkProcess) {
2034                 m_backgroundTokenForNetworkProcess = networkProcess.throttler().backgroundActivityToken();
2035                 networkProcess.sendProcessDidTransitionToBackground();
2036             }
2037             m_foregroundTokenForNetworkProcess = nullptr;
2038             return;
2039         }
2040         m_foregroundTokenForNetworkProcess = nullptr;
2041         m_backgroundTokenForNetworkProcess = nullptr;
2042     };
2043     updateNetworkProcessAssertion();
2044 #endif
2045 }
2046
2047 #if ENABLE(SERVICE_WORKER)
2048 void WebProcessPool::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destination, MessageWithMessagePorts&& message, ServiceWorkerIdentifier source, const String& sourceOrigin)
2049 {
2050     sendToNetworkingProcessRelaunchingIfNecessary(Messages::NetworkProcess::PostMessageToServiceWorkerClient(destination, WTFMove(message), source, sourceOrigin));
2051 }
2052
2053 void WebProcessPool::postMessageToServiceWorker(ServiceWorkerIdentifier destination, MessageWithMessagePorts&& message, const ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
2054 {
2055     sendToNetworkingProcessRelaunchingIfNecessary(Messages::NetworkProcess::PostMessageToServiceWorker(destination, WTFMove(message), source, connectionIdentifier));
2056 }
2057 #endif
2058
2059 void WebProcessPool::reinstateNetworkProcessAssertionState(NetworkProcessProxy& newNetworkProcessProxy)
2060 {
2061 #if PLATFORM(IOS_FAMILY)
2062     // The network process crashed; take new tokens for the new network process.
2063     if (m_backgroundTokenForNetworkProcess)
2064         m_backgroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().backgroundActivityToken();
2065     else if (m_foregroundTokenForNetworkProcess)
2066         m_foregroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().foregroundActivityToken();
2067 #else
2068     UNUSED_PARAM(newNetworkProcessProxy);
2069 #endif
2070 }
2071
2072 #if ENABLE(SERVICE_WORKER)
2073 ServiceWorkerProcessProxy* WebProcessPool::serviceWorkerProcessProxyFromPageID(uint64_t pageID) const
2074 {
2075     // FIXME: This is inefficient.
2076     for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
2077         if (serviceWorkerProcess->pageID() == pageID)
2078             return serviceWorkerProcess;
2079     }
2080     return nullptr;
2081 }
2082 #endif
2083
2084 void WebProcessPool::addProcessToOriginCacheSet(WebPageProxy& page)
2085 {
2086     auto registrableDomain = toRegistrableDomain({ { }, page.pageLoadState().url() });
2087     auto result = m_swappedProcessesPerRegistrableDomain.add(registrableDomain, &page.process());
2088     if (!result.isNewEntry)
2089         result.iterator->value = &page.process();
2090
2091     LOG(ProcessSwapping, "(ProcessSwapping) Registrable domain %s just saved a cached process with pid %i", registrableDomain.utf8().data(), page.process().processIdentifier());
2092     if (!result.isNewEntry)
2093         LOG(ProcessSwapping, "(ProcessSwapping) Note: It already had one saved");
2094 }
2095
2096 void WebProcessPool::removeProcessFromOriginCacheSet(WebProcessProxy& process)
2097 {
2098     LOG(ProcessSwapping, "(ProcessSwapping) Removing process with pid %i from the origin cache set", process.processIdentifier());
2099
2100     // FIXME: This can be very inefficient as the number of remembered origins and processes grows
2101     Vector<String> registrableDomainsToRemove;
2102     for (auto entry : m_swappedProcessesPerRegistrableDomain) {
2103         if (entry.value == &process)
2104             registrableDomainsToRemove.append(entry.key);
2105     }
2106
2107     for (auto& registrableDomain : registrableDomainsToRemove)
2108         m_swappedProcessesPerRegistrableDomain.remove(registrableDomain);
2109 }
2110
2111 void WebProcessPool::processForNavigation(WebPageProxy& page, const API::Navigation& navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
2112 {
2113     processForNavigationInternal(page, navigation, processSwapRequestedByClient, [this, page = makeRefPtr(page), navigation = makeRef(navigation), processSwapRequestedByClient, completionHandler = WTFMove(completionHandler)](Ref<WebProcessProxy>&& process, SuspendedPageProxy* suspendedPage, const String& reason) mutable {
2114         // We are process-swapping so automatic process prewarming would be beneficial if the client has not explicitly enabled / disabled it.
2115         bool doingAnAutomaticProcessSwap = processSwapRequestedByClient == ProcessSwapRequestedByClient::No && process.ptr() != &page->process();
2116         if (doingAnAutomaticProcessSwap && !configuration().wasAutomaticProcessWarmingSetByClient() && !configuration().clientWouldBenefitFromAutomaticProcessPrewarming()) {
2117             RELEASE_LOG(PerformanceLogging, "Automatically turning on process prewarming because the client would benefit from it");
2118             configuration().setClientWouldBenefitFromAutomaticProcessPrewarming(true);
2119         }
2120
2121         if (m_configuration->alwaysKeepAndReuseSwappedProcesses() && process.ptr() != &page->process()) {
2122             static std::once_flag onceFlag;
2123             std::call_once(onceFlag, [] {
2124                 WTFLogAlways("WARNING: The option to always keep swapped web processes alive is active. This is meant for debugging and testing only.");
2125             });
2126
2127             addProcessToOriginCacheSet(*page);
2128
2129             LOG(ProcessSwapping, "(ProcessSwapping) Navigating from %s to %s, keeping around old process. Now holding on to old processes for %u origins.", page->currentURL().utf8().data(), navigation->currentRequest().url().string().utf8().data(), m_swappedProcessesPerRegistrableDomain.size());
2130         }
2131
2132         completionHandler(WTFMove(process), suspendedPage, reason);
2133     });
2134 }
2135
2136 void WebProcessPool::processForNavigationInternal(WebPageProxy& page, const API::Navigation& navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
2137 {
2138     auto& targetURL = navigation.currentRequest().url();
2139
2140     auto createNewProcess = [&] () -> Ref<WebProcessProxy> {
2141         if (RefPtr<WebProcessProxy> process = tryTakePrewarmedProcess(page.websiteDataStore())) {
2142             tryPrewarmWithDomainInformation(*process, targetURL);
2143             return process.releaseNonNull();
2144         }
2145
2146         return createNewWebProcess(page.websiteDataStore());
2147     };
2148
2149     if (usesSingleWebProcess())
2150         return completionHandler(page.process(), nullptr, "Single WebProcess mode is enabled"_s);
2151
2152     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
2153         return completionHandler(createNewProcess(), nullptr, "Process swap was requested by the client"_s);
2154
2155     if (!m_configuration->processSwapsOnNavigation())
2156         return completionHandler(page.process(), nullptr, "Feature is disabled"_s);
2157
2158     if (m_automationSession)
2159         return completionHandler(page.process(), nullptr, "An automation session is active"_s);
2160
2161     if (!page.process().hasCommittedAnyProvisionalLoads()) {
2162         tryPrewarmWithDomainInformation(page.process(), targetURL);
2163         return completionHandler(page.process(), nullptr, "Process has not yet committed any provisional loads"_s);
2164     }
2165
2166     // FIXME: We should support process swap when a window has been opened via window.open() without 'noopener'.
2167     // The issue is that the opener has a handle to the WindowProxy.
2168     if (navigation.openedByDOMWithOpener() && !m_configuration->processSwapsOnWindowOpenWithOpener())
2169         return completionHandler(page.process(), nullptr, "Browsing context been opened by DOM without 'noopener'"_s);
2170
2171     // FIXME: We should support process swap when a window has opened other windows via window.open.
2172     if (navigation.hasOpenedFrames())
2173         return completionHandler(page.process(), nullptr, "Browsing context has opened other windows"_s);
2174
2175     if (auto* targetItem = navigation.targetItem()) {
2176         if (auto* suspendedPage = targetItem->suspendedPage()) {
2177             return suspendedPage->waitUntilReadyToUnsuspend([createNewProcess = WTFMove(createNewProcess), completionHandler = WTFMove(completionHandler)](SuspendedPageProxy* suspendedPage) mutable {
2178                 if (!suspendedPage)
2179                     return completionHandler(createNewProcess(), nullptr, "Using new process because target back/forward item's suspended page is not reusable"_s);
2180                 Ref<WebProcessProxy> process = suspendedPage->process();
2181                 completionHandler(WTFMove(process), suspendedPage, "Using target back/forward item's process and suspended page"_s);
2182             });
2183         }
2184
2185         if (auto* process = WebProcessProxy::processForIdentifier(targetItem->itemID().processIdentifier))
2186             return completionHandler(*process, nullptr, "Using target back/forward item's process"_s);
2187     }
2188
2189     if (navigation.treatAsSameOriginNavigation())
2190         return completionHandler(page.process(), nullptr, "The treatAsSameOriginNavigation flag is set"_s);
2191
2192     URL sourceURL;
2193     if (page.isPageOpenedByDOMShowingInitialEmptyDocument() && !navigation.requesterOrigin().isEmpty())
2194         sourceURL = URL { URL(), navigation.requesterOrigin().toString() };
2195     else
2196         sourceURL = URL { { }, page.pageLoadState().url() };
2197
2198     if (sourceURL.isEmpty() && page.configuration().relatedPage()) {
2199         sourceURL = URL { { }, page.configuration().relatedPage()->pageLoadState().url() };
2200         RELEASE_LOG(ProcessSwapping, "Using related page %p's URL as source URL for process swap decision", page.configuration().relatedPage());
2201     }
2202
2203     if (!sourceURL.isValid() || !targetURL.isValid() || sourceURL.isEmpty() || sourceURL.protocolIsAbout() || registrableDomainsAreEqual(sourceURL, targetURL))
2204         return completionHandler(page.process(), nullptr, "Navigation is same-site"_s);
2205
2206     String reason = "Navigation is cross-site"_s;
2207     
2208     auto registrableDomain = toRegistrableDomain(targetURL);
2209     if (m_configuration->alwaysKeepAndReuseSwappedProcesses()) {
2210         LOG(ProcessSwapping, "(ProcessSwapping) Considering re-use of a previously cached process for domain %s", registrableDomain.utf8().data());
2211
2212         if (auto* process = m_swappedProcessesPerRegistrableDomain.get(registrableDomain)) {
2213             if (&process->websiteDataStore() == &page.websiteDataStore()) {
2214                 LOG(ProcessSwapping, "(ProcessSwapping) Reusing a previously cached process with pid %i to continue navigation to URL %s", process->processIdentifier(), targetURL.string().utf8().data());
2215
2216                 // FIXME: Architecturally we do not currently support multiple WebPage's with the same ID in a given WebProcess.
2217                 // In the case where this WebProcess has a SuspendedPageProxy for this WebPage, we can throw it away to support
2218                 // WebProcess re-use.
2219                 // In the future it would be great to refactor-out this limitation (https://bugs.webkit.org/show_bug.cgi?id=191166).
2220                 m_suspendedPages.removeAllMatching([&](auto& suspendedPage) {
2221                     return &suspendedPage->page() == &page && &suspendedPage->process() == process;
2222                 });
2223
2224                 return completionHandler(makeRef(*process), nullptr, reason);
2225             }
2226         }
2227     }
2228
2229     // Check if we have a suspended page for the given registrable domain and use its process if we do, for performance reasons.
2230     auto it = m_suspendedPages.findIf([&](auto& suspendedPage) {
2231         return suspendedPage->registrableDomain() == registrableDomain;
2232     });
2233     if (it != m_suspendedPages.end()) {
2234         Ref<WebProcessProxy> process = (*it)->process();
2235
2236         // FIXME: If the SuspendedPage is for this page, then we need to destroy the suspended page as we do not support having
2237         // multiple WebPages with the same ID in a given WebProcess currently (https://bugs.webkit.org/show_bug.cgi?id=191166).
2238         if (&(*it)->page() == &page)
2239             m_suspendedPages.remove(it);
2240
2241         return completionHandler(WTFMove(process), nullptr, reason);
2242     }
2243
2244     return completionHandler(createNewProcess(), nullptr, reason);
2245 }
2246
2247 void WebProcessPool::addSuspendedPage(std::unique_ptr<SuspendedPageProxy>&& suspendedPage)
2248 {
2249     if (!m_maxSuspendedPageCount)
2250         return;
2251
2252     if (m_suspendedPages.size() >= m_maxSuspendedPageCount)
2253         m_suspendedPages.removeFirst();
2254
2255     m_suspendedPages.append(WTFMove(suspendedPage));
2256 }
2257
2258 void WebProcessPool::removeAllSuspendedPagesForPage(WebPageProxy& page)
2259 {
2260     m_suspendedPages.removeAllMatching([&page](auto& suspendedPage) {
2261         return &suspendedPage->page() == &page;
2262     });
2263 }
2264
2265 void WebProcessPool::closeFailedSuspendedPagesForPage(WebPageProxy& page)
2266 {
2267     for (auto& suspendedPage : m_suspendedPages) {
2268         if (&suspendedPage->page() == &page && suspendedPage->failedToSuspend())
2269             suspendedPage->close();
2270     }
2271 }
2272
2273 std::unique_ptr<SuspendedPageProxy> WebProcessPool::takeSuspendedPage(SuspendedPageProxy& suspendedPage)
2274 {
2275     return m_suspendedPages.takeFirst([&suspendedPage](auto& item) {
2276         return item.get() == &suspendedPage;
2277     });
2278 }
2279
2280 void WebProcessPool::removeSuspendedPage(SuspendedPageProxy& suspendedPage)
2281 {
2282     auto it = m_suspendedPages.findIf([&suspendedPage](auto& item) {
2283         return item.get() == &suspendedPage;
2284     });
2285     if (it != m_suspendedPages.end())
2286         m_suspendedPages.remove(it);
2287 }
2288
2289 bool WebProcessPool::hasSuspendedPageFor(WebProcessProxy& process) const
2290 {
2291     return m_suspendedPages.findIf([&process](auto& suspendedPage) {
2292         return &suspendedPage->process() == &process;
2293     }) != m_suspendedPages.end();
2294 }
2295
2296 void WebProcessPool::addMockMediaDevice(const MockMediaDevice& device)
2297 {
2298 #if ENABLE(MEDIA_STREAM)
2299     MockRealtimeMediaSourceCenter::addDevice(device);
2300     sendToAllProcesses(Messages::WebProcess::AddMockMediaDevice { device });
2301 #endif
2302 }
2303
2304 void WebProcessPool::clearMockMediaDevices()
2305 {
2306 #if ENABLE(MEDIA_STREAM)
2307     MockRealtimeMediaSourceCenter::setDevices({ });
2308     sendToAllProcesses(Messages::WebProcess::ClearMockMediaDevices { });
2309 #endif
2310 }
2311
2312 void WebProcessPool::removeMockMediaDevice(const String& persistentId)
2313 {
2314 #if ENABLE(MEDIA_STREAM)
2315     MockRealtimeMediaSourceCenter::removeDevice(persistentId);
2316     sendToAllProcesses(Messages::WebProcess::RemoveMockMediaDevice { persistentId });
2317 #endif
2318 }
2319
2320 void WebProcessPool::resetMockMediaDevices()
2321 {
2322 #if ENABLE(MEDIA_STREAM)
2323     MockRealtimeMediaSourceCenter::resetDevices();
2324     sendToAllProcesses(Messages::WebProcess::ResetMockMediaDevices { });
2325 #endif
2326 }
2327
2328 void WebProcessPool::sendDisplayConfigurationChangedMessageForTesting()
2329 {
2330 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
2331     auto display = CGSMainDisplayID();
2332
2333     for (auto& processPool : WebProcessPool::allProcessPools()) {
2334         processPool->sendToAllProcesses(Messages::WebProcess::DisplayConfigurationChanged(display, kCGDisplayBeginConfigurationFlag));
2335         processPool->sendToAllProcesses(Messages::WebProcess::DisplayConfigurationChanged(display, kCGDisplaySetModeFlag | kCGDisplayDesktopShapeChangedFlag));
2336     }
2337 #endif
2338 }
2339
2340 void WebProcessPool::didCollectPrewarmInformation(const String& registrableDomain, const WebCore::PrewarmInformation& prewarmInformation)
2341 {
2342     static const size_t maximumSizeToPreventUnlimitedGrowth = 100;
2343     if (m_prewarmInformationPerRegistrableDomain.size() == maximumSizeToPreventUnlimitedGrowth)
2344         m_prewarmInformationPerRegistrableDomain.remove(m_prewarmInformationPerRegistrableDomain.random());
2345
2346     auto& value = m_prewarmInformationPerRegistrableDomain.ensure(registrableDomain, [] {
2347         return std::make_unique<WebCore::PrewarmInformation>();
2348     }).iterator->value;
2349
2350     *value = prewarmInformation;
2351 }
2352
2353 void WebProcessPool::tryPrewarmWithDomainInformation(WebProcessProxy& process, const URL& url)
2354 {
2355     auto* prewarmInformation = m_prewarmInformationPerRegistrableDomain.get(toRegistrableDomain(url));
2356     if (!prewarmInformation)
2357         return;
2358     process.send(Messages::WebProcess::PrewarmWithDomainInformation(*prewarmInformation), 0);
2359 }
2360
2361 void WebProcessPool::clearCurrentModifierStateForTesting()
2362 {
2363     sendToAllProcesses(Messages::WebProcess::ClearCurrentModifierStateForTesting());
2364 }
2365
2366 } // namespace WebKit