Avoid copy-prone idiom "for (auto item : collection)"
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009, 2010, 2012 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 "AuthenticationManager.h"
31 #include "EventDispatcher.h"
32 #include "InjectedBundle.h"
33 #include "InjectedBundleUserMessageCoders.h"
34 #include "Logging.h"
35 #include "PluginProcessConnectionManager.h"
36 #include "SessionTracker.h"
37 #include "StatisticsData.h"
38 #include "UserData.h"
39 #include "WebApplicationCacheManager.h"
40 #include "WebConnectionToUIProcess.h"
41 #include "WebContextMessages.h"
42 #include "WebCookieManager.h"
43 #include "WebCoreArgumentCoders.h"
44 #include "WebFrame.h"
45 #include "WebFrameNetworkingContext.h"
46 #include "WebGeolocationManager.h"
47 #include "WebIconDatabaseProxy.h"
48 #include "WebMediaCacheManager.h"
49 #include "WebMemorySampler.h"
50 #include "WebPage.h"
51 #include "WebPageCreationParameters.h"
52 #include "WebPageGroupProxyMessages.h"
53 #include "WebPlatformStrategies.h"
54 #include "WebPreferencesStore.h"
55 #include "WebProcessCreationParameters.h"
56 #include "WebProcessMessages.h"
57 #include "WebProcessProxyMessages.h"
58 #include "WebResourceCacheManager.h"
59 #include <JavaScriptCore/JSLock.h>
60 #include <JavaScriptCore/MemoryStatistics.h>
61 #include <WebCore/AXObjectCache.h>
62 #include <WebCore/ApplicationCacheStorage.h>
63 #include <WebCore/AuthenticationChallenge.h>
64 #include <WebCore/CrossOriginPreflightResultCache.h>
65 #include <WebCore/Font.h>
66 #include <WebCore/FontCache.h>
67 #include <WebCore/Frame.h>
68 #include <WebCore/FrameLoader.h>
69 #include <WebCore/GCController.h>
70 #include <WebCore/GlyphPageTreeNode.h>
71 #include <WebCore/IconDatabase.h>
72 #include <WebCore/JSDOMWindow.h>
73 #include <WebCore/Language.h>
74 #include <WebCore/MemoryCache.h>
75 #include <WebCore/MemoryPressureHandler.h>
76 #include <WebCore/Page.h>
77 #include <WebCore/PageCache.h>
78 #include <WebCore/PageGroup.h>
79 #include <WebCore/ResourceHandle.h>
80 #include <WebCore/SchemeRegistry.h>
81 #include <WebCore/SecurityOrigin.h>
82 #include <WebCore/Settings.h>
83 #include <WebCore/StorageTracker.h>
84 #include <unistd.h>
85 #include <wtf/CurrentTime.h>
86 #include <wtf/HashCountedSet.h>
87 #include <wtf/PassRefPtr.h>
88 #include <wtf/RunLoop.h>
89 #include <wtf/text/StringHash.h>
90
91 #if ENABLE(NETWORK_INFO)
92 #include "WebNetworkInfoManager.h"
93 #include "WebNetworkInfoManagerMessages.h"
94 #endif
95
96 #if ENABLE(NETWORK_PROCESS)
97 #if PLATFORM(COCOA)
98 #include "CookieStorageShim.h"
99 #endif
100 #include "NetworkProcessConnection.h"
101 #endif
102
103 #if ENABLE(SEC_ITEM_SHIM)
104 #include "SecItemShim.h"
105 #endif
106
107 #if ENABLE(CUSTOM_PROTOCOLS)
108 #include "CustomProtocolManager.h"
109 #endif
110
111 #if ENABLE(DATABASE_PROCESS)
112 #include "WebToDatabaseProcessConnection.h"
113 #endif
114
115 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
116 #include "WebNotificationManager.h"
117 #endif
118
119 #if ENABLE(SQL_DATABASE)
120 #include "WebDatabaseManager.h"
121 #endif
122
123 #if ENABLE(BATTERY_STATUS)
124 #include "WebBatteryManager.h"
125 #endif
126
127 #if ENABLE(NETWORK_PROCESS)
128 #include "WebResourceLoadScheduler.h"
129 #endif
130
131 #if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS)
132 #include "WebSoupRequestManager.h"
133 #endif
134
135 using namespace JSC;
136 using namespace WebCore;
137
138 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
139 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
140
141 // This should be greater than tileRevalidationTimeout in TileController.
142 static const double nonVisibleProcessCleanupDelay = 10;
143
144 namespace WebKit {
145
146 WebProcess& WebProcess::shared()
147 {
148     static WebProcess& process = *new WebProcess;
149     return process;
150 }
151
152 WebProcess::WebProcess()
153     : m_eventDispatcher(EventDispatcher::create())
154 #if PLATFORM(IOS)
155     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
156 #endif // PLATFORM(IOS)
157     , m_inDidClose(false)
158     , m_shouldTrackVisitedLinks(true)
159     , m_hasSetCacheModel(false)
160     , m_cacheModel(CacheModelDocumentViewer)
161 #if PLATFORM(COCOA)
162     , m_compositingRenderServerPort(MACH_PORT_NULL)
163     , m_clearResourceCachesDispatchGroup(0)
164 #endif
165     , m_fullKeyboardAccessEnabled(false)
166     , m_textCheckerState()
167     , m_iconDatabaseProxy(new WebIconDatabaseProxy(this))
168 #if ENABLE(NETWORK_PROCESS)
169     , m_usesNetworkProcess(false)
170     , m_webResourceLoadScheduler(new WebResourceLoadScheduler)
171 #endif
172 #if ENABLE(NETSCAPE_PLUGIN_API)
173     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
174 #endif
175     , m_nonVisibleProcessCleanupTimer(this, &WebProcess::nonVisibleProcessCleanupTimerFired)
176 {
177     // Initialize our platform strategies.
178     WebPlatformStrategies::initialize();
179
180     // FIXME: This should moved to where WebProcess::initialize is called,
181     // so that ports have a chance to customize, and ifdefs in this file are
182     // limited.
183     addSupplement<WebGeolocationManager>();
184     addSupplement<WebApplicationCacheManager>();
185     addSupplement<WebResourceCacheManager>();
186     addSupplement<WebCookieManager>();
187     addSupplement<WebMediaCacheManager>();
188     addSupplement<AuthenticationManager>();
189     
190 #if ENABLE(SQL_DATABASE)
191     addSupplement<WebDatabaseManager>();
192 #endif
193 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
194     addSupplement<WebNotificationManager>();
195 #endif
196 #if ENABLE(CUSTOM_PROTOCOLS)
197     addSupplement<CustomProtocolManager>();
198 #endif
199 #if ENABLE(BATTERY_STATUS)
200     addSupplement<WebBatteryManager>();
201 #endif
202 #if ENABLE(NETWORK_INFO)
203     addSupplement<WebNetworkInfoManager>();
204 #endif
205 #if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS)
206     addSupplement<WebSoupRequestManager>();
207 #endif
208 }
209
210 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
211 {
212     platformInitializeProcess(parameters);
213 }
214
215 void WebProcess::initializeConnection(IPC::Connection* connection)
216 {
217     ChildProcess::initializeConnection(connection);
218
219     connection->setShouldExitOnSyncMessageSendFailure(true);
220
221     m_eventDispatcher->initializeConnection(connection);
222 #if PLATFORM(IOS)
223     m_viewUpdateDispatcher->initializeConnection(connection);
224 #endif // PLATFORM(IOS)
225
226 #if ENABLE(NETSCAPE_PLUGIN_API)
227     m_pluginProcessConnectionManager->initializeConnection(connection);
228 #endif
229
230 #if ENABLE(SEC_ITEM_SHIM)
231     SecItemShim::shared().initializeConnection(connection);
232 #endif
233     
234     WebProcessSupplementMap::const_iterator it = m_supplements.begin();
235     WebProcessSupplementMap::const_iterator end = m_supplements.end();
236     for (; it != end; ++it)
237         it->value->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(const WebProcessCreationParameters& parameters, IPC::MessageDecoder& decoder)
269 {
270     ASSERT(m_pageMap.isEmpty());
271
272     platformInitializeWebProcess(parameters, decoder);
273
274     memoryPressureHandler().install();
275
276     RefPtr<API::Object> injectedBundleInitializationUserData;
277     InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData);
278     if (!decoder.decode(messageDecoder))
279         return;
280
281     if (!parameters.injectedBundlePath.isEmpty()) {
282         m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath);
283         m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle));
284
285         if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) {
286             // Don't keep around the InjectedBundle reference if the load fails.
287             m_injectedBundle.clear();
288         }
289     }
290
291     WebProcessSupplementMap::const_iterator it = m_supplements.begin();
292     WebProcessSupplementMap::const_iterator end = m_supplements.end();
293     for (; it != end; ++it)
294         it->value->initialize(parameters);
295
296 #if ENABLE(ICONDATABASE)
297     m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled);
298 #endif
299
300     if (!parameters.applicationCacheDirectory.isEmpty())
301         cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory);
302
303     setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks);
304     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
305
306     if (!parameters.languages.isEmpty())
307         overrideUserPreferredLanguages(parameters.languages);
308
309     m_textCheckerState = parameters.textCheckerState;
310
311     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
312
313     for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i)
314         registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]);
315
316     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i)
317         registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]);
318
319     for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i)
320         setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]);
321
322     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsLocal.size(); ++i)
323         registerURLSchemeAsLocal(parameters.urlSchemesRegisteredAsLocal[i]);
324
325     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsNoAccess.size(); ++i)
326         registerURLSchemeAsNoAccess(parameters.urlSchemesRegisteredAsNoAccess[i]);
327
328     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsDisplayIsolated.size(); ++i)
329         registerURLSchemeAsDisplayIsolated(parameters.urlSchemesRegisteredAsDisplayIsolated[i]);
330
331     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsCORSEnabled.size(); ++i)
332         registerURLSchemeAsCORSEnabled(parameters.urlSchemesRegisteredAsCORSEnabled[i]);
333
334 #if ENABLE(CACHE_PARTITIONING)
335     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
336         registerURLSchemeAsCORSEnabled(scheme);
337 #endif
338
339     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
340
341     if (parameters.shouldAlwaysUseComplexTextCodePath)
342         setAlwaysUsesComplexTextCodePath(true);
343
344     if (parameters.shouldUseFontSmoothing)
345         setShouldUseFontSmoothing(true);
346
347 #if PLATFORM(COCOA) || USE(CFNETWORK)
348     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
349 #endif
350
351     if (parameters.shouldUseTestingNetworkSession)
352         NetworkStorageSession::switchToNewTestingSession();
353
354 #if ENABLE(NETWORK_PROCESS)
355     m_usesNetworkProcess = parameters.usesNetworkProcess;
356     ensureNetworkProcessConnection();
357
358 #if PLATFORM(COCOA)
359     if (usesNetworkProcess())
360         CookieStorageShim::shared().initialize();
361 #endif
362 #endif
363     setTerminationTimeout(parameters.terminationTimeout);
364
365     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
366     for (size_t i = 0; i < parameters.plugInAutoStartOrigins.size(); ++i)
367         m_plugInAutoStartOrigins.add(parameters.plugInAutoStartOrigins[i]);
368
369     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
370 }
371
372 #if ENABLE(NETWORK_PROCESS)
373 void WebProcess::ensureNetworkProcessConnection()
374 {
375     if (!m_usesNetworkProcess)
376         return;
377
378     if (m_networkProcessConnection)
379         return;
380
381     IPC::Attachment encodedConnectionIdentifier;
382
383     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
384         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
385         return;
386
387 #if OS(DARWIN)
388     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
389 #elif USE(UNIX_DOMAIN_SOCKETS)
390     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
391 #else
392     ASSERT_NOT_REACHED();
393 #endif
394     if (IPC::Connection::identifierIsNull(connectionIdentifier))
395         return;
396     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
397 }
398 #endif // ENABLE(NETWORK_PROCESS)
399
400 void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
401 {
402     m_shouldTrackVisitedLinks = shouldTrackVisitedLinks;
403     PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks);
404 }
405
406 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
407 {
408     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
409 }
410
411 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
412 {
413     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
414 }
415
416 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
417 {
418     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
419 }
420
421 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
422 {
423     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
424 }
425
426 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
427 {
428     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
429 }
430
431 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
432 {
433     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
434 }
435
436 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
437 {
438     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
439 }
440
441 #if ENABLE(CACHE_PARTITIONING)
442 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
443 {
444     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
445 }
446 #endif
447
448 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
449 {
450     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
451 }
452
453 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
454 {
455     WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto);
456 }
457
458 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
459 {
460     WebCore::Font::setShouldUseSmoothing(useFontSmoothing);
461 }
462
463 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
464 {
465     overrideUserPreferredLanguages(languages);
466     languageDidChange();
467 }
468
469 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
470 {
471     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
472 }
473
474 void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID)
475 {
476 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
477     WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID);
478 #endif
479 }
480
481 void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID)
482 {
483 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
484     SessionTracker::destroySession(sessionID);
485 #endif
486 }
487
488 DownloadManager& WebProcess::downloadManager()
489 {
490     ASSERT(!usesNetworkProcess());
491
492     static NeverDestroyed<DownloadManager> downloadManager(this);
493     return downloadManager;
494 }
495
496 #if ENABLE(NETSCAPE_PLUGIN_API)
497 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
498 {
499     return *m_pluginProcessConnectionManager;
500 }
501 #endif
502
503 void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle)
504 {
505     RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly);
506     if (!sharedMemory)
507         return;
508
509     m_visitedLinkTable.setSharedMemory(sharedMemory.release());
510 }
511
512 void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes)
513 {
514     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
515     for (const auto& webPage : m_pageMap.values()) {
516         if (Page* page = webPage->corePage()) {
517             for (auto& linkHash : linkHashes)
518                 page->invalidateStylesForLink(linkHash);
519         }
520     }
521
522     pageCache()->markPagesForVistedLinkStyleRecalc();
523 }
524
525 void WebProcess::allVisitedLinkStateChanged()
526 {
527     for (const auto& webPage : m_pageMap.values()) {
528         if (Page* page = webPage->corePage())
529             page->invalidateStylesForAllLinks();
530     }
531
532     pageCache()->markPagesForVistedLinkStyleRecalc();
533 }
534
535 bool WebProcess::isLinkVisited(LinkHash linkHash) const
536 {
537     return m_visitedLinkTable.isLinkVisited(linkHash);
538 }
539
540 void WebProcess::addVisitedLink(WebCore::LinkHash linkHash)
541 {
542     if (isLinkVisited(linkHash) || !m_shouldTrackVisitedLinks)
543         return;
544     parentProcessConnection()->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0);
545 }
546
547 void WebProcess::setCacheModel(uint32_t cm)
548 {
549     CacheModel cacheModel = static_cast<CacheModel>(cm);
550
551     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
552         m_hasSetCacheModel = true;
553         m_cacheModel = cacheModel;
554         platformSetCacheModel(cacheModel);
555     }
556 }
557
558 WebPage* WebProcess::focusedWebPage() const
559 {    
560     HashMap<uint64_t, RefPtr<WebPage>>::const_iterator end = m_pageMap.end();
561     for (HashMap<uint64_t, RefPtr<WebPage>>::const_iterator it = m_pageMap.begin(); it != end; ++it) {
562         WebPage* page = (*it).value.get();
563         if (page->windowAndWebPageAreFocused())
564             return page;
565     }
566     return 0;
567 }
568     
569 WebPage* WebProcess::webPage(uint64_t pageID) const
570 {
571     return m_pageMap.get(pageID);
572 }
573
574 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
575 {
576     // It is necessary to check for page existence here since during a window.open() (or targeted
577     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
578     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
579     if (result.isNewEntry) {
580         ASSERT(!result.iterator->value);
581         result.iterator->value = WebPage::create(pageID, parameters);
582
583         // Balanced by an enableTermination in removeWebPage.
584         disableTermination();
585     } else
586         result.iterator->value->reinitializeWebPage(parameters);
587
588     ASSERT(result.iterator->value);
589 }
590
591 void WebProcess::removeWebPage(uint64_t pageID)
592 {
593     ASSERT(m_pageMap.contains(pageID));
594
595     pageWillLeaveWindow(pageID);
596     m_pageMap.remove(pageID);
597
598     enableTermination();
599 }
600
601 bool WebProcess::shouldTerminate()
602 {
603     ASSERT(m_pageMap.isEmpty());
604     ASSERT(usesNetworkProcess() || !downloadManager().isDownloading());
605
606     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
607     bool shouldTerminate = false;
608     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
609         && !shouldTerminate)
610         return false;
611
612     return true;
613 }
614
615 void WebProcess::terminate()
616 {
617 #ifndef NDEBUG
618     gcController().garbageCollectNow();
619     fontCache()->invalidate();
620     memoryCache()->setDisabled(true);
621 #endif
622
623     m_webConnection->invalidate();
624     m_webConnection = nullptr;
625
626     platformTerminate();
627
628     ChildProcess::terminate();
629 }
630
631 void WebProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
632 {
633     messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder);
634 }
635
636 void WebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder)
637 {
638     if (messageReceiverMap().dispatchMessage(connection, decoder))
639         return;
640
641     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
642         didReceiveWebProcessMessage(connection, decoder);
643         return;
644     }
645
646     if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) {
647         uint64_t pageGroupID = decoder.destinationID();
648         if (!pageGroupID)
649             return;
650         
651         WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
652         if (!pageGroupProxy)
653             return;
654         
655         pageGroupProxy->didReceiveMessage(connection, decoder);
656     }
657 }
658
659 void WebProcess::didClose(IPC::Connection*)
660 {
661 #ifndef NDEBUG
662     m_inDidClose = true;
663
664     // Close all the live pages.
665     Vector<RefPtr<WebPage>> pages;
666     copyValuesToVector(m_pageMap, pages);
667     for (size_t i = 0; i < pages.size(); ++i)
668         pages[i]->close();
669     pages.clear();
670
671     gcController().garbageCollectSoon();
672     fontCache()->invalidate();
673     memoryCache()->setDisabled(true);
674 #endif    
675
676     // The UI process closed this connection, shut down.
677     stopRunLoop();
678 }
679
680 void WebProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference)
681 {
682     // We received an invalid message, but since this is from the UI process (which we trust),
683     // we'll let it slide.
684 }
685
686 WebFrame* WebProcess::webFrame(uint64_t frameID) const
687 {
688     return m_frameMap.get(frameID);
689 }
690
691 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
692 {
693     m_frameMap.set(frameID, frame);
694 }
695
696 void WebProcess::removeWebFrame(uint64_t frameID)
697 {
698     m_frameMap.remove(frameID);
699
700     // We can end up here after our connection has closed when WebCore's frame life-support timer
701     // fires when the application is shutting down. There's no need (and no way) to update the UI
702     // process in this case.
703     if (!parentProcessConnection())
704         return;
705
706     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
707 }
708
709 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
710 {
711     for (HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(), end = m_pageGroupMap.end(); it != end; ++it) {
712         if (it->value->corePageGroup() == pageGroup)
713             return it->value.get();
714     }
715
716     return 0;
717 }
718
719 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
720 {
721     return m_pageGroupMap.get(pageGroupID);
722 }
723
724 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
725 {
726     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
727     if (result.isNewEntry) {
728         ASSERT(!result.iterator->value);
729         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
730     }
731
732     return result.iterator->value.get();
733 }
734
735 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
736 {
737     platformClearResourceCaches(resourceCachesToClear);
738
739     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
740     // FIXME: We need a better way to do this.
741     CacheModel cacheModel = m_cacheModel;
742     setCacheModel(CacheModelDocumentViewer);
743     setCacheModel(cacheModel);
744
745     memoryCache()->evictResources();
746
747     // Empty the cross-origin preflight cache.
748     CrossOriginPreflightResultCache::shared().empty();
749 }
750
751 void WebProcess::clearApplicationCache()
752 {
753     // Empty the application cache.
754     cacheStorage().empty();
755 }
756
757 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
758 {
759     if (string.isEmpty())
760         return;
761     if (string.is8Bit()) {
762         hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length());
763         return;
764     }
765     hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length());
766 }
767
768 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
769 {
770     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
771     // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags.
772     StringHasher hasher;
773     addCaseFoldedCharacters(hasher, pageOrigin);
774     hasher.addCharacter(0);
775     addCaseFoldedCharacters(hasher, pluginOrigin);
776     hasher.addCharacter(0);
777     addCaseFoldedCharacters(hasher, mimeType);
778     return hasher.hash();
779 }
780
781 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash)
782 {
783     HashMap<unsigned, double>::const_iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
784     if (it == m_plugInAutoStartOriginHashes.end())
785         return false;
786     return currentTime() < it->value;
787 }
788
789 bool WebProcess::shouldPlugInAutoStartFromOrigin(const WebPage* page, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
790 {
791     if (m_plugInAutoStartOrigins.contains(pluginOrigin))
792         return true;
793
794 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
795     // 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).
796     if (page && page->matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
797         return true;
798 #else
799     UNUSED_PARAM(page);
800 #endif
801
802     // Lastly check against the more explicit hash list.
803     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType));
804 }
805
806 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
807 {
808     if (pageOrigin.isEmpty()) {
809         LOG(Plugins, "Not adding empty page origin");
810         return;
811     }
812
813     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
814     if (isPlugInAutoStartOriginHash(plugInOriginHash)) {
815         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
816         return;
817     }
818
819     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
820     // comes back from the parent process. Temporarily add this hash to the list with a thirty
821     // second timeout. That way, even if the parent decides not to add it, we'll only be
822     // incorrect for a little while.
823     m_plugInAutoStartOriginHashes.set(plugInOriginHash, currentTime() + 30 * 1000);
824
825     parentProcessConnection()->send(Messages::WebContext::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash), 0);
826 }
827
828 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime)
829 {
830     // When called, some web process (which also might be this one) added the origin for auto-starting,
831     // or received user interaction.
832     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
833     m_plugInAutoStartOriginHashes.set(plugInOriginHash, expirationTime);
834 }
835
836 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<unsigned, double>& hashes)
837 {
838     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<unsigned, double>&>(hashes));
839 }
840
841 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
842 {
843     if (pageOrigin.isEmpty())
844         return;
845
846     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
847     if (!plugInOriginHash)
848         return;
849
850     HashMap<unsigned, double>::iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
851     if (it == m_plugInAutoStartOriginHashes.end())
852         return;
853     if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
854         return;
855
856     parentProcessConnection()->send(Messages::WebContext::PlugInDidReceiveUserInteraction(plugInOriginHash), 0);
857 }
858
859 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
860 {
861     TypeCountSet::const_iterator end = countedSet->end();
862     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
863         map.set(it->key, it->value);
864 }
865
866 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
867 {
868     String imagesString(ASCIILiteral("Images"));
869     String cssString(ASCIILiteral("CSS"));
870     String xslString(ASCIILiteral("XSL"));
871     String javaScriptString(ASCIILiteral("JavaScript"));
872     
873     MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics();
874     
875     HashMap<String, uint64_t> counts;
876     counts.set(imagesString, memoryCacheStatistics.images.count);
877     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
878     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
879     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
880     result.append(counts);
881     
882     HashMap<String, uint64_t> sizes;
883     sizes.set(imagesString, memoryCacheStatistics.images.size);
884     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
885     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
886     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
887     result.append(sizes);
888     
889     HashMap<String, uint64_t> liveSizes;
890     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
891     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
892     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
893     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
894     result.append(liveSizes);
895     
896     HashMap<String, uint64_t> decodedSizes;
897     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
898     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
899     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
900     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
901     result.append(decodedSizes);
902     
903     HashMap<String, uint64_t> purgeableSizes;
904     purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
905     purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
906     purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
907     purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
908     result.append(purgeableSizes);
909     
910     HashMap<String, uint64_t> purgedSizes;
911     purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
912     purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
913     purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
914     purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
915     result.append(purgedSizes);
916 }
917
918 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
919 {
920     StatisticsData data;
921     
922     // Gather JavaScript statistics.
923     {
924         JSLockHolder lock(JSDOMWindow::commonVM());
925         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount());
926         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount());
927         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount());
928         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount());
929         
930         OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts());
931         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
932         
933         OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts());
934         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
935         
936         uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size();
937         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
938         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize);
939     }
940
941     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
942     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
943     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
944     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
945     
946     // Gather icon statistics.
947     data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
948     data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
949     data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
950     data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
951     
952     // Gather font statistics.
953     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache()->fontDataCount());
954     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache()->inactiveFontDataCount());
955     
956     // Gather glyph page statistics.
957     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPageTreeNode::treeGlyphPageCount());
958     
959     // Get WebCore memory cache statistics
960     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
961     
962     parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0);
963 }
964
965 void WebProcess::garbageCollectJavaScriptObjects()
966 {
967     gcController().garbageCollectNow();
968 }
969
970 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
971 {
972     gcController().setJavaScriptGarbageCollectorTimerEnabled(flag);
973 }
974
975 void WebProcess::postInjectedBundleMessage(const IPC::DataReference& messageData)
976 {
977     InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();
978     if (!injectedBundle)
979         return;
980
981     IPC::ArgumentDecoder decoder(messageData.data(), messageData.size());
982
983     String messageName;
984     if (!decoder.decode(messageName))
985         return;
986
987     RefPtr<API::Object> messageBody;
988     InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody);
989     if (!decoder.decode(messageBodyDecoder))
990         return;
991
992     injectedBundle->didReceiveMessage(messageName, messageBody.get());
993 }
994
995 bool WebProcess::usesNetworkProcess() const
996 {
997 #if ENABLE(NETWORK_PROCESS)
998     return m_usesNetworkProcess;
999 #else
1000     return false;
1001 #endif
1002 }
1003
1004 #if ENABLE(NETWORK_PROCESS)
1005 NetworkProcessConnection* WebProcess::networkConnection()
1006 {
1007     ASSERT(m_usesNetworkProcess);
1008
1009     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1010     if (!m_networkProcessConnection)
1011         ensureNetworkProcessConnection();
1012     
1013     // If we failed to re-establish it then we are beyond recovery and should crash.
1014     if (!m_networkProcessConnection)
1015         CRASH();
1016     
1017     return m_networkProcessConnection.get();
1018 }
1019
1020 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1021 {
1022     ASSERT(m_networkProcessConnection);
1023     ASSERT(m_networkProcessConnection == connection);
1024
1025     m_networkProcessConnection = 0;
1026     
1027     m_webResourceLoadScheduler->networkProcessCrashed();
1028 }
1029
1030 WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler()
1031 {
1032     return *m_webResourceLoadScheduler;
1033 }
1034 #endif // ENABLED(NETWORK_PROCESS)
1035
1036 #if ENABLE(DATABASE_PROCESS)
1037 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1038 {
1039     ASSERT(m_webToDatabaseProcessConnection);
1040     ASSERT(m_webToDatabaseProcessConnection == connection);
1041
1042     m_webToDatabaseProcessConnection = 0;
1043 }
1044
1045 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1046 {
1047     if (!m_webToDatabaseProcessConnection)
1048         ensureWebToDatabaseProcessConnection();
1049
1050     return m_webToDatabaseProcessConnection.get();
1051 }
1052
1053 void WebProcess::ensureWebToDatabaseProcessConnection()
1054 {
1055     if (m_webToDatabaseProcessConnection)
1056         return;
1057
1058     IPC::Attachment encodedConnectionIdentifier;
1059
1060     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1061         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1062         return;
1063
1064 #if OS(DARWIN)
1065     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1066     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1067         return;
1068 #else
1069     ASSERT_NOT_REACHED();
1070 #endif
1071     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1072 }
1073
1074 #endif // ENABLED(DATABASE_PROCESS)
1075
1076 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1077 {
1078     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1079
1080     ResourceRequest requestWithOriginalURL = request;
1081     if (initiatingPage)
1082         initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL);
1083
1084     downloadManager().startDownload(downloadID, requestWithOriginalURL);
1085 }
1086
1087 void WebProcess::cancelDownload(uint64_t downloadID)
1088 {
1089     downloadManager().cancelDownload(downloadID);
1090 }
1091
1092 void WebProcess::setEnhancedAccessibility(bool flag)
1093 {
1094     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1095 }
1096     
1097 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1098 {
1099 #if ENABLE(MEMORY_SAMPLER)    
1100     WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1101 #else
1102     UNUSED_PARAM(sampleLogFileHandle);
1103     UNUSED_PARAM(sampleLogFilePath);
1104     UNUSED_PARAM(interval);
1105 #endif
1106 }
1107     
1108 void WebProcess::stopMemorySampler()
1109 {
1110 #if ENABLE(MEMORY_SAMPLER)
1111     WebMemorySampler::shared()->stop();
1112 #endif
1113 }
1114
1115 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1116 {
1117     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1118     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1119
1120     m_textCheckerState = textCheckerState;
1121
1122     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1123         return;
1124
1125     HashMap<uint64_t, RefPtr<WebPage>>::iterator end = m_pageMap.end();
1126     for (HashMap<uint64_t, RefPtr<WebPage>>::iterator it = m_pageMap.begin(); it != end; ++it) {
1127         WebPage* page = (*it).value.get();
1128         if (continuousSpellCheckingTurnedOff)
1129             page->unmarkAllMisspellings();
1130         if (grammarCheckingTurnedOff)
1131             page->unmarkAllBadGrammar();
1132     }
1133 }
1134
1135 void WebProcess::releasePageCache()
1136 {
1137     int savedPageCacheCapacity = pageCache()->capacity();
1138     pageCache()->setCapacity(0);
1139     pageCache()->setCapacity(savedPageCacheCapacity);
1140 }
1141
1142 #if !PLATFORM(COCOA)
1143 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1144 {
1145 }
1146
1147 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1148 {
1149 }
1150
1151 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1152 {
1153 }
1154
1155 void WebProcess::updateActivePages()
1156 {
1157 }
1158
1159 #endif
1160
1161 #if PLATFORM(IOS)
1162 void WebProcess::resetAllGeolocationPermissions()
1163 {
1164     for (auto it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it) {
1165         WebPage* page = (*it).value.get();
1166         if (Frame* mainFrame = page->mainFrame())
1167             mainFrame->resetAllGeolocationPermission();
1168     }
1169 }
1170 #endif // PLATFORM(IOS)
1171
1172 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1173 {
1174     m_pagesInWindows.add(pageID);
1175     m_nonVisibleProcessCleanupTimer.stop();
1176 }
1177
1178 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1179 {
1180     m_pagesInWindows.remove(pageID);
1181
1182     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1183         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1184 }
1185     
1186 void WebProcess::nonVisibleProcessCleanupTimerFired(Timer<WebProcess>*)
1187 {
1188     ASSERT(m_pagesInWindows.isEmpty());
1189     if (!m_pagesInWindows.isEmpty())
1190         return;
1191
1192 #if PLATFORM(COCOA)
1193     wkDestroyRenderingResources();
1194 #endif
1195 }
1196
1197 RefPtr<API::Object> WebProcess::apiObjectByConvertingFromHandles(API::Object* object)
1198 {
1199     return UserData::transform(object, [this](const API::Object& object) -> RefPtr<API::Object> {
1200         switch (object.type()) {
1201         case API::Object::Type::FrameHandle: {
1202             auto& frameHandle = static_cast<const API::FrameHandle&>(object);
1203
1204             return webFrame(frameHandle.frameID());
1205         }
1206
1207         default:
1208             return nullptr;
1209         }
1210     });
1211 }
1212
1213 void WebProcess::setMemoryCacheDisabled(bool disabled)
1214 {
1215     if (memoryCache()->disabled() != disabled)
1216         memoryCache()->setDisabled(disabled);
1217 }
1218
1219 } // namespace WebKit