f13f1db5241d8cee4c94584397420259ab20de47
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebProcessPool.cpp
1 /*
2  * Copyright (C) 2010-2016 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 "WebProcessPool.h"
28
29 #include "APIArray.h"
30 #include "APIAutomationClient.h"
31 #include "APIDownloadClient.h"
32 #include "APILegacyContextHistoryClient.h"
33 #include "APIPageConfiguration.h"
34 #include "APIProcessPoolConfiguration.h"
35 #include "CustomProtocolManagerMessages.h"
36 #include "DownloadProxy.h"
37 #include "DownloadProxyMessages.h"
38 #include "Logging.h"
39 #include "NetworkProcessCreationParameters.h"
40 #include "NetworkProcessMessages.h"
41 #include "NetworkProcessProxy.h"
42 #include "SandboxExtension.h"
43 #include "StatisticsData.h"
44 #include "TextChecker.h"
45 #include "WKContextPrivate.h"
46 #include "WebAutomationSession.h"
47 #include "WebCertificateInfo.h"
48 #include "WebContextSupplement.h"
49 #include "WebCookieManagerProxy.h"
50 #include "WebCoreArgumentCoders.h"
51 #include "WebGeolocationManagerProxy.h"
52 #include "WebIconDatabase.h"
53 #include "WebKit2Initialize.h"
54 #include "WebMemorySampler.h"
55 #include "WebNotificationManagerProxy.h"
56 #include "WebPageGroup.h"
57 #include "WebPreferences.h"
58 #include "WebProcessCreationParameters.h"
59 #include "WebProcessMessages.h"
60 #include "WebProcessPoolMessages.h"
61 #include "WebProcessProxy.h"
62 #include "WebsiteDataStore.h"
63 #include <WebCore/ApplicationCacheStorage.h>
64 #include <WebCore/Language.h>
65 #include <WebCore/LinkHash.h>
66 #include <WebCore/Logging.h>
67 #include <WebCore/ResourceRequest.h>
68 #include <WebCore/SessionID.h>
69 #include <runtime/JSCInlines.h>
70 #include <wtf/CurrentTime.h>
71 #include <wtf/MainThread.h>
72 #include <wtf/NeverDestroyed.h>
73 #include <wtf/RunLoop.h>
74
75 #if ENABLE(BATTERY_STATUS)
76 #include "WebBatteryManagerProxy.h"
77 #endif
78
79 #if ENABLE(DATABASE_PROCESS)
80 #include "DatabaseProcessCreationParameters.h"
81 #include "DatabaseProcessMessages.h"
82 #endif
83
84 #if ENABLE(SERVICE_CONTROLS)
85 #include "ServicesController.h"
86 #endif
87
88 #if ENABLE(REMOTE_INSPECTOR)
89 #include <JavaScriptCore/RemoteInspector.h>
90 #endif
91
92 #if USE(SOUP)
93 #include "WebSoupCustomProtocolRequestManager.h"
94 #endif
95
96 #ifndef NDEBUG
97 #include <wtf/RefCountedLeakCounter.h>
98 #endif
99
100 using namespace WebCore;
101 using namespace WebKit;
102
103 namespace WebKit {
104
105 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, processPoolCounter, ("WebProcessPool"));
106
107 Ref<WebProcessPool> WebProcessPool::create(API::ProcessPoolConfiguration& configuration)
108 {
109     InitializeWebKit2();
110     return adoptRef(*new WebProcessPool(configuration));
111 }
112
113 static Vector<WebProcessPool*>& processPools()
114 {
115     static NeverDestroyed<Vector<WebProcessPool*>> processPools;
116     return processPools;
117 }
118
119 const Vector<WebProcessPool*>& WebProcessPool::allProcessPools()
120 {
121     return processPools();
122 }
123
124 static WebsiteDataStore::Configuration legacyWebsiteDataStoreConfiguration(API::ProcessPoolConfiguration& processPoolConfiguration)
125 {
126     WebsiteDataStore::Configuration configuration;
127
128     configuration.localStorageDirectory = processPoolConfiguration.localStorageDirectory();
129     configuration.webSQLDatabaseDirectory = processPoolConfiguration.webSQLDatabaseDirectory();
130     configuration.applicationCacheDirectory = processPoolConfiguration.applicationCacheDirectory();
131     configuration.mediaKeysStorageDirectory = processPoolConfiguration.mediaKeysStorageDirectory();
132     configuration.networkCacheDirectory = processPoolConfiguration.diskCacheDirectory();
133
134     // This is needed to support legacy WK2 clients, which did not have resource load statistics.
135     configuration.resourceLoadStatisticsDirectory = API::WebsiteDataStore::defaultResourceLoadStatisticsDirectory();
136
137     return configuration;
138 }
139
140 WebProcessPool::WebProcessPool(API::ProcessPoolConfiguration& configuration)
141     : m_configuration(configuration.copy())
142     , m_haveInitialEmptyProcess(false)
143     , m_processWithPageCache(0)
144     , m_defaultPageGroup(WebPageGroup::createNonNull())
145     , m_automationClient(std::make_unique<API::AutomationClient>())
146     , m_downloadClient(std::make_unique<API::DownloadClient>())
147     , m_historyClient(std::make_unique<API::LegacyContextHistoryClient>())
148     , m_visitedLinkStore(VisitedLinkStore::create())
149     , m_visitedLinksPopulated(false)
150     , m_plugInAutoStartProvider(this)
151     , m_alwaysUsesComplexTextCodePath(false)
152     , m_shouldUseFontSmoothing(true)
153     , m_memorySamplerEnabled(false)
154     , m_memorySamplerInterval(1400.0)
155     , m_websiteDataStore(m_configuration->shouldHaveLegacyDataStore() ? API::WebsiteDataStore::create(legacyWebsiteDataStoreConfiguration(m_configuration)).ptr() : nullptr)
156 #if USE(SOUP)
157     , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain)
158 #endif
159     , m_shouldUseTestingNetworkSession(false)
160     , m_processTerminationEnabled(true)
161     , m_canHandleHTTPSServerTrustEvaluation(true)
162     , m_didNetworkProcessCrash(false)
163     , m_memoryCacheDisabled(false)
164     , m_userObservablePageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
165     , m_processSuppressionDisabledForPageCounter([this](RefCounterEvent) { updateProcessSuppressionState(); })
166     , m_hiddenPageThrottlingAutoIncreasesCounter([this](RefCounterEvent) { m_hiddenPageThrottlingTimer.startOneShot(0); })
167     , m_hiddenPageThrottlingTimer(*this, &WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit)
168 {
169     for (auto& scheme : m_configuration->alwaysRevalidatedURLSchemes())
170         m_schemesToRegisterAsAlwaysRevalidated.add(scheme);
171
172 #if ENABLE(CACHE_PARTITIONING)
173     for (const auto& urlScheme : m_configuration->cachePartitionedURLSchemes())
174         m_schemesToRegisterAsCachePartitioned.add(urlScheme);
175 #endif
176
177     platformInitialize();
178
179     addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
180
181     // NOTE: These sub-objects must be initialized after m_messageReceiverMap..
182     m_iconDatabase = WebIconDatabase::create(this);
183
184     addSupplement<WebCookieManagerProxy>();
185     addSupplement<WebGeolocationManagerProxy>();
186     addSupplement<WebNotificationManagerProxy>();
187 #if USE(SOUP)
188     addSupplement<WebSoupCustomProtocolRequestManager>();
189 #endif
190 #if ENABLE(BATTERY_STATUS)
191     addSupplement<WebBatteryManagerProxy>();
192 #endif
193 #if ENABLE(MEDIA_SESSION)
194     addSupplement<WebMediaSessionFocusManager>();
195 #endif
196
197     processPools().append(this);
198
199     addLanguageChangeObserver(this, languageChanged);
200
201 #if !LOG_DISABLED
202     WebCore::initializeLoggingChannelsIfNecessary();
203     WebKit::initializeLogChannelsIfNecessary();
204 #endif // !LOG_DISABLED
205
206 #if ENABLE(NETSCAPE_PLUGIN_API)
207     m_pluginInfoStore.setClient(this);
208 #endif
209
210 #ifndef NDEBUG
211     processPoolCounter.increment();
212 #endif
213 }
214
215 #if !PLATFORM(COCOA)
216 void WebProcessPool::platformInitialize()
217 {
218 }
219 #endif
220
221 WebProcessPool::~WebProcessPool()
222 {
223     bool removed = processPools().removeFirst(this);
224     ASSERT_UNUSED(removed, removed);
225
226     removeLanguageChangeObserver(this);
227
228     m_messageReceiverMap.invalidate();
229
230     WebContextSupplementMap::const_iterator it = m_supplements.begin();
231     WebContextSupplementMap::const_iterator end = m_supplements.end();
232     for (; it != end; ++it) {
233         it->value->processPoolDestroyed();
234         it->value->clearProcessPool();
235     }
236
237     m_iconDatabase->invalidate();
238     m_iconDatabase->clearProcessPool();
239     WebIconDatabase* rawIconDatabase = m_iconDatabase.release().leakRef();
240     rawIconDatabase->derefWhenAppropriate();
241
242     invalidateCallbackMap(m_dictionaryCallbacks, CallbackBase::Error::OwnerWasInvalidated);
243
244     platformInvalidateContext();
245
246 #if ENABLE(NETSCAPE_PLUGIN_API)
247     m_pluginInfoStore.setClient(0);
248 #endif
249
250 #ifndef NDEBUG
251     processPoolCounter.decrement();
252 #endif
253
254     if (m_networkProcess)
255         m_networkProcess->shutDownProcess();
256 }
257
258 void WebProcessPool::initializeClient(const WKContextClientBase* client)
259 {
260     m_client.initialize(client);
261 }
262
263 void WebProcessPool::initializeInjectedBundleClient(const WKContextInjectedBundleClientBase* client)
264 {
265     m_injectedBundleClient.initialize(client);
266 }
267
268 void WebProcessPool::initializeConnectionClient(const WKContextConnectionClientBase* client)
269 {
270     m_connectionClient.initialize(client);
271 }
272
273 void WebProcessPool::setHistoryClient(std::unique_ptr<API::LegacyContextHistoryClient> historyClient)
274 {
275     if (!historyClient)
276         m_historyClient = std::make_unique<API::LegacyContextHistoryClient>();
277     else
278         m_historyClient = WTFMove(historyClient);
279 }
280
281 void WebProcessPool::setDownloadClient(std::unique_ptr<API::DownloadClient> downloadClient)
282 {
283     if (!downloadClient)
284         m_downloadClient = std::make_unique<API::DownloadClient>();
285     else
286         m_downloadClient = WTFMove(downloadClient);
287 }
288
289 void WebProcessPool::setAutomationClient(std::unique_ptr<API::AutomationClient> automationClient)
290 {
291     if (!automationClient)
292         m_automationClient = std::make_unique<API::AutomationClient>();
293     else
294         m_automationClient = WTFMove(automationClient);
295 }
296
297 void WebProcessPool::setMaximumNumberOfProcesses(unsigned maximumNumberOfProcesses)
298 {
299     // Guard against API misuse.
300     if (!m_processes.isEmpty())
301         CRASH();
302
303     m_configuration->setMaximumProcessCount(maximumNumberOfProcesses);
304 }
305
306 IPC::Connection* WebProcessPool::networkingProcessConnection()
307 {
308     return m_networkProcess->connection();
309 }
310
311 void WebProcessPool::languageChanged(void* context)
312 {
313     static_cast<WebProcessPool*>(context)->languageChanged();
314 }
315
316 void WebProcessPool::languageChanged()
317 {
318     sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages()));
319 #if USE(SOUP)
320     if (m_networkProcess)
321         m_networkProcess->send(Messages::NetworkProcess::UserPreferredLanguagesChanged(userPreferredLanguages()), 0);
322 #endif
323 }
324
325 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
326 {
327     sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
328 }
329
330 void WebProcessPool::textCheckerStateChanged()
331 {
332     sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
333 }
334
335 NetworkProcessProxy& WebProcessPool::ensureNetworkProcess()
336 {
337     if (m_networkProcess)
338         return *m_networkProcess;
339
340     m_networkProcess = NetworkProcessProxy::create(*this);
341
342     NetworkProcessCreationParameters parameters;
343
344     parameters.privateBrowsingEnabled = WebPreferences::anyPagesAreUsingPrivateBrowsing();
345
346     parameters.cacheModel = cacheModel();
347     parameters.diskCacheSizeOverride = m_configuration->diskCacheSizeOverride();
348     parameters.canHandleHTTPSServerTrustEvaluation = m_canHandleHTTPSServerTrustEvaluation;
349
350     parameters.diskCacheDirectory = m_configuration->diskCacheDirectory();
351     if (!parameters.diskCacheDirectory.isEmpty())
352         SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle);
353
354 #if ENABLE(SECCOMP_FILTERS)
355     parameters.cookieStorageDirectory = this->cookieStorageDirectory();
356 #endif
357
358 #if PLATFORM(IOS)
359     String cookieStorageDirectory = this->cookieStorageDirectory();
360     if (!cookieStorageDirectory.isEmpty())
361         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
362
363     String containerCachesDirectory = this->networkingCachesDirectory();
364     if (!containerCachesDirectory.isEmpty())
365         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
366
367     String parentBundleDirectory = this->parentBundleDirectory();
368     if (!parentBundleDirectory.isEmpty())
369         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
370 #endif
371
372     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
373
374     // Add any platform specific parameters
375     platformInitializeNetworkProcess(parameters);
376
377     // Initialize the network process.
378     m_networkProcess->send(Messages::NetworkProcess::InitializeNetworkProcess(parameters), 0);
379
380 #if PLATFORM(COCOA)
381     m_networkProcess->send(Messages::NetworkProcess::SetQOS(networkProcessLatencyQOS(), networkProcessThroughputQOS()), 0);
382 #endif
383
384     if (m_didNetworkProcessCrash) {
385         m_didNetworkProcessCrash = false;
386         for (auto& process : m_processes)
387             process->reinstateNetworkProcessAssertionState(*m_networkProcess);
388     }
389
390     return *m_networkProcess;
391 }
392
393 void WebProcessPool::networkProcessCrashed(NetworkProcessProxy* networkProcessProxy)
394 {
395     ASSERT(m_networkProcess);
396     ASSERT(networkProcessProxy == m_networkProcess.get());
397     m_didNetworkProcessCrash = true;
398
399     WebContextSupplementMap::const_iterator it = m_supplements.begin();
400     WebContextSupplementMap::const_iterator end = m_supplements.end();
401     for (; it != end; ++it)
402         it->value->processDidClose(networkProcessProxy);
403
404     m_client.networkProcessDidCrash(this);
405
406     // Leave the process proxy around during client call, so that the client could query the process identifier.
407     m_networkProcess = nullptr;
408 }
409
410 void WebProcessPool::getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply)
411 {
412     ASSERT(reply);
413
414     ensureNetworkProcess();
415     ASSERT(m_networkProcess);
416
417     m_networkProcess->getNetworkProcessConnection(reply);
418 }
419
420 #if ENABLE(DATABASE_PROCESS)
421 void WebProcessPool::ensureDatabaseProcess()
422 {
423     if (m_databaseProcess)
424         return;
425
426     m_databaseProcess = DatabaseProcessProxy::create(this);
427
428     // *********
429     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
430     // *********
431     DatabaseProcessCreationParameters parameters;
432 #if ENABLE(INDEXED_DATABASE)
433     ASSERT(!m_configuration->indexedDBDatabaseDirectory().isEmpty());
434     parameters.indexedDatabaseDirectory = m_configuration->indexedDBDatabaseDirectory();
435
436     SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
437 #endif
438
439     m_databaseProcess->send(Messages::DatabaseProcess::InitializeDatabaseProcess(parameters), 0);
440 }
441
442 void WebProcessPool::getDatabaseProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetDatabaseProcessConnection::DelayedReply> reply)
443 {
444     ASSERT(reply);
445
446     ensureDatabaseProcess();
447
448     m_databaseProcess->getDatabaseProcessConnection(reply);
449 }
450
451 void WebProcessPool::databaseProcessCrashed(DatabaseProcessProxy* databaseProcessProxy)
452 {
453     ASSERT(m_databaseProcess);
454     ASSERT(databaseProcessProxy == m_databaseProcess.get());
455
456     for (auto& supplement : m_supplements)
457         supplement.value->processDidClose(databaseProcessProxy);
458
459     m_client.databaseProcessDidCrash(this);
460     m_databaseProcess = nullptr;
461 }
462 #endif
463
464 void WebProcessPool::willStartUsingPrivateBrowsing()
465 {
466     for (auto* processPool : allProcessPools())
467         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(true);
468 }
469
470 void WebProcessPool::willStopUsingPrivateBrowsing()
471 {
472     for (auto* processPool : allProcessPools())
473         processPool->setAnyPageGroupMightHavePrivateBrowsingEnabled(false);
474 }
475
476 void WebProcessPool::windowServerConnectionStateChanged()
477 {
478     size_t processCount = m_processes.size();
479     for (size_t i = 0; i < processCount; ++i)
480         m_processes[i]->windowServerConnectionStateChanged();
481 }
482
483 void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool privateBrowsingEnabled)
484 {
485     m_iconDatabase->setPrivateBrowsingEnabled(privateBrowsingEnabled);
486
487     if (networkProcess()) {
488         if (privateBrowsingEnabled)
489             networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
490         else
491             networkProcess()->send(Messages::NetworkProcess::DestroyPrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
492     }
493
494     if (privateBrowsingEnabled)
495         sendToAllProcesses(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()));
496     else
497         sendToAllProcesses(Messages::WebProcess::DestroyPrivateBrowsingSession(SessionID::legacyPrivateSessionID()));
498 }
499
500 void (*s_invalidMessageCallback)(WKStringRef messageName);
501
502 void WebProcessPool::setInvalidMessageCallback(void (*invalidMessageCallback)(WKStringRef messageName))
503 {
504     s_invalidMessageCallback = invalidMessageCallback;
505 }
506
507 void WebProcessPool::didReceiveInvalidMessage(const IPC::StringReference& messageReceiverName, const IPC::StringReference& messageName)
508 {
509     if (!s_invalidMessageCallback)
510         return;
511
512     StringBuilder messageNameStringBuilder;
513     messageNameStringBuilder.append(messageReceiverName.data(), messageReceiverName.size());
514     messageNameStringBuilder.append('.');
515     messageNameStringBuilder.append(messageName.data(), messageName.size());
516
517     s_invalidMessageCallback(toAPI(API::String::create(messageNameStringBuilder.toString()).ptr()));
518 }
519
520 void WebProcessPool::processDidCachePage(WebProcessProxy* process)
521 {
522     if (m_processWithPageCache && m_processWithPageCache != process)
523         m_processWithPageCache->releasePageCache();
524     m_processWithPageCache = process;
525 }
526
527 WebProcessProxy& WebProcessPool::createNewWebProcess()
528 {
529     ensureNetworkProcess();
530
531     Ref<WebProcessProxy> process = WebProcessProxy::create(*this);
532
533     WebProcessCreationParameters parameters;
534
535     parameters.injectedBundlePath = injectedBundlePath();
536     if (!parameters.injectedBundlePath.isEmpty())
537         SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
538
539     parameters.applicationCacheDirectory = m_configuration->applicationCacheDirectory();
540     if (!parameters.applicationCacheDirectory.isEmpty())
541         SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle);
542
543     parameters.webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory();
544     if (!parameters.webSQLDatabaseDirectory.isEmpty())
545         SandboxExtension::createHandleForReadWriteDirectory(parameters.webSQLDatabaseDirectory, parameters.webSQLDatabaseDirectoryExtensionHandle);
546
547 #if ENABLE(SECCOMP_FILTERS)
548     parameters.cookieStorageDirectory = this->cookieStorageDirectory();
549 #endif
550
551 #if PLATFORM(IOS)
552     String cookieStorageDirectory = this->cookieStorageDirectory();
553     if (!cookieStorageDirectory.isEmpty())
554         SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle);
555
556     String containerCachesDirectory = this->webContentCachesDirectory();
557     if (!containerCachesDirectory.isEmpty())
558         SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle);
559
560     String containerTemporaryDirectory = this->containerTemporaryDirectory();
561     if (!containerTemporaryDirectory.isEmpty())
562         SandboxExtension::createHandleForReadWriteDirectory(containerTemporaryDirectory, parameters.containerTemporaryDirectoryExtensionHandle);
563 #endif
564
565     parameters.mediaKeyStorageDirectory = m_configuration->mediaKeysStorageDirectory();
566     if (!parameters.mediaKeyStorageDirectory.isEmpty())
567         SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaKeyStorageDirectory, parameters.mediaKeyStorageDirectoryExtensionHandle);
568
569     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
570
571     parameters.cacheModel = cacheModel();
572     parameters.languages = userPreferredLanguages();
573
574     copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegisteredAsEmptyDocument);
575     copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
576     copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy, parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy);
577     copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
578     copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal);
579     copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess);
580     copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated);
581     copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled);
582     copyToVector(m_schemesToRegisterAsAlwaysRevalidated, parameters.urlSchemesRegisteredAsAlwaysRevalidated);
583 #if ENABLE(CACHE_PARTITIONING)
584     copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned);
585 #endif
586
587     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
588     parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing;
589
590     // FIXME: This leaves UI process and WebProcess disagreeing about the state if the client hasn't set the path.
591     // iconDatabasePath is non-empty by default, but m_iconDatabase isn't enabled in UI process unless setDatabasePath is called explicitly.
592     parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty();
593
594     parameters.terminationTimeout = 0;
595
596     parameters.textCheckerState = TextChecker::state();
597
598     parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled();
599
600     parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval();
601
602 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
603     // FIXME: There should be a generic way for supplements to add to the intialization parameters.
604     supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions);
605 #endif
606
607     parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy();
608     copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins);
609
610     parameters.memoryCacheDisabled = m_memoryCacheDisabled;
611
612 #if ENABLE(SERVICE_CONTROLS)
613     auto& serviceController = ServicesController::singleton();
614     parameters.hasImageServices = serviceController.hasImageServices();
615     parameters.hasSelectionServices = serviceController.hasSelectionServices();
616     parameters.hasRichContentServices = serviceController.hasRichContentServices();
617     serviceController.refreshExistingServices();
618 #endif
619
620 #if ENABLE(NETSCAPE_PLUGIN_API)
621     parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies;
622 #endif
623
624 #if OS(LINUX)
625     parameters.shouldEnableMemoryPressureReliefLogging = true;
626 #endif
627
628     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
629
630     // Add any platform specific parameters
631     platformInitializeWebProcess(parameters);
632
633     RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this);
634     if (!injectedBundleInitializationUserData)
635         injectedBundleInitializationUserData = m_injectedBundleInitializationUserData;
636     parameters.initializationUserData = UserData(process->transformObjectsToHandles(injectedBundleInitializationUserData.get()));
637
638     process->send(Messages::WebProcess::InitializeWebProcess(parameters), 0);
639
640 #if PLATFORM(COCOA)
641     process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0);
642 #endif
643 #if PLATFORM(IOS)
644     ApplicationCacheStorage::singleton().setDefaultOriginQuota(25ULL * 1024 * 1024);
645 #endif
646
647     if (WebPreferences::anyPagesAreUsingPrivateBrowsing())
648         process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
649
650     m_processes.append(process.ptr());
651
652     ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty());
653
654 #if ENABLE(REMOTE_INSPECTOR)
655     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
656     Inspector::RemoteInspector::singleton(); 
657 #endif
658
659     return process;
660 }
661
662 void WebProcessPool::warmInitialProcess()  
663 {
664     if (m_haveInitialEmptyProcess) {
665         ASSERT(!m_processes.isEmpty());
666         return;
667     }
668
669     if (m_processes.size() >= maximumNumberOfProcesses())
670         return;
671
672     createNewWebProcess();
673     m_haveInitialEmptyProcess = true;
674 }
675
676 void WebProcessPool::enableProcessTermination()
677 {
678     m_processTerminationEnabled = true;
679     Vector<RefPtr<WebProcessProxy>> processes = m_processes;
680     for (size_t i = 0; i < processes.size(); ++i) {
681         if (shouldTerminate(processes[i].get()))
682             processes[i]->terminate();
683     }
684 }
685
686 bool WebProcessPool::shouldTerminate(WebProcessProxy* process)
687 {
688     ASSERT(m_processes.contains(process));
689
690     if (!m_processTerminationEnabled)
691         return false;
692
693     return true;
694 }
695
696 void WebProcessPool::processDidFinishLaunching(WebProcessProxy* process)
697 {
698     ASSERT(m_processes.contains(process));
699
700     if (!m_visitedLinksPopulated) {
701         populateVisitedLinks();
702         m_visitedLinksPopulated = true;
703     }
704
705     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
706     // so check if it needs to be started here
707     if (m_memorySamplerEnabled) {
708         SandboxExtension::Handle sampleLogSandboxHandle;        
709         double now = WTF::currentTime();
710         String sampleLogFilePath = String::format("WebProcess%llupid%d", static_cast<unsigned long long>(now), process->processIdentifier());
711         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
712         
713         process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
714     }
715
716     if (m_configuration->fullySynchronousModeIsAllowedForTesting())
717         process->connection()->allowFullySynchronousModeForTesting();
718
719     m_connectionClient.didCreateConnection(this, process->webConnection());
720 }
721
722 void WebProcessPool::disconnectProcess(WebProcessProxy* process)
723 {
724     ASSERT(m_processes.contains(process));
725
726     if (m_haveInitialEmptyProcess && process == m_processes.last())
727         m_haveInitialEmptyProcess = false;
728
729     // FIXME (Multi-WebProcess): <rdar://problem/12239765> Some of the invalidation calls of the other supplements are still necessary in multi-process mode, but they should only affect data structures pertaining to the process being disconnected.
730     // Clearing everything causes assertion failures, so it's less trouble to skip that for now.
731     RefPtr<WebProcessProxy> protect(process);
732     if (m_processWithPageCache == process)
733         m_processWithPageCache = nullptr;
734
735     static_cast<WebContextSupplement*>(supplement<WebGeolocationManagerProxy>())->processDidClose(process);
736
737     m_processes.removeFirst(process);
738 }
739
740 WebProcessProxy& WebProcessPool::createNewWebProcessRespectingProcessCountLimit()
741 {
742     if (m_processes.size() < maximumNumberOfProcesses())
743         return createNewWebProcess();
744
745     // Choose the process with fewest pages.
746     auto& process = *std::min_element(m_processes.begin(), m_processes.end(), [](const RefPtr<WebProcessProxy>& a, const RefPtr<WebProcessProxy>& b) {
747         return a->pageCount() < b->pageCount();
748     });
749
750     return *process;
751 }
752
753 Ref<WebPageProxy> WebProcessPool::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
754 {
755     if (!pageConfiguration->pageGroup())
756         pageConfiguration->setPageGroup(m_defaultPageGroup.ptr());
757     if (!pageConfiguration->preferences())
758         pageConfiguration->setPreferences(&pageConfiguration->pageGroup()->preferences());
759     if (!pageConfiguration->userContentController())
760         pageConfiguration->setUserContentController(&pageConfiguration->pageGroup()->userContentController());
761     if (!pageConfiguration->visitedLinkStore())
762         pageConfiguration->setVisitedLinkStore(m_visitedLinkStore.ptr());
763     if (!pageConfiguration->websiteDataStore()) {
764         ASSERT(!pageConfiguration->sessionID().isValid());
765         pageConfiguration->setWebsiteDataStore(m_websiteDataStore.get());
766         pageConfiguration->setSessionID(pageConfiguration->preferences()->privateBrowsingEnabled() ? SessionID::legacyPrivateSessionID() : SessionID::defaultSessionID());
767     }
768
769     RefPtr<WebProcessProxy> process;
770     if (m_haveInitialEmptyProcess) {
771         process = m_processes.last();
772         m_haveInitialEmptyProcess = false;
773     } else if (pageConfiguration->relatedPage()) {
774         // Sharing processes, e.g. when creating the page via window.open().
775         process = &pageConfiguration->relatedPage()->process();
776     } else
777         process = &createNewWebProcessRespectingProcessCountLimit();
778
779     return process->createWebPage(pageClient, WTFMove(pageConfiguration));
780 }
781
782 DownloadProxy* WebProcessPool::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
783 {
784     DownloadProxy* downloadProxy = createDownloadProxy(request);
785     SessionID sessionID = initiatingPage ? initiatingPage->sessionID() : SessionID::defaultSessionID();
786
787     if (networkProcess()) {
788         // FIXME (NetworkProcess): Replicate whatever FrameLoader::setOriginalURLForDownloadRequest does with the request here.
789         networkProcess()->send(Messages::NetworkProcess::DownloadRequest(sessionID, downloadProxy->downloadID(), request), 0);
790         return downloadProxy;
791     }
792
793     return downloadProxy;
794 }
795
796 DownloadProxy* WebProcessPool::resumeDownload(const API::Data* resumeData, const String& path)
797 {
798     DownloadProxy* downloadProxy = createDownloadProxy(ResourceRequest());
799
800     SandboxExtension::Handle sandboxExtensionHandle;
801     if (!path.isEmpty())
802         SandboxExtension::createHandle(path, SandboxExtension::ReadWrite, sandboxExtensionHandle);
803
804     if (networkProcess()) {
805         // FIXME: If we started a download in an ephemeral session and that session still exists, we should find a way to use that same session.
806         networkProcess()->send(Messages::NetworkProcess::ResumeDownload(SessionID::defaultSessionID(), downloadProxy->downloadID(), resumeData->dataReference(), path, sandboxExtensionHandle), 0);
807         return downloadProxy;
808     }
809
810     return downloadProxy;
811 }
812
813 void WebProcessPool::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
814 {
815     for (auto& process : m_processes) {
816         // FIXME: Return early if the message body contains any references to WKPageRefs/WKFrameRefs etc. since they're local to a process.
817         process->send(Messages::WebProcess::HandleInjectedBundleMessage(messageName, UserData(process->transformObjectsToHandles(messageBody).get())), 0);
818     }
819 }
820
821 void WebProcessPool::populateVisitedLinks()
822 {
823     m_historyClient->populateVisitedLinks(*this);
824 }
825
826 WebProcessPool::Statistics& WebProcessPool::statistics()
827 {
828     static Statistics statistics = Statistics();
829
830     return statistics;
831 }
832
833 #if ENABLE(NETSCAPE_PLUGIN_API)
834 void WebProcessPool::setAdditionalPluginsDirectory(const String& directory)
835 {
836     Vector<String> directories;
837     directories.append(directory);
838
839     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
840 }
841 #endif // ENABLE(NETSCAPE_PLUGIN_API)
842
843 pid_t WebProcessPool::networkProcessIdentifier()
844 {
845     if (!m_networkProcess)
846         return 0;
847
848     return m_networkProcess->processIdentifier();
849 }
850
851 pid_t WebProcessPool::databaseProcessIdentifier()
852 {
853 #if ENABLE(DATABASE_PROCESS)
854     if (!m_databaseProcess)
855         return 0;
856
857     return m_databaseProcess->processIdentifier();
858 #else
859     return 0;
860 #endif
861 }
862
863 void WebProcessPool::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
864 {
865     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
866     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
867 }
868
869 void WebProcessPool::setShouldUseFontSmoothing(bool useFontSmoothing)
870 {
871     m_shouldUseFontSmoothing = useFontSmoothing;
872     sendToAllProcesses(Messages::WebProcess::SetShouldUseFontSmoothing(useFontSmoothing));
873 }
874
875 void WebProcessPool::registerURLSchemeAsEmptyDocument(const String& urlScheme)
876 {
877     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
878     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
879 }
880
881 void WebProcessPool::registerURLSchemeAsSecure(const String& urlScheme)
882 {
883     m_schemesToRegisterAsSecure.add(urlScheme);
884     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
885 }
886
887 void WebProcessPool::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme)
888 {
889     m_schemesToRegisterAsBypassingContentSecurityPolicy.add(urlScheme);
890     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsBypassingContentSecurityPolicy(urlScheme));
891 }
892
893 void WebProcessPool::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
894 {
895     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
896     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
897 }
898
899 void WebProcessPool::setCanHandleHTTPSServerTrustEvaluation(bool value)
900 {
901     m_canHandleHTTPSServerTrustEvaluation = value;
902     if (m_networkProcess) {
903         m_networkProcess->send(Messages::NetworkProcess::SetCanHandleHTTPSServerTrustEvaluation(value), 0);
904         return;
905     }
906 }
907
908 void WebProcessPool::registerURLSchemeAsLocal(const String& urlScheme)
909 {
910     m_schemesToRegisterAsLocal.add(urlScheme);
911     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsLocal(urlScheme));
912 }
913
914 void WebProcessPool::registerURLSchemeAsNoAccess(const String& urlScheme)
915 {
916     m_schemesToRegisterAsNoAccess.add(urlScheme);
917     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsNoAccess(urlScheme));
918 }
919
920 void WebProcessPool::registerURLSchemeAsDisplayIsolated(const String& urlScheme)
921 {
922     m_schemesToRegisterAsDisplayIsolated.add(urlScheme);
923     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsDisplayIsolated(urlScheme));
924 }
925
926 void WebProcessPool::registerURLSchemeAsCORSEnabled(const String& urlScheme)
927 {
928     m_schemesToRegisterAsCORSEnabled.add(urlScheme);
929     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCORSEnabled(urlScheme));
930 }
931
932 HashSet<String, ASCIICaseInsensitiveHash>& WebProcessPool::globalURLSchemesWithCustomProtocolHandlers()
933 {
934     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> set;
935     return set;
936 }
937
938 void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
939 {
940     if (!urlScheme)
941         return;
942
943     globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
944     for (auto* processPool : allProcessPools())
945         processPool->registerSchemeForCustomProtocol(urlScheme);
946 }
947
948 void WebProcessPool::unregisterGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
949 {
950     if (!urlScheme)
951         return;
952
953     globalURLSchemesWithCustomProtocolHandlers().remove(urlScheme);
954     for (auto* processPool : allProcessPools())
955         processPool->unregisterSchemeForCustomProtocol(urlScheme);
956 }
957
958 #if ENABLE(CACHE_PARTITIONING)
959 void WebProcessPool::registerURLSchemeAsCachePartitioned(const String& urlScheme)
960 {
961     m_schemesToRegisterAsCachePartitioned.add(urlScheme);
962     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsCachePartitioned(urlScheme));
963 }
964 #endif
965
966 void WebProcessPool::setCacheModel(CacheModel cacheModel)
967 {
968     m_configuration->setCacheModel(cacheModel);
969     sendToAllProcesses(Messages::WebProcess::SetCacheModel(cacheModel));
970
971     if (m_networkProcess)
972         m_networkProcess->send(Messages::NetworkProcess::SetCacheModel(cacheModel), 0);
973 }
974
975 void WebProcessPool::setDefaultRequestTimeoutInterval(double timeoutInterval)
976 {
977     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
978 }
979
980 DownloadProxy* WebProcessPool::createDownloadProxy(const ResourceRequest& request)
981 {
982     return ensureNetworkProcess().createDownloadProxy(request);
983 }
984
985 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
986 {
987     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
988 }
989
990 void WebProcessPool::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
991 {
992     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
993 }
994
995 void WebProcessPool::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
996 {
997     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
998 }
999
1000 bool WebProcessPool::dispatchMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
1001 {
1002     return m_messageReceiverMap.dispatchMessage(connection, decoder);
1003 }
1004
1005 bool WebProcessPool::dispatchSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
1006 {
1007     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
1008 }
1009
1010 void WebProcessPool::setEnhancedAccessibility(bool flag)
1011 {
1012     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
1013 }
1014     
1015 void WebProcessPool::startMemorySampler(const double interval)
1016 {    
1017     // For new WebProcesses we will also want to start the Memory Sampler
1018     m_memorySamplerEnabled = true;
1019     m_memorySamplerInterval = interval;
1020     
1021     // For UIProcess
1022 #if ENABLE(MEMORY_SAMPLER)
1023     WebMemorySampler::singleton()->start(interval);
1024 #endif
1025     
1026     // For WebProcess
1027     SandboxExtension::Handle sampleLogSandboxHandle;    
1028     double now = WTF::currentTime();
1029     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<unsigned long long>(now));
1030     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::ReadWrite, sampleLogSandboxHandle);
1031     
1032     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
1033 }
1034
1035 void WebProcessPool::stopMemorySampler()
1036 {    
1037     // For WebProcess
1038     m_memorySamplerEnabled = false;
1039     
1040     // For UIProcess
1041 #if ENABLE(MEMORY_SAMPLER)
1042     WebMemorySampler::singleton()->stop();
1043 #endif
1044
1045     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
1046 }
1047
1048 void WebProcessPool::setIconDatabasePath(const String& path)
1049 {
1050     m_overrideIconDatabasePath = path;
1051     if (!m_overrideIconDatabasePath.isEmpty()) {
1052         // This implicitly enables the database on UI process side.
1053         m_iconDatabase->setDatabasePath(path);
1054     }
1055 }
1056
1057 String WebProcessPool::iconDatabasePath() const
1058 {
1059     if (!m_overrideIconDatabasePath.isNull())
1060         return m_overrideIconDatabasePath;
1061
1062     return platformDefaultIconDatabasePath();
1063 }
1064
1065 #if ENABLE(SECCOMP_FILTERS)
1066 String WebProcessPool::cookieStorageDirectory() const
1067 {
1068     if (!m_overrideCookieStorageDirectory.isEmpty())
1069         return m_overrideCookieStorageDirectory;
1070
1071     // FIXME: This doesn't make much sense. Is this function used at all? We used to call platform code, but no existing platforms implemented that function.
1072     return emptyString();
1073 }
1074 #endif
1075
1076 void WebProcessPool::useTestingNetworkSession()
1077 {
1078     ASSERT(m_processes.isEmpty());
1079     ASSERT(!m_networkProcess);
1080
1081     if (m_networkProcess)
1082         return;
1083
1084     if (!m_processes.isEmpty())
1085         return;
1086
1087     m_shouldUseTestingNetworkSession = true;
1088 }
1089
1090 void WebProcessPool::clearCachedCredentials()
1091 {
1092     sendToAllProcesses(Messages::WebProcess::ClearCachedCredentials());
1093     if (m_networkProcess)
1094         m_networkProcess->send(Messages::NetworkProcess::ClearCachedCredentials(), 0);
1095 }
1096
1097 void WebProcessPool::terminateDatabaseProcess()
1098 {
1099 #if ENABLE(DATABASE_PROCESS)
1100     ASSERT(m_processes.isEmpty());
1101     if (!m_databaseProcess)
1102         return;
1103
1104     m_databaseProcess->terminate();
1105     m_databaseProcess = nullptr;
1106 #endif
1107 }
1108
1109 void WebProcessPool::allowSpecificHTTPSCertificateForHost(const WebCertificateInfo* certificate, const String& host)
1110 {
1111     if (m_networkProcess)
1112         m_networkProcess->send(Messages::NetworkProcess::AllowSpecificHTTPSCertificateForHost(certificate->certificateInfo(), host), 0);
1113 }
1114
1115 void WebProcessPool::updateAutomationCapabilities() const
1116 {
1117 #if ENABLE(REMOTE_INSPECTOR)
1118     Inspector::RemoteInspector::singleton().clientCapabilitiesDidChange();
1119 #endif
1120 }
1121
1122 void WebProcessPool::setAutomationSession(RefPtr<WebAutomationSession>&& automationSession)
1123 {
1124     m_automationSession = WTFMove(automationSession);
1125
1126 #if ENABLE(REMOTE_INSPECTOR)
1127     if (m_automationSession) {
1128         m_automationSession->init();
1129         m_automationSession->setProcessPool(this);
1130     }
1131 #endif
1132 }
1133
1134 void WebProcessPool::setHTTPPipeliningEnabled(bool enabled)
1135 {
1136 #if PLATFORM(COCOA)
1137     ResourceRequest::setHTTPPipeliningEnabled(enabled);
1138 #else
1139     UNUSED_PARAM(enabled);
1140 #endif
1141 }
1142
1143 bool WebProcessPool::httpPipeliningEnabled() const
1144 {
1145 #if PLATFORM(COCOA)
1146     return ResourceRequest::httpPipeliningEnabled();
1147 #else
1148     return false;
1149 #endif
1150 }
1151
1152 void WebProcessPool::getStatistics(uint32_t statisticsMask, std::function<void (API::Dictionary*, CallbackBase::Error)> callbackFunction)
1153 {
1154     if (!statisticsMask) {
1155         callbackFunction(nullptr, CallbackBase::Error::Unknown);
1156         return;
1157     }
1158
1159     RefPtr<StatisticsRequest> request = StatisticsRequest::create(DictionaryCallback::create(WTFMove(callbackFunction)));
1160
1161     if (statisticsMask & StatisticsRequestTypeWebContent)
1162         requestWebContentStatistics(request.get());
1163     
1164     if (statisticsMask & StatisticsRequestTypeNetworking)
1165         requestNetworkingStatistics(request.get());
1166 }
1167
1168 void WebProcessPool::requestWebContentStatistics(StatisticsRequest* request)
1169 {
1170     // FIXME (Multi-WebProcess) <rdar://problem/13200059>: Make getting statistics from multiple WebProcesses work.
1171 }
1172
1173 void WebProcessPool::requestNetworkingStatistics(StatisticsRequest* request)
1174 {
1175     if (!m_networkProcess) {
1176         LOG_ERROR("Attempt to get NetworkProcess statistics but the NetworkProcess is unavailable");
1177         return;
1178     }
1179
1180     uint64_t requestID = request->addOutstandingRequest();
1181     m_statisticsRequests.set(requestID, request);
1182     m_networkProcess->send(Messages::NetworkProcess::GetNetworkProcessStatistics(requestID), 0);
1183 }
1184
1185 void WebProcessPool::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
1186 {
1187     auto* webProcessProxy = WebProcessProxy::fromConnection(&connection);
1188     if (!webProcessProxy)
1189         return;
1190     m_injectedBundleClient.didReceiveMessageFromInjectedBundle(this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get());
1191 }
1192
1193 void WebProcessPool::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
1194 {
1195     auto* webProcessProxy = WebProcessProxy::fromConnection(&connection);
1196     if (!webProcessProxy)
1197         return;
1198
1199     RefPtr<API::Object> returnData;
1200     m_injectedBundleClient.didReceiveSynchronousMessageFromInjectedBundle(this, messageName, webProcessProxy->transformHandlesToObjects(messageBody.object()).get(), returnData);
1201     returnUserData = UserData(webProcessProxy->transformObjectsToHandles(returnData.get()));
1202 }
1203
1204 void WebProcessPool::didGetStatistics(const StatisticsData& statisticsData, uint64_t requestID)
1205 {
1206     RefPtr<StatisticsRequest> request = m_statisticsRequests.take(requestID);
1207     if (!request) {
1208         LOG_ERROR("Cannot report networking statistics.");
1209         return;
1210     }
1211
1212     request->completedRequest(requestID, statisticsData);
1213 }
1214
1215 void WebProcessPool::garbageCollectJavaScriptObjects()
1216 {
1217     sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects());
1218 }
1219
1220 void WebProcessPool::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1221 {
1222     sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag));
1223 }
1224
1225 void WebProcessPool::addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, SessionID sessionID)
1226 {
1227     m_plugInAutoStartProvider.addAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID);
1228 }
1229
1230 void WebProcessPool::plugInDidReceiveUserInteraction(unsigned plugInOriginHash, SessionID sessionID)
1231 {
1232     m_plugInAutoStartProvider.didReceiveUserInteraction(plugInOriginHash, sessionID);
1233 }
1234
1235 PassRefPtr<API::Dictionary> WebProcessPool::plugInAutoStartOriginHashes() const
1236 {
1237     return m_plugInAutoStartProvider.autoStartOriginsTableCopy();
1238 }
1239
1240 void WebProcessPool::setPlugInAutoStartOriginHashes(API::Dictionary& dictionary)
1241 {
1242     m_plugInAutoStartProvider.setAutoStartOriginsTable(dictionary);
1243 }
1244
1245 void WebProcessPool::setPlugInAutoStartOrigins(API::Array& array)
1246 {
1247     m_plugInAutoStartProvider.setAutoStartOriginsArray(array);
1248 }
1249
1250 void WebProcessPool::setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& dictionary, double time)
1251 {
1252     m_plugInAutoStartProvider.setAutoStartOriginsFilteringOutEntriesAddedAfterTime(dictionary, time);
1253 }
1254
1255 void WebProcessPool::registerSchemeForCustomProtocol(const String& scheme)
1256 {
1257     sendToNetworkingProcess(Messages::CustomProtocolManager::RegisterScheme(scheme));
1258 }
1259
1260 void WebProcessPool::unregisterSchemeForCustomProtocol(const String& scheme)
1261 {
1262     sendToNetworkingProcess(Messages::CustomProtocolManager::UnregisterScheme(scheme));
1263 }
1264
1265 #if ENABLE(NETSCAPE_PLUGIN_API)
1266 void WebProcessPool::pluginInfoStoreDidLoadPlugins(PluginInfoStore* store)
1267 {
1268 #ifdef NDEBUG
1269     UNUSED_PARAM(store);
1270 #endif
1271     ASSERT(store == &m_pluginInfoStore);
1272
1273     Vector<PluginModuleInfo> pluginModules = m_pluginInfoStore.plugins();
1274
1275     Vector<RefPtr<API::Object>> plugins;
1276     plugins.reserveInitialCapacity(pluginModules.size());
1277
1278     for (const auto& pluginModule : pluginModules) {
1279         API::Dictionary::MapType map;
1280         map.set(ASCIILiteral("path"), API::String::create(pluginModule.path));
1281         map.set(ASCIILiteral("name"), API::String::create(pluginModule.info.name));
1282         map.set(ASCIILiteral("file"), API::String::create(pluginModule.info.file));
1283         map.set(ASCIILiteral("desc"), API::String::create(pluginModule.info.desc));
1284
1285         Vector<RefPtr<API::Object>> mimeTypes;
1286         mimeTypes.reserveInitialCapacity(pluginModule.info.mimes.size());
1287         for (const auto& mimeClassInfo : pluginModule.info.mimes)
1288             mimeTypes.uncheckedAppend(API::String::create(mimeClassInfo.type));
1289         map.set(ASCIILiteral("mimes"), API::Array::create(WTFMove(mimeTypes)));
1290
1291 #if PLATFORM(COCOA)
1292         map.set(ASCIILiteral("bundleId"), API::String::create(pluginModule.bundleIdentifier));
1293         map.set(ASCIILiteral("version"), API::String::create(pluginModule.versionString));
1294 #endif
1295
1296         plugins.uncheckedAppend(API::Dictionary::create(WTFMove(map)));
1297     }
1298
1299     m_client.plugInInformationBecameAvailable(this, API::Array::create(WTFMove(plugins)).ptr());
1300 }
1301
1302 void WebProcessPool::setPluginLoadClientPolicy(WebCore::PluginLoadClientPolicy policy, const String& host, const String& bundleIdentifier, const String& versionString)
1303 {
1304 #if ENABLE(NETSCAPE_PLUGIN_API)
1305     HashMap<String, HashMap<String, uint8_t>> policiesByIdentifier;
1306     if (m_pluginLoadClientPolicies.contains(host))
1307         policiesByIdentifier = m_pluginLoadClientPolicies.get(host);
1308
1309     HashMap<String, uint8_t> versionsToPolicies;
1310     if (policiesByIdentifier.contains(bundleIdentifier))
1311         versionsToPolicies = policiesByIdentifier.get(bundleIdentifier);
1312
1313     versionsToPolicies.set(versionString, policy);
1314     policiesByIdentifier.set(bundleIdentifier, versionsToPolicies);
1315     m_pluginLoadClientPolicies.set(host, policiesByIdentifier);
1316 #endif
1317
1318     sendToAllProcesses(Messages::WebProcess::SetPluginLoadClientPolicy(policy, host, bundleIdentifier, versionString));
1319 }
1320
1321 void WebProcessPool::clearPluginClientPolicies()
1322 {
1323 #if ENABLE(NETSCAPE_PLUGIN_API)
1324     m_pluginLoadClientPolicies.clear();
1325 #endif
1326     sendToAllProcesses(Messages::WebProcess::ClearPluginClientPolicies());
1327 }
1328 #endif
1329     
1330 void WebProcessPool::setMemoryCacheDisabled(bool disabled)
1331 {
1332     m_memoryCacheDisabled = disabled;
1333     sendToAllProcesses(Messages::WebProcess::SetMemoryCacheDisabled(disabled));
1334 }
1335
1336 void WebProcessPool::setFontWhitelist(API::Array* array)
1337 {
1338     m_fontWhitelist.clear();
1339     if (array) {
1340         for (size_t i = 0; i < array->size(); ++i) {
1341             if (API::String* font = array->at<API::String>(i))
1342                 m_fontWhitelist.append(font->string());
1343         }
1344     }
1345 }
1346
1347 void WebProcessPool::updateHiddenPageThrottlingAutoIncreaseLimit()
1348 {
1349     // We're estimating an upper bound for a set of background timer fires for a page to be 200ms
1350     // (including all timer fires, all paging-in, and any resulting GC). To ensure this does not
1351     // result in more than 1% CPU load allow for one timer fire per 100x this duration.
1352     static int maximumTimerThrottlePerPageInMS = 200 * 100;
1353
1354     int limitInMilliseconds = maximumTimerThrottlePerPageInMS * m_hiddenPageThrottlingAutoIncreasesCounter.value();
1355     sendToAllProcesses(Messages::WebProcess::SetHiddenPageTimerThrottlingIncreaseLimit(limitInMilliseconds));
1356 }
1357
1358 } // namespace WebKit