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