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