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