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