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