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