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