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