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