If there are no services available, do not show the service controls UI
[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_PROCESS)
92 #if PLATFORM(COCOA)
93 #include "CookieStorageShim.h"
94 #endif
95 #include "NetworkProcessConnection.h"
96 #endif
97
98 #if ENABLE(SEC_ITEM_SHIM)
99 #include "SecItemShim.h"
100 #endif
101
102 #if ENABLE(CUSTOM_PROTOCOLS)
103 #include "CustomProtocolManager.h"
104 #endif
105
106 #if ENABLE(DATABASE_PROCESS)
107 #include "WebToDatabaseProcessConnection.h"
108 #endif
109
110 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
111 #include "WebNotificationManager.h"
112 #endif
113
114 #if ENABLE(SQL_DATABASE)
115 #include "WebDatabaseManager.h"
116 #endif
117
118 #if ENABLE(BATTERY_STATUS)
119 #include "WebBatteryManager.h"
120 #endif
121
122 #if ENABLE(NETWORK_PROCESS)
123 #include "WebResourceLoadScheduler.h"
124 #endif
125
126 #if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS)
127 #include "WebSoupRequestManager.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::shared()
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 // PLATFORM(IOS)
152     , m_inDidClose(false)
153     , m_shouldTrackVisitedLinks(true)
154     , m_hasSetCacheModel(false)
155     , m_cacheModel(CacheModelDocumentViewer)
156 #if PLATFORM(COCOA)
157     , m_compositingRenderServerPort(MACH_PORT_NULL)
158     , m_clearResourceCachesDispatchGroup(0)
159 #endif
160     , m_fullKeyboardAccessEnabled(false)
161     , m_textCheckerState()
162     , m_iconDatabaseProxy(new WebIconDatabaseProxy(this))
163 #if ENABLE(NETWORK_PROCESS)
164     , m_usesNetworkProcess(false)
165     , m_webResourceLoadScheduler(new WebResourceLoadScheduler)
166 #endif
167 #if ENABLE(NETSCAPE_PLUGIN_API)
168     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
169 #endif
170 #if ENABLE(SERVICE_CONTROLS)
171     , m_hasImageServices(false)
172     , m_hasSelectionServices(false)
173 #endif
174     , m_nonVisibleProcessCleanupTimer(this, &WebProcess::nonVisibleProcessCleanupTimerFired)
175 {
176     // Initialize our platform strategies.
177     WebPlatformStrategies::initialize();
178
179     // FIXME: This should moved to where WebProcess::initialize is called,
180     // so that ports have a chance to customize, and ifdefs in this file are
181     // limited.
182     addSupplement<WebGeolocationManager>();
183     addSupplement<WebApplicationCacheManager>();
184     addSupplement<WebResourceCacheManager>();
185     addSupplement<WebCookieManager>();
186     addSupplement<WebMediaCacheManager>();
187     addSupplement<AuthenticationManager>();
188     
189 #if ENABLE(SQL_DATABASE)
190     addSupplement<WebDatabaseManager>();
191 #endif
192 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
193     addSupplement<WebNotificationManager>();
194 #endif
195 #if ENABLE(CUSTOM_PROTOCOLS)
196     addSupplement<CustomProtocolManager>();
197 #endif
198 #if ENABLE(BATTERY_STATUS)
199     addSupplement<WebBatteryManager>();
200 #endif
201 #if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS)
202     addSupplement<WebSoupRequestManager>();
203 #endif
204 }
205
206 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
207 {
208     platformInitializeProcess(parameters);
209 }
210
211 void WebProcess::initializeConnection(IPC::Connection* connection)
212 {
213     ChildProcess::initializeConnection(connection);
214
215     connection->setShouldExitOnSyncMessageSendFailure(true);
216
217     m_eventDispatcher->initializeConnection(connection);
218 #if PLATFORM(IOS)
219     m_viewUpdateDispatcher->initializeConnection(connection);
220 #endif // PLATFORM(IOS)
221
222 #if ENABLE(NETSCAPE_PLUGIN_API)
223     m_pluginProcessConnectionManager->initializeConnection(connection);
224 #endif
225
226 #if ENABLE(SEC_ITEM_SHIM)
227     SecItemShim::shared().initializeConnection(connection);
228 #endif
229     
230     WebProcessSupplementMap::const_iterator it = m_supplements.begin();
231     WebProcessSupplementMap::const_iterator end = m_supplements.end();
232     for (; it != end; ++it)
233         it->value->initializeConnection(connection);
234
235     m_webConnection = WebConnectionToUIProcess::create(this);
236
237     // In order to ensure that the asynchronous messages that are used for notifying the UI process
238     // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
239     // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
240     // unless when doing so would lead to a deadlock.
241     connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
242 }
243
244 void WebProcess::didCreateDownload()
245 {
246     disableTermination();
247 }
248
249 void WebProcess::didDestroyDownload()
250 {
251     enableTermination();
252 }
253
254 IPC::Connection* WebProcess::downloadProxyConnection()
255 {
256     return parentProcessConnection();
257 }
258
259 AuthenticationManager& WebProcess::downloadsAuthenticationManager()
260 {
261     return *supplement<AuthenticationManager>();
262 }
263
264 void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, IPC::MessageDecoder& decoder)
265 {
266     ASSERT(m_pageMap.isEmpty());
267
268     platformInitializeWebProcess(parameters, decoder);
269
270     memoryPressureHandler().install();
271
272     RefPtr<API::Object> injectedBundleInitializationUserData;
273     InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData);
274     if (!decoder.decode(messageDecoder))
275         return;
276
277     if (!parameters.injectedBundlePath.isEmpty()) {
278         m_injectedBundle = InjectedBundle::create(parameters);
279         m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle));
280
281         if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) {
282             // Don't keep around the InjectedBundle reference if the load fails.
283             m_injectedBundle.clear();
284         }
285     }
286
287     WebProcessSupplementMap::const_iterator it = m_supplements.begin();
288     WebProcessSupplementMap::const_iterator end = m_supplements.end();
289     for (; it != end; ++it)
290         it->value->initialize(parameters);
291
292 #if ENABLE(ICONDATABASE)
293     m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled);
294 #endif
295
296     if (!parameters.applicationCacheDirectory.isEmpty())
297         cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory);
298
299     setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks);
300     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
301
302     if (!parameters.languages.isEmpty())
303         overrideUserPreferredLanguages(parameters.languages);
304
305     m_textCheckerState = parameters.textCheckerState;
306
307     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
308
309     for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i)
310         registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]);
311
312     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i)
313         registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]);
314
315     for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i)
316         setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]);
317
318     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsLocal.size(); ++i)
319         registerURLSchemeAsLocal(parameters.urlSchemesRegisteredAsLocal[i]);
320
321     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsNoAccess.size(); ++i)
322         registerURLSchemeAsNoAccess(parameters.urlSchemesRegisteredAsNoAccess[i]);
323
324     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsDisplayIsolated.size(); ++i)
325         registerURLSchemeAsDisplayIsolated(parameters.urlSchemesRegisteredAsDisplayIsolated[i]);
326
327     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsCORSEnabled.size(); ++i)
328         registerURLSchemeAsCORSEnabled(parameters.urlSchemesRegisteredAsCORSEnabled[i]);
329
330 #if ENABLE(CACHE_PARTITIONING)
331     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
332         registerURLSchemeAsCachePartitioned(scheme);
333 #endif
334
335     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
336
337     if (parameters.shouldAlwaysUseComplexTextCodePath)
338         setAlwaysUsesComplexTextCodePath(true);
339
340     if (parameters.shouldUseFontSmoothing)
341         setShouldUseFontSmoothing(true);
342
343 #if PLATFORM(COCOA) || USE(CFNETWORK)
344     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
345 #endif
346
347     if (parameters.shouldUseTestingNetworkSession)
348         NetworkStorageSession::switchToNewTestingSession();
349
350 #if ENABLE(NETWORK_PROCESS)
351     m_usesNetworkProcess = parameters.usesNetworkProcess;
352     ensureNetworkProcessConnection();
353
354 #if PLATFORM(COCOA)
355     if (usesNetworkProcess())
356         CookieStorageShim::shared().initialize();
357 #endif
358 #endif
359     setTerminationTimeout(parameters.terminationTimeout);
360
361     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
362     for (size_t i = 0; i < parameters.plugInAutoStartOrigins.size(); ++i)
363         m_plugInAutoStartOrigins.add(parameters.plugInAutoStartOrigins[i]);
364
365     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
366
367 #if ENABLE(SERVICE_CONTROLS)
368     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices);
369 #endif
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::setCacheModel(uint32_t cm)
504 {
505     CacheModel cacheModel = static_cast<CacheModel>(cm);
506
507     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
508         m_hasSetCacheModel = true;
509         m_cacheModel = cacheModel;
510         platformSetCacheModel(cacheModel);
511     }
512 }
513
514 WebPage* WebProcess::focusedWebPage() const
515 {    
516     HashMap<uint64_t, RefPtr<WebPage>>::const_iterator end = m_pageMap.end();
517     for (HashMap<uint64_t, RefPtr<WebPage>>::const_iterator it = m_pageMap.begin(); it != end; ++it) {
518         WebPage* page = (*it).value.get();
519         if (page->windowAndWebPageAreFocused())
520             return page;
521     }
522     return 0;
523 }
524     
525 WebPage* WebProcess::webPage(uint64_t pageID) const
526 {
527     return m_pageMap.get(pageID);
528 }
529
530 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
531 {
532     // It is necessary to check for page existence here since during a window.open() (or targeted
533     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
534     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
535     if (result.isNewEntry) {
536         ASSERT(!result.iterator->value);
537         result.iterator->value = WebPage::create(pageID, parameters);
538
539         // Balanced by an enableTermination in removeWebPage.
540         disableTermination();
541     } else
542         result.iterator->value->reinitializeWebPage(parameters);
543
544     ASSERT(result.iterator->value);
545 }
546
547 void WebProcess::removeWebPage(uint64_t pageID)
548 {
549     ASSERT(m_pageMap.contains(pageID));
550
551     pageWillLeaveWindow(pageID);
552     m_pageMap.remove(pageID);
553
554     enableTermination();
555 }
556
557 bool WebProcess::shouldTerminate()
558 {
559     ASSERT(m_pageMap.isEmpty());
560     ASSERT(usesNetworkProcess() || !downloadManager().isDownloading());
561
562     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
563     bool shouldTerminate = false;
564     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
565         && !shouldTerminate)
566         return false;
567
568     return true;
569 }
570
571 void WebProcess::terminate()
572 {
573 #ifndef NDEBUG
574     gcController().garbageCollectNow();
575     fontCache().invalidate();
576     memoryCache()->setDisabled(true);
577 #endif
578
579     m_webConnection->invalidate();
580     m_webConnection = nullptr;
581
582     platformTerminate();
583
584     ChildProcess::terminate();
585 }
586
587 void WebProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
588 {
589     messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder);
590 }
591
592 void WebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder)
593 {
594     if (messageReceiverMap().dispatchMessage(connection, decoder))
595         return;
596
597     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
598         didReceiveWebProcessMessage(connection, decoder);
599         return;
600     }
601
602     if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) {
603         uint64_t pageGroupID = decoder.destinationID();
604         if (!pageGroupID)
605             return;
606         
607         WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
608         if (!pageGroupProxy)
609             return;
610         
611         pageGroupProxy->didReceiveMessage(connection, decoder);
612     }
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 (size_t i = 0; i < pages.size(); ++i)
624         pages[i]->close();
625     pages.clear();
626
627     gcController().garbageCollectSoon();
628     fontCache().invalidate();
629     memoryCache()->setDisabled(true);
630 #endif    
631
632     // The UI process closed this connection, shut down.
633     stopRunLoop();
634 }
635
636 void WebProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference)
637 {
638     // We received an invalid message, but since this is from the UI process (which we trust),
639     // we'll let it slide.
640 }
641
642 WebFrame* WebProcess::webFrame(uint64_t frameID) const
643 {
644     return m_frameMap.get(frameID);
645 }
646
647 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
648 {
649     m_frameMap.set(frameID, frame);
650 }
651
652 void WebProcess::removeWebFrame(uint64_t frameID)
653 {
654     m_frameMap.remove(frameID);
655
656     // We can end up here after our connection has closed when WebCore's frame life-support timer
657     // fires when the application is shutting down. There's no need (and no way) to update the UI
658     // process in this case.
659     if (!parentProcessConnection())
660         return;
661
662     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
663 }
664
665 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
666 {
667     for (HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(), end = m_pageGroupMap.end(); it != end; ++it) {
668         if (it->value->corePageGroup() == pageGroup)
669             return it->value.get();
670     }
671
672     return 0;
673 }
674
675 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
676 {
677     return m_pageGroupMap.get(pageGroupID);
678 }
679
680 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
681 {
682     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
683     if (result.isNewEntry) {
684         ASSERT(!result.iterator->value);
685         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
686     }
687
688     return result.iterator->value.get();
689 }
690
691 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
692 {
693     platformClearResourceCaches(resourceCachesToClear);
694
695     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
696     // FIXME: We need a better way to do this.
697     CacheModel cacheModel = m_cacheModel;
698     setCacheModel(CacheModelDocumentViewer);
699     setCacheModel(cacheModel);
700
701     memoryCache()->evictResources();
702
703     // Empty the cross-origin preflight cache.
704     CrossOriginPreflightResultCache::shared().empty();
705 }
706
707 void WebProcess::clearApplicationCache()
708 {
709     // Empty the application cache.
710     cacheStorage().empty();
711 }
712
713 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
714 {
715     if (string.isEmpty())
716         return;
717     if (string.is8Bit()) {
718         hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length());
719         return;
720     }
721     hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length());
722 }
723
724 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
725 {
726     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
727     // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags.
728     StringHasher hasher;
729     addCaseFoldedCharacters(hasher, pageOrigin);
730     hasher.addCharacter(0);
731     addCaseFoldedCharacters(hasher, pluginOrigin);
732     hasher.addCharacter(0);
733     addCaseFoldedCharacters(hasher, mimeType);
734     return hasher.hash();
735 }
736
737 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash)
738 {
739     HashMap<unsigned, double>::const_iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
740     if (it == m_plugInAutoStartOriginHashes.end())
741         return false;
742     return currentTime() < it->value;
743 }
744
745 bool WebProcess::shouldPlugInAutoStartFromOrigin(const WebPage* page, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
746 {
747     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
748         return true;
749
750 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
751     // 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).
752     if (page && page->matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
753         return true;
754 #else
755     UNUSED_PARAM(page);
756 #endif
757
758     // Lastly check against the more explicit hash list.
759     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType));
760 }
761
762 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
763 {
764     if (pageOrigin.isEmpty()) {
765         LOG(Plugins, "Not adding empty page origin");
766         return;
767     }
768
769     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
770     if (isPlugInAutoStartOriginHash(plugInOriginHash)) {
771         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
772         return;
773     }
774
775     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
776     // comes back from the parent process. Temporarily add this hash to the list with a thirty
777     // second timeout. That way, even if the parent decides not to add it, we'll only be
778     // incorrect for a little while.
779     m_plugInAutoStartOriginHashes.set(plugInOriginHash, currentTime() + 30 * 1000);
780
781     parentProcessConnection()->send(Messages::WebContext::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash), 0);
782 }
783
784 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime)
785 {
786     // When called, some web process (which also might be this one) added the origin for auto-starting,
787     // or received user interaction.
788     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
789     m_plugInAutoStartOriginHashes.set(plugInOriginHash, expirationTime);
790 }
791
792 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<unsigned, double>& hashes)
793 {
794     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<unsigned, double>&>(hashes));
795 }
796
797 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
798 {
799     if (pageOrigin.isEmpty())
800         return;
801
802     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
803     if (!plugInOriginHash)
804         return;
805
806     HashMap<unsigned, double>::iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
807     if (it == m_plugInAutoStartOriginHashes.end())
808         return;
809     if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
810         return;
811
812     parentProcessConnection()->send(Messages::WebContext::PlugInDidReceiveUserInteraction(plugInOriginHash), 0);
813 }
814
815 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
816 {
817     TypeCountSet::const_iterator end = countedSet->end();
818     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
819         map.set(it->key, it->value);
820 }
821
822 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
823 {
824     String imagesString(ASCIILiteral("Images"));
825     String cssString(ASCIILiteral("CSS"));
826     String xslString(ASCIILiteral("XSL"));
827     String javaScriptString(ASCIILiteral("JavaScript"));
828     
829     MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics();
830     
831     HashMap<String, uint64_t> counts;
832     counts.set(imagesString, memoryCacheStatistics.images.count);
833     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
834     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
835     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
836     result.append(counts);
837     
838     HashMap<String, uint64_t> sizes;
839     sizes.set(imagesString, memoryCacheStatistics.images.size);
840     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
841     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
842     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
843     result.append(sizes);
844     
845     HashMap<String, uint64_t> liveSizes;
846     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
847     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
848     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
849     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
850     result.append(liveSizes);
851     
852     HashMap<String, uint64_t> decodedSizes;
853     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
854     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
855     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
856     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
857     result.append(decodedSizes);
858     
859     HashMap<String, uint64_t> purgeableSizes;
860     purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
861     purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
862     purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
863     purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
864     result.append(purgeableSizes);
865     
866     HashMap<String, uint64_t> purgedSizes;
867     purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
868     purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
869     purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
870     purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
871     result.append(purgedSizes);
872 }
873
874 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
875 {
876     StatisticsData data;
877     
878     // Gather JavaScript statistics.
879     {
880         JSLockHolder lock(JSDOMWindow::commonVM());
881         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount());
882         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount());
883         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount());
884         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount());
885         
886         OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts());
887         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
888         
889         OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts());
890         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
891         
892         uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size();
893         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
894         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize);
895     }
896
897     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
898     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
899     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
900     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
901     
902     // Gather icon statistics.
903     data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
904     data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
905     data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
906     data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
907     
908     // Gather font statistics.
909     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache().fontDataCount());
910     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache().inactiveFontDataCount());
911     
912     // Gather glyph page statistics.
913     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPageTreeNode::treeGlyphPageCount());
914     
915     // Get WebCore memory cache statistics
916     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
917     
918     parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0);
919 }
920
921 void WebProcess::garbageCollectJavaScriptObjects()
922 {
923     gcController().garbageCollectNow();
924 }
925
926 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
927 {
928     gcController().setJavaScriptGarbageCollectorTimerEnabled(flag);
929 }
930
931 void WebProcess::postInjectedBundleMessage(const IPC::DataReference& messageData)
932 {
933     InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();
934     if (!injectedBundle)
935         return;
936
937     IPC::ArgumentDecoder decoder(messageData.data(), messageData.size());
938
939     String messageName;
940     if (!decoder.decode(messageName))
941         return;
942
943     RefPtr<API::Object> messageBody;
944     InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody);
945     if (!decoder.decode(messageBodyDecoder))
946         return;
947
948     injectedBundle->didReceiveMessage(messageName, messageBody.get());
949 }
950
951 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
952 {
953     InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();
954     if (!injectedBundle)
955         return;
956
957     injectedBundle->setBundleParameter(key, value);
958 }
959
960 bool WebProcess::usesNetworkProcess() const
961 {
962 #if ENABLE(NETWORK_PROCESS)
963     return m_usesNetworkProcess;
964 #else
965     return false;
966 #endif
967 }
968
969 #if ENABLE(NETWORK_PROCESS)
970 NetworkProcessConnection* WebProcess::networkConnection()
971 {
972     ASSERT(m_usesNetworkProcess);
973
974     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
975     if (!m_networkProcessConnection)
976         ensureNetworkProcessConnection();
977     
978     // If we failed to re-establish it then we are beyond recovery and should crash.
979     if (!m_networkProcessConnection)
980         CRASH();
981     
982     return m_networkProcessConnection.get();
983 }
984
985 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
986 {
987     ASSERT(m_networkProcessConnection);
988     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
989
990     m_networkProcessConnection = 0;
991     
992     m_webResourceLoadScheduler->networkProcessCrashed();
993 }
994
995 WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler()
996 {
997     return *m_webResourceLoadScheduler;
998 }
999 #endif // ENABLED(NETWORK_PROCESS)
1000
1001 #if ENABLE(DATABASE_PROCESS)
1002 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1003 {
1004     ASSERT(m_webToDatabaseProcessConnection);
1005     ASSERT(m_webToDatabaseProcessConnection == connection);
1006
1007     m_webToDatabaseProcessConnection = 0;
1008 }
1009
1010 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1011 {
1012     if (!m_webToDatabaseProcessConnection)
1013         ensureWebToDatabaseProcessConnection();
1014
1015     return m_webToDatabaseProcessConnection.get();
1016 }
1017
1018 void WebProcess::ensureWebToDatabaseProcessConnection()
1019 {
1020     if (m_webToDatabaseProcessConnection)
1021         return;
1022
1023     IPC::Attachment encodedConnectionIdentifier;
1024
1025     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1026         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1027         return;
1028
1029 #if OS(DARWIN)
1030     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1031     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1032         return;
1033 #else
1034     ASSERT_NOT_REACHED();
1035 #endif
1036     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1037 }
1038
1039 #endif // ENABLED(DATABASE_PROCESS)
1040
1041 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1042 {
1043     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1044
1045     ResourceRequest requestWithOriginalURL = request;
1046     if (initiatingPage)
1047         initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL);
1048
1049     downloadManager().startDownload(downloadID, requestWithOriginalURL);
1050 }
1051
1052 void WebProcess::cancelDownload(uint64_t downloadID)
1053 {
1054     downloadManager().cancelDownload(downloadID);
1055 }
1056
1057 void WebProcess::setEnhancedAccessibility(bool flag)
1058 {
1059     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1060 }
1061     
1062 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1063 {
1064 #if ENABLE(MEMORY_SAMPLER)    
1065     WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1066 #else
1067     UNUSED_PARAM(sampleLogFileHandle);
1068     UNUSED_PARAM(sampleLogFilePath);
1069     UNUSED_PARAM(interval);
1070 #endif
1071 }
1072     
1073 void WebProcess::stopMemorySampler()
1074 {
1075 #if ENABLE(MEMORY_SAMPLER)
1076     WebMemorySampler::shared()->stop();
1077 #endif
1078 }
1079
1080 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1081 {
1082     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1083     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1084
1085     m_textCheckerState = textCheckerState;
1086
1087     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1088         return;
1089
1090     HashMap<uint64_t, RefPtr<WebPage>>::iterator end = m_pageMap.end();
1091     for (HashMap<uint64_t, RefPtr<WebPage>>::iterator it = m_pageMap.begin(); it != end; ++it) {
1092         WebPage* page = (*it).value.get();
1093         if (continuousSpellCheckingTurnedOff)
1094             page->unmarkAllMisspellings();
1095         if (grammarCheckingTurnedOff)
1096             page->unmarkAllBadGrammar();
1097     }
1098 }
1099
1100 void WebProcess::releasePageCache()
1101 {
1102     int savedPageCacheCapacity = pageCache()->capacity();
1103     pageCache()->setCapacity(0);
1104     pageCache()->setCapacity(savedPageCacheCapacity);
1105 }
1106
1107 #if !PLATFORM(COCOA)
1108 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1109 {
1110 }
1111
1112 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1113 {
1114 }
1115
1116 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1117 {
1118 }
1119
1120 void WebProcess::updateActivePages()
1121 {
1122 }
1123
1124 #endif
1125
1126 #if PLATFORM(IOS)
1127 void WebProcess::resetAllGeolocationPermissions()
1128 {
1129     for (auto it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it) {
1130         WebPage* page = (*it).value.get();
1131         if (Frame* mainFrame = page->mainFrame())
1132             mainFrame->resetAllGeolocationPermission();
1133     }
1134 }
1135 #endif // PLATFORM(IOS)
1136
1137 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1138 {
1139     m_pagesInWindows.add(pageID);
1140     m_nonVisibleProcessCleanupTimer.stop();
1141 }
1142
1143 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1144 {
1145     m_pagesInWindows.remove(pageID);
1146
1147     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1148         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1149 }
1150     
1151 void WebProcess::nonVisibleProcessCleanupTimerFired(Timer<WebProcess>*)
1152 {
1153     ASSERT(m_pagesInWindows.isEmpty());
1154     if (!m_pagesInWindows.isEmpty())
1155         return;
1156
1157 #if PLATFORM(COCOA)
1158     wkDestroyRenderingResources();
1159 #endif
1160 }
1161
1162 RefPtr<API::Object> WebProcess::apiObjectByConvertingFromHandles(API::Object* object)
1163 {
1164     return UserData::transform(object, [this](const API::Object& object) -> RefPtr<API::Object> {
1165         switch (object.type()) {
1166         case API::Object::Type::FrameHandle: {
1167             auto& frameHandle = static_cast<const API::FrameHandle&>(object);
1168
1169             return webFrame(frameHandle.frameID());
1170         }
1171
1172         default:
1173             return nullptr;
1174         }
1175     });
1176 }
1177
1178 void WebProcess::setMemoryCacheDisabled(bool disabled)
1179 {
1180     if (memoryCache()->disabled() != disabled)
1181         memoryCache()->setDisabled(disabled);
1182 }
1183
1184 #if ENABLE(SERVICE_CONTROLS)
1185 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices)
1186 {
1187     m_hasImageServices = hasImageServices;
1188     m_hasSelectionServices = hasSelectionServices;
1189 }
1190 #endif
1191
1192 } // namespace WebKit