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