Remove the unneeded NetworkProcessCrashed message
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebProcess.h"
28
29 #include "DownloadManager.h"
30 #include "InjectedBundle.h"
31 #include "InjectedBundleUserMessageCoders.h"
32 #include "Logging.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 "WebFrameNetworkingContext.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/InitializeLogging.h>
66 #include <WebCore/JSDOMWindow.h>
67 #include <WebCore/Language.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(WEB_INTENTS)
84 #include <WebCore/PlatformMessagePortChannel.h>
85 #endif
86
87 #if ENABLE(NETWORK_INFO)
88 #include "WebNetworkInfoManagerMessages.h"
89 #endif
90
91 #if ENABLE(NETWORK_PROCESS)
92 #include "NetworkProcessConnection.h"
93 #endif
94
95 #if !OS(WINDOWS)
96 #include <unistd.h>
97 #endif
98
99 #if !ENABLE(PLUGIN_PROCESS)
100 #include "NetscapePluginModule.h"
101 #endif
102
103 #if ENABLE(CUSTOM_PROTOCOLS)
104 #include "CustomProtocolManager.h"
105 #endif
106
107 using namespace JSC;
108 using namespace WebCore;
109
110 namespace WebKit {
111
112 #if OS(WINDOWS)
113 static void sleep(unsigned seconds)
114 {
115     ::Sleep(seconds * 1000);
116 }
117 #endif
118
119 static void randomCrashThread(void*) NO_RETURN_DUE_TO_CRASH;
120 void randomCrashThread(void*)
121 {
122     // This delay was chosen semi-arbitrarily. We want the crash to happen somewhat quickly to
123     // enable useful stress testing, but not so quickly that the web process will always crash soon
124     // after launch.
125     static const unsigned maximumRandomCrashDelay = 180;
126
127     sleep(randomNumber() * maximumRandomCrashDelay);
128     CRASH();
129 }
130
131 static void startRandomCrashThreadIfRequested()
132 {
133     if (!getenv("WEBKIT2_CRASH_WEB_PROCESS_RANDOMLY"))
134         return;
135     createThread(randomCrashThread, 0, "WebKit2: Random Crash Thread");
136 }
137
138 WebProcess& WebProcess::shared()
139 {
140     static WebProcess& process = *new WebProcess;
141     return process;
142 }
143
144 WebProcess::WebProcess()
145     : m_inDidClose(false)
146     , m_shouldTrackVisitedLinks(true)
147     , m_hasSetCacheModel(false)
148     , m_cacheModel(CacheModelDocumentViewer)
149 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
150     , m_compositingRenderServerPort(MACH_PORT_NULL)
151 #endif
152 #if PLATFORM(MAC)
153     , m_clearResourceCachesDispatchGroup(0)
154 #endif
155     , m_fullKeyboardAccessEnabled(false)
156 #if PLATFORM(QT)
157     , m_networkAccessManager(0)
158 #endif
159     , m_textCheckerState()
160     , m_geolocationManager(this)
161 #if ENABLE(BATTERY_STATUS)
162     , m_batteryManager(this)
163 #endif
164 #if ENABLE(NETWORK_INFO)
165     , m_networkInfoManager(this)
166 #endif
167 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
168     , m_notificationManager(this)
169 #endif
170     , m_iconDatabaseProxy(this)
171 #if ENABLE(NETWORK_PROCESS)
172     , m_usesNetworkProcess(false)
173 #endif
174 #if USE(SOUP)
175     , m_soupRequestManager(this)
176 #endif
177 {
178 #if USE(PLATFORM_STRATEGIES)
179     // Initialize our platform strategies.
180     WebPlatformStrategies::initialize();
181 #endif // USE(PLATFORM_STRATEGIES)
182
183 #if !LOG_DISABLED
184     WebCore::initializeLoggingChannelsIfNecessary();
185     WebKit::initializeLogChannelsIfNecessary();
186 #endif // !LOG_DISABLED
187 }
188
189 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
190 {
191     ASSERT(!m_connection);
192
193     m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop);
194     m_connection->setDidCloseOnConnectionWorkQueueCallback(ChildProcess::didCloseOnConnectionWorkQueue);
195     m_connection->setShouldExitOnSyncMessageSendFailure(true);
196     m_connection->addQueueClient(&m_eventDispatcher);
197     m_connection->addQueueClient(this);
198     m_connection->open();
199
200     m_webConnection = WebConnectionToUIProcess::create(this);
201
202     m_runLoop = runLoop;
203
204     startRandomCrashThreadIfRequested();
205 }
206
207 void WebProcess::addMessageReceiver(CoreIPC::StringReference messageReceiverName, CoreIPC::MessageReceiver* messageReceiver)
208 {
209     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
210 }
211
212 void WebProcess::addMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID, CoreIPC::MessageReceiver* messageReceiver)
213 {
214     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
215 }
216
217 void WebProcess::removeMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID)
218 {
219     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
220 }
221
222 void WebProcess::didCreateDownload()
223 {
224     disableTermination();
225 }
226
227 void WebProcess::didDestroyDownload()
228 {
229     enableTermination();
230 }
231
232 void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::MessageDecoder& decoder)
233 {
234     ASSERT(m_pageMap.isEmpty());
235
236     platformInitializeWebProcess(parameters, decoder);
237
238     memoryPressureHandler().install();
239
240     RefPtr<APIObject> injectedBundleInitializationUserData;
241     InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData);
242     if (!decoder.decode(messageDecoder))
243         return;
244
245     if (!parameters.injectedBundlePath.isEmpty()) {
246         m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath);
247         m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle));
248
249         if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) {
250             // Don't keep around the InjectedBundle reference if the load fails.
251             m_injectedBundle.clear();
252         }
253     }
254
255 #if ENABLE(SQL_DATABASE)
256     // Make sure the WebDatabaseManager is initialized so that the Database directory is set.
257     WebDatabaseManager::initialize(parameters.databaseDirectory);
258 #endif
259
260 #if ENABLE(ICONDATABASE)
261     m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled);
262 #endif
263
264     StorageTracker::initializeTracker(parameters.localStorageDirectory, &WebKeyValueStorageManager::shared());
265     m_localStorageDirectory = parameters.localStorageDirectory;
266
267     if (!parameters.applicationCacheDirectory.isEmpty())
268         cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory);
269
270     setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks);
271     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
272
273     if (!parameters.languages.isEmpty())
274         overrideUserPreferredLanguages(parameters.languages);
275
276     m_textCheckerState = parameters.textCheckerState;
277
278     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
279
280     for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i)
281         registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]);
282
283     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i)
284         registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]);
285
286     for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i)
287         setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]);
288
289     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsLocal.size(); ++i)
290         registerURLSchemeAsLocal(parameters.urlSchemesRegisteredAsLocal[i]);
291
292     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsNoAccess.size(); ++i)
293         registerURLSchemeAsNoAccess(parameters.urlSchemesRegisteredAsNoAccess[i]);
294
295     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsDisplayIsolated.size(); ++i)
296         registerURLSchemeAsDisplayIsolated(parameters.urlSchemesRegisteredAsDisplayIsolated[i]);
297
298     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsCORSEnabled.size(); ++i)
299         registerURLSchemeAsCORSEnabled(parameters.urlSchemesRegisteredAsCORSEnabled[i]);
300
301     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
302
303     if (parameters.shouldAlwaysUseComplexTextCodePath)
304         setAlwaysUsesComplexTextCodePath(true);
305
306     if (parameters.shouldUseFontSmoothing)
307         setShouldUseFontSmoothing(true);
308
309 #if (PLATFORM(MAC) || USE(CFNETWORK)) && !PLATFORM(WIN)
310     WebFrameNetworkingContext::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier);
311 #endif
312
313 #if ENABLE(NETWORK_PROCESS)
314     m_usesNetworkProcess = parameters.usesNetworkProcess;
315     ensureNetworkProcessConnection();
316 #endif
317     setTerminationTimeout(parameters.terminationTimeout);
318
319     for (size_t i = 0; i < parameters.plugInAutoStartOrigins.size(); ++i)
320         didAddPlugInAutoStartOrigin(parameters.plugInAutoStartOrigins[i]);
321 }
322
323 #if ENABLE(NETWORK_PROCESS)
324 void WebProcess::ensureNetworkProcessConnection()
325 {
326     if (!m_usesNetworkProcess)
327         return;
328
329     if (m_networkProcessConnection)
330         return;
331
332     CoreIPC::Attachment encodedConnectionIdentifier;
333
334     if (!connection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
335         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
336         return;
337
338 #if PLATFORM(MAC)
339     CoreIPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
340     if (CoreIPC::Connection::identifierIsNull(connectionIdentifier))
341         return;
342 #else
343     ASSERT_NOT_REACHED();
344 #endif
345     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
346 }
347 #endif // ENABLE(NETWORK_PROCESS)
348
349 void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
350 {
351     m_shouldTrackVisitedLinks = shouldTrackVisitedLinks;
352     PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks);
353 }
354
355 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
356 {
357     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
358 }
359
360 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
361 {
362     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
363 }
364
365 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
366 {
367     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
368 }
369
370 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
371 {
372     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
373 }
374
375 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
376 {
377     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
378 }
379
380 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
381 {
382     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
383 }
384
385 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
386 {
387     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
388 }
389
390 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
391 {
392     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
393 }
394
395 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
396 {
397     WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto);
398 }
399
400 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
401 {
402     WebCore::Font::setShouldUseSmoothing(useFontSmoothing);
403 }
404
405 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
406 {
407     overrideUserPreferredLanguages(languages);
408     languageDidChange();
409 }
410
411 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
412 {
413     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
414 }
415
416 void WebProcess::ensurePrivateBrowsingSession()
417 {
418 #if (PLATFORM(MAC) || USE(CFNETWORK)) && !PLATFORM(WIN)
419     WebFrameNetworkingContext::ensurePrivateBrowsingSession();
420 #endif
421 }
422
423 void WebProcess::destroyPrivateBrowsingSession()
424 {
425 #if (PLATFORM(MAC) || USE(CFNETWORK)) && !PLATFORM(WIN)
426     WebFrameNetworkingContext::destroyPrivateBrowsingSession();
427 #endif
428 }
429
430 DownloadManager& WebProcess::downloadManager()
431 {
432 #if ENABLE(NETWORK_PROCESS)
433     ASSERT(!m_usesNetworkProcess);
434 #endif
435
436     DEFINE_STATIC_LOCAL(DownloadManager, downloadManager, (this));
437     return downloadManager;
438 }
439
440 void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle)
441 {
442     RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly);
443     if (!sharedMemory)
444         return;
445
446     m_visitedLinkTable.setSharedMemory(sharedMemory.release());
447 }
448
449 void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes)
450 {
451     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
452     for (size_t i = 0; i < linkHashes.size(); ++i) {
453         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
454         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
455         for (; it != end; ++it)
456             Page::visitedStateChanged(PageGroup::pageGroup(it->value->identifier()), linkHashes[i]);
457     }
458
459     pageCache()->markPagesForVistedLinkStyleRecalc();
460 }
461
462 void WebProcess::allVisitedLinkStateChanged()
463 {
464     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
465     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
466     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
467     for (; it != end; ++it)
468         Page::allVisitedStateChanged(PageGroup::pageGroup(it->value->identifier()));
469
470     pageCache()->markPagesForVistedLinkStyleRecalc();
471 }
472
473 bool WebProcess::isLinkVisited(LinkHash linkHash) const
474 {
475     return m_visitedLinkTable.isLinkVisited(linkHash);
476 }
477
478 void WebProcess::addVisitedLink(WebCore::LinkHash linkHash)
479 {
480     if (isLinkVisited(linkHash) || !m_shouldTrackVisitedLinks)
481         return;
482     connection()->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0);
483 }
484
485 void WebProcess::setCacheModel(uint32_t cm)
486 {
487     CacheModel cacheModel = static_cast<CacheModel>(cm);
488
489     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
490         m_hasSetCacheModel = true;
491         m_cacheModel = cacheModel;
492         platformSetCacheModel(cacheModel);
493     }
494 }
495
496 WebPage* WebProcess::focusedWebPage() const
497 {    
498     HashMap<uint64_t, RefPtr<WebPage> >::const_iterator end = m_pageMap.end();
499     for (HashMap<uint64_t, RefPtr<WebPage> >::const_iterator it = m_pageMap.begin(); it != end; ++it) {
500         WebPage* page = (*it).value.get();
501         if (page->windowAndWebPageAreFocused())
502             return page;
503     }
504     return 0;
505 }
506     
507 WebPage* WebProcess::webPage(uint64_t pageID) const
508 {
509     return m_pageMap.get(pageID).get();
510 }
511
512 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
513 {
514     // It is necessary to check for page existence here since during a window.open() (or targeted
515     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
516     HashMap<uint64_t, RefPtr<WebPage> >::AddResult result = m_pageMap.add(pageID, 0);
517     if (result.isNewEntry) {
518         ASSERT(!result.iterator->value);
519         result.iterator->value = WebPage::create(pageID, parameters);
520
521         // Balanced by an enableTermination in removeWebPage.
522         disableTermination();
523     }
524
525     ASSERT(result.iterator->value);
526 }
527
528 void WebProcess::removeWebPage(uint64_t pageID)
529 {
530     ASSERT(m_pageMap.contains(pageID));
531
532     m_pageMap.remove(pageID);
533
534     enableTermination();
535 }
536
537 bool WebProcess::isSeparateProcess() const
538 {
539     // If we're running on the main run loop, we assume that we're in a separate process.
540     return m_runLoop == RunLoop::main();
541 }
542  
543 bool WebProcess::shouldTerminate()
544 {
545     // Keep running forever if we're running in the same process.
546     if (!isSeparateProcess())
547         return false;
548
549     ASSERT(m_pageMap.isEmpty());
550
551 #if ENABLE(NETWORK_PROCESS)
552     ASSERT(m_usesNetworkProcess || !downloadManager().isDownloading());
553 #else
554     ASSERT(!downloadManager().isDownloading());
555 #endif
556
557     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
558     bool shouldTerminate = false;
559     if (connection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
560         && !shouldTerminate)
561         return false;
562
563     return true;
564 }
565
566 void WebProcess::terminate()
567 {
568 #ifndef NDEBUG
569     gcController().garbageCollectNow();
570     memoryCache()->setDisabled(true);
571 #endif
572
573     // Invalidate our connection.
574     m_connection->invalidate();
575     m_connection = nullptr;
576
577     m_webConnection->invalidate();
578     m_webConnection = nullptr;
579
580     platformTerminate();
581     m_runLoop->stop();
582 }
583
584 void WebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
585 {
586     m_messageReceiverMap.dispatchSyncMessage(connection, messageID, decoder, replyEncoder);
587         return;
588 }
589
590 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
591 {
592     if (m_messageReceiverMap.dispatchMessage(connection, messageID, decoder))
593         return;
594
595     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
596         didReceiveWebProcessMessage(connection, messageID, decoder);
597         return;
598     }
599
600     if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManager>()) {
601         WebApplicationCacheManager::shared().didReceiveMessage(connection, messageID, decoder);
602         return;
603     }
604
605     if (messageID.is<CoreIPC::MessageClassWebCookieManager>()) {
606         WebCookieManager::shared().didReceiveMessage(connection, messageID, decoder);
607         return;
608     }
609
610 #if ENABLE(SQL_DATABASE)
611     if (messageID.is<CoreIPC::MessageClassWebDatabaseManager>()) {
612         WebDatabaseManager::shared().didReceiveMessage(connection, messageID, decoder);
613         return;
614     }
615 #endif
616
617     if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManager>()) {
618         WebKeyValueStorageManager::shared().didReceiveMessage(connection, messageID, decoder);
619         return;
620     }
621
622     if (messageID.is<CoreIPC::MessageClassWebMediaCacheManager>()) {
623         WebMediaCacheManager::shared().didReceiveMessage(connection, messageID, decoder);
624         return;
625     }
626     
627     if (messageID.is<CoreIPC::MessageClassWebResourceCacheManager>()) {
628         WebResourceCacheManager::shared().didReceiveMessage(connection, messageID, decoder);
629         return;
630     }
631     
632 #if ENABLE(CUSTOM_PROTOCOLS)
633     if (messageID.is<CoreIPC::MessageClassCustomProtocolManager>()) {
634         CustomProtocolManager::shared().didReceiveMessage(connection, messageID, decoder);
635         return;
636     }
637 #endif
638
639     if (messageID.is<CoreIPC::MessageClassWebPageGroupProxy>()) {
640         uint64_t pageGroupID = decoder.destinationID();
641         if (!pageGroupID)
642             return;
643         
644         WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
645         if (!pageGroupProxy)
646             return;
647         
648         pageGroupProxy->didReceiveMessage(connection, messageID, decoder);
649     }
650 }
651
652 void WebProcess::didClose(CoreIPC::Connection*)
653 {
654     // When running in the same process the connection will never be closed.
655     ASSERT(isSeparateProcess());
656
657 #ifndef NDEBUG
658     m_inDidClose = true;
659
660     // Close all the live pages.
661     Vector<RefPtr<WebPage> > pages;
662     copyValuesToVector(m_pageMap, pages);
663     for (size_t i = 0; i < pages.size(); ++i)
664         pages[i]->close();
665     pages.clear();
666
667     gcController().garbageCollectSoon();
668     memoryCache()->setDisabled(true);
669 #endif    
670
671     // The UI process closed this connection, shut down.
672     m_runLoop->stop();
673 }
674
675 void WebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference, CoreIPC::StringReference)
676 {
677     // We received an invalid message, but since this is from the UI process (which we trust),
678     // we'll let it slide.
679 }
680
681 void WebProcess::didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, bool& didHandleMessage)
682 {
683     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
684         didReceiveWebProcessMessageOnConnectionWorkQueue(connection, messageID, decoder, didHandleMessage);
685         return;
686     }
687 }
688
689 WebFrame* WebProcess::webFrame(uint64_t frameID) const
690 {
691     return m_frameMap.get(frameID);
692 }
693
694 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
695 {
696     m_frameMap.set(frameID, frame);
697 }
698
699 void WebProcess::removeWebFrame(uint64_t frameID)
700 {
701     m_frameMap.remove(frameID);
702
703     // We can end up here after our connection has closed when WebCore's frame life-support timer
704     // fires when the application is shutting down. There's no need (and no way) to update the UI
705     // process in this case.
706     if (!m_connection)
707         return;
708
709     connection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
710 }
711
712 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
713 {
714     return m_pageGroupMap.get(pageGroupID).get();
715 }
716
717 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
718 {
719     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::AddResult result = m_pageGroupMap.add(pageGroupData.pageGroupID, 0);
720     if (result.isNewEntry) {
721         ASSERT(!result.iterator->value);
722         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
723     }
724
725     return result.iterator->value.get();
726 }
727
728 #if ENABLE(WEB_INTENTS)
729 uint64_t WebProcess::addMessagePortChannel(PassRefPtr<PlatformMessagePortChannel> messagePortChannel)
730 {
731     static uint64_t channelID = 0;
732     m_messagePortChannels.add(++channelID, messagePortChannel);
733
734     return channelID;
735 }
736
737 PlatformMessagePortChannel* WebProcess::messagePortChannel(uint64_t channelID)
738 {
739     return m_messagePortChannels.get(channelID).get();
740 }
741
742 void WebProcess::removeMessagePortChannel(uint64_t channelID)
743 {
744     m_messagePortChannels.remove(channelID);
745 }
746 #endif
747
748 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
749 {
750     platformClearResourceCaches(resourceCachesToClear);
751
752     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
753     // FIXME: We need a better way to do this.
754     CacheModel cacheModel = m_cacheModel;
755     setCacheModel(CacheModelDocumentViewer);
756     setCacheModel(cacheModel);
757
758     memoryCache()->evictResources();
759
760     // Empty the cross-origin preflight cache.
761     CrossOriginPreflightResultCache::shared().empty();
762 }
763
764 void WebProcess::clearApplicationCache()
765 {
766     // Empty the application cache.
767     cacheStorage().empty();
768 }
769
770 #if ENABLE(NETSCAPE_PLUGIN_API) && !ENABLE(PLUGIN_PROCESS)
771 void WebProcess::getSitesWithPluginData(const Vector<String>& pluginPaths, uint64_t callbackID)
772 {
773     LocalTerminationDisabler terminationDisabler(*this);
774
775     HashSet<String> sitesSet;
776
777 #if ENABLE(NETSCAPE_PLUGIN_API)
778     for (size_t i = 0; i < pluginPaths.size(); ++i) {
779         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
780         if (!netscapePluginModule)
781             continue;
782
783         Vector<String> sites = netscapePluginModule->sitesWithData();
784         for (size_t i = 0; i < sites.size(); ++i)
785             sitesSet.add(sites[i]);
786     }
787 #else
788     UNUSED_PARAM(pluginPaths);
789 #endif
790
791     Vector<String> sites;
792     copyToVector(sitesSet, sites);
793
794     connection()->send(Messages::WebProcessProxy::DidGetSitesWithPluginData(sites, callbackID), 0);
795 }
796
797 void WebProcess::clearPluginSiteData(const Vector<String>& pluginPaths, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
798 {
799     LocalTerminationDisabler terminationDisabler(*this);
800
801 #if ENABLE(NETSCAPE_PLUGIN_API)
802     for (size_t i = 0; i < pluginPaths.size(); ++i) {
803         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
804         if (!netscapePluginModule)
805             continue;
806
807         if (sites.isEmpty()) {
808             // Clear everything.
809             netscapePluginModule->clearSiteData(String(), flags, maxAgeInSeconds);
810             continue;
811         }
812
813         for (size_t i = 0; i < sites.size(); ++i)
814             netscapePluginModule->clearSiteData(sites[i], flags, maxAgeInSeconds);
815     }
816 #else
817     UNUSED_PARAM(pluginPaths);
818     UNUSED_PARAM(sites);
819     UNUSED_PARAM(flags);
820     UNUSED_PARAM(maxAgeInSeconds);
821 #endif
822
823     connection()->send(Messages::WebProcessProxy::DidClearPluginSiteData(callbackID), 0);
824 }
825 #endif
826
827 bool WebProcess::isPlugInAutoStartOrigin(unsigned plugInOriginHash)
828 {
829     return m_plugInAutoStartOrigins.contains(plugInOriginHash);
830 }
831
832 void WebProcess::addPlugInAutoStartOrigin(const String& pageOrigin, unsigned plugInOriginHash)
833 {
834     if (isPlugInAutoStartOrigin(plugInOriginHash)) {
835         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
836         return;
837     }
838
839     connection()->send(Messages::WebContext::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash), 0);
840 }
841
842 void WebProcess::didAddPlugInAutoStartOrigin(unsigned plugInOriginHash)
843 {
844     m_plugInAutoStartOrigins.add(plugInOriginHash);
845 }
846
847 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
848 {
849     TypeCountSet::const_iterator end = countedSet->end();
850     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
851         map.set(it->key, it->value);
852 }
853
854 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t> >& result)
855 {
856     DEFINE_STATIC_LOCAL(String, imagesString, (ASCIILiteral("Images")));
857     DEFINE_STATIC_LOCAL(String, cssString, (ASCIILiteral("CSS")));
858     DEFINE_STATIC_LOCAL(String, xslString, (ASCIILiteral("XSL")));
859     DEFINE_STATIC_LOCAL(String, javaScriptString, (ASCIILiteral("JavaScript")));
860     
861     MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics();
862     
863     HashMap<String, uint64_t> counts;
864     counts.set(imagesString, memoryCacheStatistics.images.count);
865     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
866     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
867     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
868     result.append(counts);
869     
870     HashMap<String, uint64_t> sizes;
871     sizes.set(imagesString, memoryCacheStatistics.images.size);
872     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
873     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
874     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
875     result.append(sizes);
876     
877     HashMap<String, uint64_t> liveSizes;
878     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
879     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
880     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
881     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
882     result.append(liveSizes);
883     
884     HashMap<String, uint64_t> decodedSizes;
885     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
886     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
887     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
888     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
889     result.append(decodedSizes);
890     
891     HashMap<String, uint64_t> purgeableSizes;
892     purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
893     purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
894     purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
895     purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
896     result.append(purgeableSizes);
897     
898     HashMap<String, uint64_t> purgedSizes;
899     purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
900     purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
901     purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
902     purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
903     result.append(purgedSizes);
904 }
905
906 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
907 {
908     StatisticsData data;
909     
910     // Gather JavaScript statistics.
911     {
912         JSLockHolder lock(JSDOMWindow::commonJSGlobalData());
913         data.statisticsNumbers.set("JavaScriptObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.objectCount());
914         data.statisticsNumbers.set("JavaScriptGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.globalObjectCount());
915         data.statisticsNumbers.set("JavaScriptProtectedObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedObjectCount());
916         data.statisticsNumbers.set("JavaScriptProtectedGlobalObjectsCount", JSDOMWindow::commonJSGlobalData()->heap.protectedGlobalObjectCount());
917         
918         OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.protectedObjectTypeCounts());
919         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
920         
921         OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonJSGlobalData()->heap.objectTypeCounts());
922         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
923         
924         uint64_t javaScriptHeapSize = JSDOMWindow::commonJSGlobalData()->heap.size();
925         data.statisticsNumbers.set("JavaScriptHeapSize", javaScriptHeapSize);
926         data.statisticsNumbers.set("JavaScriptFreeSize", JSDOMWindow::commonJSGlobalData()->heap.capacity() - javaScriptHeapSize);
927     }
928
929     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
930     data.statisticsNumbers.set("FastMallocReservedVMBytes", fastMallocStatistics.reservedVMBytes);
931     data.statisticsNumbers.set("FastMallocCommittedVMBytes", fastMallocStatistics.committedVMBytes);
932     data.statisticsNumbers.set("FastMallocFreeListBytes", fastMallocStatistics.freeListBytes);
933     
934     // Gather icon statistics.
935     data.statisticsNumbers.set("IconPageURLMappingCount", iconDatabase().pageURLMappingCount());
936     data.statisticsNumbers.set("IconRetainedPageURLCount", iconDatabase().retainedPageURLCount());
937     data.statisticsNumbers.set("IconRecordCount", iconDatabase().iconRecordCount());
938     data.statisticsNumbers.set("IconsWithDataCount", iconDatabase().iconRecordCountWithData());
939     
940     // Gather font statistics.
941     data.statisticsNumbers.set("CachedFontDataCount", fontCache()->fontDataCount());
942     data.statisticsNumbers.set("CachedFontDataInactiveCount", fontCache()->inactiveFontDataCount());
943     
944     // Gather glyph page statistics.
945     data.statisticsNumbers.set("GlyphPageCount", GlyphPageTreeNode::treeGlyphPageCount());
946     
947     // Get WebCore memory cache statistics
948     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
949     
950     connection()->send(Messages::WebContext::DidGetWebCoreStatistics(data, callbackID), 0);
951 }
952
953 void WebProcess::garbageCollectJavaScriptObjects()
954 {
955     gcController().garbageCollectNow();
956 }
957
958 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
959 {
960     gcController().setJavaScriptGarbageCollectorTimerEnabled(flag);
961 }
962
963 void WebProcess::postInjectedBundleMessage(const CoreIPC::DataReference& messageData)
964 {
965     InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();
966     if (!injectedBundle)
967         return;
968
969     OwnPtr<CoreIPC::ArgumentDecoder> decoder = CoreIPC::ArgumentDecoder::create(messageData.data(), messageData.size());
970
971     String messageName;
972     if (!decoder->decode(messageName))
973         return;
974
975     RefPtr<APIObject> messageBody;
976     InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody);
977     if (!decoder->decode(messageBodyDecoder))
978         return;
979
980     injectedBundle->didReceiveMessage(messageName, messageBody.get());
981 }
982
983 #if ENABLE(NETWORK_PROCESS)
984 NetworkProcessConnection* WebProcess::networkConnection()
985 {
986     // FIXME (NetworkProcess): How do we handle not having the connection when the WebProcess needs it?
987     // If the NetworkProcess crashed, for example.  Do we respawn it?
988     ASSERT(m_networkProcessConnection);
989     return m_networkProcessConnection.get();
990 }
991
992 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
993 {
994     // FIXME (NetworkProcess): How do we handle not having the connection when the WebProcess needs it?
995     // If the NetworkProcess crashed, for example.  Do we respawn it?
996     ASSERT(m_networkProcessConnection);
997     ASSERT(m_networkProcessConnection == connection);
998
999     m_networkProcessConnection = 0;
1000 }
1001
1002 #endif
1003
1004 #if ENABLE(PLUGIN_PROCESS)
1005 void WebProcess::pluginProcessCrashed(CoreIPC::Connection*, const String& pluginPath, uint32_t processType)
1006 {
1007     m_pluginProcessConnectionManager.pluginProcessCrashed(pluginPath, static_cast<PluginProcess::Type>(processType));
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().startDownload(downloadID, requestWithOriginalURL);
1020 }
1021
1022 void WebProcess::cancelDownload(uint64_t downloadID)
1023 {
1024     downloadManager().cancelDownload(downloadID);
1025 }
1026
1027 #if PLATFORM(QT)
1028 void WebProcess::startTransfer(uint64_t downloadID, const String& destination)
1029 {
1030     downloadManager().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).value.get();
1066         if (continuousSpellCheckingTurnedOff)
1067             page->unmarkAllMisspellings();
1068         if (grammarCheckingTurnedOff)
1069             page->unmarkAllBadGrammar();
1070     }
1071 }
1072
1073 #if ENABLE(NETSCAPE_PLUGIN_API)
1074 void WebProcess::didGetPlugins(CoreIPC::Connection*, uint64_t requestID, const Vector<WebCore::PluginInfo>& plugins)
1075 {
1076 #if USE(PLATFORM_STRATEGIES)
1077     // Pass this to WebPlatformStrategies.cpp.
1078     handleDidGetPlugins(requestID, plugins);
1079 #endif
1080 }
1081 #endif // ENABLE(PLUGIN_PROCESS)
1082
1083 #if ENABLE(CUSTOM_PROTOCOLS)
1084 void WebProcess::registerSchemeForCustomProtocol(const WTF::String& scheme)
1085 {
1086     CustomProtocolManager::shared().registerScheme(scheme);
1087 }
1088
1089 void WebProcess::unregisterSchemeForCustomProtocol(const WTF::String& scheme)
1090 {
1091     CustomProtocolManager::shared().unregisterScheme(scheme);
1092 }
1093 #endif
1094
1095 } // namespace WebKit