A hung webpage pretends to be responsive if you scroll
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009, 2010, 2012, 2014 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 "CustomProtocolManager.h"
35 #include "DrawingArea.h"
36 #include "EventDispatcher.h"
37 #include "InjectedBundle.h"
38 #include "Logging.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "PluginProcessConnectionManager.h"
42 #include "SessionTracker.h"
43 #include "StatisticsData.h"
44 #include "UserData.h"
45 #include "WebConnectionToUIProcess.h"
46 #include "WebCookieManager.h"
47 #include "WebCoreArgumentCoders.h"
48 #include "WebDatabaseManager.h"
49 #include "WebFrame.h"
50 #include "WebFrameNetworkingContext.h"
51 #include "WebGeolocationManager.h"
52 #include "WebIconDatabaseProxy.h"
53 #include "WebMediaCacheManager.h"
54 #include "WebMediaKeyStorageManager.h"
55 #include "WebMemorySampler.h"
56 #include "WebPage.h"
57 #include "WebPageGroupProxy.h"
58 #include "WebPageGroupProxyMessages.h"
59 #include "WebPlatformStrategies.h"
60 #include "WebProcessCreationParameters.h"
61 #include "WebProcessMessages.h"
62 #include "WebProcessPoolMessages.h"
63 #include "WebProcessProxyMessages.h"
64 #include "WebResourceLoadScheduler.h"
65 #include "WebsiteData.h"
66 #include "WebsiteDataTypes.h"
67 #include <JavaScriptCore/JSLock.h>
68 #include <JavaScriptCore/MemoryStatistics.h>
69 #include <WebCore/AXObjectCache.h>
70 #include <WebCore/ApplicationCacheStorage.h>
71 #include <WebCore/AuthenticationChallenge.h>
72 #include <WebCore/CrossOriginPreflightResultCache.h>
73 #include <WebCore/DNS.h>
74 #include <WebCore/FontCache.h>
75 #include <WebCore/FontCascade.h>
76 #include <WebCore/Frame.h>
77 #include <WebCore/FrameLoader.h>
78 #include <WebCore/GCController.h>
79 #include <WebCore/GlyphPage.h>
80 #include <WebCore/IconDatabase.h>
81 #include <WebCore/JSDOMWindow.h>
82 #include <WebCore/Language.h>
83 #include <WebCore/MainFrame.h>
84 #include <WebCore/MemoryCache.h>
85 #include <WebCore/MemoryPressureHandler.h>
86 #include <WebCore/Page.h>
87 #include <WebCore/PageCache.h>
88 #include <WebCore/PageGroup.h>
89 #include <WebCore/PlatformMediaSessionManager.h>
90 #include <WebCore/ResourceHandle.h>
91 #include <WebCore/RuntimeEnabledFeatures.h>
92 #include <WebCore/SchemeRegistry.h>
93 #include <WebCore/SecurityOrigin.h>
94 #include <WebCore/Settings.h>
95 #include <unistd.h>
96 #include <wtf/CurrentTime.h>
97 #include <wtf/HashCountedSet.h>
98 #include <wtf/PassRefPtr.h>
99 #include <wtf/RunLoop.h>
100 #include <wtf/text/StringHash.h>
101
102 #if PLATFORM(COCOA)
103 #include "ObjCObjectGraph.h"
104 #endif
105
106 #if PLATFORM(COCOA)
107 #include "CookieStorageShim.h"
108 #endif
109
110 #if ENABLE(SEC_ITEM_SHIM)
111 #include "SecItemShim.h"
112 #endif
113
114 #if ENABLE(DATABASE_PROCESS)
115 #include "WebToDatabaseProcessConnection.h"
116 #endif
117
118 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
119 #include "WebNotificationManager.h"
120 #endif
121
122 #if ENABLE(BATTERY_STATUS)
123 #include "WebBatteryManager.h"
124 #endif
125
126 #if ENABLE(REMOTE_INSPECTOR)
127 #include <JavaScriptCore/RemoteInspector.h>
128 #endif
129
130 using namespace JSC;
131 using namespace WebCore;
132
133 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
134 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
135
136 // This should be greater than tileRevalidationTimeout in TileController.
137 static const double nonVisibleProcessCleanupDelay = 10;
138
139 namespace WebKit {
140
141 WebProcess& WebProcess::singleton()
142 {
143     static WebProcess& process = *new WebProcess;
144     return process;
145 }
146
147 WebProcess::WebProcess()
148     : m_eventDispatcher(EventDispatcher::create())
149 #if PLATFORM(IOS)
150     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
151 #endif
152     , m_processSuspensionCleanupTimer(*this, &WebProcess::processSuspensionCleanupTimerFired)
153     , m_inDidClose(false)
154     , m_hasSetCacheModel(false)
155     , m_cacheModel(CacheModelDocumentViewer)
156     , m_fullKeyboardAccessEnabled(false)
157     , m_textCheckerState()
158     , m_iconDatabaseProxy(new WebIconDatabaseProxy(this))
159     , m_usesNetworkProcess(false)
160     , m_webResourceLoadScheduler(new WebResourceLoadScheduler)
161     , m_dnsPrefetchHystereris([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
162 #if ENABLE(NETSCAPE_PLUGIN_API)
163     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
164 #endif
165 #if ENABLE(SERVICE_CONTROLS)
166     , m_hasImageServices(false)
167     , m_hasSelectionServices(false)
168     , m_hasRichContentServices(false)
169 #endif
170     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
171 #if PLATFORM(IOS)
172     , m_webSQLiteDatabaseTracker(*this)
173 #endif
174 {
175     // Initialize our platform strategies.
176     WebPlatformStrategies::initialize();
177
178     // FIXME: This should moved to where WebProcess::initialize is called,
179     // so that ports have a chance to customize, and ifdefs in this file are
180     // limited.
181     addSupplement<WebGeolocationManager>();
182     addSupplement<WebCookieManager>();
183     addSupplement<WebMediaCacheManager>();
184     addSupplement<AuthenticationManager>();
185     addSupplement<WebDatabaseManager>();
186
187 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
188     addSupplement<WebNotificationManager>();
189 #endif
190     addSupplement<CustomProtocolManager>();
191 #if ENABLE(BATTERY_STATUS)
192     addSupplement<WebBatteryManager>();
193 #endif
194 #if ENABLE(ENCRYPTED_MEDIA_V2)
195     addSupplement<WebMediaKeyStorageManager>();
196 #endif
197     m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>());
198
199 #if ENABLE(INDEXED_DATABASE)
200     RuntimeEnabledFeatures::sharedFeatures().setWebkitIndexedDBEnabled(true);
201 #endif
202 }
203
204 WebProcess::~WebProcess()
205 {
206 }
207
208 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
209 {
210     platformInitializeProcess(parameters);
211 }
212
213 void WebProcess::initializeConnection(IPC::Connection* connection)
214 {
215     ChildProcess::initializeConnection(connection);
216
217     connection->setShouldExitOnSyncMessageSendFailure(true);
218
219 #if HAVE(QOS_CLASSES)
220     connection->setShouldBoostMainThreadOnSyncMessage(true);
221 #endif
222
223     m_eventDispatcher->initializeConnection(connection);
224 #if PLATFORM(IOS)
225     m_viewUpdateDispatcher->initializeConnection(connection);
226 #endif // PLATFORM(IOS)
227
228 #if ENABLE(NETSCAPE_PLUGIN_API)
229     m_pluginProcessConnectionManager->initializeConnection(connection);
230 #endif
231
232 #if ENABLE(SEC_ITEM_SHIM)
233     SecItemShim::singleton().initializeConnection(connection);
234 #endif
235
236     for (auto& supplement : m_supplements.values())
237         supplement->initializeConnection(connection);
238
239     m_webConnection = WebConnectionToUIProcess::create(this);
240
241     // In order to ensure that the asynchronous messages that are used for notifying the UI process
242     // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
243     // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
244     // unless when doing so would lead to a deadlock.
245     connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
246 }
247
248 void WebProcess::didCreateDownload()
249 {
250     disableTermination();
251 }
252
253 void WebProcess::didDestroyDownload()
254 {
255     enableTermination();
256 }
257
258 IPC::Connection* WebProcess::downloadProxyConnection()
259 {
260     return parentProcessConnection();
261 }
262
263 AuthenticationManager& WebProcess::downloadsAuthenticationManager()
264 {
265     return *supplement<AuthenticationManager>();
266 }
267
268 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
269 {
270     ASSERT(m_pageMap.isEmpty());
271
272     m_usesNetworkProcess = parameters.usesNetworkProcess;
273
274 #if OS(LINUX)
275     WebCore::MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
276 #endif
277
278     platformInitializeWebProcess(WTF::move(parameters));
279
280     WTF::setCurrentThreadIsUserInitiated();
281
282     MemoryPressureHandler::singleton().install();
283
284     if (!parameters.injectedBundlePath.isEmpty())
285         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
286
287     for (auto& supplement : m_supplements.values())
288         supplement->initialize(parameters);
289
290 #if ENABLE(ICONDATABASE)
291     m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled);
292 #endif
293
294     if (!parameters.applicationCacheDirectory.isEmpty())
295         ApplicationCacheStorage::singleton().setCacheDirectory(parameters.applicationCacheDirectory);
296
297     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
298
299     if (!parameters.languages.isEmpty())
300         overrideUserPreferredLanguages(parameters.languages);
301
302     m_textCheckerState = parameters.textCheckerState;
303
304     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
305
306     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
307         registerURLSchemeAsEmptyDocument(scheme);
308
309     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
310         registerURLSchemeAsSecure(scheme);
311
312     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
313         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
314
315     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
316         setDomainRelaxationForbiddenForURLScheme(scheme);
317
318     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
319         registerURLSchemeAsLocal(scheme);
320
321     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
322         registerURLSchemeAsNoAccess(scheme);
323
324     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
325         registerURLSchemeAsDisplayIsolated(scheme);
326
327     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
328         registerURLSchemeAsCORSEnabled(scheme);
329
330     WebCore::Settings::setShouldRewriteConstAsVar(parameters.shouldRewriteConstAsVar);
331
332 #if ENABLE(CACHE_PARTITIONING)
333     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
334         registerURLSchemeAsCachePartitioned(scheme);
335 #endif
336
337     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
338
339     if (parameters.shouldAlwaysUseComplexTextCodePath)
340         setAlwaysUsesComplexTextCodePath(true);
341
342     if (parameters.shouldUseFontSmoothing)
343         setShouldUseFontSmoothing(true);
344
345 #if PLATFORM(COCOA) || USE(CFNETWORK)
346     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
347 #endif
348
349     if (parameters.shouldUseTestingNetworkSession)
350         NetworkStorageSession::switchToNewTestingSession();
351
352     ensureNetworkProcessConnection();
353
354 #if PLATFORM(COCOA)
355     if (usesNetworkProcess())
356         CookieStorageShim::singleton().initialize();
357 #endif
358     setTerminationTimeout(parameters.terminationTimeout);
359
360     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
361     for (auto& origin : parameters.plugInAutoStartOrigins)
362         m_plugInAutoStartOrigins.add(origin);
363
364     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
365
366 #if ENABLE(SERVICE_CONTROLS)
367     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
368 #endif
369
370 #if ENABLE(REMOTE_INSPECTOR)
371     audit_token_t auditToken;
372     if (parentProcessConnection()->getAuditToken(auditToken)) {
373         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
374         Inspector::RemoteInspector::singleton().setParentProcessInformation(presenterApplicationPid(), auditData);
375     }
376 #endif
377
378 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
379     for (auto hostIter = parameters.pluginLoadClientPolicies.begin(); hostIter != parameters.pluginLoadClientPolicies.end(); ++hostIter) {
380         for (auto bundleIdentifierIter = hostIter->value.begin(); bundleIdentifierIter != hostIter->value.end(); ++bundleIdentifierIter) {
381             for (auto versionIter = bundleIdentifierIter->value.begin(); versionIter != bundleIdentifierIter->value.end(); ++versionIter)
382                 platformStrategies()->pluginStrategy()->setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionIter->value), hostIter->key, bundleIdentifierIter->key, versionIter->key);
383         }
384     }
385 #endif
386 }
387
388 void WebProcess::ensureNetworkProcessConnection()
389 {
390     if (!m_usesNetworkProcess)
391         return;
392
393     if (m_networkProcessConnection)
394         return;
395
396     IPC::Attachment encodedConnectionIdentifier;
397
398     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
399         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
400         return;
401
402 #if USE(UNIX_DOMAIN_SOCKETS)
403     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
404 #elif OS(DARWIN)
405     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
406 #else
407     ASSERT_NOT_REACHED();
408 #endif
409     if (IPC::Connection::identifierIsNull(connectionIdentifier))
410         return;
411     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
412 }
413
414 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
415 {
416     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
417 }
418
419 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
420 {
421     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
422 }
423
424 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
425 {
426     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
427 }
428
429 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
430 {
431     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
432 }
433
434 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
435 {
436     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
437 }
438
439 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
440 {
441     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
442 }
443
444 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
445 {
446     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
447 }
448
449 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
450 {
451     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
452 }
453
454 #if ENABLE(CACHE_PARTITIONING)
455 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
456 {
457     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
458 }
459 #endif
460
461 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
462 {
463     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
464 }
465
466 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
467 {
468     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
469 }
470
471 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
472 {
473     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
474 }
475
476 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
477 {
478     overrideUserPreferredLanguages(languages);
479     languageDidChange();
480 }
481
482 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
483 {
484     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
485 }
486
487 void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID)
488 {
489 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
490     WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID);
491 #endif
492 }
493
494 void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID)
495 {
496 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
497     SessionTracker::destroySession(sessionID);
498 #endif
499 }
500
501 DownloadManager& WebProcess::downloadManager()
502 {
503     ASSERT(!usesNetworkProcess());
504
505     static NeverDestroyed<DownloadManager> downloadManager(this);
506     return downloadManager;
507 }
508
509 #if ENABLE(NETSCAPE_PLUGIN_API)
510 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
511 {
512     return *m_pluginProcessConnectionManager;
513 }
514 #endif
515
516 void WebProcess::setCacheModel(uint32_t cm)
517 {
518     CacheModel cacheModel = static_cast<CacheModel>(cm);
519
520     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
521         m_hasSetCacheModel = true;
522         m_cacheModel = cacheModel;
523         platformSetCacheModel(cacheModel);
524     }
525 }
526
527 WebPage* WebProcess::focusedWebPage() const
528 {    
529     for (auto& page : m_pageMap.values()) {
530         if (page->windowAndWebPageAreFocused())
531             return page.get();
532     }
533     return 0;
534 }
535     
536 WebPage* WebProcess::webPage(uint64_t pageID) const
537 {
538     return m_pageMap.get(pageID);
539 }
540
541 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
542 {
543     // It is necessary to check for page existence here since during a window.open() (or targeted
544     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
545     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
546     if (result.isNewEntry) {
547         ASSERT(!result.iterator->value);
548         result.iterator->value = WebPage::create(pageID, parameters);
549
550         // Balanced by an enableTermination in removeWebPage.
551         disableTermination();
552     } else
553         result.iterator->value->reinitializeWebPage(parameters);
554
555     ASSERT(result.iterator->value);
556 }
557
558 void WebProcess::removeWebPage(uint64_t pageID)
559 {
560     ASSERT(m_pageMap.contains(pageID));
561
562     pageWillLeaveWindow(pageID);
563     m_pageMap.remove(pageID);
564
565     enableTermination();
566 }
567
568 bool WebProcess::shouldTerminate()
569 {
570     ASSERT(m_pageMap.isEmpty());
571     ASSERT(usesNetworkProcess() || !downloadManager().isDownloading());
572
573     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
574     bool shouldTerminate = false;
575     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
576         && !shouldTerminate)
577         return false;
578
579     return true;
580 }
581
582 void WebProcess::terminate()
583 {
584 #ifndef NDEBUG
585     GCController::singleton().garbageCollectNow();
586     FontCache::singleton().invalidate();
587     MemoryCache::singleton().setDisabled(true);
588 #endif
589
590     m_webConnection->invalidate();
591     m_webConnection = nullptr;
592
593     platformTerminate();
594
595     ChildProcess::terminate();
596 }
597
598 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
599 {
600     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
601         return;
602
603     didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
604 }
605
606 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
607 {
608     if (messageReceiverMap().dispatchMessage(connection, decoder))
609         return;
610
611     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
612         didReceiveWebProcessMessage(connection, decoder);
613         return;
614     }
615
616     if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) {
617         uint64_t pageGroupID = decoder.destinationID();
618         if (!pageGroupID)
619             return;
620         
621         WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
622         if (!pageGroupProxy)
623             return;
624         
625         pageGroupProxy->didReceiveMessage(connection, decoder);
626         return;
627     }
628
629     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
630         ChildProcess::didReceiveMessage(connection, decoder);
631         return;
632     }
633
634     LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
635 }
636
637 void WebProcess::didClose(IPC::Connection&)
638 {
639 #ifndef NDEBUG
640     m_inDidClose = true;
641
642     // Close all the live pages.
643     Vector<RefPtr<WebPage>> pages;
644     copyValuesToVector(m_pageMap, pages);
645     for (auto& page : pages)
646         page->close();
647     pages.clear();
648
649     GCController::singleton().garbageCollectSoon();
650     FontCache::singleton().invalidate();
651     MemoryCache::singleton().setDisabled(true);
652 #endif
653
654 #if ENABLE(VIDEO)
655     // FIXME(146657): This explicit media stop command should not be necessary
656     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
657         platformMediaSessionManager->stopAllMediaPlaybackForProcess();
658 #endif
659
660     // The UI process closed this connection, shut down.
661     stopRunLoop();
662 }
663
664 void WebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
665 {
666     // We received an invalid message, but since this is from the UI process (which we trust),
667     // we'll let it slide.
668 }
669
670 WebFrame* WebProcess::webFrame(uint64_t frameID) const
671 {
672     return m_frameMap.get(frameID);
673 }
674
675 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
676 {
677     m_frameMap.set(frameID, frame);
678 }
679
680 void WebProcess::removeWebFrame(uint64_t frameID)
681 {
682     m_frameMap.remove(frameID);
683
684     // We can end up here after our connection has closed when WebCore's frame life-support timer
685     // fires when the application is shutting down. There's no need (and no way) to update the UI
686     // process in this case.
687     if (!parentProcessConnection())
688         return;
689
690     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
691 }
692
693 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
694 {
695     for (auto& page : m_pageGroupMap.values()) {
696         if (page->corePageGroup() == pageGroup)
697             return page.get();
698     }
699
700     return 0;
701 }
702
703 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
704 {
705     return m_pageGroupMap.get(pageGroupID);
706 }
707
708 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
709 {
710     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
711     if (result.isNewEntry) {
712         ASSERT(!result.iterator->value);
713         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
714     }
715
716     return result.iterator->value.get();
717 }
718
719 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
720 {
721     platformClearResourceCaches(resourceCachesToClear);
722
723     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
724     // FIXME: We need a better way to do this.
725     CacheModel cacheModel = m_cacheModel;
726     setCacheModel(CacheModelDocumentViewer);
727     setCacheModel(cacheModel);
728
729     MemoryCache::singleton().evictResources();
730
731     // Empty the cross-origin preflight cache.
732     CrossOriginPreflightResultCache::singleton().empty();
733 }
734
735 void WebProcess::clearApplicationCache()
736 {
737     // Empty the application cache.
738     ApplicationCacheStorage::singleton().empty();
739 }
740
741 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
742 {
743     if (string.isEmpty())
744         return;
745     if (string.is8Bit()) {
746         hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length());
747         return;
748     }
749     hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length());
750 }
751
752 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
753 {
754     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
755     // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags.
756     StringHasher hasher;
757     addCaseFoldedCharacters(hasher, pageOrigin);
758     hasher.addCharacter(0);
759     addCaseFoldedCharacters(hasher, pluginOrigin);
760     hasher.addCharacter(0);
761     addCaseFoldedCharacters(hasher, mimeType);
762     return hasher.hash();
763 }
764
765 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, SessionID sessionID)
766 {
767     HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
768     HashMap<unsigned, double>::const_iterator it;
769     bool contains = false;
770
771     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
772         it = sessionIterator->value.find(plugInOriginHash);
773         contains = it != sessionIterator->value.end();
774     }
775     if (!contains) {
776         sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
777         it = sessionIterator->value.find(plugInOriginHash);
778         if (it == sessionIterator->value.end())
779             return false;
780     }
781     return currentTime() < it->value;
782 }
783
784 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
785 {
786     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
787         return true;
788
789 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
790     // 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).
791     if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
792         return true;
793 #else
794     UNUSED_PARAM(webPage);
795 #endif
796
797     // Lastly check against the more explicit hash list.
798     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
799 }
800
801 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
802 {
803     if (pageOrigin.isEmpty()) {
804         LOG(Plugins, "Not adding empty page origin");
805         return;
806     }
807
808     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
809     if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
810         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
811         return;
812     }
813
814     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
815     // comes back from the parent process. Temporarily add this hash to the list with a thirty
816     // second timeout. That way, even if the parent decides not to add it, we'll only be
817     // incorrect for a little while.
818     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000);
819
820     parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
821 }
822
823 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, SessionID sessionID)
824 {
825     // When called, some web process (which also might be this one) added the origin for auto-starting,
826     // or received user interaction.
827     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
828     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime);
829 }
830
831 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes)
832 {
833     m_plugInAutoStartOriginHashes.clear();
834     m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes));
835 }
836
837 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<SessionID, HashMap<unsigned, double>>& hashes)
838 {
839     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<SessionID, HashMap<unsigned, double>>&>(hashes));
840 }
841
842 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
843 {
844     if (pageOrigin.isEmpty())
845         return;
846
847     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
848     if (!plugInOriginHash)
849         return;
850
851     HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
852     HashMap<unsigned, double>::const_iterator it;
853     bool contains = false;
854     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
855         it = sessionIterator->value.find(plugInOriginHash);
856         contains = it != sessionIterator->value.end();
857     }
858     if (!contains) {
859         sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
860         it = sessionIterator->value.find(plugInOriginHash);
861         if (it == sessionIterator->value.end())
862             return;
863     }
864
865     if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
866         return;
867
868     parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
869 }
870
871 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
872 {
873 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
874     platformStrategies()->pluginStrategy()->setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
875 #endif
876 }
877
878 void WebProcess::clearPluginClientPolicies()
879 {
880 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
881     platformStrategies()->pluginStrategy()->clearPluginClientPolicies();
882 #endif
883 }
884
885 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
886 {
887     TypeCountSet::const_iterator end = countedSet->end();
888     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
889         map.set(it->key, it->value);
890 }
891
892 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
893 {
894     String imagesString(ASCIILiteral("Images"));
895     String cssString(ASCIILiteral("CSS"));
896     String xslString(ASCIILiteral("XSL"));
897     String javaScriptString(ASCIILiteral("JavaScript"));
898     
899     MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
900     
901     HashMap<String, uint64_t> counts;
902     counts.set(imagesString, memoryCacheStatistics.images.count);
903     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
904     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
905     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
906     result.append(counts);
907     
908     HashMap<String, uint64_t> sizes;
909     sizes.set(imagesString, memoryCacheStatistics.images.size);
910     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
911     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
912     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
913     result.append(sizes);
914     
915     HashMap<String, uint64_t> liveSizes;
916     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
917     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
918     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
919     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
920     result.append(liveSizes);
921     
922     HashMap<String, uint64_t> decodedSizes;
923     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
924     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
925     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
926     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
927     result.append(decodedSizes);
928 }
929
930 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
931 {
932     StatisticsData data;
933     
934     // Gather JavaScript statistics.
935     {
936         JSLockHolder lock(JSDOMWindow::commonVM());
937         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount());
938         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount());
939         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount());
940         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount());
941         
942         std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts());
943         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
944         
945         std::unique_ptr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts());
946         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
947         
948         uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size();
949         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
950         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize);
951     }
952
953     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
954     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
955     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
956     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
957     
958     // Gather icon statistics.
959     data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
960     data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
961     data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
962     data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
963     
964     // Gather font statistics.
965     auto& fontCache = FontCache::singleton();
966     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
967     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
968     
969     // Gather glyph page statistics.
970     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
971     
972     // Get WebCore memory cache statistics
973     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
974     
975     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
976 }
977
978 void WebProcess::garbageCollectJavaScriptObjects()
979 {
980     GCController::singleton().garbageCollectNow();
981 }
982
983 void WebProcess::mainThreadPing()
984 {
985     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
986 }
987
988 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
989 {
990     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
991 }
992
993 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
994 {
995     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
996     if (!injectedBundle)
997         return;
998
999     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1000 }
1001
1002 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1003 {
1004     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1005     if (!injectedBundle)
1006         return;
1007
1008     injectedBundle->setBundleParameter(key, value);
1009 }
1010
1011 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1012 {
1013     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1014     if (!injectedBundle)
1015         return;
1016
1017     injectedBundle->setBundleParameters(value);
1018 }
1019
1020 bool WebProcess::usesNetworkProcess() const
1021 {
1022     return m_usesNetworkProcess;
1023 }
1024
1025 NetworkProcessConnection* WebProcess::networkConnection()
1026 {
1027     ASSERT(m_usesNetworkProcess);
1028
1029     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1030     if (!m_networkProcessConnection)
1031         ensureNetworkProcessConnection();
1032     
1033     // If we failed to re-establish it then we are beyond recovery and should crash.
1034     if (!m_networkProcessConnection)
1035         CRASH();
1036     
1037     return m_networkProcessConnection.get();
1038 }
1039
1040 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1041 {
1042     ASSERT(m_networkProcessConnection);
1043     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1044
1045     m_networkProcessConnection = nullptr;
1046     
1047     m_webResourceLoadScheduler->networkProcessCrashed();
1048 }
1049
1050 WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler()
1051 {
1052     return *m_webResourceLoadScheduler;
1053 }
1054
1055 #if ENABLE(DATABASE_PROCESS)
1056 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1057 {
1058     ASSERT(m_webToDatabaseProcessConnection);
1059     ASSERT(m_webToDatabaseProcessConnection == connection);
1060
1061     m_webToDatabaseProcessConnection = nullptr;
1062 }
1063
1064 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1065 {
1066     if (!m_webToDatabaseProcessConnection)
1067         ensureWebToDatabaseProcessConnection();
1068
1069     return m_webToDatabaseProcessConnection.get();
1070 }
1071
1072 void WebProcess::ensureWebToDatabaseProcessConnection()
1073 {
1074     if (m_webToDatabaseProcessConnection)
1075         return;
1076
1077     IPC::Attachment encodedConnectionIdentifier;
1078
1079     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1080         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1081         return;
1082
1083 #if USE(UNIX_DOMAIN_SOCKETS)
1084     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1085 #elif OS(DARWIN)
1086     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1087 #else
1088     ASSERT_NOT_REACHED();
1089 #endif
1090     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1091         return;
1092     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1093 }
1094
1095 #endif // ENABLED(DATABASE_PROCESS)
1096
1097 void WebProcess::downloadRequest(SessionID sessionID, uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1098 {
1099     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1100
1101     ResourceRequest requestWithOriginalURL = request;
1102     if (initiatingPage)
1103         initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL);
1104
1105     downloadManager().startDownload(sessionID, downloadID, requestWithOriginalURL);
1106 }
1107
1108 void WebProcess::resumeDownload(uint64_t downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle)
1109 {
1110     downloadManager().resumeDownload(downloadID, resumeData, path, sandboxExtensionHandle);
1111 }
1112
1113 void WebProcess::cancelDownload(uint64_t downloadID)
1114 {
1115     downloadManager().cancelDownload(downloadID);
1116 }
1117
1118 void WebProcess::setEnhancedAccessibility(bool flag)
1119 {
1120     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1121 }
1122     
1123 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1124 {
1125 #if ENABLE(MEMORY_SAMPLER)    
1126     WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1127 #else
1128     UNUSED_PARAM(sampleLogFileHandle);
1129     UNUSED_PARAM(sampleLogFilePath);
1130     UNUSED_PARAM(interval);
1131 #endif
1132 }
1133     
1134 void WebProcess::stopMemorySampler()
1135 {
1136 #if ENABLE(MEMORY_SAMPLER)
1137     WebMemorySampler::singleton()->stop();
1138 #endif
1139 }
1140
1141 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1142 {
1143     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1144     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1145
1146     m_textCheckerState = textCheckerState;
1147
1148     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1149         return;
1150
1151     for (auto& page : m_pageMap.values()) {
1152         if (continuousSpellCheckingTurnedOff)
1153             page->unmarkAllMisspellings();
1154         if (grammarCheckingTurnedOff)
1155             page->unmarkAllBadGrammar();
1156     }
1157 }
1158
1159 void WebProcess::releasePageCache()
1160 {
1161     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1162 }
1163
1164 void WebProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID)
1165 {
1166     WebsiteData websiteData;
1167
1168     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1169         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1170             websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataTypeMemoryCache });
1171     }
1172
1173     parentProcessConnection()->send(Messages::WebProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1174 }
1175
1176 void WebProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
1177 {
1178     UNUSED_PARAM(modifiedSince);
1179
1180     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1181         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1182         MemoryCache::singleton().evictResources(sessionID);
1183
1184         CrossOriginPreflightResultCache::singleton().empty();
1185     }
1186
1187     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1188 }
1189
1190 void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, uint64_t websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas, uint64_t callbackID)
1191 {
1192     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1193         HashSet<RefPtr<SecurityOrigin>> origins;
1194         for (auto& originData : originDatas)
1195             origins.add(originData.securityOrigin());
1196
1197         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1198     }
1199
1200     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1201 }
1202
1203 #if !PLATFORM(COCOA)
1204 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1205 {
1206 }
1207
1208 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1209 {
1210 }
1211
1212 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1213 {
1214 }
1215
1216 void WebProcess::updateActivePages()
1217 {
1218 }
1219
1220 #endif
1221
1222 #if PLATFORM(IOS)
1223 void WebProcess::resetAllGeolocationPermissions()
1224 {
1225     for (auto& page : m_pageMap.values()) {
1226         if (Frame* mainFrame = page->mainFrame())
1227             mainFrame->resetAllGeolocationPermission();
1228     }
1229 }
1230 #endif
1231
1232 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1233 {
1234     MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1235     setAllLayerTreeStatesFrozen(true);
1236
1237     if (markAllLayersVolatileIfPossible()) {
1238         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1239             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1240         return;
1241     }
1242     m_shouldAcknowledgeWhenReadyToSuspend = shouldAcknowledgeWhenReadyToSuspend;
1243     m_processSuspensionCleanupTimer.startRepeating(std::chrono::milliseconds(20));
1244 }
1245
1246 void WebProcess::processWillSuspendImminently(bool& handled)
1247 {
1248     if (parentProcessConnection()->inSendSync()) {
1249         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1250         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1251         // reply to a sync message.
1252         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1253         return;
1254     }
1255
1256     supplement<WebDatabaseManager>()->closeAllDatabases();
1257     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1258     handled = true;
1259 }
1260
1261 void WebProcess::prepareToSuspend()
1262 {
1263     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1264 }
1265
1266 void WebProcess::cancelPrepareToSuspend()
1267 {
1268     setAllLayerTreeStatesFrozen(false);
1269
1270     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1271     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1272     if (!m_processSuspensionCleanupTimer.isActive())
1273         return;
1274
1275     m_processSuspensionCleanupTimer.stop();
1276     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1277 }
1278
1279 bool WebProcess::markAllLayersVolatileIfPossible()
1280 {
1281     bool successfullyMarkedAllLayersVolatile = true;
1282     for (auto& page : m_pageMap.values())
1283         successfullyMarkedAllLayersVolatile &= page->markLayersVolatileImmediatelyIfPossible();
1284
1285     return successfullyMarkedAllLayersVolatile;
1286 }
1287
1288 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1289 {
1290     for (auto& page : m_pageMap.values())
1291         page->setLayerTreeStateIsFrozen(frozen);
1292 }
1293
1294 void WebProcess::processSuspensionCleanupTimerFired()
1295 {
1296     if (!markAllLayersVolatileIfPossible())
1297         return;
1298     m_processSuspensionCleanupTimer.stop();
1299     if (m_shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1300         parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1301 }
1302     
1303 void WebProcess::processDidResume()
1304 {
1305     m_processSuspensionCleanupTimer.stop();
1306     setAllLayerTreeStatesFrozen(false);
1307 }
1308
1309 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1310 {
1311     m_pagesInWindows.add(pageID);
1312     m_nonVisibleProcessCleanupTimer.stop();
1313 }
1314
1315 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1316 {
1317     m_pagesInWindows.remove(pageID);
1318
1319     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1320         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1321 }
1322     
1323 void WebProcess::nonVisibleProcessCleanupTimerFired()
1324 {
1325     ASSERT(m_pagesInWindows.isEmpty());
1326     if (!m_pagesInWindows.isEmpty())
1327         return;
1328
1329 #if PLATFORM(COCOA)
1330     destroyRenderingResources();
1331 #endif
1332 }
1333
1334 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1335 {
1336     struct Transformer final : UserData::Transformer {
1337         Transformer(WebProcess& webProcess)
1338             : m_webProcess(webProcess)
1339         {
1340         }
1341
1342         virtual bool shouldTransformObject(const API::Object& object) const override
1343         {
1344             switch (object.type()) {
1345             case API::Object::Type::FrameHandle:
1346                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1347
1348             case API::Object::Type::PageHandle:
1349                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1350
1351             case API::Object::Type::PageGroupHandle:
1352 #if PLATFORM(COCOA)
1353             case API::Object::Type::ObjCObjectGraph:
1354 #endif
1355                 return true;
1356
1357             default:
1358                 return false;
1359             }
1360         }
1361
1362         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1363         {
1364             switch (object.type()) {
1365             case API::Object::Type::FrameHandle:
1366                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1367
1368             case API::Object::Type::PageGroupHandle:
1369                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1370
1371             case API::Object::Type::PageHandle:
1372                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1373
1374 #if PLATFORM(COCOA)
1375             case API::Object::Type::ObjCObjectGraph:
1376                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1377 #endif
1378             default:
1379                 return &object;
1380             }
1381         }
1382
1383         WebProcess& m_webProcess;
1384     };
1385
1386     return UserData::transform(object, Transformer(*this));
1387 }
1388
1389 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1390 {
1391     struct Transformer final : UserData::Transformer {
1392         virtual bool shouldTransformObject(const API::Object& object) const override
1393         {
1394             switch (object.type()) {
1395             case API::Object::Type::BundleFrame:
1396             case API::Object::Type::BundlePage:
1397             case API::Object::Type::BundlePageGroup:
1398 #if PLATFORM(COCOA)
1399             case API::Object::Type::ObjCObjectGraph:
1400 #endif
1401                 return true;
1402
1403             default:
1404                 return false;
1405             }
1406         }
1407
1408         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1409         {
1410             switch (object.type()) {
1411             case API::Object::Type::BundleFrame:
1412                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1413
1414             case API::Object::Type::BundlePage:
1415                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1416
1417             case API::Object::Type::BundlePageGroup: {
1418                 WebPageGroupData pageGroupData;
1419                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1420
1421                 return API::PageGroupHandle::create(WTF::move(pageGroupData));
1422             }
1423
1424 #if PLATFORM(COCOA)
1425             case API::Object::Type::ObjCObjectGraph:
1426                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1427 #endif
1428
1429             default:
1430                 return &object;
1431             }
1432         }
1433     };
1434
1435     return UserData::transform(object, Transformer());
1436 }
1437
1438 void WebProcess::setMemoryCacheDisabled(bool disabled)
1439 {
1440     auto& memoryCache = MemoryCache::singleton();
1441     if (memoryCache.disabled() != disabled)
1442         memoryCache.setDisabled(disabled);
1443 }
1444
1445 #if ENABLE(SERVICE_CONTROLS)
1446 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1447 {
1448     m_hasImageServices = hasImageServices;
1449     m_hasSelectionServices = hasSelectionServices;
1450     m_hasRichContentServices = hasRichContentServices;
1451 }
1452 #endif
1453
1454 void WebProcess::prefetchDNS(const String& hostname)
1455 {
1456     if (hostname.isEmpty())
1457         return;
1458
1459     if (usesNetworkProcess()) {
1460         if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1461             networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1462         // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1463         // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1464         // some time of no DNS requests.
1465         m_dnsPrefetchHystereris.impulse();
1466         return;
1467     }
1468     WebCore::prefetchDNS(hostname);
1469 }
1470
1471 } // namespace WebKit