Cleanup WK2 platform gamepad handling.
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebProcessPool.cpp
1 /*
2  * Copyright (C) 2010-2016 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 "APIDownloadClient.h"
32 #include "APILegacyContextHistoryClient.h"
33 #include "APIPageConfiguration.h"
34 #include "APIProcessPoolConfiguration.h"
35 #include "CustomProtocolManagerMessages.h"
36 #include "DownloadProxy.h"
37 #include "DownloadProxyMessages.h"
38 #include "GamepadData.h"
39 #include "LogInitialization.h"
40 #include "NetworkProcessCreationParameters.h"
41 #include "NetworkProcessMessages.h"
42 #include "NetworkProcessProxy.h"
43 #include "SandboxExtension.h"
44 #include "StatisticsData.h"
45 #include "TextChecker.h"
46 #include "UIGamepad.h"
47 #include "UIGamepadProvider.h"
48 #include "WKContextPrivate.h"
49 #include "WebAutomationSession.h"
50 #include "WebCertificateInfo.h"
51 #include "WebContextSupplement.h"
52 #include "WebCookieManagerProxy.h"
53 #include "WebCoreArgumentCoders.h"
54 #include "WebGeolocationManagerProxy.h"
55 #include "WebIconDatabase.h"
56 #include "WebKit2Initialize.h"
57 #include "WebMemorySampler.h"
58 #include "WebNotificationManagerProxy.h"
59 #include "WebPageGroup.h"
60 #include "WebPreferences.h"
61 #include "WebProcessCreationParameters.h"
62 #include "WebProcessMessages.h"
63 #include "WebProcessPoolMessages.h"
64 #include "WebProcessProxy.h"
65 #include "WebsiteDataStore.h"
66 #include <WebCore/ApplicationCacheStorage.h>
67 #include <WebCore/Language.h>
68 #include <WebCore/LinkHash.h>
69 #include <WebCore/LogInitialization.h>
70 #include <WebCore/ResourceRequest.h>
71 #include <WebCore/SessionID.h>
72 #include <runtime/JSCInlines.h>
73 #include <wtf/CurrentTime.h>
74 #include <wtf/MainThread.h>
75 #include <wtf/NeverDestroyed.h>
76 #include <wtf/RunLoop.h>
77
78 #if ENABLE(BATTERY_STATUS)
79 #include "WebBatteryManagerProxy.h"
80 #endif
81
82 #if ENABLE(DATABASE_PROCESS)
83 #include "DatabaseProcessCreationParameters.h"
84 #include "DatabaseProcessMessages.h"
85 #endif
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 USE(SOUP)
96 #include "WebSoupCustomProtocolRequestManager.h"
97 #endif
98
99 #if OS(LINUX)
100 #include "MemoryPressureMonitor.h"
101 #endif
102
103 #ifndef NDEBUG
104 #include <wtf/RefCountedLeakCounter.h>
105 #endif
106
107 using namespace WebCore;
108 using namespace WebKit;
109
110 namespace WebKit {
111
112 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, processPoolCounter, ("WebProcessPool"));
113
114 Ref<WebProcessPool> WebProcessPool::create(API::ProcessPoolConfiguration& configuration)
115 {
116     InitializeWebKit2();
117     return adoptRef(*new WebProcessPool(configuration));
118 }
119
120 static Vector<WebProcessPool*>& processPools()
121 {
122     static NeverDestroyed<Vector<WebProcessPool*>> processPools;
123     return processPools;
124 }
125
126 const Vector<WebProcessPool*>& WebProcessPool::allProcessPools()
127 {
128     return processPools();
129 }
130
131 static WebsiteDataStore::Configuration legacyWebsiteDataStoreConfiguration(API::ProcessPoolConfiguration& processPoolConfiguration)
132 {
133     WebsiteDataStore::Configuration configuration;
134
135     configuration.localStorageDirectory = processPoolConfiguration.localStorageDirectory();
136     configuration.webSQLDatabaseDirectory = processPoolConfiguration.webSQLDatabaseDirectory();
137     configuration.applicationCacheDirectory = processPoolConfiguration.applicationCacheDirectory();
138     configuration.applicationCacheFlatFileSubdirectoryName = processPoolConfiguration.applicationCacheFlatFileSubdirectoryName();
139     configuration.mediaCacheDirectory = processPoolConfiguration.mediaCacheDirectory();
140     configuration.mediaKeysStorageDirectory = processPoolConfiguration.mediaKeysStorageDirectory();
141     configuration.networkCacheDirectory = processPoolConfiguration.diskCacheDirectory();
142
143     // This is needed to support legacy WK2 clients, which did not have resource load statistics.
144     configuration.resourceLoadStatisticsDirectory = API::WebsiteDataStore::defaultResourceLoadStatisticsDirectory();
145
146     return configuration;
147 }
148
149 WebProcessPool::WebProcessPool(API::ProcessPoolConfiguration& configuration)
150     : m_configuration(configuration.copy())
151     , m_haveInitialEmptyProcess(false)
152     , m_processWithPageCache(0)
153     , m_defaultPageGroup(WebPageGroup::createNonNull())
154     , m_automationClient(std::make_unique<API::AutomationClient>())
155     , m_downloadClient(std::make_unique<API::DownloadClient>())
156     , m_historyClient(std::make_unique<API::LegacyContextHistoryClient>())
157     , m_visitedLinkStore(VisitedLinkStore::create())
158     , m_visitedLinksPopulated(false)
159     , m_plugInAutoStartProvider(this)
160     , m_alwaysUsesComplexTextCodePath(false)
161     , m_shouldUseFontSmoothing(true)
162     , m_memorySamplerEnabled(false)
163     , m_memorySamplerInterval(1400.0)
164     , m_websiteDataStore(m_configuration->shouldHaveLegacyDataStore() ? API::WebsiteDataStore::create(legacyWebsiteDataStoreConfiguration(m_configuration)).ptr() : nullptr)
165 #if USE(SOUP)
166     , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain)
167 #endif
168     , m_shouldUseTestingNetworkSession(false)
169     , m_processTerminationEnabled(true)
170     , m_canHandleHTTPSServerTrustEvaluation(true)
171     , m_didNetworkProcessCrash(false)
172     , m_memoryCacheDisabled(false)
173     , m_userObservablePageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
174     , m_processSuppressionDisabledForPageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
175     , m_hiddenPageThrottlingAutoIncreasesCounter([this](RefCounterEvent) { m_hiddenPageThrottlingTimer.startOneShot(0); })
176     , m_hiddenPageThrottlingTimer(RunLoop::main(), this, &WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit)
177 {
178     for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
179         m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
180
181 #if ENABLE(CACHE_PARTITIONING)
182     for (const auto& urlScheme : m_configuration->cachePartitionedURLSchemes())
183         m_schemesToRegisterAsCachePartitioned.add(urlScheme);
184 #endif
185
186     platformInitialize();
187
188     addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
189
190     // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
191     m_iconDatabase = WebIconDatabase::create(this);
192
193     addSupplement<WebCookieManagerProxy>();
194     addSupplement<WebGeolocationManagerProxy>();
195     addSupplement<WebNotificationManagerProxy>();
196 #if USE(SOUP)
197     addSupplement<WebSoupCustomProtocolRequestManager>();
198 #endif
199 #if ENABLE(BATTERY_STATUS)
200     addSupplement<WebBatteryManagerProxy>();
201 #endif
202 #if ENABLE(MEDIA_SESSION)
203     addSupplement<WebMediaSessionFocusManager>();
204 #endif
205
206     processPools().append(this);
207
208     addLanguageChangeObserver(this, languageChanged);
209
210 #if !LOG_DISABLED
211     WebCore::initializeLogChannelsIfNecessary();
212     WebKit::initializeLogChannelsIfNecessary();
213 #endif // !LOG_DISABLED
214
215 #ifndef NDEBUG
216     processPoolCounter.increment();
217 #endif
218 }
219
220 #if !PLATFORM(COCOA)
221 void WebProcessPool::platformInitialize()
222 {
223 }
224 #endif
225
226 WebProcessPool::~WebProcessPool()
227 {
228     bool removed = processPools().removeFirst(this);
229     ASSERT_UNUSED(removed, removed);
230
231     removeLanguageChangeObserver(this);
232
233     m_messageReceiverMap.invalidate();
234
235     WebContextSupplementMap::const_iterator it = m_supplements.begin();
236     WebContextSupplementMap::const_iterator end = m_supplements.end();
237     for (; it != end; ++it) {
238         it->value->processPoolDestroyed();
239         it->value->clearProcessPool();
240     }
241
242     m_iconDatabase->invalidate();
243     m_iconDatabase->clearProcessPool();
244     WebIconDatabase* rawIconDatabase = m_iconDatabase.leakRef();
245     rawIconDatabase->derefWhenAppropriate();
246
247     invalidateCallbackMap(m_dictionaryCallbacks, CallbackBase::Error::OwnerWasInvalidated);
248
249     platformInvalidateContext();
250
251 #ifndef NDEBUG
252     processPoolCounter.decrement();
253 #endif
254
255     if (m_networkProcess)
256         m_networkProcess->shutDownProcess();
257
258 #if ENABLE(GAMEPAD)
259     if (!m_processesUsingGamepads.isEmpty())
260         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
261 #endif
262 }
263
264 void WebProcessPool::initializeClient(const WKContextClientBase* client)
265 {
266     m_client.initialize(client);
267 }
268
269 void WebProcessPool::initializeInjectedBundleClient(const WKContextInjectedBundleClientBase* client)
270 {
271     m_injectedBundleClient.initialize(client);
272 }
273
274 void WebProcessPool::initializeConnectionClient(const WKContextConnectionClientBase* client)
275 {
276     m_connectionClient.initialize(client);
277 }
278
279 void WebProcessPool::setHistoryClient(std::unique_ptr<API::LegacyContextHistoryClient> historyClient)
280 {
281     if (!historyClient)
282         m_historyClient = std::make_unique<API::LegacyContextHistoryClient>();
283     else
284         m_historyClient = WTFMove(historyClient);
285 }
286
287 void WebProcessPool::setDownloadClient(std::unique_ptr<API::DownloadClient> downloadClient)
288 {
289     if (!downloadClient)
290         m_downloadClient = std::make_unique<API::DownloadClient>();
291     else
292         m_downloadClient = WTFMove(downloadClient);
293 }
294
295 void WebProcessPool::setAutomationClient(std::unique_ptr<API::AutomationClient> automationClient)
296 {
297     if (!automationClient)
298         m_automationClient = std::make_unique<API::AutomationClient>();
299     else
300         m_automationClient = WTFMove(automationClient);
301 }
302
303 void WebProcessPool::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
304 {
305     // Guard against API misuse.
306     if (!m_processes.isEmpty())
307         CRASH();
308
309     m_configuration->setMaximumProcessCount(maximumNumberOfProcesses);
310 }
311
312 IPC::Connection* WebProcessPool::networkingProcessConnection()
313 {
314     return m_networkProcess->connection();
315 }
316
317 void WebProcessPool::languageChanged(void* context)
318 {
319     static_cast<WebProcessPool*>(context)->languageChanged();
320 }
321
322 void WebProcessPool::languageChanged()
323 {
324     sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
325 #if USE(SOUP)
326     if (m_networkProcess)
327         m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
328 #endif
329 }
330
331 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
332 {
333     sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
334 }
335
336 void WebProcessPool::textCheckerStateChanged()
337 {
338     sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
339 }
340
341 NetworkProcessProxy& WebProcessPool::ensureNetworkProcess()
342 {
343     if (m_networkProcess)
344         return *m_networkProcess;
345
346     m_networkProcess = NetworkProcessProxy::create(*this);
347
348     NetworkProcessCreationParameters parameters;
349
350     parameters.privateBrowsingEnabled = WebPreferences::anyPagesAreUsingPrivateBrowsing();
351
352     parameters.cacheModel = cacheModel();
353     parameters.diskCacheSizeOverride = m_configuration->diskCacheSizeOverride();
354     parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
355
356     parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
357     if (!parameters.diskCacheDirectory.isEmpty())
358         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
359 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
360     parameters.shouldEnableNetworkCacheSpeculativeRevalidation = m_configuration->diskCacheSpeculativeValidationEnabled();
361 #endif
362
363 #if PLATFORM(IOS)
364     String cookieStorageDirectory = this->cookieStorageDirectory();
365     if (!cookieStorageDirectory.isEmpty())
366         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
367
368     String containerCachesDirectory = this->networkingCachesDirectory();
369     if (!containerCachesDirectory.isEmpty())
370         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
371
372     String parentBundleDirectory = this->parentBundleDirectory();
373     if (!parentBundleDirectory.isEmpty())
374         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
375 #endif
376
377 #if OS(LINUX)
378     if (MemoryPressureMonitor::isEnabled())
379         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
380 #endif
381
382     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
383
384     // Add any platform specific parameters
385     platformInitializeNetworkProcess(parameters);
386
387     // Initialize the network process.
388     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
389
390 #if PLATFORM(COCOA)
391     m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
392 #endif
393
394     if (m_didNetworkProcessCrash) {
395         m_didNetworkProcessCrash = false;
396         for (auto& process : m_processes)
397             process->reinstateNetworkProcessAssertionState(*m_networkProcess);
398     }
399
400     return *m_networkProcess;
401 }
402
403 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy* networkProcessProxy)
404 {
405     ASSERT(m_networkProcess);
406     ASSERT(networkProcessProxy == m_networkProcess.get());
407     m_didNetworkProcessCrash = true;
408
409     WebContextSupplementMap::const_iterator it = m_supplements.begin();
410     WebContextSupplementMap::const_iterator end = m_supplements.end();
411     for (; it != end; ++it)
412         it->value->processDidClose(networkProcessProxy);
413
414     m_client.networkProcessDidCrash(this);
415
416     // Leave the process proxy around during client call, so that the client could query the process identifier.
417     m_networkProcess = nullptr;
418 }
419
420 void WebProcessPool::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
421 {
422     ASSERT(reply);
423
424     ensureNetworkProcess();
425     ASSERT(m_networkProcess);
426
427     m_networkProcess->getNetworkProcessConnection(reply);
428 }
429
430 #if ENABLE(DATABASE_PROCESS)
431 void WebProcessPool::ensureDatabaseProcess()
432 {
433     if (m_databaseProcess)
434         return;
435
436     m_databaseProcess = DatabaseProcessProxy::create(this);
437
438     // *********
439     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
440     // *********
441     DatabaseProcessCreationParameters parameters;
442 #if ENABLE(INDEXED_DATABASE)
443     ASSERT(!m_configuration->indexedDBDatabaseDirectory().isEmpty());
444     parameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
445
446     SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
447 #endif
448
449     m_databaseProcess->send(Messages::DatabaseProcess::InitializeDatabaseProcess(parameters), 0);
450 }
451
452 void WebProcessPool::getDatabaseProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetDatabaseProcessConnection::DelayedReply> reply)
453 {
454     ASSERT(reply);
455
456     ensureDatabaseProcess();
457
458     m_databaseProcess->getDatabaseProcessConnection(reply);
459 }
460
461 void WebProcessPool::databaseProcessCrashed(DatabaseProcessProxy* databaseProcessProxy)
462 {
463     ASSERT(m_databaseProcess);
464     ASSERT(databaseProcessProxy == m_databaseProcess.get());
465
466     for (auto& supplement : m_supplements)
467         supplement.value->processDidClose(databaseProcessProxy);
468
469     m_client.databaseProcessDidCrash(this);
470     m_databaseProcess = nullptr;
471 }
472 #endif
473
474 void WebProcessPool::willStartUsingPrivateBrowsing()
475 {
476     for (auto* processPool : allProcessPools())
477         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
478 }
479
480 void WebProcessPool::willStopUsingPrivateBrowsing()
481 {
482     for (auto* processPool : allProcessPools())
483         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
484 }
485
486 void WebProcessPool::windowServerConnectionStateChanged()
487 {
488     size_t processCount = m_processes.size();
489     for (size_t i = 0; i < processCount; ++i)
490         m_processes[i]->windowServerConnectionStateChanged();
491 }
492
493 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
494 {
495     m_iconDatabase->setPrivateBrowsingEnabled(privateBrowsingEnabled);
496
497     if (networkProcess()) {
498         if (privateBrowsingEnabled)
499             networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
500         else
501             networkProcess()->send(Messages::NetworkProcess::DestroyPrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
502     }
503
504     if (privateBrowsingEnabled)
505         sendToAllProcesses(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()));
506     else
507         sendToAllProcesses(Messages::WebProcess::DestroyPrivateBrowsingSession(SessionID::legacyPrivateSessionID()));
508 }
509
510 void (*s_invalidMessageCallback)(WKStringRef messageName);
511
512 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
513 {
514     s_invalidMessageCallback = invalidMessageCallback;
515 }
516
517 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
518 {
519     if (!s_invalidMessageCallback)
520         return;
521
522     StringBuilder messageNameStringBuilder;
523     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
524     messageNameStringBuilder.append('.');
525     messageNameStringBuilder.append(messageName.data(), messageName.size());
526
527     s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
528 }
529
530 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
531 {
532     if (m_processWithPageCache && m_processWithPageCache != process)
533         m_processWithPageCache->releasePageCache();
534     m_processWithPageCache = process;
535 }
536
537 WebProcessProxy& WebProcessPool::createNewWebProcess()
538 {
539     ensureNetworkProcess();
540
541     Ref<WebProcessProxy> process = WebProcessProxy::create(*this);
542
543     WebProcessCreationParameters parameters;
544
545     parameters.injectedBundlePath = injectedBundlePath();
546     if (!parameters.injectedBundlePath.isEmpty())
547         SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
548
549     parameters.applicationCacheDirectory = m_configuration->applicationCacheDirectory();
550     parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName();
551
552     if (!parameters.applicationCacheDirectory.isEmpty())
553         SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle);
554
555     parameters.webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory();
556     if (!parameters.webSQLDatabaseDirectory.isEmpty())
557         SandboxExtension::createHandleForReadWriteDirectory(parameters.webSQLDatabaseDirectory, parameters.webSQLDatabaseDirectoryExtensionHandle);
558
559     parameters.mediaCacheDirectory = m_configuration->mediaCacheDirectory();
560     if (!parameters.mediaCacheDirectory.isEmpty())
561         SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaCacheDirectory, parameters.mediaCacheDirectoryExtensionHandle);
562
563 #if PLATFORM(IOS)
564     String cookieStorageDirectory = this->cookieStorageDirectory();
565     if (!cookieStorageDirectory.isEmpty())
566         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
567
568     String containerCachesDirectory = this->webContentCachesDirectory();
569     if (!containerCachesDirectory.isEmpty())
570         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
571
572     String containerTemporaryDirectory = this->containerTemporaryDirectory();
573     if (!containerTemporaryDirectory.isEmpty())
574         SandboxExtension::createHandleForReadWriteDirectory(containerTemporaryDirectory, parameters.containerTemporaryDirectoryExtensionHandle);
575 #endif
576
577     parameters.mediaKeyStorageDirectory = m_configuration->mediaKeysStorageDirectory();
578     if (!parameters.mediaKeyStorageDirectory.isEmpty())
579         SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaKeyStorageDirectory, parameters.mediaKeyStorageDirectoryExtensionHandle);
580
581     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
582
583     parameters.cacheModel = cacheModel();
584     parameters.languages = userPreferredLanguages();
585
586     copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegisteredAsEmptyDocument);
587     copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
588     copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy, parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy);
589     copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
590     copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal);
591     copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess);
592     copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated);
593     copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled);
594     copyToVector(m_schemesToRegisterAsAlwaysRevalidated, parameters.urlSchemesRegisteredAsAlwaysRevalidated);
595 #if ENABLE(CACHE_PARTITIONING)
596     copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned);
597 #endif
598
599     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
600     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
601
602     // FIXME: This leaves UI process and WebProcess disagreeing about the state if the client hasn't set the path.
603     // iconDatabasePath is non-empty by default, but m_iconDatabase isn't enabled in UI process unless setDatabasePath is called explicitly.
604     parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty();
605
606     parameters.terminationTimeout = 0;
607
608     parameters.textCheckerState = TextChecker::state();
609
610     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
611
612     parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
613
614 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
615     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
616     supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions);
617 #endif
618
619     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
620     copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins);
621
622     parameters.memoryCacheDisabled = m_memoryCacheDisabled;
623
624 #if ENABLE(SERVICE_CONTROLS)
625     auto& serviceController = ServicesController::singleton();
626     parameters.hasImageServices = serviceController.hasImageServices();
627     parameters.hasSelectionServices = serviceController.hasSelectionServices();
628     parameters.hasRichContentServices = serviceController.hasRichContentServices();
629     serviceController.refreshExistingServices();
630 #endif
631
632 #if ENABLE(NETSCAPE_PLUGIN_API)
633     parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
634 #endif
635
636 #if OS(LINUX)
637     parameters.shouldEnableMemoryPressureReliefLogging = true;
638     if (MemoryPressureMonitor::isEnabled())
639         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
640 #endif
641
642     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
643
644     // Add any platform specific parameters
645     platformInitializeWebProcess(parameters);
646
647     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this);
648     if (!injectedBundleInitializationUserData)
649         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
650     parameters.initializationUserData = UserData(process->transformObjectsToHandles(injectedBundleInitializationUserData.get()));
651
652     process->send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
653
654 #if PLATFORM(COCOA)
655     process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
656 #endif
657
658     if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
659         process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
660
661     if (m_automationSession)
662         process->send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0);
663
664     m_processes.append(process.ptr());
665
666     ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
667
668 #if ENABLE(REMOTE_INSPECTOR)
669     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
670     Inspector::RemoteInspector::singleton(); 
671 #endif
672
673     return process;
674 }
675
676 void WebProcessPool::warmInitialProcess()  
677 {
678     if (m_haveInitialEmptyProcess) {
679         ASSERT(!m_processes.isEmpty());
680         return;
681     }
682
683     if (m_processes.size() >= maximumNumberOfProcesses())
684         return;
685
686     createNewWebProcess();
687     m_haveInitialEmptyProcess = true;
688 }
689
690 void WebProcessPool::enableProcessTermination()
691 {
692     m_processTerminationEnabled = true;
693     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
694     for (size_t i = 0; i < processes.size(); ++i) {
695         if (shouldTerminate(processes[i].get()))
696             processes[i]->terminate();
697     }
698 }
699
700 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
701 {
702     ASSERT(m_processes.contains(process));
703
704     if (!m_processTerminationEnabled)
705         return false;
706
707     return true;
708 }
709
710 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
711 {
712     ASSERT(m_processes.contains(process));
713
714     if (!m_visitedLinksPopulated) {
715         populateVisitedLinks();
716         m_visitedLinksPopulated = true;
717     }
718
719     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
720     // so check if it needs to be started here
721     if (m_memorySamplerEnabled) {
722         SandboxExtension::Handle sampleLogSandboxHandle;        
723         double now = WTF::currentTime();
724         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now), process->processIdentifier());
725         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
726         
727         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
728     }
729
730     if (m_configuration->fullySynchronousModeIsAllowedForTesting())
731         process->connection()->allowFullySynchronousModeForTesting();
732
733     if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
734         process->connection()->ignoreTimeoutsForTesting();
735
736     m_connectionClient.didCreateConnection(this, process->webConnection());
737 }
738
739 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
740 {
741     ASSERT(m_processes.contains(process));
742
743     if (m_haveInitialEmptyProcess && process == m_processes.last())
744         m_haveInitialEmptyProcess = false;
745
746     // 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.
747     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
748     RefPtr<WebProcessProxy> protect(process);
749     if (m_processWithPageCache == process)
750         m_processWithPageCache = nullptr;
751
752     static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
753
754     m_processes.removeFirst(process);
755
756 #if ENABLE(GAMEPAD)
757     if (m_processesUsingGamepads.contains(process))
758         processStoppedUsingGamepads(*process);
759 #endif
760 }
761
762 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit()
763 {
764     if (m_processes.size() < maximumNumberOfProcesses())
765         return createNewWebProcess();
766
767     // Choose the process with fewest pages.
768     auto& process = *std::min_element(m_processes.begin(), m_processes.end(), [](const RefPtr<WebProcessProxy>& a, const RefPtr<WebProcessProxy>& b) {
769         return a->pageCount() < b->pageCount();
770     });
771
772     return *process;
773 }
774
775 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
776 {
777     if (!pageConfiguration->pageGroup())
778         pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
779     if (!pageConfiguration->preferences())
780         pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
781     if (!pageConfiguration->userContentController())
782         pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
783     if (!pageConfiguration->visitedLinkStore())
784         pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
785     if (!pageConfiguration->websiteDataStore()) {
786         ASSERT(!pageConfiguration->sessionID().isValid());
787         pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
788         pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? SessionID::legacyPrivateSessionID() : SessionID::defaultSessionID());
789     }
790
791     RefPtr<WebProcessProxy> process;
792     if (m_haveInitialEmptyProcess) {
793         process = m_processes.last();
794         m_haveInitialEmptyProcess = false;
795     } else if (pageConfiguration->relatedPage()) {
796         // Sharing processes, e.g. when creating the page via window.open().
797         process = &pageConfiguration->relatedPage()->process();
798     } else
799         process = &createNewWebProcessRespectingProcessCountLimit();
800
801     return process->createWebPage(pageClient, WTFMove(pageConfiguration));
802 }
803
804 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
805 {
806     DownloadProxy* downloadProxy = createDownloadProxy(request);
807     SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : SessionID::defaultSessionID();
808
809     if (networkProcess()) {
810         ResourceRequest updatedRequest(request);
811         // Request's firstPartyForCookies will be used as Original URL of the download request.
812         // We set the value to top level document's URL.
813         if (initiatingPage)
814             updatedRequest.setFirstPartyForCookies(URL(URL(), initiatingPage->pageLoadState().url()));
815         else
816             updatedRequest.setFirstPartyForCookies(URL());
817         networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest), 0);
818         return downloadProxy;
819     }
820
821     return downloadProxy;
822 }
823
824 DownloadProxy* WebProcessPool::resumeDownload(const API::Data* resumeData, const String& path)
825 {
826     DownloadProxy* downloadProxy = createDownloadProxy(ResourceRequest());
827
828     SandboxExtension::Handle sandboxExtensionHandle;
829     if (!path.isEmpty())
830         SandboxExtension::createHandle(path, SandboxExtension::ReadWrite, sandboxExtensionHandle);
831
832     if (networkProcess()) {
833         // 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.
834         networkProcess()->send(Messages::NetworkProcess::ResumeDownload(SessionID::defaultSessionID(), downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
835         return downloadProxy;
836     }
837
838     return downloadProxy;
839 }
840
841 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
842 {
843     for (auto& process : m_processes) {
844         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
845         process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
846     }
847 }
848
849 void WebProcessPool::populateVisitedLinks()
850 {
851     m_historyClient->populateVisitedLinks(*this);
852 }
853
854 WebProcessPool::Statistics& WebProcessPool::statistics()
855 {
856     static Statistics statistics = Statistics();
857
858     return statistics;
859 }
860
861 #if ENABLE(NETSCAPE_PLUGIN_API)
862 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
863 {
864     Vector<String> directories;
865     directories.append(directory);
866
867     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
868 }
869 #endif // ENABLE(NETSCAPE_PLUGIN_API)
870
871 pid_t WebProcessPool::networkProcessIdentifier()
872 {
873     if (!m_networkProcess)
874         return 0;
875
876     return m_networkProcess->processIdentifier();
877 }
878
879 pid_t WebProcessPool::databaseProcessIdentifier()
880 {
881 #if ENABLE(DATABASE_PROCESS)
882     if (!m_databaseProcess)
883         return 0;
884
885     return m_databaseProcess->processIdentifier();
886 #else
887     return 0;
888 #endif
889 }
890
891 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
892 {
893     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
894     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
895 }
896
897 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
898 {
899     m_shouldUseFontSmoothing = useFontSmoothing;
900     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
901 }
902
903 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
904 {
905     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
906     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
907 }
908
909 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
910 {
911     m_schemesToRegisterAsSecure.add(urlScheme);
912     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
913 }
914
915 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
916 {
917     m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
918     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
919 }
920
921 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
922 {
923     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
924     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
925 }
926
927 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
928 {
929     m_canHandleHTTPSServerTrustEvaluation = value;
930     if (m_networkProcess) {
931         m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
932         return;
933     }
934 }
935
936 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
937 {
938     m_schemesToRegisterAsLocal.add(urlScheme);
939     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
940 }
941
942 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
943 {
944     m_schemesToRegisterAsNoAccess.add(urlScheme);
945     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
946 }
947
948 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
949 {
950     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
951     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
952 }
953
954 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
955 {
956     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
957     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
958 }
959
960 HashSet<String, ASCIICaseInsensitiveHash>& WebProcessPool::globalURLSchemesWithCustomProtocolHandlers()
961 {
962     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> set;
963     return set;
964 }
965
966 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
967 {
968     if (!urlScheme)
969         return;
970
971     globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
972     for (auto* processPool : allProcessPools())
973         processPool->registerSchemeForCustomProtocol(urlScheme);
974 }
975
976 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
977 {
978     if (!urlScheme)
979         return;
980
981     globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
982     for (auto* processPool : allProcessPools())
983         processPool->unregisterSchemeForCustomProtocol(urlScheme);
984 }
985
986 #if ENABLE(CACHE_PARTITIONING)
987 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
988 {
989     m_schemesToRegisterAsCachePartitioned.add(urlScheme);
990     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
991 }
992 #endif
993
994 void WebProcessPool::setCacheModel(CacheModel cacheModel)
995 {
996     m_configuration->setCacheModel(cacheModel);
997     sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
998
999     if (m_networkProcess)
1000         m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
1001 }
1002
1003 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
1004 {
1005     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
1006 }
1007
1008 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request)
1009 {
1010     return ensureNetworkProcess().createDownloadProxy(request);
1011 }
1012
1013 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
1014 {
1015     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
1016 }
1017
1018 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
1019 {
1020     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
1021 }
1022
1023 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName)
1024 {
1025     m_messageReceiverMap.removeMessageReceiver(messageReceiverName);
1026 }
1027
1028 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
1029 {
1030     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
1031 }
1032
1033 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
1034 {
1035     return m_messageReceiverMap.dispatchMessage(connection, decoder);
1036 }
1037
1038 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
1039 {
1040     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1041 }
1042
1043 void WebProcessPool::setEnhancedAccessibility(bool flag)
1044 {
1045     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1046 }
1047     
1048 void WebProcessPool::startMemorySampler(const double interval)
1049 {    
1050     // For new WebProcesses we will also want to start the Memory Sampler
1051     m_memorySamplerEnabled = true;
1052     m_memorySamplerInterval = interval;
1053     
1054     // For UIProcess
1055 #if ENABLE(MEMORY_SAMPLER)
1056     WebMemorySampler::singleton()->start(interval);
1057 #endif
1058     
1059     // For WebProcess
1060     SandboxExtension::Handle sampleLogSandboxHandle;    
1061     double now = WTF::currentTime();
1062     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now));
1063     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
1064     
1065     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1066 }
1067
1068 void WebProcessPool::stopMemorySampler()
1069 {    
1070     // For WebProcess
1071     m_memorySamplerEnabled = false;
1072     
1073     // For UIProcess
1074 #if ENABLE(MEMORY_SAMPLER)
1075     WebMemorySampler::singleton()->stop();
1076 #endif
1077
1078     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1079 }
1080
1081 void WebProcessPool::setIconDatabasePath(const String& path)
1082 {
1083     m_overrideIconDatabasePath = path;
1084     if (!m_overrideIconDatabasePath.isEmpty()) {
1085         // This implicitly enables the database on UI process side.
1086         m_iconDatabase->setDatabasePath(path);
1087     }
1088 }
1089
1090 String WebProcessPool::iconDatabasePath() const
1091 {
1092     if (!m_overrideIconDatabasePath.isNull())
1093         return m_overrideIconDatabasePath;
1094
1095     return platformDefaultIconDatabasePath();
1096 }
1097
1098 void WebProcessPool::useTestingNetworkSession()
1099 {
1100     ASSERT(m_processes.isEmpty());
1101     ASSERT(!m_networkProcess);
1102
1103     if (m_networkProcess)
1104         return;
1105
1106     if (!m_processes.isEmpty())
1107         return;
1108
1109     m_shouldUseTestingNetworkSession = true;
1110 }
1111
1112 void WebProcessPool::clearCachedCredentials()
1113 {
1114     sendToAllProcesses(Messages::WebProcess::ClearCachedCredentials());
1115     if (m_networkProcess)
1116         m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1117 }
1118
1119 void WebProcessPool::terminateDatabaseProcess()
1120 {
1121 #if ENABLE(DATABASE_PROCESS)
1122     if (!m_databaseProcess)
1123         return;
1124
1125     m_databaseProcess->terminate();
1126     m_databaseProcess = nullptr;
1127 #endif
1128 }
1129
1130 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1131 {
1132     if (m_networkProcess)
1133         m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1134 }
1135
1136 void WebProcessPool::updateAutomationCapabilities() const
1137 {
1138 #if ENABLE(REMOTE_INSPECTOR)
1139     Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1140 #endif
1141 }
1142
1143 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1144 {
1145     m_automationSession = WTFMove(automationSession);
1146
1147 #if ENABLE(REMOTE_INSPECTOR)
1148     if (m_automationSession) {
1149         m_automationSession->init();
1150         m_automationSession->setProcessPool(this);
1151
1152         sendToAllProcesses(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()));
1153     } else
1154         sendToAllProcesses(Messages::WebProcess::DestroyAutomationSessionProxy());
1155 #endif
1156 }
1157
1158 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1159 {
1160 #if PLATFORM(COCOA)
1161     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1162 #else
1163     UNUSED_PARAM(enabled);
1164 #endif
1165 }
1166
1167 bool WebProcessPool::httpPipeliningEnabled() const
1168 {
1169 #if PLATFORM(COCOA)
1170     return ResourceRequest::httpPipeliningEnabled();
1171 #else
1172     return false;
1173 #endif
1174 }
1175
1176 void WebProcessPool::getStatistics(uint32_t statisticsMask, std::function<void (API::Dictionary*, CallbackBase::Error)> callbackFunction)
1177 {
1178     if (!statisticsMask) {
1179         callbackFunction(nullptr, CallbackBase::Error::Unknown);
1180         return;
1181     }
1182
1183     RefPtr<StatisticsRequest> request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1184
1185     if (statisticsMask & StatisticsRequestTypeWebContent)
1186         requestWebContentStatistics(request.get());
1187     
1188     if (statisticsMask & StatisticsRequestTypeNetworking)
1189         requestNetworkingStatistics(request.get());
1190 }
1191
1192 void WebProcessPool::requestWebContentStatistics(StatisticsRequest* request)
1193 {
1194     // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1195 }
1196
1197 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest* request)
1198 {
1199     if (!m_networkProcess) {
1200         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1201         return;
1202     }
1203
1204     uint64_t requestID = request->addOutstandingRequest();
1205     m_statisticsRequests.set(requestID, request);
1206     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1207 }
1208
1209 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1210 {
1211     auto* webProcessProxy = WebProcessProxy::fromConnection(&connection);
1212     if (!webProcessProxy)
1213         return;
1214     m_injectedBundleClient.didReceiveMessageFromInjectedBundle(this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1215 }
1216
1217 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1218 {
1219     auto* webProcessProxy = WebProcessProxy::fromConnection(&connection);
1220     if (!webProcessProxy)
1221         return;
1222
1223     RefPtr<API::Object> returnData;
1224     m_injectedBundleClient.didReceiveSynchronousMessageFromInjectedBundle(this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1225     returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1226 }
1227
1228 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1229 {
1230     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1231     if (!request) {
1232         LOG_ERROR("Cannot report networking statistics.");
1233         return;
1234     }
1235
1236     request->completedRequest(requestID, statisticsData);
1237 }
1238
1239 #if ENABLE(GAMEPAD)
1240
1241 void WebProcessPool::startedUsingGamepads(IPC::Connection& connection)
1242 {
1243     auto* proxy = WebProcessProxy::fromConnection(&connection);
1244     if (!proxy)
1245         return;
1246
1247     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1248
1249     ASSERT(!m_processesUsingGamepads.contains(proxy));
1250     m_processesUsingGamepads.add(proxy);
1251
1252     if (!wereAnyProcessesUsingGamepads)
1253         UIGamepadProvider::singleton().processPoolStartedUsingGamepads(*this);
1254 }
1255
1256 void WebProcessPool::stoppedUsingGamepads(IPC::Connection& connection)
1257 {
1258     auto* proxy = WebProcessProxy::fromConnection(&connection);
1259     if (!proxy)
1260         return;
1261
1262     ASSERT(m_processesUsingGamepads.contains(proxy));
1263     processStoppedUsingGamepads(*proxy);
1264 }
1265
1266 void WebProcessPool::processStoppedUsingGamepads(WebProcessProxy& process)
1267 {
1268     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1269
1270     ASSERT(m_processesUsingGamepads.contains(&process));
1271     m_processesUsingGamepads.remove(&process);
1272
1273     if (wereAnyProcessesUsingGamepads && m_processesUsingGamepads.isEmpty())
1274         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
1275 }
1276
1277 void WebProcessPool::gamepadConnected(const UIGamepad& gamepad)
1278 {
1279     for (auto& process : m_processesUsingGamepads)
1280         process->send(Messages::WebProcess::GamepadConnected(gamepad.gamepadData()), 0);
1281 }
1282
1283 void WebProcessPool::gamepadDisconnected(const UIGamepad& gamepad)
1284 {
1285     for (auto& process : m_processesUsingGamepads)
1286         process->send(Messages::WebProcess::GamepadDisconnected(gamepad.index()), 0);
1287 }
1288
1289 void WebProcessPool::setInitialConnectedGamepads(const Vector<std::unique_ptr<UIGamepad>>& gamepads)
1290 {
1291     Vector<GamepadData> gamepadDatas;
1292     gamepadDatas.resize(gamepads.size());
1293     for (size_t i = 0; i < gamepads.size(); ++i) {
1294         if (!gamepads[i])
1295             continue;
1296         gamepadDatas[i] = gamepads[i]->gamepadData();
1297     }
1298
1299     for (auto& process : m_processesUsingGamepads)
1300         process->send(Messages::WebProcess::SetInitialGamepads(gamepadDatas), 0);
1301 }
1302
1303 #endif // ENABLE(GAMEPAD)
1304
1305 void WebProcessPool::garbageCollectJavaScriptObjects()
1306 {
1307     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1308 }
1309
1310 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1311 {
1312     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1313 }
1314
1315 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, SessionID sessionID)
1316 {
1317     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1318 }
1319
1320 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, SessionID sessionID)
1321 {
1322     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1323 }
1324
1325 PassRefPtr<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1326 {
1327     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1328 }
1329
1330 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1331 {
1332     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1333 }
1334
1335 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1336 {
1337     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1338 }
1339
1340 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, double time)
1341 {
1342     m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1343 }
1344
1345 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1346 {
1347     sendToNetworkingProcess(Messages::CustomProtocolManager::RegisterScheme(scheme));
1348 }
1349
1350 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1351 {
1352     sendToNetworkingProcess(Messages::CustomProtocolManager::UnregisterScheme(scheme));
1353 }
1354
1355 #if ENABLE(NETSCAPE_PLUGIN_API)
1356 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1357 {
1358     HashMap<String, HashMap<String, uint8_t>> policiesByIdentifier;
1359     if (m_pluginLoadClientPolicies.contains(host))
1360         policiesByIdentifier = m_pluginLoadClientPolicies.get(host);
1361
1362     HashMap<String, uint8_t> versionsToPolicies;
1363     if (policiesByIdentifier.contains(bundleIdentifier))
1364         versionsToPolicies = policiesByIdentifier.get(bundleIdentifier);
1365
1366     versionsToPolicies.set(versionString, policy);
1367     policiesByIdentifier.set(bundleIdentifier, versionsToPolicies);
1368     m_pluginLoadClientPolicies.set(host, policiesByIdentifier);
1369
1370     sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1371 }
1372
1373 void WebProcessPool::clearPluginClientPolicies()
1374 {
1375     m_pluginLoadClientPolicies.clear();
1376     sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1377 }
1378 #endif
1379
1380 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1381 {
1382     m_memoryCacheDisabled = disabled;
1383     sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1384 }
1385
1386 void WebProcessPool::setFontWhitelist(API::Array* array)
1387 {
1388     m_fontWhitelist.clear();
1389     if (array) {
1390         for (size_t i = 0; i < array->size(); ++i) {
1391             if (API::String* font = array->at<API::String>(i))
1392                 m_fontWhitelist.append(font->string());
1393         }
1394     }
1395 }
1396
1397 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1398 {
1399     // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1400     // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1401     // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1402     static int maximumTimerThrottlePerPageInMS = 200 * 100;
1403
1404     int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1405     sendToAllProcesses(Messages::WebProcess::SetHiddenPageTimerThrottlingIncreaseLimit(limitInMilliseconds));
1406 }
1407
1408 } // namespace WebKit