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