[WebKit2] Add the ability to send messages to the WebPageGroupProxy
[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     if (messageID.is<CoreIPC::MessageClassWebPageGroupProxy>()) {
713         uint64_t pageGroupID = arguments->destinationID();
714         if (!pageGroupID)
715             return;
716         
717         WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
718         if (!pageGroupProxy)
719             return;
720         
721         pageGroupProxy->didReceiveMessage(connection, messageID, arguments);
722     }
723
724     uint64_t pageID = arguments->destinationID();
725     if (!pageID)
726         return;
727     
728     WebPage* page = webPage(pageID);
729     if (!page)
730         return;
731     
732     page->didReceiveMessage(connection, messageID, arguments);
733 }
734
735 void WebProcess::didClose(CoreIPC::Connection*)
736 {
737     // When running in the same process the connection will never be closed.
738     ASSERT(isSeparateProcess());
739
740 #ifndef NDEBUG
741     m_inDidClose = true;
742
743     // Close all the live pages.
744     Vector<RefPtr<WebPage> > pages;
745     copyValuesToVector(m_pageMap, pages);
746     for (size_t i = 0; i < pages.size(); ++i)
747         pages[i]->close();
748     pages.clear();
749
750     gcController().garbageCollectSoon();
751     memoryCache()->setDisabled(true);
752 #endif    
753
754     // The UI process closed this connection, shut down.
755     m_runLoop->stop();
756 }
757
758 void WebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
759 {
760     // We received an invalid message, but since this is from the UI process (which we trust),
761     // we'll let it slide.
762 }
763
764 void WebProcess::syncMessageSendTimedOut(CoreIPC::Connection*)
765 {
766 }
767
768 void WebProcess::didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, bool& didHandleMessage)
769 {
770     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
771         didReceiveWebProcessMessageOnConnectionWorkQueue(connection, messageID, arguments, didHandleMessage);
772         return;
773     }
774 }
775
776 WebFrame* WebProcess::webFrame(uint64_t frameID) const
777 {
778     return m_frameMap.get(frameID);
779 }
780
781 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
782 {
783     m_frameMap.set(frameID, frame);
784 }
785
786 void WebProcess::removeWebFrame(uint64_t frameID)
787 {
788     m_frameMap.remove(frameID);
789
790     // We can end up here after our connection has closed when WebCore's frame life-support timer
791     // fires when the application is shutting down. There's no need (and no way) to update the UI
792     // process in this case.
793     if (!m_connection)
794         return;
795
796     connection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
797 }
798
799 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
800 {
801     return m_pageGroupMap.get(pageGroupID).get();
802 }
803
804 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
805 {
806     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::AddResult result = m_pageGroupMap.add(pageGroupData.pageGroupID, 0);
807     if (result.isNewEntry) {
808         ASSERT(!result.iterator->second);
809         result.iterator->second = WebPageGroupProxy::create(pageGroupData);
810     }
811
812     return result.iterator->second.get();
813 }
814
815 #if ENABLE(WEB_INTENTS)
816 uint64_t WebProcess::addMessagePortChannel(PassRefPtr<PlatformMessagePortChannel> messagePortChannel)
817 {
818     static uint64_t channelID = 0;
819     m_messagePortChannels.add(++channelID, messagePortChannel);
820
821     return channelID;
822 }
823
824 PlatformMessagePortChannel* WebProcess::messagePortChannel(uint64_t channelID)
825 {
826     return m_messagePortChannels.get(channelID).get();
827 }
828
829 void WebProcess::removeMessagePortChannel(uint64_t channelID)
830 {
831     m_messagePortChannels.remove(channelID);
832 }
833 #endif
834
835 static bool canPluginHandleResponse(const ResourceResponse& response)
836 {
837     String pluginPath;
838     bool blocked;
839
840     if (!WebProcess::shared().connection()->sendSync(Messages::WebProcessProxy::GetPluginPath(response.mimeType(), response.url().string()), Messages::WebProcessProxy::GetPluginPath::Reply(pluginPath, blocked), 0))
841         return false;
842
843     return !blocked && !pluginPath.isEmpty();
844 }
845
846 bool WebProcess::shouldUseCustomRepresentationForResponse(const ResourceResponse& response) const
847 {
848     if (!m_mimeTypesWithCustomRepresentations.contains(response.mimeType()))
849         return false;
850
851     // If a plug-in exists that claims to support this response, it should take precedence over the custom representation.
852     return !canPluginHandleResponse(response);
853 }
854
855 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
856 {
857     platformClearResourceCaches(resourceCachesToClear);
858
859     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
860     // FIXME: We need a better way to do this.
861     CacheModel cacheModel = m_cacheModel;
862     setCacheModel(CacheModelDocumentViewer);
863     setCacheModel(cacheModel);
864
865     memoryCache()->evictResources();
866
867     // Empty the cross-origin preflight cache.
868     CrossOriginPreflightResultCache::shared().empty();
869 }
870
871 void WebProcess::clearApplicationCache()
872 {
873     // Empty the application cache.
874     cacheStorage().empty();
875 }
876
877 #if !ENABLE(PLUGIN_PROCESS)
878 void WebProcess::getSitesWithPluginData(const Vector<String>& pluginPaths, uint64_t callbackID)
879 {
880     LocalTerminationDisabler terminationDisabler(*this);
881
882     HashSet<String> sitesSet;
883
884 #if ENABLE(NETSCAPE_PLUGIN_API)
885     for (size_t i = 0; i < pluginPaths.size(); ++i) {
886         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
887         if (!netscapePluginModule)
888             continue;
889
890         Vector<String> sites = netscapePluginModule->sitesWithData();
891         for (size_t i = 0; i < sites.size(); ++i)
892             sitesSet.add(sites[i]);
893     }
894 #else
895     UNUSED_PARAM(pluginPaths);
896 #endif
897
898     Vector<String> sites;
899     copyToVector(sitesSet, sites);
900
901     connection()->send(Messages::WebProcessProxy::DidGetSitesWithPluginData(sites, callbackID), 0);
902 }
903
904 void WebProcess::clearPluginSiteData(const Vector<String>& pluginPaths, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
905 {
906     LocalTerminationDisabler terminationDisabler(*this);
907
908 #if ENABLE(NETSCAPE_PLUGIN_API)
909     for (size_t i = 0; i < pluginPaths.size(); ++i) {
910         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
911         if (!netscapePluginModule)
912             continue;
913
914         if (sites.isEmpty()) {
915             // Clear everything.
916             netscapePluginModule->clearSiteData(String(), flags, maxAgeInSeconds);
917             continue;
918         }
919
920         for (size_t i = 0; i < sites.size(); ++i)
921             netscapePluginModule->clearSiteData(sites[i], flags, maxAgeInSeconds);
922     }
923 #else
924     UNUSED_PARAM(pluginPaths);
925     UNUSED_PARAM(sites);
926     UNUSED_PARAM(flags);
927     UNUSED_PARAM(maxAgeInSeconds);
928 #endif
929
930     connection()->send(Messages::WebProcessProxy::DidClearPluginSiteData(callbackID), 0);
931 }
932 #endif
933     
934 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
935 {
936     TypeCountSet::const_iterator end = countedSet->end();
937     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
938         map.set(it->first, it->second);
939 }
940
941 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t> >& result)
942 {
943     DEFINE_STATIC_LOCAL(String, imagesString, (ASCIILiteral("Images")));
944     DEFINE_STATIC_LOCAL(String, cssString, (ASCIILiteral("CSS")));
945     DEFINE_STATIC_LOCAL(String, xslString, (ASCIILiteral("XSL")));
946     DEFINE_STATIC_LOCAL(String, javaScriptString, (ASCIILiteral("JavaScript")));
947     
948     MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics();
949     
950     HashMap<String, uint64_t> counts;
951     counts.set(imagesString, memoryCacheStatistics.images.count);
952     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
953     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
954     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
955     result.append(counts);
956     
957     HashMap<String, uint64_t> sizes;
958     sizes.set(imagesString, memoryCacheStatistics.images.size);
959     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
960     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
961     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
962     result.append(sizes);
963     
964     HashMap<String, uint64_t> liveSizes;
965     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
966     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
967     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
968     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
969     result.append(liveSizes);
970     
971     HashMap<String, uint64_t> decodedSizes;
972     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
973     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
974     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
975     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
976     result.append(decodedSizes);
977     
978     HashMap<String, uint64_t> purgeableSizes;
979     purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
980     purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
981     purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
982     purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
983     result.append(purgeableSizes);
984     
985     HashMap<String, uint64_t> purgedSizes;
986     purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
987     purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
988     purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
989     purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
990     result.append(purgedSizes);
991 }
992
993 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
994 {
995     StatisticsData data;
996     
997     // Gather JavaScript statistics.
998     {
999         JSLockHolder lock(JSDOMWindow::commonJSGlobalData());
1000         data.statisticsNumbers.set("JavaScriptObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.objectCount());
1001         data.statisticsNumbers.set("JavaScriptGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.globalObjectCount());
1002         data.statisticsNumbers.set("JavaScriptProtectedObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedObjectCount());
1003         data.statisticsNumbers.set("JavaScriptProtectedGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedGlobalObjectCount());
1004         
1005         OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.protectedObjectTypeCounts());
1006         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
1007         
1008         OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.objectTypeCounts());
1009         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
1010         
1011         uint64_t javaScriptHeapSize = JSDOMWindow::commonJSGlobalData()->heap.size();
1012         data.statisticsNumbers.set("JavaScriptHeapSize", javaScriptHeapSize);
1013         data.statisticsNumbers.set("JavaScriptFreeSize", JSDOMWindow::commonJSGlobalData()->heap.capacity() - javaScriptHeapSize);
1014     }
1015
1016     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
1017     data.statisticsNumbers.set("FastMallocReservedVMBytes", fastMallocStatistics.reservedVMBytes);
1018     data.statisticsNumbers.set("FastMallocCommittedVMBytes", fastMallocStatistics.committedVMBytes);
1019     data.statisticsNumbers.set("FastMallocFreeListBytes", fastMallocStatistics.freeListBytes);
1020     
1021     // Gather icon statistics.
1022     data.statisticsNumbers.set("IconPageURLMappingCount", iconDatabase().pageURLMappingCount());
1023     data.statisticsNumbers.set("IconRetainedPageURLCount", iconDatabase().retainedPageURLCount());
1024     data.statisticsNumbers.set("IconRecordCount", iconDatabase().iconRecordCount());
1025     data.statisticsNumbers.set("IconsWithDataCount", iconDatabase().iconRecordCountWithData());
1026     
1027     // Gather font statistics.
1028     data.statisticsNumbers.set("CachedFontDataCount", fontCache()->fontDataCount());
1029     data.statisticsNumbers.set("CachedFontDataInactiveCount", fontCache()->inactiveFontDataCount());
1030     
1031     // Gather glyph page statistics.
1032     data.statisticsNumbers.set("GlyphPageCount", GlyphPageTreeNode::treeGlyphPageCount());
1033     
1034     // Get WebCore memory cache statistics
1035     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1036     
1037     connection()->send(Messages::WebContext::DidGetWebCoreStatistics(data, callbackID), 0);
1038 }
1039
1040 void WebProcess::garbageCollectJavaScriptObjects()
1041 {
1042     gcController().garbageCollectNow();
1043 }
1044
1045 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1046 {
1047     gcController().setJavaScriptGarbageCollectorTimerEnabled(flag);
1048 }
1049
1050 #if ENABLE(PLUGIN_PROCESS)
1051 void WebProcess::pluginProcessCrashed(CoreIPC::Connection*, const String& pluginPath)
1052 {
1053     m_pluginProcessConnectionManager.pluginProcessCrashed(pluginPath);
1054 }
1055 #endif
1056
1057 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1058 {
1059     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1060
1061     ResourceRequest requestWithOriginalURL = request;
1062     if (initiatingPage)
1063         initiatingPage->mainFrame()->loader()->setOriginalURLForDownloadRequest(requestWithOriginalURL);
1064
1065     DownloadManager::shared().startDownload(downloadID, initiatingPage, requestWithOriginalURL);
1066 }
1067
1068 void WebProcess::cancelDownload(uint64_t downloadID)
1069 {
1070     DownloadManager::shared().cancelDownload(downloadID);
1071 }
1072
1073 #if PLATFORM(QT)
1074 void WebProcess::startTransfer(uint64_t downloadID, const String& destination)
1075 {
1076     DownloadManager::shared().startTransfer(downloadID, destination);
1077 }
1078 #endif
1079
1080 void WebProcess::setEnhancedAccessibility(bool flag)
1081 {
1082     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1083 }
1084     
1085 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1086 {
1087 #if ENABLE(MEMORY_SAMPLER)    
1088     WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1089 #endif
1090 }
1091     
1092 void WebProcess::stopMemorySampler()
1093 {
1094 #if ENABLE(MEMORY_SAMPLER)
1095     WebMemorySampler::shared()->stop();
1096 #endif
1097 }
1098
1099 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1100 {
1101     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1102     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1103
1104     m_textCheckerState = textCheckerState;
1105
1106     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1107         return;
1108
1109     HashMap<uint64_t, RefPtr<WebPage> >::iterator end = m_pageMap.end();
1110     for (HashMap<uint64_t, RefPtr<WebPage> >::iterator it = m_pageMap.begin(); it != end; ++it) {
1111         WebPage* page = (*it).second.get();
1112         if (continuousSpellCheckingTurnedOff)
1113             page->unmarkAllMisspellings();
1114         if (grammarCheckingTurnedOff)
1115             page->unmarkAllBadGrammar();
1116     }
1117 }
1118
1119 void WebProcess::didGetPlugins(CoreIPC::Connection*, uint64_t requestID, const Vector<WebCore::PluginInfo>& plugins)
1120 {
1121 #if USE(PLATFORM_STRATEGIES)
1122     // Pass this to WebPlatformStrategies.cpp.
1123     handleDidGetPlugins(requestID, plugins);
1124 #endif
1125 }
1126
1127 } // namespace WebKit