2 * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebProcessPool.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 "ChildProcessMessages.h"
39 #include "DownloadProxy.h"
40 #include "DownloadProxyMessages.h"
41 #include "GamepadData.h"
42 #include "HighPerformanceGraphicsUsageSampler.h"
43 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
44 #include "LegacyCustomProtocolManagerMessages.h"
46 #include "LogInitialization.h"
47 #include "NetworkProcessCreationParameters.h"
48 #include "NetworkProcessMessages.h"
49 #include "NetworkProcessProxy.h"
50 #include "PerActivityStateCPUUsageSampler.h"
51 #include "SandboxExtension.h"
52 #include "ServiceWorkerProcessProxy.h"
53 #include "StatisticsData.h"
54 #include "StorageProcessCreationParameters.h"
55 #include "StorageProcessMessages.h"
56 #include "TextChecker.h"
57 #include "UIGamepad.h"
58 #include "UIGamepadProvider.h"
59 #include "WKContextPrivate.h"
60 #include "WebAutomationSession.h"
61 #include "WebCertificateInfo.h"
62 #include "WebContextSupplement.h"
63 #include "WebCookieManagerProxy.h"
64 #include "WebCoreArgumentCoders.h"
65 #include "WebGeolocationManagerProxy.h"
66 #include "WebKit2Initialize.h"
67 #include "WebMemorySampler.h"
68 #include "WebNotificationManagerProxy.h"
69 #include "WebPageGroup.h"
70 #include "WebPreferences.h"
71 #include "WebPreferencesKeys.h"
72 #include "WebProcessCreationParameters.h"
73 #include "WebProcessMessages.h"
74 #include "WebProcessPoolMessages.h"
75 #include "WebProcessProxy.h"
76 #include "WebsiteDataStore.h"
77 #include "WebsiteDataStoreParameters.h"
78 #include <JavaScriptCore/JSCInlines.h>
79 #include <WebCore/ApplicationCacheStorage.h>
80 #include <WebCore/LogInitialization.h>
81 #include <WebCore/NetworkStorageSession.h>
82 #include <WebCore/PlatformScreen.h>
83 #include <WebCore/ResourceRequest.h>
84 #include <WebCore/URLParser.h>
85 #include <pal/SessionID.h>
86 #include <wtf/Language.h>
87 #include <wtf/MainThread.h>
88 #include <wtf/NeverDestroyed.h>
89 #include <wtf/ProcessPrivilege.h>
90 #include <wtf/RunLoop.h>
91 #include <wtf/WallTime.h>
92 #include <wtf/text/StringBuilder.h>
94 #if ENABLE(SERVICE_CONTROLS)
95 #include "ServicesController.h"
98 #if ENABLE(REMOTE_INSPECTOR)
99 #include <JavaScriptCore/RemoteInspector.h>
103 #include "MemoryPressureMonitor.h"
106 #if PLATFORM(WAYLAND)
107 #include "WaylandCompositor.h"
108 #include <WebCore/PlatformDisplay.h>
112 #include <wtf/RefCountedLeakCounter.h>
115 using namespace WebCore;
116 using namespace WebKit;
120 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, processPoolCounter, ("WebProcessPool"));
122 static const Seconds serviceWorkerTerminationDelay { 5_s };
124 static uint64_t generateListenerIdentifier()
126 static uint64_t nextIdentifier = 1;
127 return nextIdentifier++;
130 static HashMap<uint64_t, Function<void(WebProcessPool&)>>& processPoolCreationListenerFunctionMap()
132 static NeverDestroyed<HashMap<uint64_t, Function<void(WebProcessPool&)>>> map;
136 uint64_t WebProcessPool::registerProcessPoolCreationListener(Function<void(WebProcessPool&)>&& function)
140 auto identifier = generateListenerIdentifier();
141 processPoolCreationListenerFunctionMap().set(identifier, WTFMove(function));
145 void WebProcessPool::unregisterProcessPoolCreationListener(uint64_t identifier)
147 processPoolCreationListenerFunctionMap().remove(identifier);
150 Ref<WebProcessPool> WebProcessPool::create(API::ProcessPoolConfiguration& configuration)
153 return adoptRef(*new WebProcessPool(configuration));
156 void WebProcessPool::notifyThisWebProcessPoolWasCreated()
158 auto& listenerMap = processPoolCreationListenerFunctionMap();
160 Vector<uint64_t> identifiers;
161 identifiers.reserveInitialCapacity(listenerMap.size());
162 for (auto identifier : listenerMap.keys())
163 identifiers.uncheckedAppend(identifier);
165 for (auto identifier : identifiers) {
166 auto iterator = listenerMap.find(identifier);
167 if (iterator == listenerMap.end())
170 // To make sure the Function object stays alive until after the function call has been made,
171 // we temporarily move it out of the map.
172 // This protects it from the Function calling unregisterProcessPoolCreationListener thereby
173 // removing itself from the map of listeners.
174 // If the identifier still exists in the map later, we move it back in.
175 Function<void(WebProcessPool&)> function = WTFMove(iterator->value);
178 iterator = listenerMap.find(identifier);
179 if (iterator != listenerMap.end()) {
180 ASSERT(!iterator->value);
181 iterator->value = WTFMove(function);
186 static Vector<WebProcessPool*>& processPools()
188 static NeverDestroyed<Vector<WebProcessPool*>> processPools;
192 const Vector<WebProcessPool*>& WebProcessPool::allProcessPools()
194 return processPools();
197 static WebsiteDataStore::Configuration legacyWebsiteDataStoreConfiguration(API::ProcessPoolConfiguration& processPoolConfiguration)
199 WebsiteDataStore::Configuration configuration;
201 configuration.cacheStorageDirectory = API::WebsiteDataStore::defaultCacheStorageDirectory();
202 configuration.serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory();
203 configuration.localStorageDirectory = processPoolConfiguration.localStorageDirectory();
204 configuration.webSQLDatabaseDirectory = processPoolConfiguration.webSQLDatabaseDirectory();
205 configuration.applicationCacheDirectory = processPoolConfiguration.applicationCacheDirectory();
206 configuration.applicationCacheFlatFileSubdirectoryName = processPoolConfiguration.applicationCacheFlatFileSubdirectoryName();
207 configuration.mediaCacheDirectory = processPoolConfiguration.mediaCacheDirectory();
208 configuration.mediaKeysStorageDirectory = processPoolConfiguration.mediaKeysStorageDirectory();
209 configuration.resourceLoadStatisticsDirectory = processPoolConfiguration.resourceLoadStatisticsDirectory();
210 configuration.networkCacheDirectory = processPoolConfiguration.diskCacheDirectory();
211 configuration.javaScriptConfigurationDirectory = processPoolConfiguration.javaScriptConfigurationDirectory();
213 return configuration;
216 static HashSet<String, ASCIICaseInsensitiveHash>& globalURLSchemesWithCustomProtocolHandlers()
218 static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> set;
222 WebProcessPool::WebProcessPool(API::ProcessPoolConfiguration& configuration)
223 : m_configuration(configuration.copy())
224 , m_defaultPageGroup(WebPageGroup::create())
225 , m_injectedBundleClient(std::make_unique<API::InjectedBundleClient>())
226 , m_automationClient(std::make_unique<API::AutomationClient>())
227 , m_downloadClient(std::make_unique<API::DownloadClient>())
228 , m_historyClient(std::make_unique<API::LegacyContextHistoryClient>())
229 , m_customProtocolManagerClient(std::make_unique<API::CustomProtocolManagerClient>())
230 , m_visitedLinkStore(VisitedLinkStore::create())
232 , m_highPerformanceGraphicsUsageSampler(std::make_unique<HighPerformanceGraphicsUsageSampler>(*this))
233 , m_perActivityStateCPUUsageSampler(std::make_unique<PerActivityStateCPUUsageSampler>(*this))
235 , m_alwaysRunsAtBackgroundPriority(m_configuration->alwaysRunsAtBackgroundPriority())
236 , m_shouldTakeUIBackgroundAssertion(m_configuration->shouldTakeUIBackgroundAssertion())
237 , m_userObservablePageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
238 , m_processSuppressionDisabledForPageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
239 , m_hiddenPageThrottlingAutoIncreasesCounter([this](RefCounterEvent) { m_hiddenPageThrottlingTimer.startOneShot(0_s); })
240 , m_hiddenPageThrottlingTimer(RunLoop::main(), this, &WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit)
241 , m_serviceWorkerProcessesTerminationTimer(RunLoop::main(), this, &WebProcessPool::terminateServiceWorkerProcesses)
243 , m_foregroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
244 , m_backgroundWebProcessCounter([this](RefCounterEvent) { updateProcessAssertions(); })
247 static std::once_flag onceFlag;
248 std::call_once(onceFlag, [] {
249 WTF::setProcessPrivileges(allPrivileges());
250 WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
253 if (m_configuration->shouldHaveLegacyDataStore())
254 m_websiteDataStore = API::WebsiteDataStore::createLegacy(legacyWebsiteDataStoreConfiguration(m_configuration));
256 if (!m_websiteDataStore && API::WebsiteDataStore::defaultDataStoreExists())
257 m_websiteDataStore = API::WebsiteDataStore::defaultDataStore();
259 for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
260 m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
262 for (const auto& urlScheme : m_configuration->cachePartitionedURLSchemes())
263 m_schemesToRegisterAsCachePartitioned.add(urlScheme);
265 platformInitialize();
267 addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
269 // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
270 addSupplement<WebCookieManagerProxy>();
271 addSupplement<WebGeolocationManagerProxy>();
272 addSupplement<WebNotificationManagerProxy>();
273 #if ENABLE(MEDIA_SESSION)
274 addSupplement<WebMediaSessionFocusManager>();
277 processPools().append(this);
279 addLanguageChangeObserver(this, languageChanged);
281 resolvePathsForSandboxExtensions();
283 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
284 WebCore::initializeLogChannelsIfNecessary();
285 WebKit::initializeLogChannelsIfNecessary();
286 #endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
289 processPoolCounter.increment();
292 notifyThisWebProcessPoolWasCreated();
295 WebProcessPool::~WebProcessPool()
297 bool removed = processPools().removeFirst(this);
298 ASSERT_UNUSED(removed, removed);
300 removeLanguageChangeObserver(this);
302 m_messageReceiverMap.invalidate();
304 for (auto& supplement : m_supplements.values()) {
305 supplement->processPoolDestroyed();
306 supplement->clearProcessPool();
309 invalidateCallbackMap(m_dictionaryCallbacks, CallbackBase::Error::OwnerWasInvalidated);
311 platformInvalidateContext();
314 processPoolCounter.decrement();
317 if (m_networkProcess)
318 m_networkProcess->shutDownProcess();
321 if (!m_processesUsingGamepads.isEmpty())
322 UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
326 void WebProcessPool::initializeClient(const WKContextClientBase* client)
328 m_client.initialize(client);
331 void WebProcessPool::setInjectedBundleClient(std::unique_ptr<API::InjectedBundleClient>&& client)
334 m_injectedBundleClient = std::make_unique<API::InjectedBundleClient>();
336 m_injectedBundleClient = WTFMove(client);
339 void WebProcessPool::initializeConnectionClient(const WKContextConnectionClientBase* client)
341 m_connectionClient.initialize(client);
344 void WebProcessPool::setHistoryClient(std::unique_ptr<API::LegacyContextHistoryClient>&& historyClient)
347 m_historyClient = std::make_unique<API::LegacyContextHistoryClient>();
349 m_historyClient = WTFMove(historyClient);
352 void WebProcessPool::setDownloadClient(std::unique_ptr<API::DownloadClient>&& downloadClient)
355 m_downloadClient = std::make_unique<API::DownloadClient>();
357 m_downloadClient = WTFMove(downloadClient);
360 void WebProcessPool::setAutomationClient(std::unique_ptr<API::AutomationClient>&& automationClient)
362 if (!automationClient)
363 m_automationClient = std::make_unique<API::AutomationClient>();
365 m_automationClient = WTFMove(automationClient);
368 void WebProcessPool::setLegacyCustomProtocolManagerClient(std::unique_ptr<API::CustomProtocolManagerClient>&& customProtocolManagerClient)
370 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
371 if (!customProtocolManagerClient)
372 m_customProtocolManagerClient = std::make_unique<API::CustomProtocolManagerClient>();
374 m_customProtocolManagerClient = WTFMove(customProtocolManagerClient);
378 void WebProcessPool::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
380 // Guard against API misuse.
381 if (!m_processes.isEmpty())
384 m_configuration->setMaximumProcessCount(maximumNumberOfProcesses);
387 IPC::Connection* WebProcessPool::networkingProcessConnection()
389 return m_networkProcess->connection();
392 void WebProcessPool::languageChanged(void* context)
394 static_cast<WebProcessPool*>(context)->languageChanged();
397 void WebProcessPool::languageChanged()
399 sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
401 if (m_networkProcess)
402 m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
406 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
408 sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
411 void WebProcessPool::textCheckerStateChanged()
413 sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
416 NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* withWebsiteDataStore)
418 if (m_networkProcess) {
419 if (withWebsiteDataStore)
420 m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(withWebsiteDataStore->parameters()), 0);
421 return *m_networkProcess;
424 if (m_websiteDataStore)
425 m_websiteDataStore->websiteDataStore().resolveDirectoriesIfNecessary();
427 m_networkProcess = NetworkProcessProxy::create(*this);
429 NetworkProcessCreationParameters parameters;
431 if (withWebsiteDataStore) {
432 auto websiteDataStoreParameters = withWebsiteDataStore->parameters();
433 parameters.defaultSessionParameters = websiteDataStoreParameters.networkSessionParameters;
435 // FIXME: This isn't conceptually correct, but it's needed to preserve behavior introduced in r213241.
436 // We should separate the concept of the default session from the currently used persistent session.
437 parameters.defaultSessionParameters.sessionID = PAL::SessionID::defaultSessionID();
440 parameters.privateBrowsingEnabled = WebPreferences::anyPagesAreUsingPrivateBrowsing();
442 parameters.cacheModel = cacheModel();
443 parameters.diskCacheSizeOverride = m_configuration->diskCacheSizeOverride();
444 parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
446 for (auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
447 parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
449 for (auto& scheme : m_urlSchemesRegisteredForCustomProtocols)
450 parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
452 parameters.cacheStorageDirectory = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().cacheStorageDirectory() : API::WebsiteDataStore::defaultCacheStorageDirectory();
453 if (!parameters.cacheStorageDirectory.isEmpty())
454 SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
455 parameters.cacheStoragePerOriginQuota = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().cacheStoragePerOriginQuota() : WebsiteDataStore::defaultCacheStoragePerOriginQuota;
457 parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
458 if (!parameters.diskCacheDirectory.isEmpty())
459 SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
460 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
461 parameters.shouldEnableNetworkCacheSpeculativeRevalidation = m_configuration->diskCacheSpeculativeValidationEnabled();
465 String cookieStorageDirectory = this->cookieStorageDirectory();
466 if (!cookieStorageDirectory.isEmpty())
467 SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
469 String containerCachesDirectory = this->networkingCachesDirectory();
470 if (!containerCachesDirectory.isEmpty())
471 SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
473 String parentBundleDirectory = this->parentBundleDirectory();
474 if (!parentBundleDirectory.isEmpty())
475 SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::Type::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
479 if (MemoryPressureMonitor::isEnabled())
480 parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
483 parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
484 parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
486 parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
487 parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
488 parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
489 parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
490 parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
491 parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
492 parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
494 // Add any platform specific parameters
495 platformInitializeNetworkProcess(parameters);
497 // Initialize the network process.
498 m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
501 m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
504 if (m_didNetworkProcessCrash) {
505 m_didNetworkProcessCrash = false;
506 reinstateNetworkProcessAssertionState(*m_networkProcess);
507 if (m_websiteDataStore)
508 m_websiteDataStore->websiteDataStore().networkProcessDidCrash();
511 if (withWebsiteDataStore)
512 m_networkProcess->send(Messages::NetworkProcess::AddWebsiteDataStore(withWebsiteDataStore->parameters()), 0);
514 return *m_networkProcess;
517 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy& networkProcessProxy, Vector<Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>>&& pendingReplies)
519 networkProcessFailedToLaunch(networkProcessProxy);
520 ASSERT(!m_networkProcess);
521 if (pendingReplies.isEmpty())
523 auto& newNetworkProcess = ensureNetworkProcess();
524 for (auto& reply : pendingReplies)
525 newNetworkProcess.getNetworkProcessConnection(WTFMove(reply));
528 void WebProcessPool::networkProcessFailedToLaunch(NetworkProcessProxy& networkProcessProxy)
530 ASSERT(m_networkProcess);
531 ASSERT(&networkProcessProxy == m_networkProcess.get());
532 m_didNetworkProcessCrash = true;
534 for (auto& supplement : m_supplements.values())
535 supplement->processDidClose(&networkProcessProxy);
537 m_client.networkProcessDidCrash(this);
539 // Leave the process proxy around during client call, so that the client could query the process identifier.
540 m_networkProcess = nullptr;
543 void WebProcessPool::getNetworkProcessConnection(Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>&& reply)
545 ensureNetworkProcess();
546 ASSERT(m_networkProcess);
548 m_networkProcess->getNetworkProcessConnection(WTFMove(reply));
551 void WebProcessPool::ensureStorageProcessAndWebsiteDataStore(WebsiteDataStore* relevantDataStore)
554 // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
557 if (!m_storageProcess) {
558 auto parameters = m_websiteDataStore ? m_websiteDataStore->websiteDataStore().storageProcessParameters() : (relevantDataStore ? relevantDataStore->storageProcessParameters() : API::WebsiteDataStore::defaultDataStore()->websiteDataStore().storageProcessParameters());
560 ASSERT(parameters.sessionID.isValid());
562 #if ENABLE(INDEXED_DATABASE)
563 if (parameters.indexedDatabaseDirectory.isEmpty()) {
564 parameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
565 SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
568 #if ENABLE(SERVICE_WORKER)
569 if (parameters.serviceWorkerRegistrationDirectory.isEmpty()) {
570 parameters.serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultServiceWorkerRegistrationDirectory();
571 SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
574 if (!m_schemesServiceWorkersCanHandle.isEmpty())
575 parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
577 parameters.shouldDisableServiceWorkerProcessTerminationDelay = m_shouldDisableServiceWorkerProcessTerminationDelay;
580 m_storageProcess = StorageProcessProxy::create(*this);
581 m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(parameters), 0);
584 if (!relevantDataStore || !m_websiteDataStore || relevantDataStore == &m_websiteDataStore->websiteDataStore())
587 m_storageProcess->send(Messages::StorageProcess::InitializeWebsiteDataStore(relevantDataStore->storageProcessParameters()), 0);
590 void WebProcessPool::getStorageProcessConnection(WebProcessProxy& webProcessProxy, PAL::SessionID initialSessionID, Ref<Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply>&& reply)
592 ensureStorageProcessAndWebsiteDataStore(WebsiteDataStore::existingNonDefaultDataStoreForSessionID(initialSessionID));
594 m_storageProcess->getStorageProcessConnection(webProcessProxy, WTFMove(reply));
597 void WebProcessPool::storageProcessCrashed(StorageProcessProxy* storageProcessProxy)
599 ASSERT(m_storageProcess);
600 ASSERT(storageProcessProxy == m_storageProcess.get());
602 for (auto& supplement : m_supplements.values())
603 supplement->processDidClose(storageProcessProxy);
605 m_client.storageProcessDidCrash(this);
606 m_storageProcess = nullptr;
609 #if ENABLE(SERVICE_WORKER)
610 void WebProcessPool::establishWorkerContextConnectionToStorageProcess(StorageProcessProxy& proxy, SecurityOriginData&& securityOrigin, std::optional<PAL::SessionID> sessionID)
612 ASSERT_UNUSED(proxy, &proxy == m_storageProcess);
614 if (m_serviceWorkerProcesses.contains(securityOrigin))
617 m_mayHaveRegisteredServiceWorkers.clear();
619 WebsiteDataStore* websiteDataStore = nullptr;
621 websiteDataStore = WebsiteDataStore::existingNonDefaultDataStoreForSessionID(*sessionID);
623 if (!websiteDataStore) {
624 if (!m_websiteDataStore)
625 m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
626 websiteDataStore = &m_websiteDataStore->websiteDataStore();
629 if (m_serviceWorkerProcesses.isEmpty())
630 sendToAllProcesses(Messages::WebProcess::RegisterServiceWorkerClients { });
632 auto serviceWorkerProcessProxy = ServiceWorkerProcessProxy::create(*this, securityOrigin, *websiteDataStore);
633 m_serviceWorkerProcesses.add(WTFMove(securityOrigin), serviceWorkerProcessProxy.ptr());
635 updateProcessAssertions();
636 initializeNewWebProcess(serviceWorkerProcessProxy, *websiteDataStore);
638 auto* serviceWorkerProcessProxyPtr = serviceWorkerProcessProxy.ptr();
639 m_processes.append(WTFMove(serviceWorkerProcessProxy));
641 serviceWorkerProcessProxyPtr->start(m_serviceWorkerPreferences ? m_serviceWorkerPreferences.value() : m_defaultPageGroup->preferences().store(), sessionID);
642 if (!m_serviceWorkerUserAgent.isNull())
643 serviceWorkerProcessProxyPtr->setUserAgent(m_serviceWorkerUserAgent);
647 void WebProcessPool::disableServiceWorkerProcessTerminationDelay()
649 #if ENABLE(SERVICE_WORKER)
650 if (m_shouldDisableServiceWorkerProcessTerminationDelay)
653 m_shouldDisableServiceWorkerProcessTerminationDelay = true;
654 if (m_storageProcess)
655 m_storageProcess->send(Messages::StorageProcess::DisableServiceWorkerProcessTerminationDelay(), 0);
659 void WebProcessPool::willStartUsingPrivateBrowsing()
661 for (auto* processPool : allProcessPools())
662 processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
665 void WebProcessPool::willStopUsingPrivateBrowsing()
667 for (auto* processPool : allProcessPools())
668 processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
671 void WebProcessPool::windowServerConnectionStateChanged()
673 size_t processCount = m_processes.size();
674 for (size_t i = 0; i < processCount; ++i)
675 m_processes[i]->windowServerConnectionStateChanged();
678 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
680 if (networkProcess()) {
681 if (privateBrowsingEnabled)
682 networkProcess()->send(Messages::NetworkProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()), 0);
684 networkProcess()->send(Messages::NetworkProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()), 0);
687 if (privateBrowsingEnabled)
688 sendToAllProcesses(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()));
690 sendToAllProcesses(Messages::WebProcess::DestroySession(PAL::SessionID::legacyPrivateSessionID()));
693 void (*s_invalidMessageCallback)(WKStringRef messageName);
695 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
697 s_invalidMessageCallback = invalidMessageCallback;
700 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
702 if (!s_invalidMessageCallback)
705 StringBuilder messageNameStringBuilder;
706 messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
707 messageNameStringBuilder.append('.');
708 messageNameStringBuilder.append(messageName.data(), messageName.size());
710 s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
713 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
715 if (m_processWithPageCache && m_processWithPageCache != process)
716 m_processWithPageCache->releasePageCache();
717 m_processWithPageCache = process;
720 void WebProcessPool::resolvePathsForSandboxExtensions()
722 m_resolvedPaths.injectedBundlePath = resolvePathForSandboxExtension(injectedBundlePath());
723 m_resolvedPaths.applicationCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory());
724 m_resolvedPaths.webSQLDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory());
725 m_resolvedPaths.mediaCacheDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory());
726 m_resolvedPaths.mediaKeyStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory());
727 m_resolvedPaths.indexedDatabaseDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory());
729 m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.reserveCapacity(m_configuration->additionalReadAccessAllowedPaths().size());
730 for (const auto& path : m_configuration->additionalReadAccessAllowedPaths())
731 m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.uncheckedAppend(resolvePathForSandboxExtension(path.data()));
733 platformResolvePathsForSandboxExtensions();
736 WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDataStore)
738 auto processProxy = WebProcessProxy::create(*this, websiteDataStore);
739 auto& process = processProxy.get();
740 initializeNewWebProcess(process, websiteDataStore);
741 m_processes.append(WTFMove(processProxy));
743 if (m_serviceWorkerProcessesTerminationTimer.isActive())
744 m_serviceWorkerProcessesTerminationTimer.stop();
749 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
750 static void displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
752 HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
753 WebCore::getScreenProperties(screenProperties);
755 for (auto& processPool : WebProcessPool::allProcessPools())
756 processPool->sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
759 static void registerDisplayConfigurationCallback()
761 static std::once_flag onceFlag;
765 CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, nullptr);
770 void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDataStore& websiteDataStore)
772 ensureNetworkProcess();
774 WebProcessCreationParameters parameters;
776 websiteDataStore.resolveDirectoriesIfNecessary();
778 parameters.injectedBundlePath = m_resolvedPaths.injectedBundlePath;
779 if (!parameters.injectedBundlePath.isEmpty())
780 SandboxExtension::createHandleWithoutResolvingPath(parameters.injectedBundlePath, SandboxExtension::Type::ReadOnly, parameters.injectedBundlePathExtensionHandle);
782 parameters.additionalSandboxExtensionHandles.allocate(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size());
783 for (size_t i = 0, size = m_resolvedPaths.additionalWebProcessSandboxExtensionPaths.size(); i < size; ++i)
784 SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.additionalWebProcessSandboxExtensionPaths[i], SandboxExtension::Type::ReadOnly, parameters.additionalSandboxExtensionHandles[i]);
786 parameters.applicationCacheDirectory = websiteDataStore.resolvedApplicationCacheDirectory();
787 if (parameters.applicationCacheDirectory.isEmpty())
788 parameters.applicationCacheDirectory = m_resolvedPaths.applicationCacheDirectory;
789 if (!parameters.applicationCacheDirectory.isEmpty())
790 SandboxExtension::createHandleWithoutResolvingPath(parameters.applicationCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.applicationCacheDirectoryExtensionHandle);
792 parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName();
794 parameters.webSQLDatabaseDirectory = websiteDataStore.resolvedDatabaseDirectory();
795 if (parameters.webSQLDatabaseDirectory.isEmpty())
796 parameters.webSQLDatabaseDirectory = m_resolvedPaths.webSQLDatabaseDirectory;
797 if (!parameters.webSQLDatabaseDirectory.isEmpty())
798 SandboxExtension::createHandleWithoutResolvingPath(parameters.webSQLDatabaseDirectory, SandboxExtension::Type::ReadWrite, parameters.webSQLDatabaseDirectoryExtensionHandle);
800 parameters.mediaCacheDirectory = websiteDataStore.resolvedMediaCacheDirectory();
801 if (parameters.mediaCacheDirectory.isEmpty())
802 parameters.mediaCacheDirectory = m_resolvedPaths.mediaCacheDirectory;
803 if (!parameters.mediaCacheDirectory.isEmpty())
804 SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaCacheDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaCacheDirectoryExtensionHandle);
806 parameters.mediaKeyStorageDirectory = websiteDataStore.resolvedMediaKeysDirectory();
807 if (parameters.mediaKeyStorageDirectory.isEmpty())
808 parameters.mediaKeyStorageDirectory = m_resolvedPaths.mediaKeyStorageDirectory;
809 if (!parameters.mediaKeyStorageDirectory.isEmpty())
810 SandboxExtension::createHandleWithoutResolvingPath(parameters.mediaKeyStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.mediaKeyStorageDirectoryExtensionHandle);
813 setJavaScriptConfigurationFileEnabledFromDefaults();
816 if (javaScriptConfigurationFileEnabled()) {
817 parameters.javaScriptConfigurationDirectory = websiteDataStore.resolvedJavaScriptConfigurationDirectory();
818 if (!parameters.javaScriptConfigurationDirectory.isEmpty())
819 SandboxExtension::createHandleWithoutResolvingPath(parameters.javaScriptConfigurationDirectory, SandboxExtension::Type::ReadWrite, parameters.javaScriptConfigurationDirectoryExtensionHandle);
822 parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
824 parameters.cacheModel = cacheModel();
825 parameters.languages = userPreferredLanguages();
827 parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument);
828 parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);
829 parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy = copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy);
830 parameters.urlSchemesForWhichDomainRelaxationIsForbidden = copyToVector(m_schemesToSetDomainRelaxationForbiddenFor);
831 parameters.urlSchemesRegisteredAsLocal = copyToVector(m_schemesToRegisterAsLocal);
832 parameters.urlSchemesRegisteredAsNoAccess = copyToVector(m_schemesToRegisterAsNoAccess);
833 parameters.urlSchemesRegisteredAsDisplayIsolated = copyToVector(m_schemesToRegisterAsDisplayIsolated);
834 parameters.urlSchemesRegisteredAsCORSEnabled = copyToVector(m_schemesToRegisterAsCORSEnabled);
835 parameters.urlSchemesRegisteredAsAlwaysRevalidated = copyToVector(m_schemesToRegisterAsAlwaysRevalidated);
836 parameters.urlSchemesRegisteredAsCachePartitioned = copyToVector(m_schemesToRegisterAsCachePartitioned);
837 parameters.urlSchemesServiceWorkersCanHandle = copyToVector(m_schemesServiceWorkersCanHandle);
838 parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest = copyToVector(m_schemesToRegisterAsCanDisplayOnlyIfCanRequest);
840 parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
841 parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
843 parameters.terminationTimeout = 0_s;
845 parameters.textCheckerState = TextChecker::state();
847 parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
849 parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
851 #if ENABLE(NOTIFICATIONS)
852 // FIXME: There should be a generic way for supplements to add to the intialization parameters.
853 parameters.notificationPermissions = supplement<WebNotificationManagerProxy>()->notificationPermissions();
856 parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
857 parameters.plugInAutoStartOrigins = copyToVector(m_plugInAutoStartProvider.autoStartOrigins());
859 parameters.memoryCacheDisabled = m_memoryCacheDisabled;
861 #if ENABLE(SERVICE_CONTROLS)
862 auto& serviceController = ServicesController::singleton();
863 parameters.hasImageServices = serviceController.hasImageServices();
864 parameters.hasSelectionServices = serviceController.hasSelectionServices();
865 parameters.hasRichContentServices = serviceController.hasRichContentServices();
866 serviceController.refreshExistingServices();
869 #if ENABLE(NETSCAPE_PLUGIN_API)
870 parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
874 parameters.shouldEnableMemoryPressureReliefLogging = true;
875 if (MemoryPressureMonitor::isEnabled())
876 parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
879 #if PLATFORM(WAYLAND) && USE(EGL)
880 if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
881 parameters.waylandCompositorDisplayName = WaylandCompositor::singleton().displayName();
884 parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
885 #if ENABLE(MEDIA_STREAM)
886 parameters.shouldCaptureAudioInUIProcess = m_configuration->shouldCaptureAudioInUIProcess();
889 parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
891 // Add any platform specific parameters
892 platformInitializeWebProcess(parameters);
894 RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient->getInjectedBundleInitializationUserData(*this);
895 if (!injectedBundleInitializationUserData)
896 injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
897 parameters.initializationUserData = UserData(process.transformObjectsToHandles(injectedBundleInitializationUserData.get()));
899 process.send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
902 process.send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
905 if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
906 process.send(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters()), 0);
908 if (m_automationSession)
909 process.send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0);
911 ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
913 #if ENABLE(REMOTE_INSPECTOR)
914 // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
915 Inspector::RemoteInspector::singleton();
918 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
919 registerDisplayConfigurationCallback();
921 HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
922 WebCore::getScreenProperties(screenProperties);
923 process.send(Messages::WebProcess::SetScreenProperties(screenProperties), 0);
927 void WebProcessPool::warmInitialProcess()
929 if (m_haveInitialEmptyProcess) {
930 ASSERT(!m_processes.isEmpty());
934 if (m_processes.size() >= maximumNumberOfProcesses())
937 if (!m_websiteDataStore)
938 m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
939 createNewWebProcess(m_websiteDataStore->websiteDataStore());
941 m_haveInitialEmptyProcess = true;
944 void WebProcessPool::enableProcessTermination()
946 m_processTerminationEnabled = true;
947 Vector<RefPtr<WebProcessProxy>> processes = m_processes;
948 for (size_t i = 0; i < processes.size(); ++i) {
949 if (shouldTerminate(processes[i].get()))
950 processes[i]->terminate();
954 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
956 ASSERT(m_processes.contains(process));
958 if (!m_processTerminationEnabled)
964 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
966 ASSERT(m_processes.contains(process));
968 if (!m_visitedLinksPopulated) {
969 populateVisitedLinks();
970 m_visitedLinksPopulated = true;
973 // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
974 // so check if it needs to be started here
975 if (m_memorySamplerEnabled) {
976 SandboxExtension::Handle sampleLogSandboxHandle;
977 WallTime now = WallTime::now();
978 String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()), process->processIdentifier());
979 sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
981 process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
984 if (m_configuration->fullySynchronousModeIsAllowedForTesting())
985 process->connection()->allowFullySynchronousModeForTesting();
987 if (m_configuration->ignoreSynchronousMessagingTimeoutsForTesting())
988 process->connection()->ignoreTimeoutsForTesting();
990 m_connectionClient.didCreateConnection(this, process->webConnection());
993 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
995 ASSERT(m_processes.contains(process));
997 if (m_haveInitialEmptyProcess && process == m_processes.last())
998 m_haveInitialEmptyProcess = false;
1000 // 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.
1001 // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
1002 RefPtr<WebProcessProxy> protect(process);
1003 if (m_processWithPageCache == process)
1004 m_processWithPageCache = nullptr;
1006 #if ENABLE(SERVICE_WORKER)
1007 if (is<ServiceWorkerProcessProxy>(*process)) {
1008 auto* removedProcess = m_serviceWorkerProcesses.take(downcast<ServiceWorkerProcessProxy>(*process).securityOrigin());
1009 ASSERT_UNUSED(removedProcess, removedProcess == process);
1010 updateProcessAssertions();
1014 static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
1016 m_processes.removeFirst(process);
1019 if (m_processesUsingGamepads.contains(process))
1020 processStoppedUsingGamepads(*process);
1023 #if ENABLE(SERVICE_WORKER)
1024 // FIXME: We should do better than this. For now, we just destroy the ServiceWorker process
1025 // whenever there is no regular WebContent process remaining.
1026 if (m_processes.size() == m_serviceWorkerProcesses.size()) {
1027 if (!m_serviceWorkerProcessesTerminationTimer.isActive())
1028 m_serviceWorkerProcessesTerminationTimer.startOneShot(serviceWorkerTerminationDelay);
1033 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebsiteDataStore& websiteDataStore)
1035 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=168676
1036 // Once WebsiteDataStores are truly per-view instead of per-process, remove this nonsense.
1039 bool mustMatchDataStore = API::WebsiteDataStore::defaultDataStoreExists() && &websiteDataStore != &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
1041 bool mustMatchDataStore = false;
1044 if (m_processes.size() < maximumNumberOfProcesses())
1045 return createNewWebProcess(websiteDataStore);
1047 WebProcessProxy* processToReuse = nullptr;
1048 for (auto& process : m_processes) {
1049 if (mustMatchDataStore && &process->websiteDataStore() != &websiteDataStore)
1051 #if ENABLE(SERVICE_WORKER)
1052 if (is<ServiceWorkerProcessProxy>(*process))
1055 // Choose the process with fewest pages.
1056 if (!processToReuse || processToReuse->pageCount() > process->pageCount())
1057 processToReuse = process.get();
1059 return processToReuse ? *processToReuse : createNewWebProcess(websiteDataStore);
1062 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
1064 if (!pageConfiguration->pageGroup())
1065 pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
1066 if (!pageConfiguration->preferences())
1067 pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
1068 if (!pageConfiguration->userContentController())
1069 pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
1070 if (!pageConfiguration->visitedLinkStore())
1071 pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
1073 if (!pageConfiguration->websiteDataStore()) {
1074 // We try to avoid creating the default data store as long as possible.
1075 // But if there is an attempt to create a web page without any specified data store, then we have to create it.
1076 if (!m_websiteDataStore)
1077 m_websiteDataStore = API::WebsiteDataStore::defaultDataStore().ptr();
1079 ASSERT(!pageConfiguration->sessionID().isValid());
1080 pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
1081 pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? PAL::SessionID::legacyPrivateSessionID() : m_websiteDataStore->websiteDataStore().sessionID());
1084 RefPtr<WebProcessProxy> process;
1085 if (m_haveInitialEmptyProcess) {
1086 process = m_processes.last();
1087 m_haveInitialEmptyProcess = false;
1088 } else if (pageConfiguration->relatedPage()) {
1089 // Sharing processes, e.g. when creating the page via window.open().
1090 process = &pageConfiguration->relatedPage()->process();
1092 process = &createNewWebProcessRespectingProcessCountLimit(pageConfiguration->websiteDataStore()->websiteDataStore());
1094 #if ENABLE(SERVICE_WORKER)
1095 ASSERT(!is<ServiceWorkerProcessProxy>(*process));
1098 return process->createWebPage(pageClient, WTFMove(pageConfiguration));
1101 #if ENABLE(SERVICE_WORKER)
1102 void WebProcessPool::updateServiceWorkerUserAgent(const String& userAgent)
1104 if (m_serviceWorkerUserAgent == userAgent)
1106 m_serviceWorkerUserAgent = userAgent;
1107 for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1108 serviceWorkerProcess->setUserAgent(m_serviceWorkerUserAgent);
1111 bool WebProcessPool::mayHaveRegisteredServiceWorkers(const WebsiteDataStore& store)
1113 if (!m_serviceWorkerProcesses.isEmpty())
1116 String serviceWorkerRegistrationDirectory = store.resolvedServiceWorkerRegistrationDirectory();
1117 if (serviceWorkerRegistrationDirectory.isEmpty())
1118 serviceWorkerRegistrationDirectory = API::WebsiteDataStore::defaultDataStoreConfiguration().serviceWorkerRegistrationDirectory;
1120 return m_mayHaveRegisteredServiceWorkers.ensure(serviceWorkerRegistrationDirectory, [&] {
1121 // FIXME: Make this computation on a background thread.
1122 return ServiceWorkerProcessProxy::hasRegisteredServiceWorkers(serviceWorkerRegistrationDirectory);
1127 void WebProcessPool::pageBeginUsingWebsiteDataStore(WebPageProxy& page)
1129 auto result = m_sessionToPagesMap.add(page.sessionID(), HashSet<WebPageProxy*>()).iterator->value.add(&page);
1130 ASSERT_UNUSED(result, result.isNewEntry);
1132 auto sessionID = page.sessionID();
1133 if (sessionID.isEphemeral()) {
1134 ASSERT(page.websiteDataStore().parameters().networkSessionParameters.sessionID == sessionID);
1135 sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
1136 page.process().send(Messages::WebProcess::AddWebsiteDataStore(WebsiteDataStoreParameters::privateSessionParameters(sessionID)), 0);
1137 } else if (sessionID != PAL::SessionID::defaultSessionID()) {
1138 sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
1139 page.process().send(Messages::WebProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()), 0);
1141 #if ENABLE(INDEXED_DATABASE)
1142 if (!page.websiteDataStore().resolvedIndexedDatabaseDirectory().isEmpty())
1143 ensureStorageProcessAndWebsiteDataStore(&page.websiteDataStore());
1147 #if ENABLE(SERVICE_WORKER)
1148 if (!m_serviceWorkerPreferences) {
1149 m_serviceWorkerPreferences = page.preferencesStore();
1150 for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values())
1151 serviceWorkerProcess->updatePreferencesStore(*m_serviceWorkerPreferences);
1156 void WebProcessPool::pageEndUsingWebsiteDataStore(WebPageProxy& page)
1158 auto sessionID = page.sessionID();
1159 auto iterator = m_sessionToPagesMap.find(sessionID);
1160 ASSERT(iterator != m_sessionToPagesMap.end());
1162 auto takenPage = iterator->value.take(&page);
1163 ASSERT_UNUSED(takenPage, takenPage == &page);
1165 if (iterator->value.isEmpty()) {
1166 m_sessionToPagesMap.remove(iterator);
1168 if (sessionID == PAL::SessionID::defaultSessionID())
1171 // The last user of this non-default PAL::SessionID is gone, so clean it up in the child processes.
1172 if (networkProcess())
1173 networkProcess()->send(Messages::NetworkProcess::DestroySession(sessionID), 0);
1174 page.process().send(Messages::WebProcess::DestroySession(sessionID), 0);
1178 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request, const String& suggestedFilename)
1180 auto* downloadProxy = createDownloadProxy(request, initiatingPage);
1181 PAL::SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : PAL::SessionID::defaultSessionID();
1184 initiatingPage->handleDownloadRequest(downloadProxy);
1186 if (networkProcess()) {
1187 ResourceRequest updatedRequest(request);
1188 // Request's firstPartyForCookies will be used as Original URL of the download request.
1189 // We set the value to top level document's URL.
1191 updatedRequest.setFirstPartyForCookies(URL(URL(), initiatingPage->pageLoadState().url()));
1193 updatedRequest.setFirstPartyForCookies(URL());
1194 networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), updatedRequest, suggestedFilename), 0);
1195 return downloadProxy;
1198 return downloadProxy;
1201 DownloadProxy* WebProcessPool::resumeDownload(const API::Data* resumeData, const String& path)
1203 auto* downloadProxy = createDownloadProxy(ResourceRequest(), nullptr);
1205 SandboxExtension::Handle sandboxExtensionHandle;
1206 if (!path.isEmpty())
1207 SandboxExtension::createHandle(path, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle);
1209 if (networkProcess()) {
1210 // 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.
1211 networkProcess()->send(Messages::NetworkProcess::ResumeDownload(PAL::SessionID::defaultSessionID(), downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
1212 return downloadProxy;
1215 return downloadProxy;
1218 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
1220 for (auto& process : m_processes) {
1221 // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
1222 process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
1226 void WebProcessPool::populateVisitedLinks()
1228 m_historyClient->populateVisitedLinks(*this);
1231 WebProcessPool::Statistics& WebProcessPool::statistics()
1233 static Statistics statistics = Statistics();
1238 #if ENABLE(NETSCAPE_PLUGIN_API)
1239 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
1241 Vector<String> directories;
1242 directories.append(directory);
1244 m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
1247 void WebProcessPool::refreshPlugins()
1249 m_pluginInfoStore.refresh();
1250 sendToAllProcesses(Messages::WebProcess::RefreshPlugins());
1253 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1255 ProcessID WebProcessPool::networkProcessIdentifier()
1257 if (!m_networkProcess)
1260 return m_networkProcess->processIdentifier();
1263 ProcessID WebProcessPool::storageProcessIdentifier()
1265 if (!m_storageProcess)
1268 return m_storageProcess->processIdentifier();
1271 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
1273 m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
1274 sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
1277 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
1279 m_shouldUseFontSmoothing = useFontSmoothing;
1280 sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
1283 void WebProcessPool::setResourceLoadStatisticsEnabled(bool enabled)
1285 m_resourceLoadStatisticsEnabled = enabled;
1286 sendToAllProcesses(Messages::WebProcess::SetResourceLoadStatisticsEnabled(enabled));
1289 void WebProcessPool::clearResourceLoadStatistics()
1291 sendToAllProcesses(Messages::WebProcess::ClearResourceLoadStatistics());
1294 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
1296 m_schemesToRegisterAsEmptyDocument.add(urlScheme);
1297 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
1300 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
1302 m_schemesToRegisterAsSecure.add(urlScheme);
1303 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
1304 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsSecure(urlScheme));
1307 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
1309 m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
1310 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1311 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
1314 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
1316 m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
1317 sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
1320 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
1322 m_canHandleHTTPSServerTrustEvaluation = value;
1323 if (m_networkProcess) {
1324 m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
1329 void WebProcessPool::preconnectToServer(const URL& url)
1331 if (!url.isValid() || !url.protocolIsInHTTPFamily())
1334 ensureNetworkProcess().send(Messages::NetworkProcess::PreconnectTo(url, StoredCredentialsPolicy::Use), 0);
1337 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
1339 m_schemesToRegisterAsLocal.add(urlScheme);
1340 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
1341 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsLocal(urlScheme));
1344 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
1346 m_schemesToRegisterAsNoAccess.add(urlScheme);
1347 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1348 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsNoAccess(urlScheme));
1351 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
1353 m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
1354 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1355 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
1358 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
1360 m_schemesToRegisterAsCORSEnabled.add(urlScheme);
1361 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1362 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
1365 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1370 globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
1371 for (auto* processPool : allProcessPools())
1372 processPool->registerSchemeForCustomProtocol(urlScheme);
1375 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
1380 globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
1381 for (auto* processPool : allProcessPools())
1382 processPool->unregisterSchemeForCustomProtocol(urlScheme);
1385 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
1387 m_schemesToRegisterAsCachePartitioned.add(urlScheme);
1388 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
1391 void WebProcessPool::registerURLSchemeServiceWorkersCanHandle(const String& urlScheme)
1393 m_schemesServiceWorkersCanHandle.add(urlScheme);
1394 sendToAllProcesses(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme));
1395 if (m_storageProcess)
1396 m_storageProcess->send(Messages::ChildProcess::RegisterURLSchemeServiceWorkersCanHandle(urlScheme), 0);
1399 void WebProcessPool::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& urlScheme)
1401 m_schemesToRegisterAsCanDisplayOnlyIfCanRequest.add(urlScheme);
1402 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1403 sendToNetworkingProcess(Messages::NetworkProcess::RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(urlScheme));
1406 void WebProcessPool::setCacheModel(CacheModel cacheModel)
1408 m_configuration->setCacheModel(cacheModel);
1409 sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
1411 if (m_networkProcess)
1412 m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
1415 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
1417 sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
1420 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request, WebPageProxy* originatingPage)
1422 auto downloadProxy = ensureNetworkProcess().createDownloadProxy(request);
1423 downloadProxy->setOriginatingPage(originatingPage);
1424 return downloadProxy;
1427 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
1429 m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
1432 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
1434 m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
1437 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName)
1439 m_messageReceiverMap.removeMessageReceiver(messageReceiverName);
1442 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
1444 m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
1447 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
1449 return m_messageReceiverMap.dispatchMessage(connection, decoder);
1452 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
1454 return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1457 void WebProcessPool::setEnhancedAccessibility(bool flag)
1459 sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1462 void WebProcessPool::startMemorySampler(const double interval)
1464 // For new WebProcesses we will also want to start the Memory Sampler
1465 m_memorySamplerEnabled = true;
1466 m_memorySamplerInterval = interval;
1469 #if ENABLE(MEMORY_SAMPLER)
1470 WebMemorySampler::singleton()->start(interval);
1474 SandboxExtension::Handle sampleLogSandboxHandle;
1475 WallTime now = WallTime::now();
1476 String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now.secondsSinceEpoch().seconds()));
1477 sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::Type::ReadWrite, sampleLogSandboxHandle);
1479 sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1482 void WebProcessPool::stopMemorySampler()
1485 m_memorySamplerEnabled = false;
1488 #if ENABLE(MEMORY_SAMPLER)
1489 WebMemorySampler::singleton()->stop();
1492 sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1495 void WebProcessPool::useTestingNetworkSession()
1497 ASSERT(m_processes.isEmpty());
1498 ASSERT(!m_networkProcess);
1500 if (m_networkProcess)
1503 if (!m_processes.isEmpty())
1506 m_shouldUseTestingNetworkSession = true;
1509 template<typename T, typename U>
1510 void WebProcessPool::sendSyncToNetworkingProcess(T&& message, U&& reply)
1512 if (m_networkProcess && m_networkProcess->canSendMessage())
1513 m_networkProcess->sendSync(std::forward<T>(message), std::forward<U>(reply), 0);
1516 void WebProcessPool::setAllowsAnySSLCertificateForWebSocket(bool allows)
1518 sendSyncToNetworkingProcess(Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket(allows), Messages::NetworkProcess::SetAllowsAnySSLCertificateForWebSocket::Reply());
1521 void WebProcessPool::clearCachedCredentials()
1523 sendToAllProcesses(Messages::WebProcess::ClearCachedCredentials());
1524 if (m_networkProcess)
1525 m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1528 void WebProcessPool::terminateStorageProcess()
1530 if (!m_storageProcess)
1533 m_storageProcess->terminate();
1534 m_storageProcess = nullptr;
1537 void WebProcessPool::terminateNetworkProcess()
1539 if (!m_networkProcess)
1542 m_networkProcess->terminate();
1543 m_networkProcess = nullptr;
1544 m_didNetworkProcessCrash = true;
1547 void WebProcessPool::terminateServiceWorkerProcesses()
1549 #if ENABLE(SERVICE_WORKER)
1550 auto protectedThis = makeRef(*this);
1551 while (!m_serviceWorkerProcesses.isEmpty())
1552 m_serviceWorkerProcesses.begin()->value->requestTermination(ProcessTerminationReason::RequestedByClient);
1556 void WebProcessPool::syncNetworkProcessCookies()
1558 sendSyncToNetworkingProcess(Messages::NetworkProcess::SyncAllCookies(), Messages::NetworkProcess::SyncAllCookies::Reply());
1561 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1563 ensureNetworkProcess();
1564 m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1567 void WebProcessPool::updateAutomationCapabilities() const
1569 #if ENABLE(REMOTE_INSPECTOR)
1570 Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1574 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1576 if (m_automationSession)
1577 m_automationSession->setProcessPool(nullptr);
1579 m_automationSession = WTFMove(automationSession);
1581 #if ENABLE(REMOTE_INSPECTOR)
1582 if (m_automationSession) {
1583 m_automationSession->init();
1584 m_automationSession->setProcessPool(this);
1586 sendToAllProcesses(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()));
1588 sendToAllProcesses(Messages::WebProcess::DestroyAutomationSessionProxy());
1592 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1595 ResourceRequest::setHTTPPipeliningEnabled(enabled);
1597 UNUSED_PARAM(enabled);
1601 bool WebProcessPool::httpPipeliningEnabled() const
1604 return ResourceRequest::httpPipeliningEnabled();
1610 void WebProcessPool::getStatistics(uint32_t statisticsMask, Function<void (API::Dictionary*, CallbackBase::Error)>&& callbackFunction)
1612 if (!statisticsMask) {
1613 callbackFunction(nullptr, CallbackBase::Error::Unknown);
1617 RefPtr<StatisticsRequest> request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1619 if (statisticsMask & StatisticsRequestTypeWebContent)
1620 requestWebContentStatistics(request.get());
1622 if (statisticsMask & StatisticsRequestTypeNetworking)
1623 requestNetworkingStatistics(request.get());
1626 void WebProcessPool::requestWebContentStatistics(StatisticsRequest* request)
1628 // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1631 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest* request)
1633 if (!m_networkProcess) {
1634 LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1638 uint64_t requestID = request->addOutstandingRequest();
1639 m_statisticsRequests.set(requestID, request);
1640 m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1643 static WebProcessProxy* webProcessProxyFromConnection(IPC::Connection& connection, const Vector<RefPtr<WebProcessProxy>>& processes)
1645 for (auto& process : processes) {
1646 if (process->hasConnection(connection))
1647 return process.get();
1650 ASSERT_NOT_REACHED();
1654 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1656 auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1657 if (!webProcessProxy)
1659 m_injectedBundleClient->didReceiveMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1662 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1664 auto* webProcessProxy = webProcessProxyFromConnection(connection, m_processes);
1665 if (!webProcessProxy)
1668 RefPtr<API::Object> returnData;
1669 m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(*this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1670 returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1673 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1675 RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1677 LOG_ERROR("Cannot report networking statistics.");
1681 request->completedRequest(requestID, statisticsData);
1686 void WebProcessPool::startedUsingGamepads(IPC::Connection& connection)
1688 auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1692 bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1694 ASSERT(!m_processesUsingGamepads.contains(proxy));
1695 m_processesUsingGamepads.add(proxy);
1697 if (!wereAnyProcessesUsingGamepads)
1698 UIGamepadProvider::singleton().processPoolStartedUsingGamepads(*this);
1700 proxy->send(Messages::WebProcess::SetInitialGamepads(UIGamepadProvider::singleton().snapshotGamepads()), 0);
1703 void WebProcessPool::stoppedUsingGamepads(IPC::Connection& connection)
1705 auto* proxy = webProcessProxyFromConnection(connection, m_processes);
1709 ASSERT(m_processesUsingGamepads.contains(proxy));
1710 processStoppedUsingGamepads(*proxy);
1713 void WebProcessPool::processStoppedUsingGamepads(WebProcessProxy& process)
1715 bool wereAnyProcessesUsingGamepads = !m_processesUsingGamepads.isEmpty();
1717 ASSERT(m_processesUsingGamepads.contains(&process));
1718 m_processesUsingGamepads.remove(&process);
1720 if (wereAnyProcessesUsingGamepads && m_processesUsingGamepads.isEmpty())
1721 UIGamepadProvider::singleton().processPoolStoppedUsingGamepads(*this);
1724 void WebProcessPool::gamepadConnected(const UIGamepad& gamepad)
1726 for (auto& process : m_processesUsingGamepads)
1727 process->send(Messages::WebProcess::GamepadConnected(gamepad.fullGamepadData()), 0);
1730 void WebProcessPool::gamepadDisconnected(const UIGamepad& gamepad)
1732 for (auto& process : m_processesUsingGamepads)
1733 process->send(Messages::WebProcess::GamepadDisconnected(gamepad.index()), 0);
1736 void WebProcessPool::setInitialConnectedGamepads(const Vector<std::unique_ptr<UIGamepad>>& gamepads)
1738 Vector<GamepadData> gamepadDatas;
1739 gamepadDatas.grow(gamepads.size());
1740 for (size_t i = 0; i < gamepads.size(); ++i) {
1743 gamepadDatas[i] = gamepads[i]->fullGamepadData();
1746 for (auto& process : m_processesUsingGamepads)
1747 process->send(Messages::WebProcess::SetInitialGamepads(gamepadDatas), 0);
1750 #endif // ENABLE(GAMEPAD)
1752 void WebProcessPool::setJavaScriptConfigurationFileEnabled(bool flag)
1754 m_javaScriptConfigurationFileEnabled = flag;
1757 void WebProcessPool::garbageCollectJavaScriptObjects()
1759 sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1762 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1764 sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1767 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, PAL::SessionID sessionID)
1769 m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1772 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, PAL::SessionID sessionID)
1774 m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1777 Ref<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1779 return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1782 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1784 m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1787 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1789 m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1792 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, WallTime time)
1794 m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1797 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1799 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1800 if (!globalURLSchemesWithCustomProtocolHandlers().contains(scheme))
1801 m_urlSchemesRegisteredForCustomProtocols.add(scheme);
1802 sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::RegisterScheme(scheme));
1806 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1808 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
1809 m_urlSchemesRegisteredForCustomProtocols.remove(scheme);
1810 sendToNetworkingProcess(Messages::LegacyCustomProtocolManager::UnregisterScheme(scheme));
1814 #if ENABLE(NETSCAPE_PLUGIN_API)
1815 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1817 auto& policiesForHost = m_pluginLoadClientPolicies.ensure(host, [] { return HashMap<String, HashMap<String, uint8_t>>(); }).iterator->value;
1818 auto& versionsToPolicies = policiesForHost.ensure(bundleIdentifier, [] { return HashMap<String, uint8_t>(); }).iterator->value;
1819 versionsToPolicies.set(versionString, policy);
1821 sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1824 void WebProcessPool::resetPluginLoadClientPolicies(HashMap<String, HashMap<String, HashMap<String, uint8_t>>>&& pluginLoadClientPolicies)
1826 m_pluginLoadClientPolicies = WTFMove(pluginLoadClientPolicies);
1827 sendToAllProcesses(Messages::WebProcess::ResetPluginLoadClientPolicies(m_pluginLoadClientPolicies));
1830 void WebProcessPool::clearPluginClientPolicies()
1832 m_pluginLoadClientPolicies.clear();
1833 sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1837 void WebProcessPool::addSupportedPlugin(String&& matchingDomain, String&& name, HashSet<String>&& mimeTypes, HashSet<String> extensions)
1839 #if ENABLE(NETSCAPE_PLUGIN_API)
1840 m_pluginInfoStore.addSupportedPlugin(WTFMove(matchingDomain), WTFMove(name), WTFMove(mimeTypes), WTFMove(extensions));
1842 UNUSED_PARAM(matchingDomain);
1844 UNUSED_PARAM(mimeTypes);
1845 UNUSED_PARAM(extensions);
1849 void WebProcessPool::clearSupportedPlugins()
1851 #if ENABLE(NETSCAPE_PLUGIN_API)
1852 m_pluginInfoStore.clearSupportedPlugins();
1856 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1858 m_memoryCacheDisabled = disabled;
1859 sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1862 void WebProcessPool::setFontWhitelist(API::Array* array)
1864 m_fontWhitelist.clear();
1866 for (size_t i = 0; i < array->size(); ++i) {
1867 if (API::String* font = array->at<API::String>(i))
1868 m_fontWhitelist.append(font->string());
1873 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1875 // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1876 // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1877 // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1878 static int maximumTimerThrottlePerPageInMS = 200 * 100;
1880 int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1881 sendToAllProcesses(Messages::WebProcess::SetHiddenPageDOMTimerThrottlingIncreaseLimit(limitInMilliseconds));
1884 void WebProcessPool::reportWebContentCPUTime(Seconds cpuTime, uint64_t activityState)
1887 if (m_perActivityStateCPUUsageSampler)
1888 m_perActivityStateCPUUsageSampler->reportWebContentCPUTime(cpuTime, static_cast<WebCore::ActivityStateForCPUSampling>(activityState));
1890 UNUSED_PARAM(cpuTime);
1891 UNUSED_PARAM(activityState);
1895 void WebProcessPool::updateProcessAssertions()
1898 #if ENABLE(SERVICE_WORKER)
1899 auto updateServiceWorkerProcessAssertion = [&] {
1900 if (!m_serviceWorkerProcesses.isEmpty() && m_foregroundWebProcessCounter.value()) {
1901 // FIXME: We can do better than this once we have process per origin.
1902 for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1903 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
1904 if (!m_foregroundTokensForServiceWorkerProcesses.contains(securityOrigin))
1905 m_foregroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().foregroundActivityToken());
1907 m_backgroundTokensForServiceWorkerProcesses.clear();
1910 if (!m_serviceWorkerProcesses.isEmpty() && m_backgroundWebProcessCounter.value()) {
1911 // FIXME: We can do better than this once we have process per origin.
1912 for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1913 auto& securityOrigin = serviceWorkerProcess->securityOrigin();
1914 if (!m_backgroundTokensForServiceWorkerProcesses.contains(securityOrigin))
1915 m_backgroundTokensForServiceWorkerProcesses.add(securityOrigin, serviceWorkerProcess->throttler().backgroundActivityToken());
1917 m_foregroundTokensForServiceWorkerProcesses.clear();
1920 m_foregroundTokensForServiceWorkerProcesses.clear();
1921 m_backgroundTokensForServiceWorkerProcesses.clear();
1923 updateServiceWorkerProcessAssertion();
1926 auto updateNetworkProcessAssertion = [&] {
1927 if (m_foregroundWebProcessCounter.value()) {
1928 if (!m_foregroundTokenForNetworkProcess)
1929 m_foregroundTokenForNetworkProcess = ensureNetworkProcess().throttler().foregroundActivityToken();
1930 m_backgroundTokenForNetworkProcess = nullptr;
1933 if (m_backgroundWebProcessCounter.value()) {
1934 if (!m_backgroundTokenForNetworkProcess)
1935 m_backgroundTokenForNetworkProcess = ensureNetworkProcess().throttler().backgroundActivityToken();
1936 m_foregroundTokenForNetworkProcess = nullptr;
1939 m_foregroundTokenForNetworkProcess = nullptr;
1940 m_backgroundTokenForNetworkProcess = nullptr;
1942 updateNetworkProcessAssertion();
1946 #if ENABLE(SERVICE_WORKER)
1947 void WebProcessPool::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destination, MessageWithMessagePorts&& message, ServiceWorkerIdentifier source, const String& sourceOrigin)
1949 sendToStorageProcessRelaunchingIfNecessary(Messages::StorageProcess::PostMessageToServiceWorkerClient(destination, WTFMove(message), source, sourceOrigin));
1952 void WebProcessPool::postMessageToServiceWorker(ServiceWorkerIdentifier destination, MessageWithMessagePorts&& message, const ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
1954 sendToStorageProcessRelaunchingIfNecessary(Messages::StorageProcess::PostMessageToServiceWorker(destination, WTFMove(message), source, connectionIdentifier));
1958 void WebProcessPool::reinstateNetworkProcessAssertionState(NetworkProcessProxy& newNetworkProcessProxy)
1961 // The network process crashed; take new tokens for the new network process.
1962 if (m_backgroundTokenForNetworkProcess)
1963 m_backgroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().backgroundActivityToken();
1964 else if (m_foregroundTokenForNetworkProcess)
1965 m_foregroundTokenForNetworkProcess = newNetworkProcessProxy.throttler().foregroundActivityToken();
1967 UNUSED_PARAM(newNetworkProcessProxy);
1971 #if ENABLE(SERVICE_WORKER)
1972 ServiceWorkerProcessProxy* WebProcessPool::serviceWorkerProcessProxyFromPageID(uint64_t pageID) const
1974 // FIXME: This is inefficient.
1975 for (auto* serviceWorkerProcess : m_serviceWorkerProcesses.values()) {
1976 if (serviceWorkerProcess->pageID() == pageID)
1977 return serviceWorkerProcess;
1983 Ref<WebProcessProxy> WebProcessPool::processForNavigation(WebPageProxy& page, const API::Navigation& navigation, PolicyAction& action)
1985 if (!m_configuration->processSwapsOnNavigation())
1986 return page.process();
1988 // FIXME: We should support process swap when a window has an opener.
1989 if (navigation.opener())
1990 return page.process();
1992 if (navigation.isCrossOriginWindowOpenNavigation()) {
1993 action = PolicyAction::Ignore;
1994 return createNewWebProcess(page.websiteDataStore());
1997 auto targetURL = navigation.request().url();
1998 auto url = URL { ParsedURLString, page.pageLoadState().url() };
1999 if (!url.isValid() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL))
2000 return page.process();
2002 action = PolicyAction::Suspend;
2003 return createNewWebProcess(page.websiteDataStore());
2006 } // namespace WebKit