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