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