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