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