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