bf140f81ec5c6ccf0215ffc2fd8ac417ae3b42b2
[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::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
984 {
985     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
986 }
987
988 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
989 {
990     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
991     if (!injectedBundle)
992         return;
993
994     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
995 }
996
997 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
998 {
999     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1000     if (!injectedBundle)
1001         return;
1002
1003     injectedBundle->setBundleParameter(key, value);
1004 }
1005
1006 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1007 {
1008     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1009     if (!injectedBundle)
1010         return;
1011
1012     injectedBundle->setBundleParameters(value);
1013 }
1014
1015 bool WebProcess::usesNetworkProcess() const
1016 {
1017     return m_usesNetworkProcess;
1018 }
1019
1020 NetworkProcessConnection* WebProcess::networkConnection()
1021 {
1022     ASSERT(m_usesNetworkProcess);
1023
1024     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1025     if (!m_networkProcessConnection)
1026         ensureNetworkProcessConnection();
1027     
1028     // If we failed to re-establish it then we are beyond recovery and should crash.
1029     if (!m_networkProcessConnection)
1030         CRASH();
1031     
1032     return m_networkProcessConnection.get();
1033 }
1034
1035 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1036 {
1037     ASSERT(m_networkProcessConnection);
1038     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1039
1040     m_networkProcessConnection = nullptr;
1041     
1042     m_webResourceLoadScheduler->networkProcessCrashed();
1043 }
1044
1045 WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler()
1046 {
1047     return *m_webResourceLoadScheduler;
1048 }
1049
1050 #if ENABLE(DATABASE_PROCESS)
1051 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1052 {
1053     ASSERT(m_webToDatabaseProcessConnection);
1054     ASSERT(m_webToDatabaseProcessConnection == connection);
1055
1056     m_webToDatabaseProcessConnection = nullptr;
1057 }
1058
1059 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1060 {
1061     if (!m_webToDatabaseProcessConnection)
1062         ensureWebToDatabaseProcessConnection();
1063
1064     return m_webToDatabaseProcessConnection.get();
1065 }
1066
1067 void WebProcess::ensureWebToDatabaseProcessConnection()
1068 {
1069     if (m_webToDatabaseProcessConnection)
1070         return;
1071
1072     IPC::Attachment encodedConnectionIdentifier;
1073
1074     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1075         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1076         return;
1077
1078 #if USE(UNIX_DOMAIN_SOCKETS)
1079     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1080 #elif OS(DARWIN)
1081     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1082 #else
1083     ASSERT_NOT_REACHED();
1084 #endif
1085     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1086         return;
1087     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1088 }
1089
1090 #endif // ENABLED(DATABASE_PROCESS)
1091
1092 void WebProcess::downloadRequest(SessionID sessionID, uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1093 {
1094     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1095
1096     ResourceRequest requestWithOriginalURL = request;
1097     if (initiatingPage)
1098         initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL);
1099
1100     downloadManager().startDownload(sessionID, downloadID, requestWithOriginalURL);
1101 }
1102
1103 void WebProcess::resumeDownload(uint64_t downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle)
1104 {
1105     downloadManager().resumeDownload(downloadID, resumeData, path, sandboxExtensionHandle);
1106 }
1107
1108 void WebProcess::cancelDownload(uint64_t downloadID)
1109 {
1110     downloadManager().cancelDownload(downloadID);
1111 }
1112
1113 void WebProcess::setEnhancedAccessibility(bool flag)
1114 {
1115     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1116 }
1117     
1118 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1119 {
1120 #if ENABLE(MEMORY_SAMPLER)    
1121     WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1122 #else
1123     UNUSED_PARAM(sampleLogFileHandle);
1124     UNUSED_PARAM(sampleLogFilePath);
1125     UNUSED_PARAM(interval);
1126 #endif
1127 }
1128     
1129 void WebProcess::stopMemorySampler()
1130 {
1131 #if ENABLE(MEMORY_SAMPLER)
1132     WebMemorySampler::singleton()->stop();
1133 #endif
1134 }
1135
1136 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1137 {
1138     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1139     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1140
1141     m_textCheckerState = textCheckerState;
1142
1143     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1144         return;
1145
1146     for (auto& page : m_pageMap.values()) {
1147         if (continuousSpellCheckingTurnedOff)
1148             page->unmarkAllMisspellings();
1149         if (grammarCheckingTurnedOff)
1150             page->unmarkAllBadGrammar();
1151     }
1152 }
1153
1154 void WebProcess::releasePageCache()
1155 {
1156     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1157 }
1158
1159 void WebProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID)
1160 {
1161     WebsiteData websiteData;
1162
1163     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1164         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1165             websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataTypeMemoryCache });
1166     }
1167
1168     parentProcessConnection()->send(Messages::WebProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1169 }
1170
1171 void WebProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
1172 {
1173     UNUSED_PARAM(modifiedSince);
1174
1175     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1176         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1177         MemoryCache::singleton().evictResources(sessionID);
1178
1179         CrossOriginPreflightResultCache::singleton().empty();
1180     }
1181
1182     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1183 }
1184
1185 void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, uint64_t websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas, uint64_t callbackID)
1186 {
1187     if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1188         HashSet<RefPtr<SecurityOrigin>> origins;
1189         for (auto& originData : originDatas)
1190             origins.add(originData.securityOrigin());
1191
1192         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1193     }
1194
1195     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1196 }
1197
1198 #if !PLATFORM(COCOA)
1199 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1200 {
1201 }
1202
1203 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1204 {
1205 }
1206
1207 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1208 {
1209 }
1210
1211 void WebProcess::updateActivePages()
1212 {
1213 }
1214
1215 #endif
1216
1217 #if PLATFORM(IOS)
1218 void WebProcess::resetAllGeolocationPermissions()
1219 {
1220     for (auto& page : m_pageMap.values()) {
1221         if (Frame* mainFrame = page->mainFrame())
1222             mainFrame->resetAllGeolocationPermission();
1223     }
1224 }
1225 #endif
1226
1227 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1228 {
1229     MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1230     setAllLayerTreeStatesFrozen(true);
1231
1232     if (markAllLayersVolatileIfPossible()) {
1233         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1234             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1235         return;
1236     }
1237     m_shouldAcknowledgeWhenReadyToSuspend = shouldAcknowledgeWhenReadyToSuspend;
1238     m_processSuspensionCleanupTimer.startRepeating(std::chrono::milliseconds(20));
1239 }
1240
1241 void WebProcess::processWillSuspendImminently(bool& handled)
1242 {
1243     if (parentProcessConnection()->inSendSync()) {
1244         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1245         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1246         // reply to a sync message.
1247         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1248         return;
1249     }
1250
1251     supplement<WebDatabaseManager>()->closeAllDatabases();
1252     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1253     handled = true;
1254 }
1255
1256 void WebProcess::prepareToSuspend()
1257 {
1258     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1259 }
1260
1261 void WebProcess::cancelPrepareToSuspend()
1262 {
1263     setAllLayerTreeStatesFrozen(false);
1264
1265     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1266     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1267     if (!m_processSuspensionCleanupTimer.isActive())
1268         return;
1269
1270     m_processSuspensionCleanupTimer.stop();
1271     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1272 }
1273
1274 bool WebProcess::markAllLayersVolatileIfPossible()
1275 {
1276     bool successfullyMarkedAllLayersVolatile = true;
1277     for (auto& page : m_pageMap.values())
1278         successfullyMarkedAllLayersVolatile &= page->markLayersVolatileImmediatelyIfPossible();
1279
1280     return successfullyMarkedAllLayersVolatile;
1281 }
1282
1283 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1284 {
1285     for (auto& page : m_pageMap.values())
1286         page->setLayerTreeStateIsFrozen(frozen);
1287 }
1288
1289 void WebProcess::processSuspensionCleanupTimerFired()
1290 {
1291     if (!markAllLayersVolatileIfPossible())
1292         return;
1293     m_processSuspensionCleanupTimer.stop();
1294     if (m_shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1295         parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1296 }
1297     
1298 void WebProcess::processDidResume()
1299 {
1300     m_processSuspensionCleanupTimer.stop();
1301     setAllLayerTreeStatesFrozen(false);
1302 }
1303
1304 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1305 {
1306     m_pagesInWindows.add(pageID);
1307     m_nonVisibleProcessCleanupTimer.stop();
1308 }
1309
1310 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1311 {
1312     m_pagesInWindows.remove(pageID);
1313
1314     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1315         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1316 }
1317     
1318 void WebProcess::nonVisibleProcessCleanupTimerFired()
1319 {
1320     ASSERT(m_pagesInWindows.isEmpty());
1321     if (!m_pagesInWindows.isEmpty())
1322         return;
1323
1324 #if PLATFORM(COCOA)
1325     destroyRenderingResources();
1326 #endif
1327 }
1328
1329 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1330 {
1331     struct Transformer final : UserData::Transformer {
1332         Transformer(WebProcess& webProcess)
1333             : m_webProcess(webProcess)
1334         {
1335         }
1336
1337         virtual bool shouldTransformObject(const API::Object& object) const override
1338         {
1339             switch (object.type()) {
1340             case API::Object::Type::FrameHandle:
1341                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1342
1343             case API::Object::Type::PageHandle:
1344                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1345
1346             case API::Object::Type::PageGroupHandle:
1347 #if PLATFORM(COCOA)
1348             case API::Object::Type::ObjCObjectGraph:
1349 #endif
1350                 return true;
1351
1352             default:
1353                 return false;
1354             }
1355         }
1356
1357         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1358         {
1359             switch (object.type()) {
1360             case API::Object::Type::FrameHandle:
1361                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1362
1363             case API::Object::Type::PageGroupHandle:
1364                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1365
1366             case API::Object::Type::PageHandle:
1367                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1368
1369 #if PLATFORM(COCOA)
1370             case API::Object::Type::ObjCObjectGraph:
1371                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1372 #endif
1373             default:
1374                 return &object;
1375             }
1376         }
1377
1378         WebProcess& m_webProcess;
1379     };
1380
1381     return UserData::transform(object, Transformer(*this));
1382 }
1383
1384 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1385 {
1386     struct Transformer final : UserData::Transformer {
1387         virtual bool shouldTransformObject(const API::Object& object) const override
1388         {
1389             switch (object.type()) {
1390             case API::Object::Type::BundleFrame:
1391             case API::Object::Type::BundlePage:
1392             case API::Object::Type::BundlePageGroup:
1393 #if PLATFORM(COCOA)
1394             case API::Object::Type::ObjCObjectGraph:
1395 #endif
1396                 return true;
1397
1398             default:
1399                 return false;
1400             }
1401         }
1402
1403         virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1404         {
1405             switch (object.type()) {
1406             case API::Object::Type::BundleFrame:
1407                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1408
1409             case API::Object::Type::BundlePage:
1410                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1411
1412             case API::Object::Type::BundlePageGroup: {
1413                 WebPageGroupData pageGroupData;
1414                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1415
1416                 return API::PageGroupHandle::create(WTF::move(pageGroupData));
1417             }
1418
1419 #if PLATFORM(COCOA)
1420             case API::Object::Type::ObjCObjectGraph:
1421                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1422 #endif
1423
1424             default:
1425                 return &object;
1426             }
1427         }
1428     };
1429
1430     return UserData::transform(object, Transformer());
1431 }
1432
1433 void WebProcess::setMemoryCacheDisabled(bool disabled)
1434 {
1435     auto& memoryCache = MemoryCache::singleton();
1436     if (memoryCache.disabled() != disabled)
1437         memoryCache.setDisabled(disabled);
1438 }
1439
1440 #if ENABLE(SERVICE_CONTROLS)
1441 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1442 {
1443     m_hasImageServices = hasImageServices;
1444     m_hasSelectionServices = hasSelectionServices;
1445     m_hasRichContentServices = hasRichContentServices;
1446 }
1447 #endif
1448
1449 void WebProcess::prefetchDNS(const String& hostname)
1450 {
1451     if (hostname.isEmpty())
1452         return;
1453
1454     if (usesNetworkProcess()) {
1455         if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1456             networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1457         // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1458         // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1459         // some time of no DNS requests.
1460         m_dnsPrefetchHystereris.impulse();
1461         return;
1462     }
1463     WebCore::prefetchDNS(hostname);
1464 }
1465
1466 } // namespace WebKit