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