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