3e756ec03367ce1c597c633412317108535a31dc
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009, 2010 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 "DownloadManager.h"
31 #include "InjectedBundle.h"
32 #include "InjectedBundleMessageKinds.h"
33 #include "InjectedBundleUserMessageCoders.h"
34 #include "SandboxExtension.h"
35 #include "StatisticsData.h"
36 #include "WebApplicationCacheManager.h"
37 #include "WebContextMessages.h"
38 #include "WebCookieManager.h"
39 #include "WebCoreArgumentCoders.h"
40 #include "WebDatabaseManager.h"
41 #include "WebFrame.h"
42 #include "WebGeolocationManagerMessages.h"
43 #include "WebKeyValueStorageManager.h"
44 #include "WebMediaCacheManager.h"
45 #include "WebMemorySampler.h"
46 #include "WebPage.h"
47 #include "WebPageCreationParameters.h"
48 #include "WebPlatformStrategies.h"
49 #include "WebPreferencesStore.h"
50 #include "WebProcessCreationParameters.h"
51 #include "WebProcessMessages.h"
52 #include "WebProcessProxyMessages.h"
53 #include "WebResourceCacheManager.h"
54 #include <JavaScriptCore/JSLock.h>
55 #include <JavaScriptCore/MemoryStatistics.h>
56 #include <WebCore/AXObjectCache.h>
57 #include <WebCore/ApplicationCacheStorage.h>
58 #include <WebCore/CrossOriginPreflightResultCache.h>
59 #include <WebCore/Font.h>
60 #include <WebCore/FontCache.h>
61 #include <WebCore/Frame.h>
62 #include <WebCore/GCController.h>
63 #include <WebCore/GlyphPageTreeNode.h>
64 #include <WebCore/IconDatabase.h>
65 #include <WebCore/JSDOMWindow.h>
66 #include <WebCore/Language.h>
67 #include <WebCore/Logging.h>
68 #include <WebCore/MemoryCache.h>
69 #include <WebCore/MemoryPressureHandler.h>
70 #include <WebCore/Page.h>
71 #include <WebCore/PageCache.h>
72 #include <WebCore/PageGroup.h>
73 #include <WebCore/ResourceHandle.h>
74 #include <WebCore/RunLoop.h>
75 #include <WebCore/SchemeRegistry.h>
76 #include <WebCore/SecurityOrigin.h>
77 #include <WebCore/Settings.h>
78 #include <WebCore/StorageTracker.h>
79 #include <wtf/HashCountedSet.h>
80 #include <wtf/PassRefPtr.h>
81 #include <wtf/RandomNumber.h>
82
83 #if ENABLE(NETWORK_INFO)
84 #include "WebNetworkInfoManagerMessages.h"
85 #endif
86
87 #if !OS(WINDOWS)
88 #include <unistd.h>
89 #endif
90
91 #if !ENABLE(PLUGIN_PROCESS)
92 #include "NetscapePluginModule.h"
93 #endif
94
95 using namespace JSC;
96 using namespace WebCore;
97
98 namespace WebKit {
99
100 #if OS(WINDOWS)
101 static void sleep(unsigned seconds)
102 {
103     ::Sleep(seconds * 1000);
104 }
105 #endif
106
107 static void randomCrashThread(void*) NO_RETURN_DUE_TO_CRASH;
108 void randomCrashThread(void*)
109 {
110     // This delay was chosen semi-arbitrarily. We want the crash to happen somewhat quickly to
111     // enable useful stress testing, but not so quickly that the web process will always crash soon
112     // after launch.
113     static const unsigned maximumRandomCrashDelay = 180;
114
115     sleep(randomNumber() * maximumRandomCrashDelay);
116     CRASH();
117 }
118
119 static void startRandomCrashThreadIfRequested()
120 {
121     if (!getenv("WEBKIT2_CRASH_WEB_PROCESS_RANDOMLY"))
122         return;
123     createThread(randomCrashThread, 0, "WebKit2: Random Crash Thread");
124 }
125
126 WebProcess& WebProcess::shared()
127 {
128     static WebProcess& process = *new WebProcess;
129     return process;
130 }
131
132 static const double shutdownTimeout = 60;
133
134 WebProcess::WebProcess()
135     : ChildProcess(shutdownTimeout)
136     , m_inDidClose(false)
137     , m_shouldTrackVisitedLinks(true)
138     , m_hasSetCacheModel(false)
139     , m_cacheModel(CacheModelDocumentViewer)
140 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
141     , m_compositingRenderServerPort(MACH_PORT_NULL)
142 #endif
143 #if PLATFORM(MAC)
144     , m_clearResourceCachesDispatchGroup(0)
145 #endif
146     , m_fullKeyboardAccessEnabled(false)
147 #if PLATFORM(QT)
148     , m_networkAccessManager(0)
149 #endif
150     , m_textCheckerState()
151     , m_geolocationManager(this)
152 #if ENABLE(BATTERY_STATUS)
153     , m_batteryManager(this)
154 #endif
155 #if ENABLE(NETWORK_INFO)
156     , m_networkInfoManager(this)
157 #endif
158 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
159     , m_notificationManager(this)
160 #endif
161     , m_iconDatabaseProxy(this)
162 #if ENABLE(PLUGIN_PROCESS)
163     , m_disablePluginProcessMessageTimeout(false)
164 #endif
165 #if USE(SOUP)
166     , m_soupRequestManager(this)
167 #endif
168 {
169 #if USE(PLATFORM_STRATEGIES)
170     // Initialize our platform strategies.
171     WebPlatformStrategies::initialize();
172 #endif // USE(PLATFORM_STRATEGIES)
173
174 #if !LOG_DISABLED
175     WebCore::initializeLoggingChannelsIfNecessary();
176 #endif // !LOG_DISABLED
177 }
178
179 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
180 {
181     ASSERT(!m_connection);
182
183     m_connection = WebConnectionToUIProcess::create(this, serverIdentifier, runLoop);
184
185     m_connection->connection()->addQueueClient(&m_eventDispatcher);
186     m_connection->connection()->addQueueClient(this);
187
188     m_connection->connection()->open();
189     m_runLoop = runLoop;
190
191     startRandomCrashThreadIfRequested();
192 }
193
194 void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::ArgumentDecoder* arguments)
195 {
196     ASSERT(m_pageMap.isEmpty());
197
198     platformInitializeWebProcess(parameters, arguments);
199
200     memoryPressureHandler().install();
201
202     RefPtr<APIObject> injectedBundleInitializationUserData;
203     InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData);
204     if (!arguments->decode(messageDecoder))
205         return;
206
207     if (!parameters.injectedBundlePath.isEmpty()) {
208         m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath);
209         m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle));
210
211         if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) {
212             // Don't keep around the InjectedBundle reference if the load fails.
213             m_injectedBundle.clear();
214         }
215     }
216
217 #if ENABLE(SQL_DATABASE)
218     // Make sure the WebDatabaseManager is initialized so that the Database directory is set.
219     WebDatabaseManager::initialize(parameters.databaseDirectory);
220 #endif
221
222 #if ENABLE(ICONDATABASE)
223     m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled);
224 #endif
225
226     StorageTracker::initializeTracker(parameters.localStorageDirectory, &WebKeyValueStorageManager::shared());
227     m_localStorageDirectory = parameters.localStorageDirectory;
228
229     if (!parameters.applicationCacheDirectory.isEmpty())
230         cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory);
231
232     setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks);
233     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
234
235     if (!parameters.languages.isEmpty())
236         overrideUserPreferredLanguages(parameters.languages);
237
238     m_textCheckerState = parameters.textCheckerState;
239
240     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
241
242     for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i)
243         registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]);
244
245     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i)
246         registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]);
247
248     for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i)
249         setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]);
250
251     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
252
253     for (size_t i = 0; i < parameters.mimeTypesWithCustomRepresentation.size(); ++i)
254         m_mimeTypesWithCustomRepresentations.add(parameters.mimeTypesWithCustomRepresentation[i]);
255     
256 #if PLATFORM(MAC)
257     m_presenterApplicationPid = parameters.presenterApplicationPid;
258 #endif
259
260     if (parameters.shouldAlwaysUseComplexTextCodePath)
261         setAlwaysUsesComplexTextCodePath(true);
262
263     if (parameters.shouldUseFontSmoothing)
264         setShouldUseFontSmoothing(true);
265
266 #if USE(CFURLSTORAGESESSIONS)
267     WebCore::ResourceHandle::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier);
268 #endif
269
270 #if ENABLE(PLUGIN_PROCESS)
271     m_disablePluginProcessMessageTimeout = parameters.disablePluginProcessMessageTimeout;
272 #endif
273 }
274
275 void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
276 {
277     m_shouldTrackVisitedLinks = shouldTrackVisitedLinks;
278     PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks);
279 }
280
281 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
282 {
283     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
284 }
285
286 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
287 {
288     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
289 }
290
291 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
292 {
293     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
294 }
295
296 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
297 {
298     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
299 }
300
301 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
302 {
303     WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto);
304 }
305
306 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
307 {
308     WebCore::Font::setShouldUseSmoothing(useFontSmoothing);
309 }
310
311 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
312 {
313     overrideUserPreferredLanguages(languages);
314 }
315
316 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
317 {
318     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
319 }
320
321 void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle)
322 {
323     RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly);
324     if (!sharedMemory)
325         return;
326
327     m_visitedLinkTable.setSharedMemory(sharedMemory.release());
328 }
329
330 void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes)
331 {
332     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
333     for (size_t i = 0; i < linkHashes.size(); ++i) {
334         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
335         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
336         for (; it != end; ++it)
337             Page::visitedStateChanged(PageGroup::pageGroup(it->second->identifier()), linkHashes[i]);
338     }
339
340     pageCache()->markPagesForVistedLinkStyleRecalc();
341 }
342
343 void WebProcess::allVisitedLinkStateChanged()
344 {
345     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
346     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
347     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
348     for (; it != end; ++it)
349         Page::allVisitedStateChanged(PageGroup::pageGroup(it->second->identifier()));
350
351     pageCache()->markPagesForVistedLinkStyleRecalc();
352 }
353
354 bool WebProcess::isLinkVisited(LinkHash linkHash) const
355 {
356     return m_visitedLinkTable.isLinkVisited(linkHash);
357 }
358
359 void WebProcess::addVisitedLink(WebCore::LinkHash linkHash)
360 {
361     if (isLinkVisited(linkHash) || !m_shouldTrackVisitedLinks)
362         return;
363     connection()->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0);
364 }
365
366 void WebProcess::setCacheModel(uint32_t cm)
367 {
368     CacheModel cacheModel = static_cast<CacheModel>(cm);
369
370     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
371         m_hasSetCacheModel = true;
372         m_cacheModel = cacheModel;
373         platformSetCacheModel(cacheModel);
374     }
375 }
376
377 void WebProcess::calculateCacheSizes(CacheModel cacheModel, uint64_t memorySize, uint64_t diskFreeSize,
378     unsigned& cacheTotalCapacity, unsigned& cacheMinDeadCapacity, unsigned& cacheMaxDeadCapacity, double& deadDecodedDataDeletionInterval,
379     unsigned& pageCacheCapacity, unsigned long& urlCacheMemoryCapacity, unsigned long& urlCacheDiskCapacity)
380 {
381     switch (cacheModel) {
382     case CacheModelDocumentViewer: {
383         // Page cache capacity (in pages)
384         pageCacheCapacity = 0;
385
386         // Object cache capacities (in bytes)
387         if (memorySize >= 2048)
388             cacheTotalCapacity = 96 * 1024 * 1024;
389         else if (memorySize >= 1536)
390             cacheTotalCapacity = 64 * 1024 * 1024;
391         else if (memorySize >= 1024)
392             cacheTotalCapacity = 32 * 1024 * 1024;
393         else if (memorySize >= 512)
394             cacheTotalCapacity = 16 * 1024 * 1024;
395
396         cacheMinDeadCapacity = 0;
397         cacheMaxDeadCapacity = 0;
398
399         // Foundation memory cache capacity (in bytes)
400         urlCacheMemoryCapacity = 0;
401
402         // Foundation disk cache capacity (in bytes)
403         urlCacheDiskCapacity = 0;
404
405         break;
406     }
407     case CacheModelDocumentBrowser: {
408         // Page cache capacity (in pages)
409         if (memorySize >= 1024)
410             pageCacheCapacity = 3;
411         else if (memorySize >= 512)
412             pageCacheCapacity = 2;
413         else if (memorySize >= 256)
414             pageCacheCapacity = 1;
415         else
416             pageCacheCapacity = 0;
417
418         // Object cache capacities (in bytes)
419         if (memorySize >= 2048)
420             cacheTotalCapacity = 96 * 1024 * 1024;
421         else if (memorySize >= 1536)
422             cacheTotalCapacity = 64 * 1024 * 1024;
423         else if (memorySize >= 1024)
424             cacheTotalCapacity = 32 * 1024 * 1024;
425         else if (memorySize >= 512)
426             cacheTotalCapacity = 16 * 1024 * 1024;
427
428         cacheMinDeadCapacity = cacheTotalCapacity / 8;
429         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
430
431         // Foundation memory cache capacity (in bytes)
432         if (memorySize >= 2048)
433             urlCacheMemoryCapacity = 4 * 1024 * 1024;
434         else if (memorySize >= 1024)
435             urlCacheMemoryCapacity = 2 * 1024 * 1024;
436         else if (memorySize >= 512)
437             urlCacheMemoryCapacity = 1 * 1024 * 1024;
438         else
439             urlCacheMemoryCapacity =      512 * 1024; 
440
441         // Foundation disk cache capacity (in bytes)
442         if (diskFreeSize >= 16384)
443             urlCacheDiskCapacity = 50 * 1024 * 1024;
444         else if (diskFreeSize >= 8192)
445             urlCacheDiskCapacity = 40 * 1024 * 1024;
446         else if (diskFreeSize >= 4096)
447             urlCacheDiskCapacity = 30 * 1024 * 1024;
448         else
449             urlCacheDiskCapacity = 20 * 1024 * 1024;
450
451         break;
452     }
453     case CacheModelPrimaryWebBrowser: {
454         // Page cache capacity (in pages)
455         // (Research indicates that value / page drops substantially after 3 pages.)
456         if (memorySize >= 2048)
457             pageCacheCapacity = 5;
458         else if (memorySize >= 1024)
459             pageCacheCapacity = 4;
460         else if (memorySize >= 512)
461             pageCacheCapacity = 3;
462         else if (memorySize >= 256)
463             pageCacheCapacity = 2;
464         else
465             pageCacheCapacity = 1;
466
467         // Object cache capacities (in bytes)
468         // (Testing indicates that value / MB depends heavily on content and
469         // browsing pattern. Even growth above 128MB can have substantial 
470         // value / MB for some content / browsing patterns.)
471         if (memorySize >= 2048)
472             cacheTotalCapacity = 128 * 1024 * 1024;
473         else if (memorySize >= 1536)
474             cacheTotalCapacity = 96 * 1024 * 1024;
475         else if (memorySize >= 1024)
476             cacheTotalCapacity = 64 * 1024 * 1024;
477         else if (memorySize >= 512)
478             cacheTotalCapacity = 32 * 1024 * 1024;
479
480         cacheMinDeadCapacity = cacheTotalCapacity / 4;
481         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
482
483         // This code is here to avoid a PLT regression. We can remove it if we
484         // can prove that the overall system gain would justify the regression.
485         cacheMaxDeadCapacity = std::max(24u, cacheMaxDeadCapacity);
486
487         deadDecodedDataDeletionInterval = 60;
488
489         // Foundation memory cache capacity (in bytes)
490         // (These values are small because WebCore does most caching itself.)
491         if (memorySize >= 1024)
492             urlCacheMemoryCapacity = 4 * 1024 * 1024;
493         else if (memorySize >= 512)
494             urlCacheMemoryCapacity = 2 * 1024 * 1024;
495         else if (memorySize >= 256)
496             urlCacheMemoryCapacity = 1 * 1024 * 1024;
497         else
498             urlCacheMemoryCapacity =      512 * 1024; 
499
500         // Foundation disk cache capacity (in bytes)
501         if (diskFreeSize >= 16384)
502             urlCacheDiskCapacity = 175 * 1024 * 1024;
503         else if (diskFreeSize >= 8192)
504             urlCacheDiskCapacity = 150 * 1024 * 1024;
505         else if (diskFreeSize >= 4096)
506             urlCacheDiskCapacity = 125 * 1024 * 1024;
507         else if (diskFreeSize >= 2048)
508             urlCacheDiskCapacity = 100 * 1024 * 1024;
509         else if (diskFreeSize >= 1024)
510             urlCacheDiskCapacity = 75 * 1024 * 1024;
511         else
512             urlCacheDiskCapacity = 50 * 1024 * 1024;
513
514         break;
515     }
516     default:
517         ASSERT_NOT_REACHED();
518     };
519 }
520
521 WebPage* WebProcess::focusedWebPage() const
522 {    
523     HashMap<uint64_t, RefPtr<WebPage> >::const_iterator end = m_pageMap.end();
524     for (HashMap<uint64_t, RefPtr<WebPage> >::const_iterator it = m_pageMap.begin(); it != end; ++it) {
525         WebPage* page = (*it).second.get();
526         if (page->windowAndWebPageAreFocused())
527             return page;
528     }
529     return 0;
530 }
531     
532 WebPage* WebProcess::webPage(uint64_t pageID) const
533 {
534     return m_pageMap.get(pageID).get();
535 }
536
537 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
538 {
539     // It is necessary to check for page existence here since during a window.open() (or targeted
540     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
541     HashMap<uint64_t, RefPtr<WebPage> >::AddResult result = m_pageMap.add(pageID, 0);
542     if (result.isNewEntry) {
543         ASSERT(!result.iterator->second);
544         result.iterator->second = WebPage::create(pageID, parameters);
545
546         // Balanced by an enableTermination in removeWebPage.
547         disableTermination();
548     }
549
550     ASSERT(result.iterator->second);
551 }
552
553 void WebProcess::removeWebPage(uint64_t pageID)
554 {
555     ASSERT(m_pageMap.contains(pageID));
556
557     m_pageMap.remove(pageID);
558
559     enableTermination();
560 }
561
562 bool WebProcess::isSeparateProcess() const
563 {
564     // If we're running on the main run loop, we assume that we're in a separate process.
565     return m_runLoop == RunLoop::main();
566 }
567  
568 bool WebProcess::shouldTerminate()
569 {
570     // Keep running forever if we're running in the same process.
571     if (!isSeparateProcess())
572         return false;
573
574     ASSERT(m_pageMap.isEmpty());
575     ASSERT(!DownloadManager::shared().isDownloading());
576
577     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
578     bool shouldTerminate = false;
579     if (connection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
580         && !shouldTerminate)
581         return false;
582
583     return true;
584 }
585
586 void WebProcess::terminate()
587 {
588 #ifndef NDEBUG
589     gcController().garbageCollectNow();
590     memoryCache()->setDisabled(true);
591 #endif
592
593     // Invalidate our connection.
594     m_connection->invalidate();
595     m_connection = nullptr;
596
597     platformTerminate();
598     m_runLoop->stop();
599 }
600
601 void WebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
602 {   
603     uint64_t pageID = arguments->destinationID();
604     if (!pageID)
605         return;
606     
607     WebPage* page = webPage(pageID);
608     if (!page)
609         return;
610     
611     page->didReceiveSyncMessage(connection, messageID, arguments, reply);
612 }
613
614 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
615 {
616     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
617         didReceiveWebProcessMessage(connection, messageID, arguments);
618         return;
619     }
620
621     if (messageID.is<CoreIPC::MessageClassAuthenticationManager>()) {
622         AuthenticationManager::shared().didReceiveMessage(connection, messageID, arguments);
623         return;
624     }
625
626     if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManager>()) {
627         WebApplicationCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
628         return;
629     }
630
631     if (messageID.is<CoreIPC::MessageClassWebCookieManager>()) {
632         WebCookieManager::shared().didReceiveMessage(connection, messageID, arguments);
633         return;
634     }
635
636 #if ENABLE(SQL_DATABASE)
637     if (messageID.is<CoreIPC::MessageClassWebDatabaseManager>()) {
638         WebDatabaseManager::shared().didReceiveMessage(connection, messageID, arguments);
639         return;
640     }
641 #endif
642
643     if (messageID.is<CoreIPC::MessageClassWebGeolocationManager>()) {
644         m_geolocationManager.didReceiveMessage(connection, messageID, arguments);
645         return;
646     }
647
648 #if ENABLE(BATTERY_STATUS)
649     if (messageID.is<CoreIPC::MessageClassWebBatteryManager>()) {
650         m_batteryManager.didReceiveMessage(connection, messageID, arguments);
651         return;
652     }
653 #endif
654
655 #if ENABLE(NETWORK_INFO)
656     if (messageID.is<CoreIPC::MessageClassWebNetworkInfoManager>()) {
657         m_networkInfoManager.didReceiveMessage(connection, messageID, arguments);
658         return;
659     }
660 #endif
661
662     if (messageID.is<CoreIPC::MessageClassWebIconDatabaseProxy>()) {
663         m_iconDatabaseProxy.didReceiveMessage(connection, messageID, arguments);
664         return;
665     }
666
667     if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManager>()) {
668         WebKeyValueStorageManager::shared().didReceiveMessage(connection, messageID, arguments);
669         return;
670     }
671
672     if (messageID.is<CoreIPC::MessageClassWebMediaCacheManager>()) {
673         WebMediaCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
674         return;
675     }
676
677 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
678     if (messageID.is<CoreIPC::MessageClassWebNotificationManager>()) {
679         m_notificationManager.didReceiveMessage(connection, messageID, arguments);
680         return;
681     }
682 #endif
683     
684     if (messageID.is<CoreIPC::MessageClassWebResourceCacheManager>()) {
685         WebResourceCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
686         return;
687     }
688
689 #if USE(SOUP)
690     if (messageID.is<CoreIPC::MessageClassWebSoupRequestManager>()) {
691         m_soupRequestManager.didReceiveMessage(connection, messageID, arguments);
692         return;
693     }
694 #endif
695
696     if (messageID.is<CoreIPC::MessageClassInjectedBundle>()) {
697         if (!m_injectedBundle)
698             return;
699         m_injectedBundle->didReceiveMessage(connection, messageID, arguments);    
700         return;
701     }
702
703     uint64_t pageID = arguments->destinationID();
704     if (!pageID)
705         return;
706     
707     WebPage* page = webPage(pageID);
708     if (!page)
709         return;
710     
711     page->didReceiveMessage(connection, messageID, arguments);
712 }
713
714 void WebProcess::didClose(CoreIPC::Connection*)
715 {
716     // When running in the same process the connection will never be closed.
717     ASSERT(isSeparateProcess());
718
719 #ifndef NDEBUG
720     m_inDidClose = true;
721
722     // Close all the live pages.
723     Vector<RefPtr<WebPage> > pages;
724     copyValuesToVector(m_pageMap, pages);
725     for (size_t i = 0; i < pages.size(); ++i)
726         pages[i]->close();
727     pages.clear();
728
729     gcController().garbageCollectSoon();
730     memoryCache()->setDisabled(true);
731 #endif    
732
733     // The UI process closed this connection, shut down.
734     m_runLoop->stop();
735 }
736
737 void WebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
738 {
739     // We received an invalid message, but since this is from the UI process (which we trust),
740     // we'll let it slide.
741 }
742
743 void WebProcess::syncMessageSendTimedOut(CoreIPC::Connection*)
744 {
745 }
746
747 void WebProcess::didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, bool& didHandleMessage)
748 {
749     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
750         didReceiveWebProcessMessageOnConnectionWorkQueue(connection, messageID, arguments, didHandleMessage);
751         return;
752     }
753 }
754
755 WebFrame* WebProcess::webFrame(uint64_t frameID) const
756 {
757     return m_frameMap.get(frameID);
758 }
759
760 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
761 {
762     m_frameMap.set(frameID, frame);
763 }
764
765 void WebProcess::removeWebFrame(uint64_t frameID)
766 {
767     m_frameMap.remove(frameID);
768
769     // We can end up here after our connection has closed when WebCore's frame life-support timer
770     // fires when the application is shutting down. There's no need (and no way) to update the UI
771     // process in this case.
772     if (!m_connection)
773         return;
774
775     connection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
776 }
777
778 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
779 {
780     return m_pageGroupMap.get(pageGroupID).get();
781 }
782
783 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
784 {
785     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::AddResult result = m_pageGroupMap.add(pageGroupData.pageGroupID, 0);
786     if (result.isNewEntry) {
787         ASSERT(!result.iterator->second);
788         result.iterator->second = WebPageGroupProxy::create(pageGroupData);
789     }
790
791     return result.iterator->second.get();
792 }
793
794 static bool canPluginHandleResponse(const ResourceResponse& response)
795 {
796     String pluginPath;
797     bool blocked;
798
799     if (!WebProcess::shared().connection()->sendSync(Messages::WebProcessProxy::GetPluginPath(response.mimeType(), response.url().string()), Messages::WebProcessProxy::GetPluginPath::Reply(pluginPath, blocked), 0))
800         return false;
801
802     return !blocked && !pluginPath.isEmpty();
803 }
804
805 bool WebProcess::shouldUseCustomRepresentationForResponse(const ResourceResponse& response) const
806 {
807     if (!m_mimeTypesWithCustomRepresentations.contains(response.mimeType()))
808         return false;
809
810     // If a plug-in exists that claims to support this response, it should take precedence over the custom representation.
811     return !canPluginHandleResponse(response);
812 }
813
814 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
815 {
816     platformClearResourceCaches(resourceCachesToClear);
817
818     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
819     // FIXME: We need a better way to do this.
820     CacheModel cacheModel = m_cacheModel;
821     setCacheModel(CacheModelDocumentViewer);
822     setCacheModel(cacheModel);
823
824     memoryCache()->evictResources();
825
826     // Empty the cross-origin preflight cache.
827     CrossOriginPreflightResultCache::shared().empty();
828 }
829
830 void WebProcess::clearApplicationCache()
831 {
832     // Empty the application cache.
833     cacheStorage().empty();
834 }
835
836 #if !ENABLE(PLUGIN_PROCESS)
837 void WebProcess::getSitesWithPluginData(const Vector<String>& pluginPaths, uint64_t callbackID)
838 {
839     LocalTerminationDisabler terminationDisabler(*this);
840
841     HashSet<String> sitesSet;
842
843 #if ENABLE(NETSCAPE_PLUGIN_API)
844     for (size_t i = 0; i < pluginPaths.size(); ++i) {
845         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
846         if (!netscapePluginModule)
847             continue;
848
849         Vector<String> sites = netscapePluginModule->sitesWithData();
850         for (size_t i = 0; i < sites.size(); ++i)
851             sitesSet.add(sites[i]);
852     }
853 #endif
854
855     Vector<String> sites;
856     copyToVector(sitesSet, sites);
857
858     connection()->send(Messages::WebProcessProxy::DidGetSitesWithPluginData(sites, callbackID), 0);
859 }
860
861 void WebProcess::clearPluginSiteData(const Vector<String>& pluginPaths, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
862 {
863     LocalTerminationDisabler terminationDisabler(*this);
864
865 #if ENABLE(NETSCAPE_PLUGIN_API)
866     for (size_t i = 0; i < pluginPaths.size(); ++i) {
867         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
868         if (!netscapePluginModule)
869             continue;
870
871         if (sites.isEmpty()) {
872             // Clear everything.
873             netscapePluginModule->clearSiteData(String(), flags, maxAgeInSeconds);
874             continue;
875         }
876
877         for (size_t i = 0; i < sites.size(); ++i)
878             netscapePluginModule->clearSiteData(sites[i], flags, maxAgeInSeconds);
879     }
880 #endif
881
882     connection()->send(Messages::WebProcessProxy::DidClearPluginSiteData(callbackID), 0);
883 }
884 #endif
885     
886 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
887 {
888     TypeCountSet::const_iterator end = countedSet->end();
889     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
890         map.set(it->first, it->second);
891 }
892
893 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t> >& result)
894 {
895     DEFINE_STATIC_LOCAL(String, imagesString, ("Images"));
896     DEFINE_STATIC_LOCAL(String, cssString, ("CSS"));
897     DEFINE_STATIC_LOCAL(String, xslString, ("XSL"));
898     DEFINE_STATIC_LOCAL(String, javaScriptString, ("JavaScript"));
899     
900     MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics();
901     
902     HashMap<String, uint64_t> counts;
903     counts.set(imagesString, memoryCacheStatistics.images.count);
904     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
905     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
906     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
907     result.append(counts);
908     
909     HashMap<String, uint64_t> sizes;
910     sizes.set(imagesString, memoryCacheStatistics.images.size);
911     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
912     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
913     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
914     result.append(sizes);
915     
916     HashMap<String, uint64_t> liveSizes;
917     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
918     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
919     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
920     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
921     result.append(liveSizes);
922     
923     HashMap<String, uint64_t> decodedSizes;
924     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
925     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
926     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
927     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
928     result.append(decodedSizes);
929     
930     HashMap<String, uint64_t> purgeableSizes;
931     purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
932     purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
933     purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
934     purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
935     result.append(purgeableSizes);
936     
937     HashMap<String, uint64_t> purgedSizes;
938     purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
939     purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
940     purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
941     purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
942     result.append(purgedSizes);
943 }
944
945 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
946 {
947     StatisticsData data;
948     
949     // Gather JavaScript statistics.
950     {
951         JSLockHolder lock(JSDOMWindow::commonJSGlobalData());
952         data.statisticsNumbers.set("JavaScriptObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.objectCount());
953         data.statisticsNumbers.set("JavaScriptGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.globalObjectCount());
954         data.statisticsNumbers.set("JavaScriptProtectedObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedObjectCount());
955         data.statisticsNumbers.set("JavaScriptProtectedGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedGlobalObjectCount());
956         
957         OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.protectedObjectTypeCounts());
958         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
959         
960         OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.objectTypeCounts());
961         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
962         
963         uint64_t javaScriptHeapSize = JSDOMWindow::commonJSGlobalData()->heap.size();
964         data.statisticsNumbers.set("JavaScriptHeapSize", javaScriptHeapSize);
965         data.statisticsNumbers.set("JavaScriptFreeSize", JSDOMWindow::commonJSGlobalData()->heap.capacity() - javaScriptHeapSize);
966     }
967
968     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
969     data.statisticsNumbers.set("FastMallocReservedVMBytes", fastMallocStatistics.reservedVMBytes);
970     data.statisticsNumbers.set("FastMallocCommittedVMBytes", fastMallocStatistics.committedVMBytes);
971     data.statisticsNumbers.set("FastMallocFreeListBytes", fastMallocStatistics.freeListBytes);
972     
973     // Gather icon statistics.
974     data.statisticsNumbers.set("IconPageURLMappingCount", iconDatabase().pageURLMappingCount());
975     data.statisticsNumbers.set("IconRetainedPageURLCount", iconDatabase().retainedPageURLCount());
976     data.statisticsNumbers.set("IconRecordCount", iconDatabase().iconRecordCount());
977     data.statisticsNumbers.set("IconsWithDataCount", iconDatabase().iconRecordCountWithData());
978     
979     // Gather font statistics.
980     data.statisticsNumbers.set("CachedFontDataCount", fontCache()->fontDataCount());
981     data.statisticsNumbers.set("CachedFontDataInactiveCount", fontCache()->inactiveFontDataCount());
982     
983     // Gather glyph page statistics.
984 #if !(PLATFORM(QT) && !HAVE(QRAWFONT)) // Qt doesn't use the glyph page tree currently. See: bug 63467.
985     data.statisticsNumbers.set("GlyphPageCount", GlyphPageTreeNode::treeGlyphPageCount());
986 #endif
987     
988     // Get WebCore memory cache statistics
989     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
990     
991     connection()->send(Messages::WebContext::DidGetWebCoreStatistics(data, callbackID), 0);
992 }
993
994 void WebProcess::garbageCollectJavaScriptObjects()
995 {
996     gcController().garbageCollectNow();
997 }
998
999 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1000 {
1001     gcController().setJavaScriptGarbageCollectorTimerEnabled(flag);
1002 }
1003
1004 #if ENABLE(PLUGIN_PROCESS)
1005 void WebProcess::pluginProcessCrashed(CoreIPC::Connection*, const String& pluginPath)
1006 {
1007     m_pluginProcessConnectionManager.pluginProcessCrashed(pluginPath);
1008 }
1009 #endif
1010
1011 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1012 {
1013     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1014
1015     ResourceRequest requestWithOriginalURL = request;
1016     if (initiatingPage)
1017         initiatingPage->mainFrame()->loader()->setOriginalURLForDownloadRequest(requestWithOriginalURL);
1018
1019     DownloadManager::shared().startDownload(downloadID, initiatingPage, requestWithOriginalURL);
1020 }
1021
1022 void WebProcess::cancelDownload(uint64_t downloadID)
1023 {
1024     DownloadManager::shared().cancelDownload(downloadID);
1025 }
1026
1027 #if PLATFORM(QT)
1028 void WebProcess::startTransfer(uint64_t downloadID, const String& destination)
1029 {
1030     DownloadManager::shared().startTransfer(downloadID, destination);
1031 }
1032 #endif
1033
1034 void WebProcess::setEnhancedAccessibility(bool flag)
1035 {
1036     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1037 }
1038     
1039 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1040 {
1041 #if ENABLE(MEMORY_SAMPLER)    
1042     WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1043 #endif
1044 }
1045     
1046 void WebProcess::stopMemorySampler()
1047 {
1048 #if ENABLE(MEMORY_SAMPLER)
1049     WebMemorySampler::shared()->stop();
1050 #endif
1051 }
1052
1053 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1054 {
1055     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1056     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1057
1058     m_textCheckerState = textCheckerState;
1059
1060     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1061         return;
1062
1063     HashMap<uint64_t, RefPtr<WebPage> >::iterator end = m_pageMap.end();
1064     for (HashMap<uint64_t, RefPtr<WebPage> >::iterator it = m_pageMap.begin(); it != end; ++it) {
1065         WebPage* page = (*it).second.get();
1066         if (continuousSpellCheckingTurnedOff)
1067             page->unmarkAllMisspellings();
1068         if (grammarCheckingTurnedOff)
1069             page->unmarkAllBadGrammar();
1070     }
1071 }
1072
1073 void WebProcess::didGetPlugins(CoreIPC::Connection*, uint64_t requestID, const Vector<WebCore::PluginInfo>& plugins)
1074 {
1075 #if USE(PLATFORM_STRATEGIES)
1076     // Pass this to WebPlatformStrategies.cpp.
1077     handleDidGetPlugins(requestID, plugins);
1078 #endif
1079 }
1080
1081 } // namespace WebKit