Fix warnings for unused lambda captures in Source/WebKit
[WebKit-https.git] / Source / WebKit / UIProcess / WebProcessProxy.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 "WebProcessProxy.h"
28
29 #include "APIFrameHandle.h"
30 #include "APIPageGroupHandle.h"
31 #include "APIPageHandle.h"
32 #include "DataReference.h"
33 #include "DownloadProxyMap.h"
34 #include "Logging.h"
35 #include "PluginInfoStore.h"
36 #include "PluginProcessManager.h"
37 #include "TextChecker.h"
38 #include "TextCheckerState.h"
39 #include "UIMessagePortChannelProvider.h"
40 #include "UserData.h"
41 #include "WebBackForwardListItem.h"
42 #include "WebInspectorUtilities.h"
43 #include "WebNavigationDataStore.h"
44 #include "WebNotificationManagerProxy.h"
45 #include "WebPageGroup.h"
46 #include "WebPageProxy.h"
47 #include "WebPasteboardProxy.h"
48 #include "WebProcessMessages.h"
49 #include "WebProcessPool.h"
50 #include "WebProcessProxyMessages.h"
51 #include "WebUserContentControllerProxy.h"
52 #include "WebsiteData.h"
53 #include "WebsiteDataFetchOption.h"
54 #include <WebCore/DiagnosticLoggingKeys.h>
55 #include <WebCore/PublicSuffix.h>
56 #include <WebCore/SuddenTermination.h>
57 #include <WebCore/URL.h>
58 #include <stdio.h>
59 #include <wtf/NeverDestroyed.h>
60 #include <wtf/RunLoop.h>
61 #include <wtf/text/CString.h>
62 #include <wtf/text/StringBuilder.h>
63 #include <wtf/text/WTFString.h>
64
65 #if PLATFORM(COCOA)
66 #include "ObjCObjectGraph.h"
67 #include "PDFPlugin.h"
68 #include "UserMediaCaptureManagerProxy.h"
69 #endif
70
71 #if ENABLE(SEC_ITEM_SHIM)
72 #include "SecItemShimProxy.h"
73 #endif
74
75 using namespace WebCore;
76
77 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
78 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromWebProcess(url), connection())
79
80 namespace WebKit {
81
82 static HashMap<ProcessIdentifier, WebProcessProxy*>& allProcesses()
83 {
84     ASSERT(isMainThread());
85     static NeverDestroyed<HashMap<ProcessIdentifier, WebProcessProxy*>> map;
86     return map;
87 }
88
89 WebProcessProxy* WebProcessProxy::processForIdentifier(ProcessIdentifier identifier)
90 {
91     return allProcesses().get(identifier);
92 }
93
94 uint64_t WebProcessProxy::generatePageID()
95 {
96     static uint64_t uniquePageID;
97     return ++uniquePageID;
98 }
99
100 static WebProcessProxy::WebPageProxyMap& globalPageMap()
101 {
102     ASSERT(RunLoop::isMain());
103     static NeverDestroyed<WebProcessProxy::WebPageProxyMap> pageMap;
104     return pageMap;
105 }
106
107 Ref<WebProcessProxy> WebProcessProxy::create(WebProcessPool& processPool, WebsiteDataStore& websiteDataStore)
108 {
109     auto proxy = adoptRef(*new WebProcessProxy(processPool, websiteDataStore));
110     proxy->connect();
111     return proxy;
112 }
113
114 WebProcessProxy::WebProcessProxy(WebProcessPool& processPool, WebsiteDataStore& websiteDataStore)
115     : ChildProcessProxy(processPool.alwaysRunsAtBackgroundPriority())
116     , m_responsivenessTimer(*this)
117     , m_backgroundResponsivenessTimer(*this)
118     , m_processPool(processPool)
119     , m_mayHaveUniversalFileReadSandboxExtension(false)
120     , m_numberOfTimesSuddenTerminationWasDisabled(0)
121     , m_throttler(*this, processPool.shouldTakeUIBackgroundAssertion())
122     , m_isResponsive(NoOrMaybe::Maybe)
123     , m_visiblePageCounter([this](RefCounterEvent) { updateBackgroundResponsivenessTimer(); })
124     , m_websiteDataStore(websiteDataStore)
125 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
126     , m_userMediaCaptureManagerProxy(std::make_unique<UserMediaCaptureManagerProxy>(*this))
127 #endif
128 {
129     auto result = allProcesses().add(coreProcessIdentifier(), this);
130     ASSERT_UNUSED(result, result.isNewEntry);
131
132     WebPasteboardProxy::singleton().addWebProcessProxy(*this);
133 }
134
135 WebProcessProxy::~WebProcessProxy()
136 {
137     ASSERT(m_pageURLRetainCountMap.isEmpty());
138
139     auto result = allProcesses().remove(coreProcessIdentifier());
140     ASSERT_UNUSED(result, result);
141
142     WebPasteboardProxy::singleton().removeWebProcessProxy(*this);
143
144     if (m_webConnection)
145         m_webConnection->invalidate();
146
147     while (m_numberOfTimesSuddenTerminationWasDisabled-- > 0)
148         WebCore::enableSuddenTermination();
149
150     for (auto& callback : m_localPortActivityCompletionHandlers.values())
151         callback(MessagePortChannelProvider::HasActivity::No);
152 }
153
154 void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
155 {
156     launchOptions.processType = ProcessLauncher::ProcessType::Web;
157
158     ChildProcessProxy::getLaunchOptions(launchOptions);
159
160     if (WebKit::isInspectorProcessPool(m_processPool))
161         launchOptions.extraInitializationData.add(ASCIILiteral("inspector-process"), ASCIILiteral("1"));
162
163     auto overrideLanguages = m_processPool->configuration().overrideLanguages();
164     if (overrideLanguages.size()) {
165         StringBuilder languageString;
166         for (size_t i = 0; i < overrideLanguages.size(); ++i) {
167             if (i)
168                 languageString.append(',');
169             languageString.append(overrideLanguages[i]);
170         }
171         launchOptions.extraInitializationData.add(ASCIILiteral("OverrideLanguages"), languageString.toString());
172     }
173
174     launchOptions.nonValidInjectedCodeAllowed = shouldAllowNonValidInjectedCode();
175 }
176
177 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
178 {
179     ASSERT(this->connection() == &connection);
180
181 #if ENABLE(SEC_ITEM_SHIM)
182     SecItemShimProxy::singleton().initializeConnection(connection);
183 #endif
184
185     for (auto& page : m_pageMap.values())
186         page->connectionWillOpen(connection);
187 }
188
189 void WebProcessProxy::processWillShutDown(IPC::Connection& connection)
190 {
191     ASSERT_UNUSED(connection, this->connection() == &connection);
192
193     for (auto& page : m_pageMap.values())
194         page->webProcessWillShutDown();
195 }
196
197 void WebProcessProxy::shutDown()
198 {
199     shutDownProcess();
200
201     if (m_webConnection) {
202         m_webConnection->invalidate();
203         m_webConnection = nullptr;
204     }
205
206     m_responsivenessTimer.invalidate();
207     m_backgroundResponsivenessTimer.invalidate();
208     m_tokenForHoldingLockedFiles = nullptr;
209
210     for (auto& frame : copyToVector(m_frameMap.values()))
211         frame->webProcessWillShutDown();
212     m_frameMap.clear();
213
214     for (auto* visitedLinkStore : m_visitedLinkStores)
215         visitedLinkStore->removeProcess(*this);
216     m_visitedLinkStores.clear();
217
218     for (auto* webUserContentControllerProxy : m_webUserContentControllerProxies)
219         webUserContentControllerProxy->removeProcess(*this);
220     m_webUserContentControllerProxies.clear();
221
222     m_userInitiatedActionMap.clear();
223
224     for (auto& port : m_processEntangledPorts)
225         UIMessagePortChannelProvider::singleton().registry().didCloseMessagePort(port);
226
227     m_processPool->disconnectProcess(this);
228 }
229
230 WebPageProxy* WebProcessProxy::webPage(uint64_t pageID)
231 {
232     return globalPageMap().get(pageID);
233 }
234
235 void WebProcessProxy::deleteWebsiteDataForTopPrivatelyControlledDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType> dataTypes, Vector<String>&& topPrivatelyControlledDomains, bool shouldNotifyPage, Function<void (const HashSet<String>&)>&& completionHandler)
236 {
237     // We expect this to be called on the main thread so we get the default website data store.
238     ASSERT(RunLoop::isMain());
239     
240     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
241         explicit CallbackAggregator(Function<void(HashSet<String>)>&& completionHandler)
242             : completionHandler(WTFMove(completionHandler))
243         {
244         }
245         void addDomainsWithDeletedWebsiteData(const HashSet<String>& domains)
246         {
247             domainsWithDeletedWebsiteData.add(domains.begin(), domains.end());
248         }
249         
250         void addPendingCallback()
251         {
252             ++pendingCallbacks;
253         }
254         
255         void removePendingCallback()
256         {
257             ASSERT(pendingCallbacks);
258             --pendingCallbacks;
259             
260             callIfNeeded();
261         }
262         
263         void callIfNeeded()
264         {
265             if (!pendingCallbacks)
266                 completionHandler(domainsWithDeletedWebsiteData);
267         }
268         
269         unsigned pendingCallbacks = 0;
270         Function<void(HashSet<String>)> completionHandler;
271         HashSet<String> domainsWithDeletedWebsiteData;
272     };
273     
274     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(WTFMove(completionHandler)));
275     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
276
277     HashSet<PAL::SessionID> visitedSessionIDs;
278     for (auto& page : globalPageMap()) {
279         auto& dataStore = page.value->websiteDataStore();
280         if (!dataStore.isPersistent() || visitedSessionIDs.contains(dataStore.sessionID()))
281             continue;
282         visitedSessionIDs.add(dataStore.sessionID());
283         callbackAggregator->addPendingCallback();
284         dataStore.removeDataForTopPrivatelyControlledDomains(dataTypes, fetchOptions, topPrivatelyControlledDomains, [callbackAggregator, shouldNotifyPage, page](HashSet<String>&& domainsWithDeletedWebsiteData) {
285             // When completing the task, we should be getting called on the main thread.
286             ASSERT(RunLoop::isMain());
287             
288             if (shouldNotifyPage)
289                 page.value->postMessageToInjectedBundle("WebsiteDataDeletionForTopPrivatelyOwnedDomainsFinished", nullptr);
290             
291             callbackAggregator->addDomainsWithDeletedWebsiteData(WTFMove(domainsWithDeletedWebsiteData));
292             callbackAggregator->removePendingCallback();
293         });
294     }
295 }
296
297 void WebProcessProxy::topPrivatelyControlledDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, Function<void(HashSet<String>&&)>&& completionHandler)
298 {
299     // We expect this to be called on the main thread so we get the default website data store.
300     ASSERT(RunLoop::isMain());
301     
302     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
303         explicit CallbackAggregator(Function<void(HashSet<String>&&)>&& completionHandler)
304             : completionHandler(WTFMove(completionHandler))
305         {
306         }
307         
308         void addDomainsWithDeletedWebsiteData(HashSet<String>&& domains)
309         {
310             domainsWithDeletedWebsiteData.add(domains.begin(), domains.end());
311         }
312         
313         void addPendingCallback()
314         {
315             ++pendingCallbacks;
316         }
317         
318         void removePendingCallback()
319         {
320             ASSERT(pendingCallbacks);
321             --pendingCallbacks;
322             
323             callIfNeeded();
324         }
325         
326         void callIfNeeded()
327         {
328             if (!pendingCallbacks)
329                 completionHandler(WTFMove(domainsWithDeletedWebsiteData));
330         }
331         
332         unsigned pendingCallbacks = 0;
333         Function<void(HashSet<String>&&)> completionHandler;
334         HashSet<String> domainsWithDeletedWebsiteData;
335     };
336     
337     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(WTFMove(completionHandler)));
338     
339     HashSet<PAL::SessionID> visitedSessionIDs;
340     for (auto& page : globalPageMap()) {
341         auto& dataStore = page.value->websiteDataStore();
342         if (!dataStore.isPersistent() || visitedSessionIDs.contains(dataStore.sessionID()))
343             continue;
344         visitedSessionIDs.add(dataStore.sessionID());
345         callbackAggregator->addPendingCallback();
346         dataStore.topPrivatelyControlledDomainsWithWebsiteData(dataTypes, { }, [callbackAggregator, shouldNotifyPage, page](HashSet<String>&& domainsWithDataRecords) {
347             // When completing the task, we should be getting called on the main thread.
348             ASSERT(RunLoop::isMain());
349             
350             if (shouldNotifyPage)
351                 page.value->postMessageToInjectedBundle("WebsiteDataScanForTopPrivatelyControlledDomainsFinished", nullptr);
352             
353             callbackAggregator->addDomainsWithDeletedWebsiteData(WTFMove(domainsWithDataRecords));
354             callbackAggregator->removePendingCallback();
355         });
356     }
357
358     // FIXME: It's bizarre that this call is on WebProcessProxy and that it doesn't work if there are no visited pages.
359     // This should actually be a function of WebsiteDataStore and it should work even if there are no WebViews instances.
360     callbackAggregator->callIfNeeded();
361 }
362     
363 void WebProcessProxy::notifyPageStatisticsAndDataRecordsProcessed()
364 {
365     for (auto& page : globalPageMap())
366         page.value->postMessageToInjectedBundle("WebsiteDataScanForTopPrivatelyControlledDomainsFinished", nullptr);
367 }
368     
369 void WebProcessProxy::notifyPageStatisticsTelemetryFinished(API::Object* messageBody)
370 {
371     for (auto& page : globalPageMap())
372         page.value->postMessageToInjectedBundle("ResourceLoadStatisticsTelemetryFinished", messageBody);
373 }
374     
375 Ref<WebPageProxy> WebProcessProxy::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
376 {
377     uint64_t pageID = generatePageID();
378     Ref<WebPageProxy> webPage = WebPageProxy::create(pageClient, *this, pageID, WTFMove(pageConfiguration));
379
380     addExistingWebPage(webPage.get(), pageID);
381
382     return webPage;
383 }
384
385 void WebProcessProxy::addExistingWebPage(WebPageProxy& webPage, uint64_t pageID)
386 {
387     ASSERT(!m_pageMap.contains(pageID));
388     ASSERT(!globalPageMap().contains(pageID));
389
390     m_processPool->pageBeginUsingWebsiteDataStore(webPage);
391
392     m_pageMap.set(pageID, &webPage);
393     globalPageMap().set(pageID, &webPage);
394
395     updateBackgroundResponsivenessTimer();
396 }
397
398 void WebProcessProxy::removeWebPage(WebPageProxy& webPage, uint64_t pageID)
399 {
400     auto* removedPage = m_pageMap.take(pageID);
401     ASSERT_UNUSED(removedPage, removedPage == &webPage);
402     removedPage = globalPageMap().take(pageID);
403     ASSERT_UNUSED(removedPage, removedPage == &webPage);
404
405     m_processPool->pageEndUsingWebsiteDataStore(webPage);
406
407     updateBackgroundResponsivenessTimer();
408     
409     Vector<uint64_t> itemIDsToRemove;
410     for (auto& idAndItem : m_backForwardListItemMap) {
411         if (idAndItem.value->pageID() == pageID)
412             itemIDsToRemove.append(idAndItem.key);
413     }
414     for (auto itemID : itemIDsToRemove)
415         m_backForwardListItemMap.remove(itemID);
416
417     // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
418     // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
419     if (state() == State::Terminated || !canTerminateChildProcess())
420         return;
421
422     shutDown();
423 }
424
425 void WebProcessProxy::addVisitedLinkStore(VisitedLinkStore& store)
426 {
427     m_visitedLinkStores.add(&store);
428     store.addProcess(*this);
429 }
430
431 void WebProcessProxy::addWebUserContentControllerProxy(WebUserContentControllerProxy& proxy, WebPageCreationParameters& parameters)
432 {
433     m_webUserContentControllerProxies.add(&proxy);
434     proxy.addProcess(*this, parameters);
435 }
436
437 void WebProcessProxy::didDestroyVisitedLinkStore(VisitedLinkStore& store)
438 {
439     ASSERT(m_visitedLinkStores.contains(&store));
440     m_visitedLinkStores.remove(&store);
441 }
442
443 void WebProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
444 {
445     ASSERT(m_webUserContentControllerProxies.contains(&proxy));
446     m_webUserContentControllerProxies.remove(&proxy);
447 }
448
449 WebBackForwardListItem* WebProcessProxy::webBackForwardItem(uint64_t itemID) const
450 {
451     return m_backForwardListItemMap.get(itemID);
452 }
453
454 void WebProcessProxy::registerNewWebBackForwardListItem(WebBackForwardListItem& item)
455 {
456     // This item was just created by the UIProcess and is being added to the map for the first time
457     // so we should not already have an item for this ID.
458     ASSERT(!m_backForwardListItemMap.contains(item.itemID()));
459
460     m_backForwardListItemMap.set(item.itemID(), &item);
461 }
462
463 void WebProcessProxy::removeBackForwardItem(uint64_t itemID)
464 {
465     m_backForwardListItemMap.remove(itemID);
466 }
467
468 void WebProcessProxy::assumeReadAccessToBaseURL(const String& urlString)
469 {
470     URL url(URL(), urlString);
471     if (!url.isLocalFile())
472         return;
473
474     // There's a chance that urlString does not point to a directory.
475     // Get url's base URL to add to m_localPathsWithAssumedReadAccess.
476     URL baseURL(URL(), url.baseAsString());
477     String path = baseURL.fileSystemPath();
478     if (path.isNull())
479         return;
480     
481     // Client loads an alternate string. This doesn't grant universal file read, but the web process is assumed
482     // to have read access to this directory already.
483     m_localPathsWithAssumedReadAccess.add(path);
484 }
485
486 bool WebProcessProxy::hasAssumedReadAccessToURL(const URL& url) const
487 {
488     if (!url.isLocalFile())
489         return false;
490
491     String path = url.fileSystemPath();
492     auto startsWithURLPath = [&path](const String& assumedAccessPath) {
493         // There are no ".." components, because URL removes those.
494         return path.startsWith(assumedAccessPath);
495     };
496
497     auto& platformPaths = platformPathsWithAssumedReadAccess();
498     auto platformPathsEnd = platformPaths.end();
499     if (std::find_if(platformPaths.begin(), platformPathsEnd, startsWithURLPath) != platformPathsEnd)
500         return true;
501
502     auto localPathsEnd = m_localPathsWithAssumedReadAccess.end();
503     if (std::find_if(m_localPathsWithAssumedReadAccess.begin(), localPathsEnd, startsWithURLPath) != localPathsEnd)
504         return true;
505
506     return false;
507 }
508
509 bool WebProcessProxy::checkURLReceivedFromWebProcess(const String& urlString)
510 {
511     return checkURLReceivedFromWebProcess(URL(URL(), urlString));
512 }
513
514 bool WebProcessProxy::checkURLReceivedFromWebProcess(const URL& url)
515 {
516     // FIXME: Consider checking that the URL is valid. Currently, WebProcess sends invalid URLs in many cases, but it probably doesn't have good reasons to do that.
517
518     // Any other non-file URL is OK.
519     if (!url.isLocalFile())
520         return true;
521
522     // Any file URL is also OK if we've loaded a file URL through API before, granting universal read access.
523     if (m_mayHaveUniversalFileReadSandboxExtension)
524         return true;
525
526     // If we loaded a string with a file base URL before, loading resources from that subdirectory is fine.
527     if (hasAssumedReadAccessToURL(url))
528         return true;
529
530     // Items in back/forward list have been already checked.
531     // One case where we don't have sandbox extensions for file URLs in b/f list is if the list has been reinstated after a crash or a browser restart.
532     String path = url.fileSystemPath();
533     for (WebBackForwardListItemMap::iterator iter = m_backForwardListItemMap.begin(), end = m_backForwardListItemMap.end(); iter != end; ++iter) {
534         URL itemURL(URL(), iter->value->url());
535         if (itemURL.isLocalFile() && itemURL.fileSystemPath() == path)
536             return true;
537         URL itemOriginalURL(URL(), iter->value->originalURL());
538         if (itemOriginalURL.isLocalFile() && itemOriginalURL.fileSystemPath() == path)
539             return true;
540     }
541
542     // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL.
543     WTFLogAlways("Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data());
544     return false;
545 }
546
547 #if !PLATFORM(COCOA)
548 bool WebProcessProxy::fullKeyboardAccessEnabled()
549 {
550     return false;
551 }
552 #endif
553
554 void WebProcessProxy::addOrUpdateBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState& pageState)
555 {
556     MESSAGE_CHECK_URL(pageState.mainFrameState.originalURLString);
557     MESSAGE_CHECK_URL(pageState.mainFrameState.urlString);
558
559     auto& backForwardListItem = m_backForwardListItemMap.add(itemID, nullptr).iterator->value;
560     if (!backForwardListItem) {
561         BackForwardListItemState backForwardListItemState;
562         backForwardListItemState.identifier = itemID;
563         backForwardListItemState.pageState = pageState;
564         backForwardListItem = WebBackForwardListItem::create(WTFMove(backForwardListItemState), pageID);
565         return;
566     }
567
568     // Update existing item.
569     backForwardListItem->setPageState(pageState);
570 }
571
572 #if ENABLE(NETSCAPE_PLUGIN_API)
573 void WebProcessProxy::getPlugins(bool refresh, Vector<PluginInfo>& plugins, Vector<PluginInfo>& applicationPlugins, std::optional<Vector<WebCore::SupportedPluginName>>& supportedPluginNames)
574 {
575     if (refresh)
576         m_processPool->pluginInfoStore().refresh();
577
578     supportedPluginNames = m_processPool->pluginInfoStore().supportedPluginNames();
579
580     Vector<PluginModuleInfo> pluginModules = m_processPool->pluginInfoStore().plugins();
581     for (size_t i = 0; i < pluginModules.size(); ++i)
582         plugins.append(pluginModules[i].info);
583
584 #if ENABLE(PDFKIT_PLUGIN)
585     // Add built-in PDF last, so that it's not used when a real plug-in is installed.
586     if (!m_processPool->omitPDFSupport()) {
587         plugins.append(PDFPlugin::pluginInfo());
588         applicationPlugins.append(PDFPlugin::pluginInfo());
589     }
590 #else
591     UNUSED_PARAM(applicationPlugins);
592 #endif
593 }
594 #endif // ENABLE(NETSCAPE_PLUGIN_API)
595
596 #if ENABLE(NETSCAPE_PLUGIN_API)
597 void WebProcessProxy::getPluginProcessConnection(uint64_t pluginProcessToken, Ref<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>&& reply)
598 {
599     PluginProcessManager::singleton().getPluginProcessConnection(pluginProcessToken, WTFMove(reply));
600 }
601 #endif
602
603 void WebProcessProxy::getNetworkProcessConnection(Ref<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>&& reply)
604 {
605     m_processPool->getNetworkProcessConnection(WTFMove(reply));
606 }
607
608 void WebProcessProxy::getStorageProcessConnection(PAL::SessionID initialSessionID, Ref<Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply>&& reply)
609 {
610     m_processPool->getStorageProcessConnection(*this, initialSessionID, WTFMove(reply));
611 }
612
613 #if !PLATFORM(COCOA)
614 bool WebProcessProxy::platformIsBeingDebugged() const
615 {
616     return false;
617 }
618 #endif
619
620 #if !PLATFORM(MAC)
621 bool WebProcessProxy::shouldAllowNonValidInjectedCode() const
622 {
623     return false;
624 }
625 #endif
626
627 void WebProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
628 {
629     if (dispatchMessage(connection, decoder))
630         return;
631
632     if (m_processPool->dispatchMessage(connection, decoder))
633         return;
634
635     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
636         didReceiveWebProcessProxyMessage(connection, decoder);
637         return;
638     }
639
640     // FIXME: Add unhandled message logging.
641 }
642
643 void WebProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
644 {
645     if (dispatchSyncMessage(connection, decoder, replyEncoder))
646         return;
647
648     if (m_processPool->dispatchSyncMessage(connection, decoder, replyEncoder))
649         return;
650
651     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
652         didReceiveSyncWebProcessProxyMessage(connection, decoder, replyEncoder);
653         return;
654     }
655
656     // FIXME: Add unhandled message logging.
657 }
658
659 void WebProcessProxy::didClose(IPC::Connection&)
660 {
661     // Protect ourselves, as the call to disconnect() below may otherwise cause us
662     // to be deleted before we can finish our work.
663     Ref<WebProcessProxy> protect(*this);
664
665     webConnection()->didClose();
666
667     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
668
669     shutDown();
670
671 #if ENABLE(PUBLIC_SUFFIX_LIST)
672     if (pages.size() == 1) {
673         auto& page = *pages[0];
674         String domain = topPrivatelyControlledDomain(WebCore::URL(WebCore::ParsedURLString, page.currentURL()).host());
675         if (!domain.isEmpty())
676             page.logDiagnosticMessageWithEnhancedPrivacy(WebCore::DiagnosticLoggingKeys::domainCausingCrashKey(), domain, WebCore::ShouldSample::No);
677     }
678 #endif
679
680     for (auto& page : pages)
681         page->processDidTerminate(ProcessTerminationReason::Crash);
682
683 }
684
685 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
686 {
687     WTFLogAlways("Received an invalid message \"%s.%s\" from the web process.\n", messageReceiverName.toString().data(), messageName.toString().data());
688
689     WebProcessPool::didReceiveInvalidMessage(messageReceiverName, messageName);
690
691     // Terminate the WebProcess.
692     terminate();
693
694     // Since we've invalidated the connection we'll never get a IPC::Connection::Client::didClose
695     // callback so we'll explicitly call it here instead.
696     didClose(connection);
697 }
698
699 void WebProcessProxy::didBecomeUnresponsive()
700 {
701     m_isResponsive = NoOrMaybe::No;
702
703     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
704
705     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
706         page->processDidBecomeUnresponsive();
707
708     bool isWebProcessResponsive = false;
709     for (auto& callback : isResponsiveCallbacks)
710         callback(isWebProcessResponsive);
711 }
712
713 void WebProcessProxy::didBecomeResponsive()
714 {
715     m_isResponsive = NoOrMaybe::Maybe;
716
717     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
718         page->processDidBecomeResponsive();
719 }
720
721 void WebProcessProxy::willChangeIsResponsive()
722 {
723     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
724         page->willChangeProcessIsResponsive();
725 }
726
727 void WebProcessProxy::didChangeIsResponsive()
728 {
729     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
730         page->didChangeProcessIsResponsive();
731 }
732
733 bool WebProcessProxy::mayBecomeUnresponsive()
734 {
735     return !platformIsBeingDebugged();
736 }
737
738 void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
739 {
740     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
741
742     for (WebPageProxy* page : m_pageMap.values()) {
743         ASSERT(this == &page->process());
744         page->processDidFinishLaunching();
745     }
746
747     m_webConnection = WebConnectionToWebProcess::create(this);
748
749     m_processPool->processDidFinishLaunching(this);
750
751 #if PLATFORM(IOS)
752     if (connection()) {
753         if (xpc_connection_t xpcConnection = connection()->xpcConnection())
754             m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection));
755     }
756 #endif
757 }
758
759 WebFrameProxy* WebProcessProxy::webFrame(uint64_t frameID) const
760 {
761     if (!WebFrameProxyMap::isValidKey(frameID))
762         return 0;
763
764     return m_frameMap.get(frameID);
765 }
766
767 bool WebProcessProxy::canCreateFrame(uint64_t frameID) const
768 {
769     return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
770 }
771
772 void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy* frameProxy)
773 {
774     ASSERT(canCreateFrame(frameID));
775     m_frameMap.set(frameID, frameProxy);
776 }
777
778 void WebProcessProxy::didDestroyFrame(uint64_t frameID)
779 {
780     // If the page is closed before it has had the chance to send the DidCreateMainFrame message
781     // back to the UIProcess, then the frameDestroyed message will still be received because it
782     // gets sent directly to the WebProcessProxy.
783     ASSERT(WebFrameProxyMap::isValidKey(frameID));
784     m_frameMap.remove(frameID);
785 }
786
787 void WebProcessProxy::disconnectFramesFromPage(WebPageProxy* page)
788 {
789     for (auto& frame : copyToVector(m_frameMap.values())) {
790         if (frame->page() == page)
791             frame->webProcessWillShutDown();
792     }
793 }
794
795 size_t WebProcessProxy::frameCountInPage(WebPageProxy* page) const
796 {
797     size_t result = 0;
798     for (auto& frame : m_frameMap.values()) {
799         if (frame->page() == page)
800             ++result;
801     }
802     return result;
803 }
804
805 auto WebProcessProxy::visiblePageToken() const -> VisibleWebPageToken
806 {
807     return m_visiblePageCounter.count();
808 }
809
810 RefPtr<API::UserInitiatedAction> WebProcessProxy::userInitiatedActivity(uint64_t identifier)
811 {
812     if (!UserInitiatedActionMap::isValidKey(identifier) || !identifier)
813         return nullptr;
814
815     auto result = m_userInitiatedActionMap.ensure(identifier, [] { return API::UserInitiatedAction::create(); });
816     return result.iterator->value;
817 }
818
819 bool WebProcessProxy::isResponsive() const
820 {
821     return m_responsivenessTimer.isResponsive() && m_backgroundResponsivenessTimer.isResponsive();
822 }
823
824 void WebProcessProxy::didDestroyUserGestureToken(uint64_t identifier)
825 {
826     ASSERT(UserInitiatedActionMap::isValidKey(identifier));
827     m_userInitiatedActionMap.remove(identifier);
828 }
829
830 bool WebProcessProxy::canTerminateChildProcess()
831 {
832     if (!m_pageMap.isEmpty())
833         return false;
834
835     if (!m_processPool->shouldTerminate(this))
836         return false;
837
838     return true;
839 }
840
841 void WebProcessProxy::shouldTerminate(bool& shouldTerminate)
842 {
843     shouldTerminate = canTerminateChildProcess();
844     if (shouldTerminate) {
845         // We know that the web process is going to terminate so start shutting it down in the UI process.
846         shutDown();
847     }
848 }
849
850 void WebProcessProxy::testIncomingSyncIPCMessageWhileWaitingForSyncReply(bool& handled)
851 {
852     // Send Synchronous IPC back to the WebProcess while it is waiting for a sync reply from us.
853     // This should time out.
854     bool didSyncIPCsucceed = sendSync(Messages::WebProcess::SyncIPCMessageWhileWaitingForSyncReplyForTesting(), Messages::WebProcess::SyncIPCMessageWhileWaitingForSyncReplyForTesting::Reply(), 0, 100_ms);
855     RELEASE_ASSERT(!didSyncIPCsucceed);
856     handled = true;
857 }
858
859 void WebProcessProxy::updateTextCheckerState()
860 {
861     if (canSendMessage())
862         send(Messages::WebProcess::SetTextCheckerState(TextChecker::state()), 0);
863 }
864
865 void WebProcessProxy::didSaveToPageCache()
866 {
867     m_processPool->processDidCachePage(this);
868 }
869
870 void WebProcessProxy::releasePageCache()
871 {
872     if (canSendMessage())
873         send(Messages::WebProcess::ReleasePageCache(), 0);
874 }
875
876 void WebProcessProxy::windowServerConnectionStateChanged()
877 {
878     for (const auto& page : m_pageMap.values())
879         page->activityStateDidChange(ActivityState::IsVisuallyIdle);
880 }
881
882 void WebProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, Function<void(WebsiteData)>&& completionHandler)
883 {
884     ASSERT(canSendMessage());
885
886     auto token = throttler().backgroundActivityToken();
887     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is fetching Website data", this);
888
889     connection()->sendWithReply(Messages::WebProcess::FetchWebsiteData(sessionID, dataTypes), 0, RunLoop::main(), [this, token, completionHandler = WTFMove(completionHandler), sessionID](auto reply) {
890 #if RELEASE_LOG_DISABLED
891         UNUSED_PARAM(sessionID);
892         UNUSED_PARAM(this);
893 #endif
894         if (!reply) {
895             completionHandler(WebsiteData { });
896             return;
897         }
898
899         completionHandler(WTFMove(std::get<0>(*reply)));
900         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done fetching Website data", this);
901     });
902 }
903
904 void WebProcessProxy::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, Function<void()>&& completionHandler)
905 {
906     ASSERT(canSendMessage());
907
908     auto token = throttler().backgroundActivityToken();
909     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is deleting Website data", this);
910
911     connection()->sendWithReply(Messages::WebProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince), 0, RunLoop::main(), [this, token, completionHandler = WTFMove(completionHandler), sessionID](auto reply) {
912 #if RELEASE_LOG_DISABLED
913         UNUSED_PARAM(this);
914         UNUSED_PARAM(sessionID);
915 #endif
916         completionHandler();
917         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done deleting Website data", this);
918     });
919 }
920
921 void WebProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, Function<void()>&& completionHandler)
922 {
923     ASSERT(canSendMessage());
924
925     auto token = throttler().backgroundActivityToken();
926     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is deleting Website data for several origins", this);
927
928     connection()->sendWithReply(Messages::WebProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins), 0, RunLoop::main(), [this, token, completionHandler = WTFMove(completionHandler), sessionID](auto reply) {
929 #if RELEASE_LOG_DISABLED
930         UNUSED_PARAM(this);
931         UNUSED_PARAM(sessionID);
932 #endif
933         completionHandler();
934         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done deleting Website data for several origins", this);
935     });
936 }
937
938 void WebProcessProxy::requestTermination(ProcessTerminationReason reason)
939 {
940     if (state() == State::Terminated)
941         return;
942
943     ChildProcessProxy::terminate();
944
945     if (webConnection())
946         webConnection()->didClose();
947
948     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
949
950     shutDown();
951
952     for (auto& page : pages)
953         page->processDidTerminate(reason);
954 }
955
956 void WebProcessProxy::stopResponsivenessTimer()
957 {
958     responsivenessTimer().stop();
959 }
960
961 void WebProcessProxy::enableSuddenTermination()
962 {
963     if (state() != State::Running)
964         return;
965
966     ASSERT(m_numberOfTimesSuddenTerminationWasDisabled);
967     WebCore::enableSuddenTermination();
968     --m_numberOfTimesSuddenTerminationWasDisabled;
969 }
970
971 void WebProcessProxy::disableSuddenTermination()
972 {
973     if (state() != State::Running)
974         return;
975
976     WebCore::disableSuddenTermination();
977     ++m_numberOfTimesSuddenTerminationWasDisabled;
978 }
979
980 RefPtr<API::Object> WebProcessProxy::transformHandlesToObjects(API::Object* object)
981 {
982     struct Transformer final : UserData::Transformer {
983         Transformer(WebProcessProxy& webProcessProxy)
984             : m_webProcessProxy(webProcessProxy)
985         {
986         }
987
988         bool shouldTransformObject(const API::Object& object) const override
989         {
990             switch (object.type()) {
991             case API::Object::Type::FrameHandle:
992                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
993
994             case API::Object::Type::PageHandle:
995                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
996
997             case API::Object::Type::PageGroupHandle:
998 #if PLATFORM(COCOA)
999             case API::Object::Type::ObjCObjectGraph:
1000 #endif
1001                 return true;
1002
1003             default:
1004                 return false;
1005             }
1006         }
1007
1008         RefPtr<API::Object> transformObject(API::Object& object) const override
1009         {
1010             switch (object.type()) {
1011             case API::Object::Type::FrameHandle:
1012                 ASSERT(static_cast<API::FrameHandle&>(object).isAutoconverting());
1013                 return m_webProcessProxy.webFrame(static_cast<API::FrameHandle&>(object).frameID());
1014
1015             case API::Object::Type::PageGroupHandle:
1016                 return WebPageGroup::get(static_cast<API::PageGroupHandle&>(object).webPageGroupData().pageGroupID);
1017
1018             case API::Object::Type::PageHandle:
1019                 ASSERT(static_cast<API::PageHandle&>(object).isAutoconverting());
1020                 return m_webProcessProxy.webPage(static_cast<API::PageHandle&>(object).pageID());
1021
1022 #if PLATFORM(COCOA)
1023             case API::Object::Type::ObjCObjectGraph:
1024                 return m_webProcessProxy.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1025 #endif
1026             default:
1027                 return &object;
1028             }
1029         }
1030
1031         WebProcessProxy& m_webProcessProxy;
1032     };
1033
1034     return UserData::transform(object, Transformer(*this));
1035 }
1036
1037 RefPtr<API::Object> WebProcessProxy::transformObjectsToHandles(API::Object* object)
1038 {
1039     struct Transformer final : UserData::Transformer {
1040         bool shouldTransformObject(const API::Object& object) const override
1041         {
1042             switch (object.type()) {
1043             case API::Object::Type::Frame:
1044             case API::Object::Type::Page:
1045             case API::Object::Type::PageGroup:
1046 #if PLATFORM(COCOA)
1047             case API::Object::Type::ObjCObjectGraph:
1048 #endif
1049                 return true;
1050
1051             default:
1052                 return false;
1053             }
1054         }
1055
1056         RefPtr<API::Object> transformObject(API::Object& object) const override
1057         {
1058             switch (object.type()) {
1059             case API::Object::Type::Frame:
1060                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrameProxy&>(object).frameID());
1061
1062             case API::Object::Type::Page:
1063                 return API::PageHandle::createAutoconverting(static_cast<const WebPageProxy&>(object).pageID());
1064
1065             case API::Object::Type::PageGroup:
1066                 return API::PageGroupHandle::create(WebPageGroupData(static_cast<const WebPageGroup&>(object).data()));
1067
1068 #if PLATFORM(COCOA)
1069             case API::Object::Type::ObjCObjectGraph:
1070                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1071 #endif
1072
1073             default:
1074                 return &object;
1075             }
1076         }
1077     };
1078
1079     return UserData::transform(object, Transformer());
1080 }
1081
1082 void WebProcessProxy::sendProcessWillSuspendImminently()
1083 {
1084     if (!canSendMessage())
1085         return;
1086
1087     bool handled = false;
1088     sendSync(Messages::WebProcess::ProcessWillSuspendImminently(), Messages::WebProcess::ProcessWillSuspendImminently::Reply(handled), 0, 1_s);
1089 }
1090
1091 void WebProcessProxy::sendPrepareToSuspend()
1092 {
1093     if (canSendMessage())
1094         send(Messages::WebProcess::PrepareToSuspend(), 0);
1095 }
1096
1097 void WebProcessProxy::sendCancelPrepareToSuspend()
1098 {
1099     if (canSendMessage())
1100         send(Messages::WebProcess::CancelPrepareToSuspend(), 0);
1101 }
1102
1103 void WebProcessProxy::sendProcessDidResume()
1104 {
1105     if (canSendMessage())
1106         send(Messages::WebProcess::ProcessDidResume(), 0);
1107 }
1108
1109 void WebProcessProxy::processReadyToSuspend()
1110 {
1111     m_throttler.processReadyToSuspend();
1112 }
1113
1114 void WebProcessProxy::didCancelProcessSuspension()
1115 {
1116     m_throttler.didCancelProcessSuspension();
1117 }
1118
1119 void WebProcessProxy::didSetAssertionState(AssertionState state)
1120 {
1121 #if PLATFORM(IOS)
1122     if (isServiceWorkerProcess())
1123         return;
1124
1125     ASSERT(!m_backgroundToken || !m_foregroundToken);
1126
1127     switch (state) {
1128     case AssertionState::Suspended:
1129         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Suspended) release all assertions for network process", this);
1130         m_foregroundToken = nullptr;
1131         m_backgroundToken = nullptr;
1132         for (auto& page : m_pageMap.values())
1133             page->processWillBecomeSuspended();
1134         break;
1135
1136     case AssertionState::Background:
1137         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Background) taking background assertion for network process", this);
1138         m_backgroundToken = processPool().backgroundWebProcessToken();
1139         m_foregroundToken = nullptr;
1140         break;
1141     
1142     case AssertionState::Foreground:
1143         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Foreground) taking foreground assertion for network process", this);
1144         m_foregroundToken = processPool().foregroundWebProcessToken();
1145         m_backgroundToken = nullptr;
1146         for (auto& page : m_pageMap.values())
1147             page->processWillBecomeForeground();
1148         break;
1149     }
1150
1151     ASSERT(!m_backgroundToken || !m_foregroundToken);
1152 #else
1153     UNUSED_PARAM(state);
1154 #endif
1155 }
1156     
1157 void WebProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
1158 {
1159     if (!isHoldingLockedFiles) {
1160         RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the WebContent process is no longer holding locked files");
1161         m_tokenForHoldingLockedFiles = nullptr;
1162         return;
1163     }
1164     if (!m_tokenForHoldingLockedFiles) {
1165         RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the WebContent process is holding locked files");
1166         m_tokenForHoldingLockedFiles = m_throttler.backgroundActivityToken();
1167     }
1168 }
1169
1170 void WebProcessProxy::isResponsive(WTF::Function<void(bool isWebProcessResponsive)>&& callback)
1171 {
1172     if (m_isResponsive == NoOrMaybe::No) {
1173         if (callback) {
1174             RunLoop::main().dispatch([callback = WTFMove(callback)] {
1175                 bool isWebProcessResponsive = false;
1176                 callback(isWebProcessResponsive);
1177             });
1178         }
1179         return;
1180     }
1181
1182     if (callback)
1183         m_isResponsiveCallbacks.append(WTFMove(callback));
1184
1185     responsivenessTimer().start();
1186     send(Messages::WebProcess::MainThreadPing(), 0);
1187 }
1188
1189 void WebProcessProxy::didReceiveMainThreadPing()
1190 {
1191     responsivenessTimer().stop();
1192
1193     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
1194     bool isWebProcessResponsive = true;
1195     for (auto& callback : isResponsiveCallbacks)
1196         callback(isWebProcessResponsive);
1197 }
1198
1199 void WebProcessProxy::didReceiveBackgroundResponsivenessPing()
1200 {
1201     m_backgroundResponsivenessTimer.didReceiveBackgroundResponsivenessPong();
1202 }
1203
1204 void WebProcessProxy::processTerminated()
1205 {
1206     m_responsivenessTimer.processTerminated();
1207     m_backgroundResponsivenessTimer.processTerminated();
1208 }
1209
1210 void WebProcessProxy::logDiagnosticMessageForResourceLimitTermination(const String& limitKey)
1211 {
1212     if (pageCount())
1213         (*pages().begin())->logDiagnosticMessage(DiagnosticLoggingKeys::simulatedPageCrashKey(), limitKey, ShouldSample::No);
1214 }
1215
1216 void WebProcessProxy::didExceedInactiveMemoryLimitWhileActive()
1217 {
1218     for (auto& page : pages())
1219         page->didExceedInactiveMemoryLimitWhileActive();
1220 }
1221
1222 void WebProcessProxy::didExceedActiveMemoryLimit()
1223 {
1224     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedActiveMemoryLimit() Terminating WebProcess with pid %d that has exceeded the active memory limit", this, processIdentifier());
1225     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededActiveMemoryLimitKey());
1226     requestTermination(ProcessTerminationReason::ExceededMemoryLimit);
1227 }
1228
1229 void WebProcessProxy::didExceedInactiveMemoryLimit()
1230 {
1231     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedInactiveMemoryLimit() Terminating WebProcess with pid %d that has exceeded the inactive memory limit", this, processIdentifier());
1232     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededInactiveMemoryLimitKey());
1233     requestTermination(ProcessTerminationReason::ExceededMemoryLimit);
1234 }
1235
1236 void WebProcessProxy::didExceedCPULimit()
1237 {
1238     for (auto& page : pages()) {
1239         if (page->isPlayingAudio()) {
1240             RELEASE_LOG(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() WebProcess with pid %d has exceeded the background CPU limit but we are not terminating it because there is audio playing", this, processIdentifier());
1241             return;
1242         }
1243
1244         if (page->hasActiveAudioStream() || page->hasActiveVideoStream()) {
1245             RELEASE_LOG(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() WebProcess with pid %d has exceeded the background CPU limit but we are not terminating it because it is capturing audio / video", this, processIdentifier());
1246             return;
1247         }
1248     }
1249
1250     bool hasVisiblePage = false;
1251     for (auto& page : pages()) {
1252         if (page->isViewVisible()) {
1253             page->didExceedBackgroundCPULimitWhileInForeground();
1254             hasVisiblePage = true;
1255         }
1256     }
1257
1258     // We only notify the client that the process exceeded the CPU limit when it is visible, we do not terminate it.
1259     if (hasVisiblePage)
1260         return;
1261
1262     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() Terminating background WebProcess with pid %d that has exceeded the background CPU limit", this, processIdentifier());
1263     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededBackgroundCPULimitKey());
1264     requestTermination(ProcessTerminationReason::ExceededCPULimit);
1265 }
1266
1267 void WebProcessProxy::updateBackgroundResponsivenessTimer()
1268 {
1269     m_backgroundResponsivenessTimer.updateState();
1270 }
1271
1272 #if !PLATFORM(COCOA)
1273 const HashSet<String>& WebProcessProxy::platformPathsWithAssumedReadAccess()
1274 {
1275     static NeverDestroyed<HashSet<String>> platformPathsWithAssumedReadAccess;
1276     return platformPathsWithAssumedReadAccess;
1277 }
1278 #endif
1279
1280 void WebProcessProxy::createNewMessagePortChannel(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
1281 {
1282     m_processEntangledPorts.add(port1);
1283     m_processEntangledPorts.add(port2);
1284     UIMessagePortChannelProvider::singleton().registry().didCreateMessagePortChannel(port1, port2);
1285 }
1286
1287 void WebProcessProxy::entangleLocalPortInThisProcessToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote)
1288 {
1289     m_processEntangledPorts.add(local);
1290     UIMessagePortChannelProvider::singleton().registry().didEntangleLocalToRemote(local, remote, coreProcessIdentifier());
1291
1292     auto* channel = UIMessagePortChannelProvider::singleton().registry().existingChannelContainingPort(local);
1293     if (channel && channel->hasAnyMessagesPendingOrInFlight())
1294         send(Messages::WebProcess::MessagesAvailableForPort(local), 0);
1295 }
1296
1297 void WebProcessProxy::messagePortDisentangled(const MessagePortIdentifier& port)
1298 {
1299     auto result = m_processEntangledPorts.remove(port);
1300     ASSERT_UNUSED(result, result);
1301
1302     UIMessagePortChannelProvider::singleton().registry().didDisentangleMessagePort(port);
1303 }
1304
1305 void WebProcessProxy::messagePortClosed(const MessagePortIdentifier& port)
1306 {
1307     UIMessagePortChannelProvider::singleton().registry().didCloseMessagePort(port);
1308 }
1309
1310 void WebProcessProxy::takeAllMessagesForPort(const MessagePortIdentifier& port, uint64_t messagesCallbackIdentifier)
1311 {
1312     UIMessagePortChannelProvider::singleton().registry().takeAllMessagesForPort(port, [this, protectedThis = makeRef(*this), messagesCallbackIdentifier](Vector<MessageWithMessagePorts>&& messages, Function<void()>&& deliveryCallback) {
1313
1314         static uint64_t currentMessageBatchIdentifier;
1315         auto result = m_messageBatchDeliveryCompletionHandlers.ensure(++currentMessageBatchIdentifier, [deliveryCallback = WTFMove(deliveryCallback)]() mutable {
1316             return WTFMove(deliveryCallback);
1317         });
1318         ASSERT_UNUSED(result, result.isNewEntry);
1319
1320         send(Messages::WebProcess::DidTakeAllMessagesForPort(WTFMove(messages), messagesCallbackIdentifier, currentMessageBatchIdentifier), 0);
1321     });
1322 }
1323
1324 void WebProcessProxy::didDeliverMessagePortMessages(uint64_t messageBatchIdentifier)
1325 {
1326     auto callback = m_messageBatchDeliveryCompletionHandlers.take(messageBatchIdentifier);
1327     ASSERT(callback);
1328     callback();
1329 }
1330
1331 void WebProcessProxy::postMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& port)
1332 {
1333     if (UIMessagePortChannelProvider::singleton().registry().didPostMessageToRemote(WTFMove(message), port)) {
1334         // Look up the process for that port
1335         auto* channel = UIMessagePortChannelProvider::singleton().registry().existingChannelContainingPort(port);
1336         ASSERT(channel);
1337         auto processIdentifier = channel->processForPort(port);
1338         if (processIdentifier) {
1339             if (auto* process = WebProcessProxy::processForIdentifier(*processIdentifier))
1340                 process->send(Messages::WebProcess::MessagesAvailableForPort(port), 0);
1341         }
1342     }
1343 }
1344
1345 void WebProcessProxy::checkRemotePortForActivity(const WebCore::MessagePortIdentifier port, uint64_t callbackIdentifier)
1346 {
1347     UIMessagePortChannelProvider::singleton().registry().checkRemotePortForActivity(port, [this, protectedThis = makeRef(*this), callbackIdentifier](MessagePortChannelProvider::HasActivity hasActivity) {
1348         send(Messages::WebProcess::DidCheckRemotePortForActivity(callbackIdentifier, hasActivity == MessagePortChannelProvider::HasActivity::Yes), 0);
1349     });
1350 }
1351
1352 void WebProcessProxy::checkProcessLocalPortForActivity(const MessagePortIdentifier& port, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback)
1353 {
1354     static uint64_t currentCallbackIdentifier;
1355     auto result = m_localPortActivityCompletionHandlers.ensure(++currentCallbackIdentifier, [callback = WTFMove(callback)]() mutable {
1356         return WTFMove(callback);
1357     });
1358     ASSERT_UNUSED(result, result.isNewEntry);
1359
1360     send(Messages::WebProcess::CheckProcessLocalPortForActivity(port, currentCallbackIdentifier), 0);
1361 }
1362
1363 void WebProcessProxy::didCheckProcessLocalPortForActivity(uint64_t callbackIdentifier, bool isLocallyReachable)
1364 {
1365     auto callback = m_localPortActivityCompletionHandlers.take(callbackIdentifier);
1366     if (!callback)
1367         return;
1368
1369     callback(isLocallyReachable ? MessagePortChannelProvider::HasActivity::Yes : MessagePortChannelProvider::HasActivity::No);
1370 }
1371
1372 } // namespace WebKit