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