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