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