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