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