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