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