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