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