Try to avoid creating the default WKWebsiteDataStore until its actually needed.
[WebKit-https.git] / Source / WebKit / UIProcess / WebProcessPool.cpp
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebProcessPool.h"
28
29 #include "APIArray.h"
30 #include "APIAutomationClient.h"
31 #include "APICustomProtocolManagerClient.h"
32 #include "APIDownloadClient.h"
33 #include "APIHTTPCookieStore.h"
34 #include "APIInjectedBundleClient.h"
35 #include "APILegacyContextHistoryClient.h"
36 #include "APIPageConfiguration.h"
37 #include "APIProcessPoolConfiguration.h"
38 #include "DownloadProxy.h"
39 #include "DownloadProxyMessages.h"
40 #include "GamepadData.h"
41 #include "HighPerformanceGraphicsUsageSampler.h"
42 #include "LegacyCustomProtocolManagerMessages.h"
43 #include "LogInitialization.h"
44 #include "NetworkProcessCreationParameters.h"
45 #include "NetworkProcessMessages.h"
46 #include "NetworkProcessProxy.h"
47 #include "PerActivityStateCPUUsageSampler.h"
48 #include "SandboxExtension.h"
49 #include "StatisticsData.h"
50 #include "StorageProcessCreationParameters.h"
51 #include "StorageProcessMessages.h"
52 #include "TextChecker.h"
53 #include "UIGamepad.h"
54 #include "UIGamepadProvider.h"
55 #include "WKContextPrivate.h"
56 #include "WebAutomationSession.h"
57 #include "WebCertificateInfo.h"
58 #include "WebContextSupplement.h"
59 #include "WebCookieManagerProxy.h"
60 #include "WebCoreArgumentCoders.h"
61 #include "WebGeolocationManagerProxy.h"
62 #include "WebKit2Initialize.h"
63 #include "WebMemorySampler.h"
64 #include "WebNotificationManagerProxy.h"
65 #include "WebPageGroup.h"
66 #include "WebPreferences.h"
67 #include "WebPreferencesKeys.h"
68 #include "WebProcessCreationParameters.h"
69 #include "WebProcessMessages.h"
70 #include "WebProcessPoolMessages.h"
71 #include "WebProcessProxy.h"
72 #include "WebsiteDataStore.h"
73 #include "WebsiteDataStoreParameters.h"
74 #include <WebCore/ApplicationCacheStorage.h>
75 #include <WebCore/LinkHash.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.localStorageDirectory = processPoolConfiguration.localStorageDirectory();
194     configuration.webSQLDatabaseDirectory = processPoolConfiguration.webSQLDatabaseDirectory();
195     configuration.applicationCacheDirectory = processPoolConfiguration.applicationCacheDirectory();
196     configuration.applicationCacheFlatFileSubdirectoryName = processPoolConfiguration.applicationCacheFlatFileSubdirectoryName();
197     configuration.mediaCacheDirectory = processPoolConfiguration.mediaCacheDirectory();
198     configuration.mediaKeysStorageDirectory = processPoolConfiguration.mediaKeysStorageDirectory();
199     configuration.resourceLoadStatisticsDirectory = processPoolConfiguration.resourceLoadStatisticsDirectory();
200     configuration.cacheStorageDirectory = processPoolConfiguration.cacheStorageDirectory();
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     m_networkProcess = NetworkProcessProxy::create(*this);
422
423     NetworkProcessCreationParameters parameters;
424
425     parameters.privateBrowsingEnabled = WebPreferences::anyPagesAreUsingPrivateBrowsing();
426
427     parameters.cacheModel = cacheModel();
428     parameters.diskCacheSizeOverride = m_configuration->diskCacheSizeOverride();
429     parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
430
431     for (auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
432         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
433
434     for (auto& scheme : m_urlSchemesRegisteredForCustomProtocols)
435         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
436
437     parameters.cacheStorageDirectory = m_configuration->cacheStorageDirectory();
438     if (!parameters.cacheStorageDirectory.isEmpty())
439         SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
440
441     parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
442     if (!parameters.diskCacheDirectory.isEmpty())
443         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
444 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
445     parameters.shouldEnableNetworkCacheSpeculativeRevalidation = m_configuration->diskCacheSpeculativeValidationEnabled();
446 #endif
447
448 #if PLATFORM(IOS)
449     String cookieStorageDirectory = this->cookieStorageDirectory();
450     if (!cookieStorageDirectory.isEmpty())
451         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
452
453     String containerCachesDirectory = this->networkingCachesDirectory();
454     if (!containerCachesDirectory.isEmpty())
455         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
456
457     String parentBundleDirectory = this->parentBundleDirectory();
458     if (!parentBundleDirectory.isEmpty())
459         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
460 #endif
461
462 #if OS(LINUX)
463     if (MemoryPressureMonitor::isEnabled())
464         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
465 #endif
466
467     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
468     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
469
470     // Add any platform specific parameters
471     platformInitializeNetworkProcess(parameters);
472
473     // Initialize the network process.
474     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
475
476 #if PLATFORM(COCOA)
477     m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
478 #endif
479
480     if (m_didNetworkProcessCrash) {
481         m_didNetworkProcessCrash = false;
482         for (auto& process : m_processes)
483             process->reinstateNetworkProcessAssertionState(*m_networkProcess);
484         if (m_websiteDataStore)
485             m_websiteDataStore->websiteDataStore().networkProcessDidCrash();
486     }
487
488     if (withWebsiteDataStore)
489         m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(withWebsiteDataStore->parameters()), 0);
490
491     return *m_networkProcess;
492 }
493
494 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy& networkProcessProxy, Vector<Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>>&& pendingReplies)
495 {
496     networkProcessFailedToLaunch(networkProcessProxy);
497     ASSERT(!m_networkProcess);
498     if (pendingReplies.isEmpty())
499         return;
500     auto& newNetworkProcess = ensureNetworkProcess();
501     for (auto& reply : pendingReplies)
502         newNetworkProcess.getNetworkProcessConnection(WTFMove(reply));
503 }
504
505 void WebProcessPool::networkProcessFailedToLaunch(NetworkProcessProxy& networkProcessProxy)
506 {
507     ASSERT(m_networkProcess);
508     ASSERT(&networkProcessProxy == m_networkProcess.get());
509     m_didNetworkProcessCrash = true;
510
511     for (auto& supplement : m_supplements.values())
512         supplement->processDidClose(&networkProcessProxy);
513
514     m_client.networkProcessDidCrash(this);
515
516     // Leave the process proxy around during client call, so that the client could query the process identifier.
517     m_networkProcess = nullptr;
518 }
519
520 void WebProcessPool::getNetworkProcessConnection(Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>&& reply)
521 {
522     ensureNetworkProcess();
523     ASSERT(m_networkProcess);
524
525     m_networkProcess->getNetworkProcessConnection(WTFMove(reply));
526 }
527
528 void WebProcessPool::ensureStorageProcessAndWebsiteDataStore(WebsiteDataStore* relevantDataStore)
529 {
530     // *********
531     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
532     // *********
533
534     if (!m_storageProcess) {
535         auto parameters = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().storageProcessParameters() : (relevantDataStore ? relevantDataStore->storageProcessParameters() : API::WebsiteDataStore::defaultDataStore()->websiteDataStore().storageProcessParameters());
536
537         ASSERT(parameters.sessionID.isValid());
538
539 #if ENABLE(INDEXED_DATABASE)
540         if (parameters.indexedDatabaseDirectory.isEmpty()) {
541             parameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
542             SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
543         }
544 #endif
545
546         m_storageProcess = StorageProcessProxy::create(this);
547         m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(parameters), 0);
548     }
549
550     if (!relevantDataStore || !m_websiteDataStore || relevantDataStore == &m_websiteDataStore->websiteDataStore())
551         return;
552
553     m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(relevantDataStore->storageProcessParameters()), 0);
554 }
555
556 void WebProcessPool::getStorageProcessConnection(Ref<Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply>&& reply)
557 {
558     ensureStorageProcessAndWebsiteDataStore(nullptr);
559
560     m_storageProcess->getStorageProcessConnection(WTFMove(reply));
561 }
562
563 void WebProcessPool::storageProcessCrashed(StorageProcessProxy* storageProcessProxy)
564 {
565     ASSERT(m_storageProcess);
566     ASSERT(storageProcessProxy == m_storageProcess.get());
567
568     for (auto& supplement : m_supplements.values())
569         supplement->processDidClose(storageProcessProxy);
570
571     m_client.storageProcessDidCrash(this);
572     m_storageProcess = nullptr;
573 }
574
575 void WebProcessPool::willStartUsingPrivateBrowsing()
576 {
577     for (auto* processPool : allProcessPools())
578         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
579 }
580
581 void WebProcessPool::willStopUsingPrivateBrowsing()
582 {
583     for (auto* processPool : allProcessPools())
584         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
585 }
586
587 void WebProcessPool::windowServerConnectionStateChanged()
588 {
589     size_t processCount = m_processes.size();
590     for (size_t i = 0; i < processCount; ++i)
591         m_processes[i]->windowServerConnectionStateChanged();
592 }
593
594 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
595 {
596     if (networkProcess()) {
597         if (privateBrowsingEnabled)
598             networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession({PAL::SessionID::legacyPrivateSessionID(), { }, { }, { }, { }, { }}), 0);
599         else
600             networkProcess()->send(Messages::NetworkProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()), 0);
601     }
602
603     if (privateBrowsingEnabled)
604         sendToAllProcesses(Messages::WebProcess::EnsurePrivateBrowsingSession(PAL::SessionID::legacyPrivateSessionID()));
605     else
606         sendToAllProcesses(Messages::WebProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()));
607 }
608
609 void (*s_invalidMessageCallback)(WKStringRef messageName);
610
611 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
612 {
613     s_invalidMessageCallback = invalidMessageCallback;
614 }
615
616 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
617 {
618     if (!s_invalidMessageCallback)
619         return;
620
621     StringBuilder messageNameStringBuilder;
622     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
623     messageNameStringBuilder.append('.');
624     messageNameStringBuilder.append(messageName.data(), messageName.size());
625
626     s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
627 }
628
629 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
630 {
631     if (m_processWithPageCache && m_processWithPageCache != process)
632         m_processWithPageCache->releasePageCache();
633     m_processWithPageCache = process;
634 }
635
636 void WebProcessPool::resolvePathsForSandboxExtensions()
637 {
638     m_resolvedPaths.injectedBundlePath = resolvePathForSandboxExtension(injectedBundlePath());
639     m_resolvedPaths.applicationCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory());
640     m_resolvedPaths.webSQLDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory());
641     m_resolvedPaths.mediaCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory());
642     m_resolvedPaths.mediaKeyStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory());
643     m_resolvedPaths.indexedDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory());
644
645     m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.reserveCapacity(m_configuration->additionalReadAccessAllowedPaths().size());
646     for (const auto& path : m_configuration->additionalReadAccessAllowedPaths())
647         m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.uncheckedAppend(resolvePathForSandboxExtension(path.data()));
648
649     platformResolvePathsForSandboxExtensions();
650 }
651
652 WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDataStore)
653 {
654     ensureNetworkProcess();
655
656     Ref<WebProcessProxy> process = WebProcessProxy::create(*this, websiteDataStore);
657
658     WebProcessCreationParameters parameters;
659
660     websiteDataStore.resolveDirectoriesIfNecessary();
661
662     parameters.injectedBundlePath = m_resolvedPaths.injectedBundlePath;
663     if (!parameters.injectedBundlePath.isEmpty())
664         SandboxExtension::createHandleWithoutResolvingPath(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
665
666     parameters.additionalSandboxExtensionHandles.allocate(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size());
667     for (size_t i = 0, size = m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size(); i < size; ++i)
668         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths[i], SandboxExtension::ReadOnly, parameters.additionalSandboxExtensionHandles[i]);
669
670     parameters.applicationCacheDirectory = websiteDataStore.resolvedApplicationCacheDirectory();
671     if (parameters.applicationCacheDirectory.isEmpty())
672         parameters.applicationCacheDirectory = m_resolvedPaths.applicationCacheDirectory;
673     if (!parameters.applicationCacheDirectory.isEmpty())
674         SandboxExtension::createHandleWithoutResolvingPath(parameters.applicationCacheDirectory, SandboxExtension::ReadWrite, parameters.applicationCacheDirectoryExtensionHandle);
675
676     parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName();
677
678     parameters.webSQLDatabaseDirectory = websiteDataStore.resolvedDatabaseDirectory();
679     if (parameters.webSQLDatabaseDirectory.isEmpty())
680         parameters.webSQLDatabaseDirectory = m_resolvedPaths.webSQLDatabaseDirectory;
681     if (!parameters.webSQLDatabaseDirectory.isEmpty())
682         SandboxExtension::createHandleWithoutResolvingPath(parameters.webSQLDatabaseDirectory, SandboxExtension::ReadWrite, parameters.webSQLDatabaseDirectoryExtensionHandle);
683
684     parameters.mediaCacheDirectory = websiteDataStore.resolvedMediaCacheDirectory();
685     if (parameters.mediaCacheDirectory.isEmpty())
686         parameters.mediaCacheDirectory = m_resolvedPaths.mediaCacheDirectory;
687     if (!parameters.mediaCacheDirectory.isEmpty())
688         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaCacheDirectory, SandboxExtension::ReadWrite, parameters.mediaCacheDirectoryExtensionHandle);
689
690     parameters.mediaKeyStorageDirectory = websiteDataStore.resolvedMediaKeysDirectory();
691     if (parameters.mediaKeyStorageDirectory.isEmpty())
692         parameters.mediaKeyStorageDirectory = m_resolvedPaths.mediaKeyStorageDirectory;
693     if (!parameters.mediaKeyStorageDirectory.isEmpty())
694         SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaKeyStorageDirectory, SandboxExtension::ReadWrite, parameters.mediaKeyStorageDirectoryExtensionHandle);
695
696 #if PLATFORM(IOS)
697     setJavaScriptConfigurationFileEnabledFromDefaults();
698 #endif
699
700     if (javaScriptConfigurationFileEnabled()) {
701         parameters.javaScriptConfigurationDirectory = websiteDataStore.resolvedJavaScriptConfigurationDirectory();
702         if (!parameters.javaScriptConfigurationDirectory.isEmpty())
703             SandboxExtension::createHandleWithoutResolvingPath(parameters.javaScriptConfigurationDirectory, SandboxExtension::ReadWrite, parameters.javaScriptConfigurationDirectoryExtensionHandle);
704     }
705
706     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
707
708     parameters.cacheModel = cacheModel();
709     parameters.languages = userPreferredLanguages();
710
711     copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegisteredAsEmptyDocument);
712     copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
713     copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy, parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy);
714     copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
715     copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal);
716     copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess);
717     copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated);
718     copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled);
719     copyToVector(m_schemesToRegisterAsAlwaysRevalidated, parameters.urlSchemesRegisteredAsAlwaysRevalidated);
720     copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned);
721
722     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
723     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
724
725     parameters.terminationTimeout = 0_s;
726
727     parameters.textCheckerState = TextChecker::state();
728
729     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
730
731     parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
732
733 #if ENABLE(NOTIFICATIONS)
734     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
735     parameters.notificationPermissions = supplement<WebNotificationManagerProxy>()->notificationPermissions();
736 #endif
737
738     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
739     copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins);
740
741     parameters.memoryCacheDisabled = m_memoryCacheDisabled;
742
743 #if ENABLE(SERVICE_CONTROLS)
744     auto& serviceController = ServicesController::singleton();
745     parameters.hasImageServices = serviceController.hasImageServices();
746     parameters.hasSelectionServices = serviceController.hasSelectionServices();
747     parameters.hasRichContentServices = serviceController.hasRichContentServices();
748     serviceController.refreshExistingServices();
749 #endif
750
751 #if ENABLE(NETSCAPE_PLUGIN_API)
752     parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
753 #endif
754
755 #if OS(LINUX)
756     parameters.shouldEnableMemoryPressureReliefLogging = true;
757     if (MemoryPressureMonitor::isEnabled())
758         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
759 #endif
760
761 #if PLATFORM(WAYLAND) && USE(EGL)
762     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
763         parameters.waylandCompositorDisplayName = WaylandCompositor::singleton().displayName();
764 #endif
765
766     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
767 #if ENABLE(MEDIA_STREAM)
768     parameters.shouldCaptureAudioInUIProcess = m_configuration->shouldCaptureAudioInUIProcess();
769 #endif
770
771     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
772
773     // Add any platform specific parameters
774     platformInitializeWebProcess(parameters);
775
776     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient->getInjectedBundleInitializationUserData(*this);
777     if (!injectedBundleInitializationUserData)
778         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
779     parameters.initializationUserData = UserData(process->transformObjectsToHandles(injectedBundleInitializationUserData.get()));
780
781     process->send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
782
783 #if PLATFORM(COCOA)
784     process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
785 #endif
786
787     if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
788         process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(PAL::SessionID::legacyPrivateSessionID()), 0);
789
790     if (m_automationSession)
791         process->send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0);
792
793     m_processes.append(process.ptr());
794
795     ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
796
797 #if ENABLE(REMOTE_INSPECTOR)
798     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
799     Inspector::RemoteInspector::singleton(); 
800 #endif
801
802     return process;
803 }
804
805 void WebProcessPool::warmInitialProcess()  
806 {
807     if (m_haveInitialEmptyProcess) {
808         ASSERT(!m_processes.isEmpty());
809         return;
810     }
811
812     if (m_processes.size() >= maximumNumberOfProcesses())
813         return;
814
815     if (!m_websiteDataStore)
816         m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
817     createNewWebProcess(m_websiteDataStore->websiteDataStore());
818
819     m_haveInitialEmptyProcess = true;
820 }
821
822 void WebProcessPool::enableProcessTermination()
823 {
824     m_processTerminationEnabled = true;
825     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
826     for (size_t i = 0; i < processes.size(); ++i) {
827         if (shouldTerminate(processes[i].get()))
828             processes[i]->terminate();
829     }
830 }
831
832 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
833 {
834     ASSERT(m_processes.contains(process));
835
836     if (!m_processTerminationEnabled)
837         return false;
838
839     return true;
840 }
841
842 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
843 {
844     ASSERT(m_processes.contains(process));
845
846     if (!m_visitedLinksPopulated) {
847         populateVisitedLinks();
848         m_visitedLinksPopulated = true;
849     }
850
851     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
852     // so check if it needs to be started here
853     if (m_memorySamplerEnabled) {
854         SandboxExtension::Handle sampleLogSandboxHandle;        
855         double now = WTF::currentTime();
856         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now), process->processIdentifier());
857         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
858         
859         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
860     }
861
862     if (m_configuration->fullySynchronousModeIsAllowedForTesting())
863         process->connection()->allowFullySynchronousModeForTesting();
864
865     if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
866         process->connection()->ignoreTimeoutsForTesting();
867
868     m_connectionClient.didCreateConnection(this, process->webConnection());
869 }
870
871 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
872 {
873     ASSERT(m_processes.contains(process));
874
875     if (m_haveInitialEmptyProcess && process == m_processes.last())
876         m_haveInitialEmptyProcess = false;
877
878     // 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.
879     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
880     RefPtr<WebProcessProxy> protect(process);
881     if (m_processWithPageCache == process)
882         m_processWithPageCache = nullptr;
883
884     static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
885
886     m_processes.removeFirst(process);
887
888 #if ENABLE(GAMEPAD)
889     if (m_processesUsingGamepads.contains(process))
890         processStoppedUsingGamepads(*process);
891 #endif
892 }
893
894 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebsiteDataStore& websiteDataStore)
895 {
896     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=168676
897     // Once WebsiteDataStores are truly per-view instead of per-process, remove this nonsense.
898
899 #if PLATFORM(COCOA)
900     bool mustMatchDataStore = API::WebsiteDataStore::defaultDataStoreExists() && &websiteDataStore != &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
901 #else
902     bool mustMatchDataStore = false;
903 #endif
904
905     if (m_processes.size() < maximumNumberOfProcesses())
906         return createNewWebProcess(websiteDataStore);
907
908     Vector<RefPtr<WebProcessProxy>> processesMatchingDataStore;
909     if (mustMatchDataStore) {
910         for (auto& process : m_processes) {
911             if (&process->websiteDataStore() == &websiteDataStore)
912                 processesMatchingDataStore.append(process);
913         }
914
915         if (processesMatchingDataStore.isEmpty())
916             return createNewWebProcess(websiteDataStore);
917     }
918
919     // Choose the process with fewest pages.
920     auto* processes = mustMatchDataStore ? &processesMatchingDataStore : &m_processes;
921     ASSERT(!processes->isEmpty());
922     auto& process = *std::min_element(processes->begin(), processes->end(), [](const RefPtr<WebProcessProxy>& a, const RefPtr<WebProcessProxy>& b) {
923         return a->pageCount() < b->pageCount();
924     });
925
926     return *process;
927 }
928
929 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
930 {
931     if (!pageConfiguration->pageGroup())
932         pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
933     if (!pageConfiguration->preferences())
934         pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
935     if (!pageConfiguration->userContentController())
936         pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
937     if (!pageConfiguration->visitedLinkStore())
938         pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
939
940     if (!pageConfiguration->websiteDataStore()) {
941         // We try to avoid creating the default data store as long as possible.
942         // But if there is an attempt to create a web page without any specified data store, then we have to create it.
943         if (!m_websiteDataStore)
944             m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
945
946         ASSERT(!pageConfiguration->sessionID().isValid());
947         pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
948         pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? PAL::SessionID::legacyPrivateSessionID() : m_websiteDataStore->websiteDataStore().sessionID());
949     }
950
951     RefPtr<WebProcessProxy> process;
952     if (m_haveInitialEmptyProcess) {
953         process = m_processes.last();
954         m_haveInitialEmptyProcess = false;
955     } else if (pageConfiguration->relatedPage()) {
956         // Sharing processes, e.g. when creating the page via window.open().
957         process = &pageConfiguration->relatedPage()->process();
958     } else
959         process = &createNewWebProcessRespectingProcessCountLimit(pageConfiguration->websiteDataStore()->websiteDataStore());
960
961     return process->createWebPage(pageClient, WTFMove(pageConfiguration));
962 }
963
964 void WebProcessPool::pageAddedToProcess(WebPageProxy& page)
965 {
966     auto result = m_sessionToPagesMap.add(page.sessionID(), HashSet<WebPageProxy*>()).iterator->value.add(&page);
967     ASSERT_UNUSED(result, result.isNewEntry);
968
969     auto sessionID = page.sessionID();
970     if (sessionID.isEphemeral()) {
971         // FIXME: Merge NetworkProcess::EnsurePrivateBrowsingSession and NetworkProcess::AddWebsiteDataStore into one message type.
972         // They do basically the same thing.
973         ASSERT(page.websiteDataStore().parameters().sessionID == sessionID);
974         sendToNetworkingProcess(Messages::NetworkProcess::EnsurePrivateBrowsingSession(page.websiteDataStore().parameters()));
975         page.process().send(Messages::WebProcess::EnsurePrivateBrowsingSession(sessionID), 0);
976     } else if (sessionID != PAL::SessionID::defaultSessionID()) {
977         sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
978         page.process().send(Messages::WebProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()), 0);
979
980 #if ENABLE(INDEXED_DATABASE)
981         if (!page.websiteDataStore().resolvedIndexedDatabaseDirectory().isEmpty())
982             ensureStorageProcessAndWebsiteDataStore(&page.websiteDataStore());
983 #endif
984     }
985 }
986
987 void WebProcessPool::pageRemovedFromProcess(WebPageProxy& page)
988 {
989     auto sessionID = page.sessionID();
990     auto iterator = m_sessionToPagesMap.find(sessionID);
991     ASSERT(iterator != m_sessionToPagesMap.end());
992
993     auto takenPage = iterator->value.take(&page);
994     ASSERT_UNUSED(takenPage, takenPage == &page);
995
996     if (iterator->value.isEmpty()) {
997         m_sessionToPagesMap.remove(iterator);
998
999         if (sessionID == PAL::SessionID::defaultSessionID())
1000             return;
1001
1002         // The last user of this non-default PAL::SessionID is gone, so clean it up in the child processes.
1003         if (networkProcess())
1004             networkProcess()->send(Messages::NetworkProcess::DestroySession(sessionID), 0);
1005         page.process().send(Messages::WebProcess::DestroySession(sessionID), 0);
1006     }
1007 }
1008
1009 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
1010 {
1011     auto* downloadProxy = createDownloadProxy(request, initiatingPage);
1012     PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
1013
1014     if (initiatingPage)
1015         initiatingPage->handleDownloadRequest(downloadProxy);
1016
1017     if (networkProcess()) {
1018         ResourceRequest updatedRequest(request);
1019         // Request's firstPartyForCookies will be used as Original URL of the download request.
1020         // We set the value to top level document's URL.
1021         if (initiatingPage)
1022             updatedRequest.setFirstPartyForCookies(URL(URL(), initiatingPage->pageLoadState().url()));
1023         else
1024             updatedRequest.setFirstPartyForCookies(URL());
1025         networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest, suggestedFilename), 0);
1026         return downloadProxy;
1027     }
1028
1029     return downloadProxy;
1030 }
1031
1032 DownloadProxy* WebProcessPool::resumeDownload(const API::Data* resumeData, const String& path)
1033 {
1034     auto* downloadProxy = createDownloadProxy(ResourceRequest(), nullptr);
1035
1036     SandboxExtension::Handle sandboxExtensionHandle;
1037     if (!path.isEmpty())
1038         SandboxExtension::createHandle(path, SandboxExtension::ReadWrite, sandboxExtensionHandle);
1039
1040     if (networkProcess()) {
1041         // 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.
1042         networkProcess()->send(Messages::NetworkProcess::ResumeDownload(PAL::SessionID::defaultSessionID(), downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
1043         return downloadProxy;
1044     }
1045
1046     return downloadProxy;
1047 }
1048
1049 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
1050 {
1051     for (auto& process : m_processes) {
1052         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
1053         process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
1054     }
1055 }
1056
1057 void WebProcessPool::populateVisitedLinks()
1058 {
1059     m_historyClient->populateVisitedLinks(*this);
1060 }
1061
1062 WebProcessPool::Statistics& WebProcessPool::statistics()
1063 {
1064     static Statistics statistics = Statistics();
1065
1066     return statistics;
1067 }
1068
1069 #if ENABLE(NETSCAPE_PLUGIN_API)
1070 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
1071 {
1072     Vector<String> directories;
1073     directories.append(directory);
1074
1075     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
1076 }
1077
1078 void WebProcessPool::refreshPlugins()
1079 {
1080     m_pluginInfoStore.refresh();
1081     sendToAllProcesses(Messages::WebProcess::RefreshPlugins());
1082 }
1083
1084 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1085
1086 pid_t WebProcessPool::networkProcessIdentifier()
1087 {
1088     if (!m_networkProcess)
1089         return 0;
1090
1091     return m_networkProcess->processIdentifier();
1092 }
1093
1094 pid_t WebProcessPool::storageProcessIdentifier()
1095 {
1096     if (!m_storageProcess)
1097         return 0;
1098
1099     return m_storageProcess->processIdentifier();
1100 }
1101
1102 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
1103 {
1104     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
1105     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
1106 }
1107
1108 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
1109 {
1110     m_shouldUseFontSmoothing = useFontSmoothing;
1111     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
1112 }
1113
1114 void WebProcessPool::setResourceLoadStatisticsEnabled(bool enabled)
1115 {
1116     m_resourceLoadStatisticsEnabled = enabled;
1117     sendToAllProcesses(Messages::WebProcess::SetResourceLoadStatisticsEnabled(enabled));
1118 }
1119
1120 void WebProcessPool::clearResourceLoadStatistics()
1121 {
1122     sendToAllProcesses(Messages::WebProcess::ClearResourceLoadStatistics());
1123 }
1124
1125 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
1126 {
1127     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
1128     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
1129 }
1130
1131 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
1132 {
1133     m_schemesToRegisterAsSecure.add(urlScheme);
1134     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
1135 }
1136
1137 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
1138 {
1139     m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
1140     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1141 }
1142
1143 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
1144 {
1145     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
1146     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
1147 }
1148
1149 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
1150 {
1151     m_canHandleHTTPSServerTrustEvaluation = value;
1152     if (m_networkProcess) {
1153         m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
1154         return;
1155     }
1156 }
1157
1158 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
1159 {
1160     m_schemesToRegisterAsLocal.add(urlScheme);
1161     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
1162 }
1163
1164 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
1165 {
1166     m_schemesToRegisterAsNoAccess.add(urlScheme);
1167     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1168 }
1169
1170 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
1171 {
1172     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
1173     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1174 }
1175
1176 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
1177 {
1178     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
1179     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1180 }
1181
1182 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1183 {
1184     if (!urlScheme)
1185         return;
1186
1187     globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
1188     for (auto* processPool : allProcessPools())
1189         processPool->registerSchemeForCustomProtocol(urlScheme);
1190 }
1191
1192 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1193 {
1194     if (!urlScheme)
1195         return;
1196
1197     globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
1198     for (auto* processPool : allProcessPools())
1199         processPool->unregisterSchemeForCustomProtocol(urlScheme);
1200 }
1201
1202 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
1203 {
1204     m_schemesToRegisterAsCachePartitioned.add(urlScheme);
1205     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
1206 }
1207
1208 void WebProcessPool::setCacheModel(CacheModel cacheModel)
1209 {
1210     m_configuration->setCacheModel(cacheModel);
1211     sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
1212
1213     if (m_networkProcess)
1214         m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
1215 }
1216
1217 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
1218 {
1219     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
1220 }
1221
1222 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
1223 {
1224     auto downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
1225     downloadProxy->setOriginatingPage(originatingPage);
1226     return downloadProxy;
1227 }
1228
1229 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
1230 {
1231     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
1232 }
1233
1234 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
1235 {
1236     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
1237 }
1238
1239 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName)
1240 {
1241     m_messageReceiverMap.removeMessageReceiver(messageReceiverName);
1242 }
1243
1244 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
1245 {
1246     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
1247 }
1248
1249 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
1250 {
1251     return m_messageReceiverMap.dispatchMessage(connection, decoder);
1252 }
1253
1254 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
1255 {
1256     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1257 }
1258
1259 void WebProcessPool::setEnhancedAccessibility(bool flag)
1260 {
1261     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1262 }
1263     
1264 void WebProcessPool::startMemorySampler(const double interval)
1265 {    
1266     // For new WebProcesses we will also want to start the Memory Sampler
1267     m_memorySamplerEnabled = true;
1268     m_memorySamplerInterval = interval;
1269     
1270     // For UIProcess
1271 #if ENABLE(MEMORY_SAMPLER)
1272     WebMemorySampler::singleton()->start(interval);
1273 #endif
1274     
1275     // For WebProcess
1276     SandboxExtension::Handle sampleLogSandboxHandle;    
1277     double now = WTF::currentTime();
1278     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now));
1279     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
1280     
1281     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1282 }
1283
1284 void WebProcessPool::stopMemorySampler()
1285 {    
1286     // For WebProcess
1287     m_memorySamplerEnabled = false;
1288     
1289     // For UIProcess
1290 #if ENABLE(MEMORY_SAMPLER)
1291     WebMemorySampler::singleton()->stop();
1292 #endif
1293
1294     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1295 }
1296
1297 void WebProcessPool::useTestingNetworkSession()
1298 {
1299     ASSERT(m_processes.isEmpty());
1300     ASSERT(!m_networkProcess);
1301
1302     if (m_networkProcess)
1303         return;
1304
1305     if (!m_processes.isEmpty())
1306         return;
1307
1308     m_shouldUseTestingNetworkSession = true;
1309 }
1310
1311 template<typename T, typename U>
1312 void WebProcessPool::sendSyncToNetworkingProcess(T&& message, U&& reply)
1313 {
1314     if (m_networkProcess && m_networkProcess->canSendMessage())
1315         m_networkProcess->sendSync(std::forward<T>(message), std::forward<U>(reply), 0);
1316 }
1317
1318 void WebProcessPool::setAllowsAnySSLCertificateForWebSocket(bool allows)
1319 {
1320     sendSyncToNetworkingProcess(Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket(allows), Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket::Reply());
1321 }
1322
1323 void WebProcessPool::clearCachedCredentials()
1324 {
1325     sendToAllProcesses(Messages::WebProcess::ClearCachedCredentials());
1326     if (m_networkProcess)
1327         m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1328 }
1329
1330 void WebProcessPool::terminateStorageProcess()
1331 {
1332     if (!m_storageProcess)
1333         return;
1334
1335     m_storageProcess->terminate();
1336     m_storageProcess = nullptr;
1337 }
1338
1339 void WebProcessPool::terminateNetworkProcess()
1340 {
1341     if (!m_networkProcess)
1342         return;
1343     
1344     m_networkProcess->terminate();
1345     m_networkProcess = nullptr;
1346     m_didNetworkProcessCrash = true;
1347 }
1348
1349 void WebProcessPool::syncNetworkProcessCookies()
1350 {
1351     sendSyncToNetworkingProcess(Messages::NetworkProcess::SyncAllCookies(), Messages::NetworkProcess::SyncAllCookies::Reply());
1352 }
1353
1354 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1355 {
1356     ensureNetworkProcess();
1357     m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1358 }
1359
1360 void WebProcessPool::updateAutomationCapabilities() const
1361 {
1362 #if ENABLE(REMOTE_INSPECTOR)
1363     Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1364 #endif
1365 }
1366
1367 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1368 {
1369     m_automationSession = WTFMove(automationSession);
1370
1371 #if ENABLE(REMOTE_INSPECTOR)
1372     if (m_automationSession) {
1373         m_automationSession->init();
1374         m_automationSession->setProcessPool(this);
1375
1376         sendToAllProcesses(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()));
1377     } else
1378         sendToAllProcesses(Messages::WebProcess::DestroyAutomationSessionProxy());
1379 #endif
1380 }
1381
1382 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1383 {
1384 #if PLATFORM(COCOA)
1385     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1386 #else
1387     UNUSED_PARAM(enabled);
1388 #endif
1389 }
1390
1391 bool WebProcessPool::httpPipeliningEnabled() const
1392 {
1393 #if PLATFORM(COCOA)
1394     return ResourceRequest::httpPipeliningEnabled();
1395 #else
1396     return false;
1397 #endif
1398 }
1399
1400 void WebProcessPool::getStatistics(uint32_t statisticsMask, Function<void (API::Dictionary*, CallbackBase::Error)>&& callbackFunction)
1401 {
1402     if (!statisticsMask) {
1403         callbackFunction(nullptr, CallbackBase::Error::Unknown);
1404         return;
1405     }
1406
1407     RefPtr<StatisticsRequest> request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1408
1409     if (statisticsMask & StatisticsRequestTypeWebContent)
1410         requestWebContentStatistics(request.get());
1411     
1412     if (statisticsMask & StatisticsRequestTypeNetworking)
1413         requestNetworkingStatistics(request.get());
1414 }
1415
1416 void WebProcessPool::requestWebContentStatistics(StatisticsRequest* request)
1417 {
1418     // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1419 }
1420
1421 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest* request)
1422 {
1423     if (!m_networkProcess) {
1424         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1425         return;
1426     }
1427
1428     uint64_t requestID = request->addOutstandingRequest();
1429     m_statisticsRequests.set(requestID, request);
1430     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1431 }
1432
1433 static WebProcessProxy* webProcessProxyFromConnection(IPC::Connection& connection, const Vector<RefPtr<WebProcessProxy>>& processes)
1434 {
1435     for (auto& process : processes) {
1436         if (process->hasConnection(connection))
1437             return process.get();
1438     }
1439
1440     ASSERT_NOT_REACHED();
1441     return nullptr;
1442 }
1443
1444 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1445 {
1446     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1447     if (!webProcessProxy)
1448         return;
1449     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1450 }
1451
1452 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1453 {
1454     auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1455     if (!webProcessProxy)
1456         return;
1457
1458     RefPtr<API::Object> returnData;
1459     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1460     returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1461 }
1462
1463 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1464 {
1465     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1466     if (!request) {
1467         LOG_ERROR("Cannot report networking statistics.");
1468         return;
1469     }
1470
1471     request->completedRequest(requestID, statisticsData);
1472 }
1473
1474 #if ENABLE(GAMEPAD)
1475
1476 void WebProcessPool::startedUsingGamepads(IPC::Connection& connection)
1477 {
1478     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1479     if (!proxy)
1480         return;
1481
1482     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1483
1484     ASSERT(!m_processesUsingGamepads.contains(proxy));
1485     m_processesUsingGamepads.add(proxy);
1486
1487     if (!wereAnyProcessesUsingGamepads)
1488         UIGamepadProvider::singleton().processPoolStartedUsingGamepads(*this);
1489
1490     proxy->send(Messages::WebProcess::SetInitialGamepads(UIGamepadProvider::singleton().snapshotGamepads()), 0);
1491 }
1492
1493 void WebProcessPool::stoppedUsingGamepads(IPC::Connection& connection)
1494 {
1495     auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1496     if (!proxy)
1497         return;
1498
1499     ASSERT(m_processesUsingGamepads.contains(proxy));
1500     processStoppedUsingGamepads(*proxy);
1501 }
1502
1503 void WebProcessPool::processStoppedUsingGamepads(WebProcessProxy& process)
1504 {
1505     bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1506
1507     ASSERT(m_processesUsingGamepads.contains(&process));
1508     m_processesUsingGamepads.remove(&process);
1509
1510     if (wereAnyProcessesUsingGamepads && m_processesUsingGamepads.isEmpty())
1511         UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
1512 }
1513
1514 void WebProcessPool::gamepadConnected(const UIGamepad& gamepad)
1515 {
1516     for (auto& process : m_processesUsingGamepads)
1517         process->send(Messages::WebProcess::GamepadConnected(gamepad.fullGamepadData()), 0);
1518 }
1519
1520 void WebProcessPool::gamepadDisconnected(const UIGamepad& gamepad)
1521 {
1522     for (auto& process : m_processesUsingGamepads)
1523         process->send(Messages::WebProcess::GamepadDisconnected(gamepad.index()), 0);
1524 }
1525
1526 void WebProcessPool::setInitialConnectedGamepads(const Vector<std::unique_ptr<UIGamepad>>& gamepads)
1527 {
1528     Vector<GamepadData> gamepadDatas;
1529     gamepadDatas.grow(gamepads.size());
1530     for (size_t i = 0; i < gamepads.size(); ++i) {
1531         if (!gamepads[i])
1532             continue;
1533         gamepadDatas[i] = gamepads[i]->fullGamepadData();
1534     }
1535
1536     for (auto& process : m_processesUsingGamepads)
1537         process->send(Messages::WebProcess::SetInitialGamepads(gamepadDatas), 0);
1538 }
1539
1540 #endif // ENABLE(GAMEPAD)
1541
1542 void WebProcessPool::setJavaScriptConfigurationFileEnabled(bool flag)
1543 {
1544     m_javaScriptConfigurationFileEnabled = flag;
1545 }
1546
1547 void WebProcessPool::garbageCollectJavaScriptObjects()
1548 {
1549     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1550 }
1551
1552 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1553 {
1554     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1555 }
1556
1557 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, PAL::SessionID sessionID)
1558 {
1559     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1560 }
1561
1562 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, PAL::SessionID sessionID)
1563 {
1564     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1565 }
1566
1567 Ref<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1568 {
1569     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1570 }
1571
1572 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1573 {
1574     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1575 }
1576
1577 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1578 {
1579     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1580 }
1581
1582 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, double time)
1583 {
1584     m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1585 }
1586
1587 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1588 {
1589     if (!globalURLSchemesWithCustomProtocolHandlers().contains(scheme))
1590         m_urlSchemesRegisteredForCustomProtocols.add(scheme);
1591     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::RegisterScheme(scheme));
1592 }
1593
1594 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1595 {
1596     m_urlSchemesRegisteredForCustomProtocols.remove(scheme);
1597     sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::UnregisterScheme(scheme));
1598 }
1599
1600 #if ENABLE(NETSCAPE_PLUGIN_API)
1601 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1602 {
1603     auto& policiesForHost = m_pluginLoadClientPolicies.ensure(host, [] { return HashMap<String, HashMap<String, uint8_t>>(); }).iterator->value;
1604     auto& versionsToPolicies = policiesForHost.ensure(bundleIdentifier, [] { return HashMap<String, uint8_t>(); }).iterator->value;
1605     versionsToPolicies.set(versionString, policy);
1606
1607     sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1608 }
1609
1610 void WebProcessPool::resetPluginLoadClientPolicies(HashMap<String, HashMap<String, HashMap<String, uint8_t>>>&& pluginLoadClientPolicies)
1611 {
1612     m_pluginLoadClientPolicies = WTFMove(pluginLoadClientPolicies);
1613     sendToAllProcesses(Messages::WebProcess::ResetPluginLoadClientPolicies(m_pluginLoadClientPolicies));
1614 }
1615
1616 void WebProcessPool::clearPluginClientPolicies()
1617 {
1618     m_pluginLoadClientPolicies.clear();
1619     sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1620 }
1621 #endif
1622
1623 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1624 {
1625     m_memoryCacheDisabled = disabled;
1626     sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1627 }
1628
1629 void WebProcessPool::setFontWhitelist(API::Array* array)
1630 {
1631     m_fontWhitelist.clear();
1632     if (array) {
1633         for (size_t i = 0; i < array->size(); ++i) {
1634             if (API::String* font = array->at<API::String>(i))
1635                 m_fontWhitelist.append(font->string());
1636         }
1637     }
1638 }
1639
1640 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1641 {
1642     // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1643     // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1644     // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1645     static int maximumTimerThrottlePerPageInMS = 200 * 100;
1646
1647     int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1648     sendToAllProcesses(Messages::WebProcess::SetHiddenPageDOMTimerThrottlingIncreaseLimit(limitInMilliseconds));
1649 }
1650
1651 void WebProcessPool::reportWebContentCPUTime(Seconds cpuTime, uint64_t activityState)
1652 {
1653 #if PLATFORM(MAC)
1654     if (m_perActivityStateCPUUsageSampler)
1655         m_perActivityStateCPUUsageSampler->reportWebContentCPUTime(cpuTime, static_cast<WebCore::ActivityStateForCPUSampling>(activityState));
1656 #else
1657     UNUSED_PARAM(cpuTime);
1658     UNUSED_PARAM(activityState);
1659 #endif
1660 }
1661
1662 } // namespace WebKit