3384ab809b8bb7627e6101be34ba1e671ac7f15f
[WebKit-https.git] / Source / WebKit / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009-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 "WebProcess.h"
28
29 #include "APIFrameHandle.h"
30 #include "APIPageGroupHandle.h"
31 #include "APIPageHandle.h"
32 #include "AuthenticationManager.h"
33 #include "ChildProcessMessages.h"
34 #include "DrawingArea.h"
35 #include "EventDispatcher.h"
36 #include "InjectedBundle.h"
37 #include "LibWebRTCNetwork.h"
38 #include "Logging.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "NetworkSession.h"
42 #include "NetworkSessionCreationParameters.h"
43 #include "PluginProcessConnectionManager.h"
44 #include "ServiceWorkerContextManager.h"
45 #include "ServiceWorkerContextManagerMessages.h"
46 #include "SessionTracker.h"
47 #include "StatisticsData.h"
48 #include "StorageProcessMessages.h"
49 #include "UserData.h"
50 #include "WebAutomationSessionProxy.h"
51 #include "WebCacheStorageProvider.h"
52 #include "WebConnectionToUIProcess.h"
53 #include "WebCookieManager.h"
54 #include "WebCoreArgumentCoders.h"
55 #include "WebFrame.h"
56 #include "WebFrameNetworkingContext.h"
57 #include "WebGamepadProvider.h"
58 #include "WebGeolocationManager.h"
59 #include "WebLoaderStrategy.h"
60 #include "WebMediaKeyStorageManager.h"
61 #include "WebMemorySampler.h"
62 #include "WebPage.h"
63 #include "WebPageGroupProxy.h"
64 #include "WebPlatformStrategies.h"
65 #include "WebPluginInfoProvider.h"
66 #include "WebProcessCreationParameters.h"
67 #include "WebProcessMessages.h"
68 #include "WebProcessPoolMessages.h"
69 #include "WebProcessProxyMessages.h"
70 #include "WebResourceLoadStatisticsStoreMessages.h"
71 #include "WebServiceWorkerProvider.h"
72 #include "WebSocketStream.h"
73 #include "WebToStorageProcessConnection.h"
74 #include "WebsiteData.h"
75 #include "WebsiteDataStoreParameters.h"
76 #include "WebsiteDataType.h"
77 #include <JavaScriptCore/JSLock.h>
78 #include <JavaScriptCore/MemoryStatistics.h>
79 #include <JavaScriptCore/WasmFaultSignalHandler.h>
80 #include <WebCore/AXObjectCache.h>
81 #include <WebCore/ApplicationCacheStorage.h>
82 #include <WebCore/AuthenticationChallenge.h>
83 #include <WebCore/CPUMonitor.h>
84 #include <WebCore/CommonVM.h>
85 #include <WebCore/CrossOriginPreflightResultCache.h>
86 #include <WebCore/DNS.h>
87 #include <WebCore/DOMWindow.h>
88 #include <WebCore/DatabaseManager.h>
89 #include <WebCore/DatabaseTracker.h>
90 #include <WebCore/DeprecatedGlobalSettings.h>
91 #include <WebCore/DiagnosticLoggingClient.h>
92 #include <WebCore/DiagnosticLoggingKeys.h>
93 #include <WebCore/FontCache.h>
94 #include <WebCore/FontCascade.h>
95 #include <WebCore/Frame.h>
96 #include <WebCore/FrameLoader.h>
97 #include <WebCore/GCController.h>
98 #include <WebCore/GlyphPage.h>
99 #include <WebCore/HTMLMediaElement.h>
100 #include <WebCore/JSDOMWindow.h>
101 #include <WebCore/MainFrame.h>
102 #include <WebCore/MemoryCache.h>
103 #include <WebCore/MemoryRelease.h>
104 #include <WebCore/NetworkStorageSession.h>
105 #include <WebCore/Page.h>
106 #include <WebCore/PageCache.h>
107 #include <WebCore/PageGroup.h>
108 #include <WebCore/PlatformMediaSessionManager.h>
109 #include <WebCore/ResourceHandle.h>
110 #include <WebCore/ResourceLoadObserver.h>
111 #include <WebCore/ResourceLoadStatistics.h>
112 #include <WebCore/RuntimeApplicationChecks.h>
113 #include <WebCore/SchemeRegistry.h>
114 #include <WebCore/SecurityOrigin.h>
115 #include <WebCore/ServiceWorkerContextData.h>
116 #include <WebCore/Settings.h>
117 #include <WebCore/URLParser.h>
118 #include <WebCore/UserGestureIndicator.h>
119 #include <unistd.h>
120 #include <wtf/CurrentTime.h>
121 #include <wtf/Language.h>
122 #include <wtf/RunLoop.h>
123 #include <wtf/text/StringHash.h>
124
125 #if PLATFORM(WAYLAND)
126 #include "WaylandCompositorDisplay.h"
127 #endif
128
129 #if PLATFORM(COCOA)
130 #include "CookieStorageShim.h"
131 #include "ObjCObjectGraph.h"
132 #include "UserMediaCaptureManager.h"
133 #endif
134
135 #if ENABLE(SEC_ITEM_SHIM)
136 #include "SecItemShim.h"
137 #endif
138
139 #if ENABLE(NOTIFICATIONS)
140 #include "WebNotificationManager.h"
141 #endif
142
143 #if ENABLE(REMOTE_INSPECTOR)
144 #include <JavaScriptCore/RemoteInspector.h>
145 #endif
146
147 using namespace JSC;
148 using namespace WebCore;
149
150 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
151 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
152
153 // This should be greater than tileRevalidationTimeout in TileController.
154 static const Seconds nonVisibleProcessCleanupDelay { 10_s };
155
156 namespace WebKit {
157
158 WebProcess& WebProcess::singleton()
159 {
160     static WebProcess& process = *new WebProcess;
161     return process;
162 }
163
164 WebProcess::WebProcess()
165     : m_eventDispatcher(EventDispatcher::create())
166 #if PLATFORM(IOS)
167     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
168 #endif
169     , m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
170     , m_webLoaderStrategy(*new WebLoaderStrategy)
171     , m_cacheStorageProvider(WebCacheStorageProvider::create())
172     , m_dnsPrefetchHystereris([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
173 #if ENABLE(NETSCAPE_PLUGIN_API)
174     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
175 #endif
176     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
177 #if PLATFORM(IOS)
178     , m_webSQLiteDatabaseTracker(*this)
179 #endif
180 {
181     // Initialize our platform strategies.
182     WebPlatformStrategies::initialize();
183
184     // FIXME: This should moved to where WebProcess::initialize is called,
185     // so that ports have a chance to customize, and ifdefs in this file are
186     // limited.
187     addSupplement<WebGeolocationManager>();
188     addSupplement<WebCookieManager>();
189     addSupplement<AuthenticationManager>();
190
191 #if ENABLE(NOTIFICATIONS)
192     addSupplement<WebNotificationManager>();
193 #endif
194
195 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
196     addSupplement<WebMediaKeyStorageManager>();
197 #endif
198
199 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
200     addSupplement<UserMediaCaptureManager>();
201 #endif
202
203     m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, double>());
204
205     ResourceLoadObserver::shared().setNotificationCallback([this] (Vector<ResourceLoadStatistics>&& statistics) {
206         ASSERT(!statistics.isEmpty());
207         parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
208     });
209
210     Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
211 }
212
213 WebProcess::~WebProcess()
214 {
215 }
216
217 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
218 {
219     platformInitializeProcess(parameters);
220 }
221
222 void WebProcess::initializeConnection(IPC::Connection* connection)
223 {
224     ChildProcess::initializeConnection(connection);
225
226 #if !PLATFORM(GTK) && !PLATFORM(WPE)
227     connection->setShouldExitOnSyncMessageSendFailure(true);
228 #endif
229
230 #if HAVE(QOS_CLASSES)
231     connection->setShouldBoostMainThreadOnSyncMessage(true);
232 #endif
233
234     m_eventDispatcher->initializeConnection(connection);
235 #if PLATFORM(IOS)
236     m_viewUpdateDispatcher->initializeConnection(connection);
237 #endif // PLATFORM(IOS)
238     m_webInspectorInterruptDispatcher->initializeConnection(connection);
239
240 #if ENABLE(NETSCAPE_PLUGIN_API)
241     m_pluginProcessConnectionManager->initializeConnection(connection);
242 #endif
243
244     for (auto& supplement : m_supplements.values())
245         supplement->initializeConnection(connection);
246
247     m_webConnection = WebConnectionToUIProcess::create(this);
248
249     // In order to ensure that the asynchronous messages that are used for notifying the UI process
250     // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
251     // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
252     // unless when doing so would lead to a deadlock.
253     connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
254 }
255
256 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
257 {    
258     ASSERT(m_pageMap.isEmpty());
259
260     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
261
262 #if OS(LINUX)
263     if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
264         MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
265     MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
266 #endif
267
268     platformInitializeWebProcess(WTFMove(parameters));
269
270 #if USE(NETWORK_SESSION)
271     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create({ }));
272 #endif
273
274     // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority.
275     WTF::Thread::setCurrentThreadIsUserInteractive(-1);
276
277     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
278     if (!m_suppressMemoryPressureHandler) {
279         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
280         memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) {
281             WebCore::releaseMemory(critical, synchronous);
282         });
283 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
284         memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true);
285         memoryPressureHandler.setMemoryKillCallback([this] () {
286             WebCore::logMemoryStatisticsAtTimeOfDeath();
287             if (MemoryPressureHandler::singleton().processState() == WebsamProcessState::Active)
288                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedActiveMemoryLimit(), 0);
289             else
290                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimit(), 0);
291         });
292         memoryPressureHandler.setDidExceedInactiveLimitWhileActiveCallback([this] () {
293             parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimitWhileActive(), 0);
294         });
295 #endif
296         memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
297             if (parentProcessConnection())
298                 parentProcessConnection()->send(Messages::WebProcessProxy::MemoryPressureStatusChanged(isUnderMemoryPressure), 0);
299         });
300         memoryPressureHandler.install();
301     }
302
303     for (size_t i = 0, size = parameters.additionalSandboxExtensionHandles.size(); i < size; ++i)
304         SandboxExtension::consumePermanently(parameters.additionalSandboxExtensionHandles[i]);
305
306     if (!parameters.injectedBundlePath.isEmpty())
307         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
308
309     for (auto& supplement : m_supplements.values())
310         supplement->initialize(parameters);
311
312     auto& databaseManager = DatabaseManager::singleton();
313     databaseManager.initialize(parameters.webSQLDatabaseDirectory);
314
315     // FIXME: This should be constructed per data store, not per process.
316     m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
317 #if PLATFORM(IOS)
318     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
319 #endif
320
321 #if ENABLE(VIDEO)
322     if (!parameters.mediaCacheDirectory.isEmpty())
323         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
324 #endif
325
326     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
327
328     if (!parameters.languages.isEmpty())
329         overrideUserPreferredLanguages(parameters.languages);
330
331     m_textCheckerState = parameters.textCheckerState;
332
333     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
334
335     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
336         registerURLSchemeAsEmptyDocument(scheme);
337
338     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
339         registerURLSchemeAsSecure(scheme);
340
341     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
342         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
343
344     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
345         setDomainRelaxationForbiddenForURLScheme(scheme);
346
347     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
348         registerURLSchemeAsLocal(scheme);
349
350     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
351         registerURLSchemeAsNoAccess(scheme);
352
353     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
354         registerURLSchemeAsDisplayIsolated(scheme);
355
356     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
357         registerURLSchemeAsCORSEnabled(scheme);
358
359     for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
360         registerURLSchemeAsAlwaysRevalidated(scheme);
361
362     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
363         registerURLSchemeAsCachePartitioned(scheme);
364
365     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
366
367     setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
368
369     if (parameters.shouldAlwaysUseComplexTextCodePath)
370         setAlwaysUsesComplexTextCodePath(true);
371
372     if (parameters.shouldUseFontSmoothing)
373         setShouldUseFontSmoothing(true);
374
375     if (parameters.shouldUseTestingNetworkSession)
376         NetworkStorageSession::switchToNewTestingSession();
377
378     ensureNetworkProcessConnection();
379
380 #if PLATFORM(COCOA)
381     CookieStorageShim::singleton().initialize();
382 #endif
383     setTerminationTimeout(parameters.terminationTimeout);
384
385     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
386     for (auto& origin : parameters.plugInAutoStartOrigins)
387         m_plugInAutoStartOrigins.add(origin);
388
389     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
390
391 #if ENABLE(SERVICE_CONTROLS)
392     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
393 #endif
394
395 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA)
396     audit_token_t auditToken;
397     if (parentProcessConnection()->getAuditToken(auditToken)) {
398         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
399         Inspector::RemoteInspector::singleton().setParentProcessInformation(WebCore::presentingApplicationPID(), auditData);
400     }
401 #endif
402
403 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
404     resetPluginLoadClientPolicies(parameters.pluginLoadClientPolicies);
405 #endif
406
407 #if ENABLE(GAMEPAD)
408     GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
409 #endif
410
411 #if ENABLE(SERVICE_WORKER)
412     ServiceWorkerProvider::setSharedProvider(WebServiceWorkerProvider::singleton());
413 #endif
414
415 #if ENABLE(WEBASSEMBLY)
416     JSC::Wasm::enableFastMemory();
417 #endif
418 }
419
420 void WebProcess::ensureNetworkProcessConnection()
421 {
422     if (m_networkProcessConnection)
423         return;
424
425     IPC::Attachment encodedConnectionIdentifier;
426
427     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
428         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
429         return;
430
431 #if USE(UNIX_DOMAIN_SOCKETS)
432     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
433 #elif OS(DARWIN)
434     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
435 #else
436     ASSERT_NOT_REACHED();
437 #endif
438     if (IPC::Connection::identifierIsNull(connectionIdentifier))
439         return;
440     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
441 }
442
443 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
444 {
445     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
446 }
447
448 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
449 {
450     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
451 }
452
453 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
454 {
455     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
456 }
457
458 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
459 {
460     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
461 }
462
463 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
464 {
465     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
466 }
467
468 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
469 {
470     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
471 }
472
473 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
474 {
475     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
476 }
477
478 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
479 {
480     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
481 }
482
483 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
484 {
485     SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
486 }
487
488 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
489 {
490     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
491 }
492
493 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
494 {
495     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
496 }
497
498 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
499 {
500     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
501 }
502
503 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
504 {
505     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
506 }
507
508 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
509 {
510     overrideUserPreferredLanguages(languages);
511 }
512
513 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
514 {
515     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
516 }
517
518 void WebProcess::ensurePrivateBrowsingSession(PAL::SessionID sessionID)
519 {
520     WebFrameNetworkingContext::ensurePrivateBrowsingSession({ { }, { }, { }, { }, { }, { }, { sessionID, { }, { }, AllowsCellularAccess::Yes }});
521 }
522
523 void WebProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
524 {
525     WebFrameNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
526 }
527
528 void WebProcess::destroySession(PAL::SessionID sessionID)
529 {
530     SessionTracker::destroySession(sessionID);
531 }
532
533 void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess()
534 {
535     networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0);
536 }
537
538 #if ENABLE(NETSCAPE_PLUGIN_API)
539 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
540 {
541     return *m_pluginProcessConnectionManager;
542 }
543 #endif
544
545 void WebProcess::setCacheModel(uint32_t cm)
546 {
547     CacheModel cacheModel = static_cast<CacheModel>(cm);
548
549     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
550         return;
551
552     m_hasSetCacheModel = true;
553     m_cacheModel = cacheModel;
554
555     unsigned cacheTotalCapacity = 0;
556     unsigned cacheMinDeadCapacity = 0;
557     unsigned cacheMaxDeadCapacity = 0;
558     Seconds deadDecodedDataDeletionInterval;
559     unsigned pageCacheSize = 0;
560     calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize);
561
562     auto& memoryCache = MemoryCache::singleton();
563     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
564     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
565     PageCache::singleton().setMaxSize(pageCacheSize);
566
567     platformSetCacheModel(cacheModel);
568 }
569
570 void WebProcess::clearCachedCredentials()
571 {
572     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
573 #if USE(NETWORK_SESSION)
574     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
575         networkSession->clearCredentials();
576     else
577         ASSERT_NOT_REACHED();
578 #endif
579 }
580
581 WebPage* WebProcess::focusedWebPage() const
582 {    
583     for (auto& page : m_pageMap.values()) {
584         if (page->windowAndWebPageAreFocused())
585             return page.get();
586     }
587     return 0;
588 }
589     
590 WebPage* WebProcess::webPage(uint64_t pageID) const
591 {
592     return m_pageMap.get(pageID);
593 }
594
595 void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
596 {
597     // It is necessary to check for page existence here since during a window.open() (or targeted
598     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
599     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
600     if (result.isNewEntry) {
601         ASSERT(!result.iterator->value);
602         result.iterator->value = WebPage::create(pageID, WTFMove(parameters));
603
604         // Balanced by an enableTermination in removeWebPage.
605         disableTermination();
606         updateCPULimit();
607     } else
608         result.iterator->value->reinitializeWebPage(WTFMove(parameters));
609
610     ASSERT(result.iterator->value);
611 }
612
613 void WebProcess::removeWebPage(uint64_t pageID)
614 {
615     ASSERT(m_pageMap.contains(pageID));
616
617     pageWillLeaveWindow(pageID);
618     m_pageMap.remove(pageID);
619
620     enableTermination();
621     updateCPULimit();
622 }
623
624 bool WebProcess::shouldTerminate()
625 {
626     ASSERT(m_pageMap.isEmpty());
627
628     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
629     bool shouldTerminate = false;
630     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
631         && !shouldTerminate)
632         return false;
633
634     return true;
635 }
636
637 void WebProcess::terminate()
638 {
639 #ifndef NDEBUG
640     GCController::singleton().garbageCollectNow();
641     FontCache::singleton().invalidate();
642     MemoryCache::singleton().setDisabled(true);
643 #endif
644
645     m_webConnection->invalidate();
646     m_webConnection = nullptr;
647
648     platformTerminate();
649
650     ChildProcess::terminate();
651 }
652
653 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
654 {
655     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
656         return;
657
658     didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
659 }
660
661 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
662 {
663     if (messageReceiverMap().dispatchMessage(connection, decoder))
664         return;
665
666     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
667         didReceiveWebProcessMessage(connection, decoder);
668         return;
669     }
670
671     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
672         ChildProcess::didReceiveMessage(connection, decoder);
673         return;
674     }
675
676 #if ENABLE(SERVICE_WORKER)
677     if (decoder.messageReceiverName() == Messages::ServiceWorkerContextManager::messageReceiverName()) {
678         ASSERT(m_serviceWorkerManager);
679         if (m_serviceWorkerManager)
680             m_serviceWorkerManager->didReceiveMessage(connection, decoder);
681         return;
682     }
683 #endif
684
685     LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
686 }
687
688 void WebProcess::didClose(IPC::Connection&)
689 {
690 #ifndef NDEBUG
691     for (auto& page : copyToVector(m_pageMap.values()))
692         page->close();
693
694     GCController::singleton().garbageCollectSoon();
695     FontCache::singleton().invalidate();
696     MemoryCache::singleton().setDisabled(true);
697 #endif
698
699 #if ENABLE(VIDEO)
700     // FIXME(146657): This explicit media stop command should not be necessary
701     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
702         platformMediaSessionManager->stopAllMediaPlaybackForProcess();
703 #endif
704
705     // The UI process closed this connection, shut down.
706     stopRunLoop();
707 }
708
709 WebFrame* WebProcess::webFrame(uint64_t frameID) const
710 {
711     return m_frameMap.get(frameID);
712 }
713
714 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
715 {
716     m_frameMap.set(frameID, frame);
717 }
718
719 void WebProcess::removeWebFrame(uint64_t frameID)
720 {
721     m_frameMap.remove(frameID);
722
723     // We can end up here after our connection has closed when WebCore's frame life-support timer
724     // fires when the application is shutting down. There's no need (and no way) to update the UI
725     // process in this case.
726     if (!parentProcessConnection())
727         return;
728
729     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
730 }
731
732 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
733 {
734     for (auto& page : m_pageGroupMap.values()) {
735         if (page->corePageGroup() == pageGroup)
736             return page.get();
737     }
738
739     return 0;
740 }
741
742 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
743 {
744     return m_pageGroupMap.get(pageGroupID);
745 }
746
747 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
748 {
749     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
750     if (result.isNewEntry) {
751         ASSERT(!result.iterator->value);
752         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
753     }
754
755     return result.iterator->value.get();
756 }
757
758 static uint64_t nextUserGestureTokenIdentifier()
759 {
760     static uint64_t identifier = 1;
761     return identifier++;
762 }
763
764 uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token)
765 {
766     if (!token || !token->processingUserGesture())
767         return 0;
768
769     auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); });
770     if (result.isNewEntry) {
771         result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) {
772             WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed);
773         });
774     }
775     
776     return result.iterator->value;
777 }
778
779 void WebProcess::userGestureTokenDestroyed(UserGestureToken& token)
780 {
781     auto identifier = m_userGestureTokens.take(&token);
782     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0);
783 }
784
785 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
786 {
787     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
788     // FIXME: We need a better way to do this.
789     CacheModel cacheModel = m_cacheModel;
790     setCacheModel(CacheModelDocumentViewer);
791     setCacheModel(cacheModel);
792
793     MemoryCache::singleton().evictResources();
794
795     // Empty the cross-origin preflight cache.
796     CrossOriginPreflightResultCache::singleton().empty();
797 }
798
799 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
800 {
801     if (string.isEmpty())
802         return;
803     if (string.is8Bit()) {
804         hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::foldCase<LChar>>(string.characters8(), string.length());
805         return;
806     }
807     hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::foldCase<UChar>>(string.characters16(), string.length());
808 }
809
810 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
811 {
812     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
813     // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags.
814     StringHasher hasher;
815     addCaseFoldedCharacters(hasher, pageOrigin);
816     hasher.addCharacter(0);
817     addCaseFoldedCharacters(hasher, pluginOrigin);
818     hasher.addCharacter(0);
819     addCaseFoldedCharacters(hasher, mimeType);
820     return hasher.hash();
821 }
822
823 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, PAL::SessionID sessionID)
824 {
825     HashMap<PAL::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
826     HashMap<unsigned, double>::const_iterator it;
827     bool contains = false;
828
829     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
830         it = sessionIterator->value.find(plugInOriginHash);
831         contains = it != sessionIterator->value.end();
832     }
833     if (!contains) {
834         sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
835         it = sessionIterator->value.find(plugInOriginHash);
836         if (it == sessionIterator->value.end())
837             return false;
838     }
839     return currentTime() < it->value;
840 }
841
842 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
843 {
844     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
845         return true;
846
847 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
848     // The plugin wasn't in the general whitelist, so check if it similar to the primary plugin for the page (if we've found one).
849     if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
850         return true;
851 #else
852     UNUSED_PARAM(webPage);
853 #endif
854
855     // Lastly check against the more explicit hash list.
856     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
857 }
858
859 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
860 {
861     if (pageOrigin.isEmpty()) {
862         LOG(Plugins, "Not adding empty page origin");
863         return;
864     }
865
866     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
867     if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
868         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
869         return;
870     }
871
872     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
873     // comes back from the parent process. Temporarily add this hash to the list with a thirty
874     // second timeout. That way, even if the parent decides not to add it, we'll only be
875     // incorrect for a little while.
876     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000);
877
878     parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
879 }
880
881 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, PAL::SessionID sessionID)
882 {
883     // When called, some web process (which also might be this one) added the origin for auto-starting,
884     // or received user interaction.
885     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
886     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime);
887 }
888
889 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes)
890 {
891     m_plugInAutoStartOriginHashes.clear();
892     m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes));
893 }
894
895 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<PAL::SessionID, HashMap<unsigned, double>>& hashes)
896 {
897     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<PAL::SessionID, HashMap<unsigned, double>>&>(hashes));
898 }
899
900 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
901 {
902     if (pageOrigin.isEmpty())
903         return;
904
905     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
906     if (!plugInOriginHash)
907         return;
908
909     HashMap<PAL::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
910     HashMap<unsigned, double>::const_iterator it;
911     bool contains = false;
912     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
913         it = sessionIterator->value.find(plugInOriginHash);
914         contains = it != sessionIterator->value.end();
915     }
916     if (!contains) {
917         sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
918         it = sessionIterator->value.find(plugInOriginHash);
919         if (it == sessionIterator->value.end())
920             return;
921     }
922
923     if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
924         return;
925
926     parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
927 }
928
929 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
930 {
931 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
932     WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
933 #endif
934 }
935
936 void WebProcess::resetPluginLoadClientPolicies(const HashMap<WTF::String, HashMap<WTF::String, HashMap<WTF::String, uint8_t>>>& pluginLoadClientPolicies)
937 {
938 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
939     clearPluginClientPolicies();
940
941     for (auto& hostPair : pluginLoadClientPolicies) {
942         for (auto& bundleIdentifierPair : hostPair.value) {
943             for (auto& versionPair : bundleIdentifierPair.value)
944                 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionPair.value), hostPair.key, bundleIdentifierPair.key, versionPair.key);
945         }
946     }
947 #endif
948 }
949
950 void WebProcess::clearPluginClientPolicies()
951 {
952 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
953     WebPluginInfoProvider::singleton().clearPluginClientPolicies();
954 #endif
955 }
956
957 void WebProcess::refreshPlugins()
958 {
959 #if ENABLE(NETSCAPE_PLUGIN_API)
960     WebPluginInfoProvider::singleton().refresh(false);
961 #endif
962 }
963
964 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
965 {
966     TypeCountSet::const_iterator end = countedSet->end();
967     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
968         map.set(it->key, it->value);
969 }
970
971 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
972 {
973     String imagesString(ASCIILiteral("Images"));
974     String cssString(ASCIILiteral("CSS"));
975     String xslString(ASCIILiteral("XSL"));
976     String javaScriptString(ASCIILiteral("JavaScript"));
977     
978     MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
979     
980     HashMap<String, uint64_t> counts;
981     counts.set(imagesString, memoryCacheStatistics.images.count);
982     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
983     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
984     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
985     result.append(counts);
986     
987     HashMap<String, uint64_t> sizes;
988     sizes.set(imagesString, memoryCacheStatistics.images.size);
989     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
990     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
991     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
992     result.append(sizes);
993     
994     HashMap<String, uint64_t> liveSizes;
995     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
996     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
997     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
998     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
999     result.append(liveSizes);
1000     
1001     HashMap<String, uint64_t> decodedSizes;
1002     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
1003     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
1004     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
1005     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
1006     result.append(decodedSizes);
1007 }
1008
1009 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
1010 {
1011     StatisticsData data;
1012     
1013     // Gather JavaScript statistics.
1014     {
1015         JSLockHolder lock(commonVM());
1016         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), commonVM().heap.objectCount());
1017         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), commonVM().heap.globalObjectCount());
1018         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), commonVM().heap.protectedObjectCount());
1019         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), commonVM().heap.protectedGlobalObjectCount());
1020         
1021         std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(commonVM().heap.protectedObjectTypeCounts());
1022         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
1023         
1024         std::unique_ptr<TypeCountSet> objectTypeCounts(commonVM().heap.objectTypeCounts());
1025         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
1026         
1027         uint64_t javaScriptHeapSize = commonVM().heap.size();
1028         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
1029         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), commonVM().heap.capacity() - javaScriptHeapSize);
1030     }
1031
1032     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
1033     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
1034     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
1035     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
1036     
1037     // Gather font statistics.
1038     auto& fontCache = FontCache::singleton();
1039     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
1040     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
1041     
1042     // Gather glyph page statistics.
1043     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
1044     
1045     // Get WebCore memory cache statistics
1046     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1047     
1048     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1049 }
1050
1051 void WebProcess::garbageCollectJavaScriptObjects()
1052 {
1053     GCController::singleton().garbageCollectNow();
1054 }
1055
1056 void WebProcess::mainThreadPing()
1057 {
1058     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1059 }
1060
1061 void WebProcess::backgroundResponsivenessPing()
1062 {
1063     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveBackgroundResponsivenessPing(), 0);
1064 }
1065
1066 #if ENABLE(GAMEPAD)
1067
1068 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1069 {
1070     WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1071 }
1072
1073 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1074 {
1075     WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1076 }
1077
1078 void WebProcess::gamepadDisconnected(unsigned index)
1079 {
1080     WebGamepadProvider::singleton().gamepadDisconnected(index);
1081 }
1082
1083 #endif
1084
1085 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1086 {
1087     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1088 }
1089
1090 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1091 {
1092     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1093     if (!injectedBundle)
1094         return;
1095
1096     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1097 }
1098
1099 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1100 {
1101     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1102     if (!injectedBundle)
1103         return;
1104
1105     injectedBundle->setBundleParameter(key, value);
1106 }
1107
1108 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1109 {
1110     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1111     if (!injectedBundle)
1112         return;
1113
1114     injectedBundle->setBundleParameters(value);
1115 }
1116
1117 NetworkProcessConnection& WebProcess::networkConnection()
1118 {
1119     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1120     if (!m_networkProcessConnection)
1121         ensureNetworkProcessConnection();
1122     
1123     // If we failed to re-establish it then we are beyond recovery and should crash.
1124     if (!m_networkProcessConnection)
1125         CRASH();
1126     
1127     return *m_networkProcessConnection;
1128 }
1129
1130 void WebProcess::logDiagnosticMessageForNetworkProcessCrash()
1131 {
1132     WebCore::Page* page = nullptr;
1133
1134     if (auto* webPage = focusedWebPage())
1135         page = webPage->corePage();
1136
1137     if (!page) {
1138         for (auto& webPage : m_pageMap.values()) {
1139             if (auto* corePage = webPage->corePage()) {
1140                 page = corePage;
1141                 break;
1142             }
1143         }
1144     }
1145
1146     if (page)
1147         page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No);
1148 }
1149
1150 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1151 {
1152     ASSERT(m_networkProcessConnection);
1153     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1154
1155     m_networkProcessConnection = nullptr;
1156
1157     logDiagnosticMessageForNetworkProcessCrash();
1158
1159     m_webLoaderStrategy.networkProcessCrashed();
1160     WebSocketStream::networkProcessCrashed();
1161
1162     for (auto& page : m_pageMap.values())
1163         page->stopAllURLSchemeTasks();
1164 }
1165
1166 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1167 {
1168     return m_webLoaderStrategy;
1169 }
1170
1171 void WebProcess::webToStorageProcessConnectionClosed(WebToStorageProcessConnection* connection)
1172 {
1173     ASSERT(m_webToStorageProcessConnection);
1174     ASSERT(m_webToStorageProcessConnection == connection);
1175
1176     m_webToStorageProcessConnection = nullptr;
1177 }
1178
1179 WebToStorageProcessConnection* WebProcess::webToStorageProcessConnection()
1180 {
1181     if (!m_webToStorageProcessConnection)
1182         ensureWebToStorageProcessConnection();
1183
1184     return m_webToStorageProcessConnection.get();
1185 }
1186
1187 void WebProcess::ensureWebToStorageProcessConnection()
1188 {
1189     if (m_webToStorageProcessConnection)
1190         return;
1191
1192     IPC::Attachment encodedConnectionIdentifier;
1193
1194     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetStorageProcessConnection(), Messages::WebProcessProxy::GetStorageProcessConnection::Reply(encodedConnectionIdentifier), 0))
1195         return;
1196
1197 #if USE(UNIX_DOMAIN_SOCKETS)
1198     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1199 #elif OS(DARWIN)
1200     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1201 #elif OS(WINDOWS)
1202     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
1203 #else
1204     ASSERT_NOT_REACHED();
1205 #endif
1206     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1207         return;
1208     m_webToStorageProcessConnection = WebToStorageProcessConnection::create(connectionIdentifier);
1209 }
1210
1211 void WebProcess::setEnhancedAccessibility(bool flag)
1212 {
1213     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1214 }
1215     
1216 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1217 {
1218 #if ENABLE(MEMORY_SAMPLER)    
1219     WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1220 #else
1221     UNUSED_PARAM(sampleLogFileHandle);
1222     UNUSED_PARAM(sampleLogFilePath);
1223     UNUSED_PARAM(interval);
1224 #endif
1225 }
1226     
1227 void WebProcess::stopMemorySampler()
1228 {
1229 #if ENABLE(MEMORY_SAMPLER)
1230     WebMemorySampler::singleton()->stop();
1231 #endif
1232 }
1233
1234 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1235 {
1236     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1237     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1238
1239     m_textCheckerState = textCheckerState;
1240
1241     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1242         return;
1243
1244     for (auto& page : m_pageMap.values()) {
1245         if (continuousSpellCheckingTurnedOff)
1246             page->unmarkAllMisspellings();
1247         if (grammarCheckingTurnedOff)
1248             page->unmarkAllBadGrammar();
1249     }
1250 }
1251
1252 void WebProcess::releasePageCache()
1253 {
1254     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1255 }
1256
1257 void WebProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WebsiteData& websiteData)
1258 {
1259     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1260         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1261             websiteData.entries.append(WebsiteData::Entry { SecurityOriginData::fromSecurityOrigin(*origin), WebsiteDataType::MemoryCache, 0 });
1262     }
1263
1264     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1265         if (NetworkStorageSession::storageSession(sessionID))
1266             websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
1267     }
1268 }
1269
1270 void WebProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince)
1271 {
1272     UNUSED_PARAM(modifiedSince);
1273
1274     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1275         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1276         MemoryCache::singleton().evictResources(sessionID);
1277
1278         CrossOriginPreflightResultCache::singleton().empty();
1279     }
1280
1281     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1282         if (WebCore::NetworkStorageSession::storageSession(sessionID))
1283             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
1284     }
1285 }
1286
1287 void WebProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas)
1288 {
1289     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1290         HashSet<RefPtr<SecurityOrigin>> origins;
1291         for (auto& originData : originDatas)
1292             origins.add(originData.securityOrigin());
1293
1294         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1295     }
1296 }
1297
1298 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1299 {
1300     for (auto& page : m_pageMap.values())
1301         page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1302 }
1303
1304 #if !PLATFORM(COCOA)
1305 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1306 {
1307 }
1308
1309 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1310 {
1311 }
1312
1313 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1314 {
1315 }
1316
1317 void WebProcess::updateActivePages()
1318 {
1319 }
1320
1321 void WebProcess::updateCPULimit()
1322 {
1323 }
1324
1325 void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason)
1326 {
1327 }
1328
1329 #endif
1330
1331 void WebProcess::pageActivityStateDidChange(uint64_t, WebCore::ActivityState::Flags changed)
1332 {
1333     if (changed & WebCore::ActivityState::IsVisible)
1334         updateCPUMonitorState(CPUMonitorUpdateReason::VisibilityHasChanged);
1335 }
1336
1337 #if PLATFORM(IOS)
1338 void WebProcess::resetAllGeolocationPermissions()
1339 {
1340     for (auto& page : m_pageMap.values()) {
1341         if (Frame* mainFrame = page->mainFrame())
1342             mainFrame->resetAllGeolocationPermission();
1343     }
1344 }
1345 #endif
1346
1347 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1348 {
1349     if (!m_suppressMemoryPressureHandler)
1350         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1351
1352     setAllLayerTreeStatesFrozen(true);
1353     
1354 #if PLATFORM(COCOA)
1355     destroyRenderingResources();
1356 #endif
1357
1358     markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend] {
1359         RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1360
1361         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1362             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1363             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1364         }
1365     });
1366 }
1367
1368 void WebProcess::processWillSuspendImminently(bool& handled)
1369 {
1370     if (parentProcessConnection()->inSendSync()) {
1371         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1372         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1373         // reply to a sync message.
1374         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1375         return;
1376     }
1377
1378     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this);
1379     DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1380     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1381     handled = true;
1382 }
1383
1384 void WebProcess::prepareToSuspend()
1385 {
1386     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
1387     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1388 }
1389
1390 void WebProcess::cancelPrepareToSuspend()
1391 {
1392     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
1393     setAllLayerTreeStatesFrozen(false);
1394
1395     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1396     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1397     if (!m_pageMarkingLayersAsVolatileCounter)
1398         return;
1399
1400     cancelMarkAllLayersVolatile();
1401
1402     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1403     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1404 }
1405
1406 void WebProcess::markAllLayersVolatile(WTF::Function<void()>&& completionHandler)
1407 {
1408     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
1409     ASSERT(!m_pageMarkingLayersAsVolatileCounter);
1410     m_pageMarkingLayersAsVolatileCounter = std::make_unique<PageMarkingLayersAsVolatileCounter>([this, completionHandler = WTFMove(completionHandler)] (RefCounterEvent) {
1411         if (m_pageMarkingLayersAsVolatileCounter->value())
1412             return;
1413
1414         completionHandler();
1415         m_pageMarkingLayersAsVolatileCounter = nullptr;
1416     });
1417     auto token = m_pageMarkingLayersAsVolatileCounter->count();
1418     for (auto& page : m_pageMap.values())
1419         page->markLayersVolatile([token] { });
1420 }
1421
1422 void WebProcess::cancelMarkAllLayersVolatile()
1423 {
1424     if (!m_pageMarkingLayersAsVolatileCounter)
1425         return;
1426
1427     m_pageMarkingLayersAsVolatileCounter = nullptr;
1428     for (auto& page : m_pageMap.values())
1429         page->cancelMarkLayersVolatile();
1430 }
1431
1432 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1433 {
1434     for (auto& page : m_pageMap.values())
1435         page->setLayerTreeStateIsFrozen(frozen);
1436 }
1437     
1438 void WebProcess::processDidResume()
1439 {
1440     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this);
1441
1442     cancelMarkAllLayersVolatile();
1443     setAllLayerTreeStatesFrozen(false);
1444 }
1445
1446 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1447 {
1448     m_pagesInWindows.add(pageID);
1449     m_nonVisibleProcessCleanupTimer.stop();
1450 }
1451
1452 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1453 {
1454     m_pagesInWindows.remove(pageID);
1455
1456     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1457         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1458 }
1459     
1460 void WebProcess::nonVisibleProcessCleanupTimerFired()
1461 {
1462     ASSERT(m_pagesInWindows.isEmpty());
1463     if (!m_pagesInWindows.isEmpty())
1464         return;
1465
1466 #if PLATFORM(COCOA)
1467     destroyRenderingResources();
1468 #endif
1469 }
1470
1471 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1472 {
1473     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
1474 }
1475
1476 void WebProcess::clearResourceLoadStatistics()
1477 {
1478     ResourceLoadObserver::shared().clearState();
1479 }
1480
1481 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1482 {
1483     struct Transformer final : UserData::Transformer {
1484         Transformer(WebProcess& webProcess)
1485             : m_webProcess(webProcess)
1486         {
1487         }
1488
1489         bool shouldTransformObject(const API::Object& object) const override
1490         {
1491             switch (object.type()) {
1492             case API::Object::Type::FrameHandle:
1493                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1494
1495             case API::Object::Type::PageHandle:
1496                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1497
1498             case API::Object::Type::PageGroupHandle:
1499 #if PLATFORM(COCOA)
1500             case API::Object::Type::ObjCObjectGraph:
1501 #endif
1502                 return true;
1503
1504             default:
1505                 return false;
1506             }
1507         }
1508
1509         RefPtr<API::Object> transformObject(API::Object& object) const override
1510         {
1511             switch (object.type()) {
1512             case API::Object::Type::FrameHandle:
1513                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1514
1515             case API::Object::Type::PageGroupHandle:
1516                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1517
1518             case API::Object::Type::PageHandle:
1519                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1520
1521 #if PLATFORM(COCOA)
1522             case API::Object::Type::ObjCObjectGraph:
1523                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1524 #endif
1525             default:
1526                 return &object;
1527             }
1528         }
1529
1530         WebProcess& m_webProcess;
1531     };
1532
1533     return UserData::transform(object, Transformer(*this));
1534 }
1535
1536 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1537 {
1538     struct Transformer final : UserData::Transformer {
1539         bool shouldTransformObject(const API::Object& object) const override
1540         {
1541             switch (object.type()) {
1542             case API::Object::Type::BundleFrame:
1543             case API::Object::Type::BundlePage:
1544             case API::Object::Type::BundlePageGroup:
1545 #if PLATFORM(COCOA)
1546             case API::Object::Type::ObjCObjectGraph:
1547 #endif
1548                 return true;
1549
1550             default:
1551                 return false;
1552             }
1553         }
1554
1555         RefPtr<API::Object> transformObject(API::Object& object) const override
1556         {
1557             switch (object.type()) {
1558             case API::Object::Type::BundleFrame:
1559                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1560
1561             case API::Object::Type::BundlePage:
1562                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1563
1564             case API::Object::Type::BundlePageGroup: {
1565                 WebPageGroupData pageGroupData;
1566                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1567
1568                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1569             }
1570
1571 #if PLATFORM(COCOA)
1572             case API::Object::Type::ObjCObjectGraph:
1573                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1574 #endif
1575
1576             default:
1577                 return &object;
1578             }
1579         }
1580     };
1581
1582     return UserData::transform(object, Transformer());
1583 }
1584
1585 void WebProcess::setMemoryCacheDisabled(bool disabled)
1586 {
1587     auto& memoryCache = MemoryCache::singleton();
1588     if (memoryCache.disabled() != disabled)
1589         memoryCache.setDisabled(disabled);
1590 }
1591
1592 #if ENABLE(SERVICE_CONTROLS)
1593 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1594 {
1595     m_hasImageServices = hasImageServices;
1596     m_hasSelectionServices = hasSelectionServices;
1597     m_hasRichContentServices = hasRichContentServices;
1598 }
1599 #endif
1600
1601 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1602 {
1603     m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1604 }
1605
1606 void WebProcess::destroyAutomationSessionProxy()
1607 {
1608     m_automationSessionProxy = nullptr;
1609 }
1610
1611 void WebProcess::prefetchDNS(const String& hostname)
1612 {
1613     if (hostname.isEmpty())
1614         return;
1615
1616     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1617         networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1618     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1619     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1620     // some time of no DNS requests.
1621     m_dnsPrefetchHystereris.impulse();
1622 }
1623
1624 bool WebProcess::hasVisibleWebPage() const
1625 {
1626     for (auto& page : m_pageMap.values()) {
1627         if (page->isVisible())
1628             return true;
1629     }
1630     return false;
1631 }
1632
1633 #if USE(LIBWEBRTC)
1634 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1635 {
1636     if (!m_libWebRTCNetwork)
1637         m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>();
1638     return *m_libWebRTCNetwork;
1639 }
1640 #endif
1641
1642 #if ENABLE(SERVICE_WORKER)
1643 void WebProcess::getWorkerContextConnection(uint64_t pageID, const WebPreferencesStore& store)
1644 {
1645     ASSERT(!m_serviceWorkerManager);
1646
1647 #if USE(UNIX_DOMAIN_SOCKETS)
1648     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
1649     IPC::Connection::Identifier connectionIdentifier(socketPair.server);
1650     IPC::Attachment connectionClientPort(socketPair.client);
1651 #elif OS(DARWIN)
1652     mach_port_t listeningPort;
1653     if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort) != KERN_SUCCESS)
1654         CRASH();
1655
1656     if (mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
1657         CRASH();
1658
1659     IPC::Connection::Identifier connectionIdentifier(listeningPort);
1660     IPC::Attachment connectionClientPort(listeningPort, MACH_MSG_TYPE_MOVE_SEND);
1661 #else
1662     RELEASE_ASSERT_NOT_REACHED();
1663 #endif
1664
1665     auto workerContextConnection = IPC::Connection::createServerConnection(connectionIdentifier, *this);
1666     workerContextConnection->open();
1667     m_serviceWorkerManager = ServiceWorkerContextManager(WTFMove(workerContextConnection), pageID, store);
1668     WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::DidGetWorkerContextConnection(connectionClientPort), 0);
1669 }
1670 #endif
1671
1672 } // namespace WebKit