• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "WebProcess.h"
28 
29 #include "AuthenticationManager.h"
30 #include "DownloadManager.h"
31 #include "InjectedBundle.h"
32 #include "InjectedBundleMessageKinds.h"
33 #include "InjectedBundleUserMessageCoders.h"
34 #include "RunLoop.h"
35 #include "SandboxExtension.h"
36 #include "WebApplicationCacheManager.h"
37 #include "WebContextMessages.h"
38 #include "WebCookieManager.h"
39 #include "WebCoreArgumentCoders.h"
40 #include "WebDatabaseManager.h"
41 #include "WebFrame.h"
42 #include "WebGeolocationManagerMessages.h"
43 #include "WebKeyValueStorageManager.h"
44 #include "WebMediaCacheManager.h"
45 #include "WebMemorySampler.h"
46 #include "WebPage.h"
47 #include "WebPageCreationParameters.h"
48 #include "WebPlatformStrategies.h"
49 #include "WebPreferencesStore.h"
50 #include "WebProcessCreationParameters.h"
51 #include "WebProcessMessages.h"
52 #include "WebProcessProxyMessages.h"
53 #include "WebResourceCacheManager.h"
54 #include <WebCore/AXObjectCache.h>
55 #include <WebCore/ApplicationCacheStorage.h>
56 #include <WebCore/CrossOriginPreflightResultCache.h>
57 #include <WebCore/Font.h>
58 #include <WebCore/Language.h>
59 #include <WebCore/Logging.h>
60 #include <WebCore/MemoryCache.h>
61 #include <WebCore/Page.h>
62 #include <WebCore/PageCache.h>
63 #include <WebCore/PageGroup.h>
64 #include <WebCore/ResourceHandle.h>
65 #include <WebCore/SchemeRegistry.h>
66 #include <WebCore/SecurityOrigin.h>
67 #include <WebCore/Settings.h>
68 #include <WebCore/StorageTracker.h>
69 #include <wtf/PassRefPtr.h>
70 #include <wtf/RandomNumber.h>
71 
72 #ifndef NDEBUG
73 #include <WebCore/GCController.h>
74 #endif
75 
76 #if !OS(WINDOWS)
77 #include <unistd.h>
78 #endif
79 
80 #if !ENABLE(PLUGIN_PROCESS)
81 #include "NetscapePluginModule.h"
82 #endif
83 
84 using namespace WebCore;
85 
86 namespace WebKit {
87 
88 #if OS(WINDOWS)
sleep(unsigned seconds)89 static void sleep(unsigned seconds)
90 {
91     ::Sleep(seconds * 1000);
92 }
93 #endif
94 
randomCrashThread(void *)95 static void* randomCrashThread(void*)
96 {
97     // This delay was chosen semi-arbitrarily. We want the crash to happen somewhat quickly to
98     // enable useful stress testing, but not so quickly that the web process will always crash soon
99     // after launch.
100     static const unsigned maximumRandomCrashDelay = 180;
101 
102     sleep(randomNumber() * maximumRandomCrashDelay);
103     CRASH();
104     return 0;
105 }
106 
startRandomCrashThreadIfRequested()107 static void startRandomCrashThreadIfRequested()
108 {
109     if (!getenv("WEBKIT2_CRASH_WEB_PROCESS_RANDOMLY"))
110         return;
111     createThread(randomCrashThread, 0, "WebKit2: Random Crash Thread");
112 }
113 
shared()114 WebProcess& WebProcess::shared()
115 {
116     static WebProcess& process = *new WebProcess;
117     return process;
118 }
119 
120 static const double shutdownTimeout = 60;
121 
WebProcess()122 WebProcess::WebProcess()
123     : ChildProcess(shutdownTimeout)
124     , m_inDidClose(false)
125     , m_hasSetCacheModel(false)
126     , m_cacheModel(CacheModelDocumentViewer)
127 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
128     , m_compositingRenderServerPort(MACH_PORT_NULL)
129 #endif
130 #if PLATFORM(QT)
131     , m_networkAccessManager(0)
132 #endif
133     , m_textCheckerState()
134     , m_geolocationManager(this)
135     , m_iconDatabaseProxy(this)
136 {
137 #if USE(PLATFORM_STRATEGIES)
138     // Initialize our platform strategies.
139     WebPlatformStrategies::initialize();
140 #endif // USE(PLATFORM_STRATEGIES)
141 
142     WebCore::InitializeLoggingChannelsIfNecessary();
143 }
144 
initialize(CoreIPC::Connection::Identifier serverIdentifier,RunLoop * runLoop)145 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
146 {
147     ASSERT(!m_connection);
148 
149     m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop);
150     m_connection->setDidCloseOnConnectionWorkQueueCallback(didCloseOnConnectionWorkQueue);
151     m_connection->setShouldExitOnSyncMessageSendFailure(true);
152 
153     m_connection->open();
154 
155     m_runLoop = runLoop;
156 
157     startRandomCrashThreadIfRequested();
158 }
159 
initializeWebProcess(const WebProcessCreationParameters & parameters,CoreIPC::ArgumentDecoder * arguments)160 void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::ArgumentDecoder* arguments)
161 {
162     ASSERT(m_pageMap.isEmpty());
163 
164     platformInitializeWebProcess(parameters, arguments);
165 
166     RefPtr<APIObject> injectedBundleInitializationUserData;
167     InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData);
168     if (!arguments->decode(messageDecoder))
169         return;
170 
171     if (!parameters.injectedBundlePath.isEmpty()) {
172         m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath);
173         m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle));
174 
175         if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) {
176             // Don't keep around the InjectedBundle reference if the load fails.
177             m_injectedBundle.clear();
178         }
179     }
180 
181 #if ENABLE(DATABASE)
182     // Make sure the WebDatabaseManager is initialized so that the Database directory is set.
183     WebDatabaseManager::initialize(parameters.databaseDirectory);
184 #endif
185 
186 #if ENABLE(ICONDATABASE)
187     m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled);
188 #endif
189 
190 #if ENABLE(DOM_STORAGE)
191     StorageTracker::initializeTracker(parameters.localStorageDirectory);
192     m_localStorageDirectory = parameters.localStorageDirectory;
193 #endif
194 
195 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
196     if (!parameters.applicationCacheDirectory.isEmpty())
197         cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory);
198 #endif
199 
200     setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks);
201     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
202 
203     if (!parameters.languageCode.isEmpty())
204         overrideDefaultLanguage(parameters.languageCode);
205 
206     m_textCheckerState = parameters.textCheckerState;
207 
208     for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i)
209         registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]);
210 
211     for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i)
212         registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]);
213 
214     for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i)
215         setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]);
216 
217     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
218 
219     for (size_t i = 0; i < parameters.mimeTypesWithCustomRepresentation.size(); ++i)
220         m_mimeTypesWithCustomRepresentations.add(parameters.mimeTypesWithCustomRepresentation[i]);
221 
222 #if PLATFORM(MAC)
223     m_presenterApplicationPid = parameters.presenterApplicationPid;
224 #endif
225 
226     if (parameters.shouldAlwaysUseComplexTextCodePath)
227         setAlwaysUsesComplexTextCodePath(true);
228 
229 #if USE(CFURLSTORAGESESSIONS)
230     WebCore::ResourceHandle::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier);
231 #endif
232 }
233 
setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)234 void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
235 {
236     PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks);
237 }
238 
registerURLSchemeAsEmptyDocument(const String & urlScheme)239 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
240 {
241     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
242 }
243 
registerURLSchemeAsSecure(const String & urlScheme) const244 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
245 {
246     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
247 }
248 
setDomainRelaxationForbiddenForURLScheme(const String & urlScheme) const249 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
250 {
251     SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
252 }
253 
setDefaultRequestTimeoutInterval(double timeoutInterval)254 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
255 {
256     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
257 }
258 
setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)259 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
260 {
261     WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto);
262 }
263 
languageChanged(const String & language) const264 void WebProcess::languageChanged(const String& language) const
265 {
266     overrideDefaultLanguage(language);
267 }
268 
setVisitedLinkTable(const SharedMemory::Handle & handle)269 void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle)
270 {
271     RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly);
272     if (!sharedMemory)
273         return;
274 
275     m_visitedLinkTable.setSharedMemory(sharedMemory.release());
276 }
277 
visitedLinkStateChanged(const Vector<WebCore::LinkHash> & linkHashes)278 void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes)
279 {
280     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
281     for (size_t i = 0; i < linkHashes.size(); ++i) {
282         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
283         HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
284         for (; it != end; ++it)
285             Page::visitedStateChanged(PageGroup::pageGroup(it->second->identifier()), linkHashes[i]);
286     }
287 
288     pageCache()->markPagesForVistedLinkStyleRecalc();
289 }
290 
allVisitedLinkStateChanged()291 void WebProcess::allVisitedLinkStateChanged()
292 {
293     // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext.
294     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin();
295     HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end();
296     for (; it != end; ++it)
297         Page::allVisitedStateChanged(PageGroup::pageGroup(it->second->identifier()));
298 
299     pageCache()->markPagesForVistedLinkStyleRecalc();
300 }
301 
isLinkVisited(LinkHash linkHash) const302 bool WebProcess::isLinkVisited(LinkHash linkHash) const
303 {
304     return m_visitedLinkTable.isLinkVisited(linkHash);
305 }
306 
addVisitedLink(WebCore::LinkHash linkHash)307 void WebProcess::addVisitedLink(WebCore::LinkHash linkHash)
308 {
309     if (isLinkVisited(linkHash))
310         return;
311     m_connection->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0);
312 }
313 
314 #if !PLATFORM(MAC)
fullKeyboardAccessEnabled()315 bool WebProcess::fullKeyboardAccessEnabled()
316 {
317     return false;
318 }
319 #endif
320 
setCacheModel(uint32_t cm)321 void WebProcess::setCacheModel(uint32_t cm)
322 {
323     CacheModel cacheModel = static_cast<CacheModel>(cm);
324 
325     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
326         m_hasSetCacheModel = true;
327         m_cacheModel = cacheModel;
328         platformSetCacheModel(cacheModel);
329     }
330 }
331 
calculateCacheSizes(CacheModel cacheModel,uint64_t memorySize,uint64_t diskFreeSize,unsigned & cacheTotalCapacity,unsigned & cacheMinDeadCapacity,unsigned & cacheMaxDeadCapacity,double & deadDecodedDataDeletionInterval,unsigned & pageCacheCapacity,unsigned long & urlCacheMemoryCapacity,unsigned long & urlCacheDiskCapacity)332 void WebProcess::calculateCacheSizes(CacheModel cacheModel, uint64_t memorySize, uint64_t diskFreeSize,
333     unsigned& cacheTotalCapacity, unsigned& cacheMinDeadCapacity, unsigned& cacheMaxDeadCapacity, double& deadDecodedDataDeletionInterval,
334     unsigned& pageCacheCapacity, unsigned long& urlCacheMemoryCapacity, unsigned long& urlCacheDiskCapacity)
335 {
336     switch (cacheModel) {
337     case CacheModelDocumentViewer: {
338         // Page cache capacity (in pages)
339         pageCacheCapacity = 0;
340 
341         // Object cache capacities (in bytes)
342         if (memorySize >= 2048)
343             cacheTotalCapacity = 96 * 1024 * 1024;
344         else if (memorySize >= 1536)
345             cacheTotalCapacity = 64 * 1024 * 1024;
346         else if (memorySize >= 1024)
347             cacheTotalCapacity = 32 * 1024 * 1024;
348         else if (memorySize >= 512)
349             cacheTotalCapacity = 16 * 1024 * 1024;
350 
351         cacheMinDeadCapacity = 0;
352         cacheMaxDeadCapacity = 0;
353 
354         // Foundation memory cache capacity (in bytes)
355         urlCacheMemoryCapacity = 0;
356 
357         // Foundation disk cache capacity (in bytes)
358         urlCacheDiskCapacity = 0;
359 
360         break;
361     }
362     case CacheModelDocumentBrowser: {
363         // Page cache capacity (in pages)
364         if (memorySize >= 1024)
365             pageCacheCapacity = 3;
366         else if (memorySize >= 512)
367             pageCacheCapacity = 2;
368         else if (memorySize >= 256)
369             pageCacheCapacity = 1;
370         else
371             pageCacheCapacity = 0;
372 
373         // Object cache capacities (in bytes)
374         if (memorySize >= 2048)
375             cacheTotalCapacity = 96 * 1024 * 1024;
376         else if (memorySize >= 1536)
377             cacheTotalCapacity = 64 * 1024 * 1024;
378         else if (memorySize >= 1024)
379             cacheTotalCapacity = 32 * 1024 * 1024;
380         else if (memorySize >= 512)
381             cacheTotalCapacity = 16 * 1024 * 1024;
382 
383         cacheMinDeadCapacity = cacheTotalCapacity / 8;
384         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
385 
386         // Foundation memory cache capacity (in bytes)
387         if (memorySize >= 2048)
388             urlCacheMemoryCapacity = 4 * 1024 * 1024;
389         else if (memorySize >= 1024)
390             urlCacheMemoryCapacity = 2 * 1024 * 1024;
391         else if (memorySize >= 512)
392             urlCacheMemoryCapacity = 1 * 1024 * 1024;
393         else
394             urlCacheMemoryCapacity =      512 * 1024;
395 
396         // Foundation disk cache capacity (in bytes)
397         if (diskFreeSize >= 16384)
398             urlCacheDiskCapacity = 50 * 1024 * 1024;
399         else if (diskFreeSize >= 8192)
400             urlCacheDiskCapacity = 40 * 1024 * 1024;
401         else if (diskFreeSize >= 4096)
402             urlCacheDiskCapacity = 30 * 1024 * 1024;
403         else
404             urlCacheDiskCapacity = 20 * 1024 * 1024;
405 
406         break;
407     }
408     case CacheModelPrimaryWebBrowser: {
409         // Page cache capacity (in pages)
410         // (Research indicates that value / page drops substantially after 3 pages.)
411         if (memorySize >= 2048)
412             pageCacheCapacity = 5;
413         else if (memorySize >= 1024)
414             pageCacheCapacity = 4;
415         else if (memorySize >= 512)
416             pageCacheCapacity = 3;
417         else if (memorySize >= 256)
418             pageCacheCapacity = 2;
419         else
420             pageCacheCapacity = 1;
421 
422         // Object cache capacities (in bytes)
423         // (Testing indicates that value / MB depends heavily on content and
424         // browsing pattern. Even growth above 128MB can have substantial
425         // value / MB for some content / browsing patterns.)
426         if (memorySize >= 2048)
427             cacheTotalCapacity = 128 * 1024 * 1024;
428         else if (memorySize >= 1536)
429             cacheTotalCapacity = 96 * 1024 * 1024;
430         else if (memorySize >= 1024)
431             cacheTotalCapacity = 64 * 1024 * 1024;
432         else if (memorySize >= 512)
433             cacheTotalCapacity = 32 * 1024 * 1024;
434 
435         cacheMinDeadCapacity = cacheTotalCapacity / 4;
436         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
437 
438         // This code is here to avoid a PLT regression. We can remove it if we
439         // can prove that the overall system gain would justify the regression.
440         cacheMaxDeadCapacity = std::max(24u, cacheMaxDeadCapacity);
441 
442         deadDecodedDataDeletionInterval = 60;
443 
444         // Foundation memory cache capacity (in bytes)
445         // (These values are small because WebCore does most caching itself.)
446         if (memorySize >= 1024)
447             urlCacheMemoryCapacity = 4 * 1024 * 1024;
448         else if (memorySize >= 512)
449             urlCacheMemoryCapacity = 2 * 1024 * 1024;
450         else if (memorySize >= 256)
451             urlCacheMemoryCapacity = 1 * 1024 * 1024;
452         else
453             urlCacheMemoryCapacity =      512 * 1024;
454 
455         // Foundation disk cache capacity (in bytes)
456         if (diskFreeSize >= 16384)
457             urlCacheDiskCapacity = 175 * 1024 * 1024;
458         else if (diskFreeSize >= 8192)
459             urlCacheDiskCapacity = 150 * 1024 * 1024;
460         else if (diskFreeSize >= 4096)
461             urlCacheDiskCapacity = 125 * 1024 * 1024;
462         else if (diskFreeSize >= 2048)
463             urlCacheDiskCapacity = 100 * 1024 * 1024;
464         else if (diskFreeSize >= 1024)
465             urlCacheDiskCapacity = 75 * 1024 * 1024;
466         else
467             urlCacheDiskCapacity = 50 * 1024 * 1024;
468 
469         break;
470     }
471     default:
472         ASSERT_NOT_REACHED();
473     };
474 }
475 
focusedWebPage() const476 WebPage* WebProcess::focusedWebPage() const
477 {
478     HashMap<uint64_t, RefPtr<WebPage> >::const_iterator end = m_pageMap.end();
479     for (HashMap<uint64_t, RefPtr<WebPage> >::const_iterator it = m_pageMap.begin(); it != end; ++it) {
480         WebPage* page = (*it).second.get();
481         if (page->windowIsFocused())
482             return page;
483     }
484     return 0;
485 }
486 
webPage(uint64_t pageID) const487 WebPage* WebProcess::webPage(uint64_t pageID) const
488 {
489     return m_pageMap.get(pageID).get();
490 }
491 
createWebPage(uint64_t pageID,const WebPageCreationParameters & parameters)492 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
493 {
494     // It is necessary to check for page existence here since during a window.open() (or targeted
495     // link) the WebPage gets created both in the synchronous handler and through the normal way.
496     std::pair<HashMap<uint64_t, RefPtr<WebPage> >::iterator, bool> result = m_pageMap.add(pageID, 0);
497     if (result.second) {
498         ASSERT(!result.first->second);
499         result.first->second = WebPage::create(pageID, parameters);
500 
501         // Balanced by an enableTermination in removeWebPage.
502         disableTermination();
503     }
504 
505     ASSERT(result.first->second);
506 }
507 
removeWebPage(uint64_t pageID)508 void WebProcess::removeWebPage(uint64_t pageID)
509 {
510     ASSERT(m_pageMap.contains(pageID));
511 
512     m_pageMap.remove(pageID);
513 
514     enableTermination();
515 }
516 
isSeparateProcess() const517 bool WebProcess::isSeparateProcess() const
518 {
519     // If we're running on the main run loop, we assume that we're in a separate process.
520     return m_runLoop == RunLoop::main();
521 }
522 
shouldTerminate()523 bool WebProcess::shouldTerminate()
524 {
525     // Keep running forever if we're running in the same process.
526     if (!isSeparateProcess())
527         return false;
528 
529     ASSERT(m_pageMap.isEmpty());
530     ASSERT(!DownloadManager::shared().isDownloading());
531 
532     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
533     bool shouldTerminate = false;
534     if (m_connection->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
535         && !shouldTerminate)
536         return false;
537 
538     return true;
539 }
540 
terminate()541 void WebProcess::terminate()
542 {
543 #ifndef NDEBUG
544     gcController().garbageCollectNow();
545     memoryCache()->setDisabled(true);
546 #endif
547 
548     // Invalidate our connection.
549     m_connection->invalidate();
550     m_connection = nullptr;
551 
552     platformTerminate();
553     m_runLoop->stop();
554 }
555 
didReceiveSyncMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments,CoreIPC::ArgumentEncoder * reply)556 CoreIPC::SyncReplyMode WebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
557 {
558     uint64_t pageID = arguments->destinationID();
559     if (!pageID)
560         return CoreIPC::AutomaticReply;
561 
562     WebPage* page = webPage(pageID);
563     if (!page)
564         return CoreIPC::AutomaticReply;
565 
566     page->didReceiveSyncMessage(connection, messageID, arguments, reply);
567     return CoreIPC::AutomaticReply;
568 }
569 
didReceiveMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments)570 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
571 {
572     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
573         didReceiveWebProcessMessage(connection, messageID, arguments);
574         return;
575     }
576 
577     if (messageID.is<CoreIPC::MessageClassAuthenticationManager>()) {
578         AuthenticationManager::shared().didReceiveMessage(connection, messageID, arguments);
579         return;
580     }
581 
582     if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManager>()) {
583         WebApplicationCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
584         return;
585     }
586 
587     if (messageID.is<CoreIPC::MessageClassWebCookieManager>()) {
588         WebCookieManager::shared().didReceiveMessage(connection, messageID, arguments);
589         return;
590     }
591 
592     if (messageID.is<CoreIPC::MessageClassWebDatabaseManager>()) {
593         WebDatabaseManager::shared().didReceiveMessage(connection, messageID, arguments);
594         return;
595     }
596 
597     if (messageID.is<CoreIPC::MessageClassWebGeolocationManager>()) {
598         m_geolocationManager.didReceiveMessage(connection, messageID, arguments);
599         return;
600     }
601 
602     if (messageID.is<CoreIPC::MessageClassWebIconDatabaseProxy>()) {
603         m_iconDatabaseProxy.didReceiveMessage(connection, messageID, arguments);
604         return;
605     }
606 
607     if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManager>()) {
608         WebKeyValueStorageManager::shared().didReceiveMessage(connection, messageID, arguments);
609         return;
610     }
611 
612     if (messageID.is<CoreIPC::MessageClassWebMediaCacheManager>()) {
613         WebMediaCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
614         return;
615     }
616 
617     if (messageID.is<CoreIPC::MessageClassWebResourceCacheManager>()) {
618         WebResourceCacheManager::shared().didReceiveMessage(connection, messageID, arguments);
619         return;
620     }
621 
622     if (messageID.is<CoreIPC::MessageClassInjectedBundle>()) {
623         if (!m_injectedBundle)
624             return;
625         m_injectedBundle->didReceiveMessage(connection, messageID, arguments);
626         return;
627     }
628 
629     uint64_t pageID = arguments->destinationID();
630     if (!pageID)
631         return;
632 
633     WebPage* page = webPage(pageID);
634     if (!page)
635         return;
636 
637     page->didReceiveMessage(connection, messageID, arguments);
638 }
639 
didClose(CoreIPC::Connection *)640 void WebProcess::didClose(CoreIPC::Connection*)
641 {
642     // When running in the same process the connection will never be closed.
643     ASSERT(isSeparateProcess());
644 
645 #ifndef NDEBUG
646     m_inDidClose = true;
647 
648     // Close all the live pages.
649     Vector<RefPtr<WebPage> > pages;
650     copyValuesToVector(m_pageMap, pages);
651     for (size_t i = 0; i < pages.size(); ++i)
652         pages[i]->close();
653     pages.clear();
654 
655     gcController().garbageCollectNow();
656     memoryCache()->setDisabled(true);
657 #endif
658 
659     // The UI process closed this connection, shut down.
660     m_runLoop->stop();
661 }
662 
didReceiveInvalidMessage(CoreIPC::Connection *,CoreIPC::MessageID)663 void WebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
664 {
665     // We received an invalid message, but since this is from the UI process (which we trust),
666     // we'll let it slide.
667 }
668 
syncMessageSendTimedOut(CoreIPC::Connection *)669 void WebProcess::syncMessageSendTimedOut(CoreIPC::Connection*)
670 {
671 }
672 
webFrame(uint64_t frameID) const673 WebFrame* WebProcess::webFrame(uint64_t frameID) const
674 {
675     return m_frameMap.get(frameID);
676 }
677 
addWebFrame(uint64_t frameID,WebFrame * frame)678 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
679 {
680     m_frameMap.set(frameID, frame);
681 }
682 
removeWebFrame(uint64_t frameID)683 void WebProcess::removeWebFrame(uint64_t frameID)
684 {
685     m_frameMap.remove(frameID);
686 
687     // We can end up here after our connection has closed when WebCore's frame life-support timer
688     // fires when the application is shutting down. There's no need (and no way) to update the UI
689     // process in this case.
690     if (!m_connection)
691         return;
692 
693     m_connection->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
694 }
695 
webPageGroup(uint64_t pageGroupID)696 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
697 {
698     return m_pageGroupMap.get(pageGroupID).get();
699 }
700 
webPageGroup(const WebPageGroupData & pageGroupData)701 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
702 {
703     std::pair<HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::iterator, bool> result = m_pageGroupMap.add(pageGroupData.pageGroupID, 0);
704     if (result.second) {
705         ASSERT(!result.first->second);
706         result.first->second = WebPageGroupProxy::create(pageGroupData);
707     }
708 
709     return result.first->second.get();
710 }
711 
clearResourceCaches(ResourceCachesToClear resourceCachesToClear)712 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
713 {
714     platformClearResourceCaches(resourceCachesToClear);
715 
716     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
717     // FIXME: We need a better way to do this.
718     CacheModel cacheModel = m_cacheModel;
719     setCacheModel(CacheModelDocumentViewer);
720     setCacheModel(cacheModel);
721 
722     memoryCache()->evictResources();
723 
724     // Empty the cross-origin preflight cache.
725     CrossOriginPreflightResultCache::shared().empty();
726 }
727 
clearApplicationCache()728 void WebProcess::clearApplicationCache()
729 {
730 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
731     // Empty the application cache.
732     cacheStorage().empty();
733 #endif
734 }
735 
736 #if !ENABLE(PLUGIN_PROCESS)
getSitesWithPluginData(const Vector<String> & pluginPaths,uint64_t callbackID)737 void WebProcess::getSitesWithPluginData(const Vector<String>& pluginPaths, uint64_t callbackID)
738 {
739     LocalTerminationDisabler terminationDisabler(*this);
740 
741     HashSet<String> sitesSet;
742 
743     for (size_t i = 0; i < pluginPaths.size(); ++i) {
744         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
745         if (!netscapePluginModule)
746             continue;
747 
748         Vector<String> sites = netscapePluginModule->sitesWithData();
749         for (size_t i = 0; i < sites.size(); ++i)
750             sitesSet.add(sites[i]);
751     }
752 
753     Vector<String> sites;
754     copyToVector(sitesSet, sites);
755 
756     m_connection->send(Messages::WebContext::DidGetSitesWithPluginData(sites, callbackID), 0);
757 }
758 
clearPluginSiteData(const Vector<String> & pluginPaths,const Vector<String> & sites,uint64_t flags,uint64_t maxAgeInSeconds,uint64_t callbackID)759 void WebProcess::clearPluginSiteData(const Vector<String>& pluginPaths, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
760 {
761     LocalTerminationDisabler terminationDisabler(*this);
762 
763     for (size_t i = 0; i < pluginPaths.size(); ++i) {
764         RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]);
765         if (!netscapePluginModule)
766             continue;
767 
768         if (sites.isEmpty()) {
769             // Clear everything.
770             netscapePluginModule->clearSiteData(String(), flags, maxAgeInSeconds);
771             continue;
772         }
773 
774         for (size_t i = 0; i < sites.size(); ++i)
775             netscapePluginModule->clearSiteData(sites[i], flags, maxAgeInSeconds);
776     }
777 
778     m_connection->send(Messages::WebContext::DidClearPluginSiteData(callbackID), 0);
779 }
780 #endif
781 
downloadRequest(uint64_t downloadID,uint64_t initiatingPageID,const ResourceRequest & request)782 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
783 {
784     WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
785 
786     DownloadManager::shared().startDownload(downloadID, initiatingPage, request);
787 }
788 
cancelDownload(uint64_t downloadID)789 void WebProcess::cancelDownload(uint64_t downloadID)
790 {
791     DownloadManager::shared().cancelDownload(downloadID);
792 }
793 
setEnhancedAccessibility(bool flag)794 void WebProcess::setEnhancedAccessibility(bool flag)
795 {
796     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
797 }
798 
startMemorySampler(const SandboxExtension::Handle & sampleLogFileHandle,const String & sampleLogFilePath,const double interval)799 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
800 {
801 #if ENABLE(MEMORY_SAMPLER)
802     WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval);
803 #endif
804 }
805 
stopMemorySampler()806 void WebProcess::stopMemorySampler()
807 {
808 #if ENABLE(MEMORY_SAMPLER)
809     WebMemorySampler::shared()->stop();
810 #endif
811 }
812 
setTextCheckerState(const TextCheckerState & textCheckerState)813 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
814 {
815     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
816     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
817 
818     m_textCheckerState = textCheckerState;
819 
820     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
821         return;
822 
823     HashMap<uint64_t, RefPtr<WebPage> >::iterator end = m_pageMap.end();
824     for (HashMap<uint64_t, RefPtr<WebPage> >::iterator it = m_pageMap.begin(); it != end; ++it) {
825         WebPage* page = (*it).second.get();
826         if (continuousSpellCheckingTurnedOff)
827             page->unmarkAllMisspellings();
828         if (grammarCheckingTurnedOff)
829             page->unmarkAllBadGrammar();
830     }
831 }
832 
833 } // namespace WebKit
834