[Cocoa] Fix incorrect rebase
[WebKit.git] / Source / WebKit / UIProcess / WebProcessProxy.cpp
1 /*
2  * Copyright (C) 2010-2020 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 "AuthenticatorManager.h"
33 #include "DataReference.h"
34 #include "DownloadProxyMap.h"
35 #include "LoadParameters.h"
36 #include "Logging.h"
37 #include "PluginInfoStore.h"
38 #include "PluginProcessManager.h"
39 #include "ProvisionalPageProxy.h"
40 #include "TextChecker.h"
41 #include "TextCheckerState.h"
42 #include "UserData.h"
43 #include "WebBackForwardCache.h"
44 #include "WebBackForwardListItem.h"
45 #include "WebInspectorUtilities.h"
46 #include "WebNavigationDataStore.h"
47 #include "WebNotificationManagerProxy.h"
48 #include "WebPageGroup.h"
49 #include "WebPageMessages.h"
50 #include "WebPageProxy.h"
51 #include "WebPasteboardProxy.h"
52 #include "WebProcessCache.h"
53 #include "WebProcessDataStoreParameters.h"
54 #include "WebProcessMessages.h"
55 #include "WebProcessPool.h"
56 #include "WebProcessProxyMessages.h"
57 #include "WebSWContextManagerConnectionMessages.h"
58 #include "WebUserContentControllerProxy.h"
59 #include "WebsiteData.h"
60 #include "WebsiteDataFetchOption.h"
61 #include <WebCore/DiagnosticLoggingKeys.h>
62 #include <WebCore/PlatformMediaSessionManager.h>
63 #include <WebCore/PrewarmInformation.h>
64 #include <WebCore/PublicSuffix.h>
65 #include <WebCore/SuddenTermination.h>
66 #include <stdio.h>
67 #include <wtf/Algorithms.h>
68 #include <wtf/NeverDestroyed.h>
69 #include <wtf/RunLoop.h>
70 #include <wtf/URL.h>
71 #include <wtf/text/CString.h>
72 #include <wtf/text/StringBuilder.h>
73 #include <wtf/text/WTFString.h>
74
75 #if PLATFORM(COCOA)
76 #include "ObjCObjectGraph.h"
77 #include "PDFPlugin.h"
78 #include "UserMediaCaptureManagerProxy.h"
79 #include "VersionChecks.h"
80 #endif
81
82 #if PLATFORM(MAC)
83 #include "HighPerformanceGPUManager.h"
84 #endif
85
86 #if ENABLE(SEC_ITEM_SHIM)
87 #include "SecItemShimProxy.h"
88 #endif
89
90 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
91 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromWebProcess(url), connection())
92
93 namespace WebKit {
94 using namespace WebCore;
95
96 static bool isMainThreadOrCheckDisabled()
97 {
98 #if PLATFORM(IOS_FAMILY)
99     return LIKELY(RunLoop::isMain()) || !linkedOnOrAfter(SDKVersion::FirstWithMainThreadReleaseAssertionInWebPageProxy);
100 #elif PLATFORM(MAC)
101     return LIKELY(RunLoop::isMain()) || !linkedOnOrAfter(SDKVersion::FirstWithMainThreadReleaseAssertionInWebPageProxy);
102 #else
103     return RunLoop::isMain();
104 #endif
105 }
106
107 static HashMap<ProcessIdentifier, WebProcessProxy*>& allProcesses()
108 {
109     ASSERT(isMainThreadOrCheckDisabled());
110     static NeverDestroyed<HashMap<ProcessIdentifier, WebProcessProxy*>> map;
111     return map;
112 }
113
114 WebProcessProxy* WebProcessProxy::processForIdentifier(ProcessIdentifier identifier)
115 {
116     return allProcesses().get(identifier);
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 #if ENABLE(SERVICE_WORKER)
144 Ref<WebProcessProxy> WebProcessProxy::createForServiceWorkers(WebProcessPool& processPool, RegistrableDomain&& registrableDomain, WebsiteDataStore& websiteDataStore)
145 {
146     auto proxy = adoptRef(*new WebProcessProxy(processPool, &websiteDataStore, IsPrewarmed::No));
147     proxy->m_registrableDomain = WTFMove(registrableDomain);
148     proxy->enableServiceWorkers(processPool.userContentControllerIdentifierForServiceWorkers());
149     proxy->connect();
150     return proxy;
151 }
152 #endif
153
154 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
155 class UIProxyForCapture final : public UserMediaCaptureManagerProxy::ConnectionProxy {
156     WTF_MAKE_FAST_ALLOCATED;
157 public:
158     explicit UIProxyForCapture(WebProcessProxy& process) : m_process(process) { }
159 private:
160     void addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& receiver) final { m_process.addMessageReceiver(messageReceiverName, receiver); }
161     void removeMessageReceiver(IPC::StringReference messageReceiverName) final { m_process.removeMessageReceiver(messageReceiverName); }
162     IPC::Connection& connection() final { return *m_process.connection(); }
163     Logger& logger() final
164     {
165         if (!m_logger) {
166             m_logger = Logger::create(this);
167             m_logger->setEnabled(this, m_process.sessionID().isAlwaysOnLoggingAllowed());
168         }
169         return *m_logger;
170     }
171     bool willStartCapture(CaptureDevice::DeviceType) const final
172     {
173         // FIXME: We should validate this is granted.
174         return true;
175     }
176
177     RefPtr<Logger> m_logger;
178     WebProcessProxy& m_process;
179 };
180 #endif
181
182 WebProcessProxy::WebProcessProxy(WebProcessPool& processPool, WebsiteDataStore* websiteDataStore, IsPrewarmed isPrewarmed)
183     : AuxiliaryProcessProxy(processPool.alwaysRunsAtBackgroundPriority())
184     , m_responsivenessTimer(*this)
185     , m_backgroundResponsivenessTimer(*this)
186     , m_processPool(processPool, isPrewarmed == IsPrewarmed::Yes ? IsWeak::Yes : IsWeak::No)
187     , m_mayHaveUniversalFileReadSandboxExtension(false)
188     , m_numberOfTimesSuddenTerminationWasDisabled(0)
189     , m_throttler(*this, processPool.shouldTakeUIBackgroundAssertion())
190     , m_isResponsive(NoOrMaybe::Maybe)
191     , m_visiblePageCounter([this](RefCounterEvent) { updateBackgroundResponsivenessTimer(); })
192     , m_websiteDataStore(websiteDataStore)
193 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
194     , m_userMediaCaptureManagerProxy(makeUnique<UserMediaCaptureManagerProxy>(makeUniqueRef<UIProxyForCapture>(*this)))
195 #endif
196     , m_isPrewarmed(isPrewarmed == IsPrewarmed::Yes)
197 {
198     RELEASE_ASSERT(isMainThreadOrCheckDisabled());
199
200     auto result = allProcesses().add(coreProcessIdentifier(), this);
201     ASSERT_UNUSED(result, result.isNewEntry);
202
203     WebPasteboardProxy::singleton().addWebProcessProxy(*this);
204 }
205
206 WebProcessProxy::~WebProcessProxy()
207 {
208     RELEASE_ASSERT(isMainThreadOrCheckDisabled());
209     ASSERT(m_pageURLRetainCountMap.isEmpty());
210
211     if (m_processPool)
212         m_processPool->clearWebProcessHasUploads(coreProcessIdentifier());
213
214     auto result = allProcesses().remove(coreProcessIdentifier());
215     ASSERT_UNUSED(result, result);
216
217     WebPasteboardProxy::singleton().removeWebProcessProxy(*this);
218
219 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
220     if (state() == State::Running)
221         processPool().stopDisplayLinks(*connection());
222 #endif
223
224     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
225     for (auto& callback : isResponsiveCallbacks)
226         callback(false);
227
228     if (m_webConnection)
229         m_webConnection->invalidate();
230
231     while (m_numberOfTimesSuddenTerminationWasDisabled-- > 0)
232         WebCore::enableSuddenTermination();
233
234 #if PLATFORM(MAC)
235     HighPerformanceGPUManager::singleton().removeProcessRequiringHighPerformance(this);
236 #endif
237 }
238
239 void WebProcessProxy::setIsInProcessCache(bool value)
240 {
241     if (value) {
242         RELEASE_ASSERT(m_pageMap.isEmpty());
243         RELEASE_ASSERT(!m_suspendedPageCount);
244         RELEASE_ASSERT(m_provisionalPages.isEmpty());
245     }
246
247     ASSERT(m_isInProcessCache != value);
248     m_isInProcessCache = value;
249
250     send(Messages::WebProcess::SetIsInProcessCache(m_isInProcessCache), 0);
251
252     if (m_isInProcessCache) {
253         // WebProcessProxy objects normally keep the process pool alive but we do not want this to be the case
254         // for cached processes or it would leak the pool.
255         m_processPool.setIsWeak(IsWeak::Yes);
256     } else {
257         RELEASE_ASSERT(m_processPool);
258         m_processPool.setIsWeak(IsWeak::No);
259     }
260 }
261
262 void WebProcessProxy::setWebsiteDataStore(WebsiteDataStore& dataStore)
263 {
264     ASSERT(!m_websiteDataStore);
265     m_websiteDataStore = &dataStore;
266     updateRegistrationWithDataStore();
267     send(Messages::WebProcess::SetWebsiteDataStoreParameters(processPool().webProcessDataStoreParameters(*this, dataStore)), 0);
268 }
269
270 bool WebProcessProxy::isDummyProcessProxy() const
271 {
272     return m_websiteDataStore && processPool().dummyProcessProxy(m_websiteDataStore->sessionID()) == this;
273 }
274
275 void WebProcessProxy::updateRegistrationWithDataStore()
276 {
277     if (!m_websiteDataStore)
278         return;
279     
280     bool shouldBeRegistered = pageCount() || provisionalPageCount();
281     if (shouldBeRegistered)
282         m_websiteDataStore->registerProcess(*this);
283     else
284         m_websiteDataStore->unregisterProcess(*this);
285 }
286
287 void WebProcessProxy::addProvisionalPageProxy(ProvisionalPageProxy& provisionalPage)
288 {
289     ASSERT(!m_isInProcessCache);
290     ASSERT(!m_provisionalPages.contains(&provisionalPage));
291     m_provisionalPages.add(&provisionalPage);
292     updateRegistrationWithDataStore();
293 }
294
295 void WebProcessProxy::removeProvisionalPageProxy(ProvisionalPageProxy& provisionalPage)
296 {
297     ASSERT(m_provisionalPages.contains(&provisionalPage));
298     m_provisionalPages.remove(&provisionalPage);
299     updateRegistrationWithDataStore();
300     if (m_provisionalPages.isEmpty())
301         maybeShutDown();
302 }
303
304 void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
305 {
306     launchOptions.processType = ProcessLauncher::ProcessType::Web;
307
308     AuxiliaryProcessProxy::getLaunchOptions(launchOptions);
309
310     if (!m_processPool->customWebContentServiceBundleIdentifier().isEmpty())
311         launchOptions.customWebContentServiceBundleIdentifier = m_processPool->customWebContentServiceBundleIdentifier().ascii();
312     if (WebKit::isInspectorProcessPool(processPool()))
313         launchOptions.extraInitializationData.add("inspector-process"_s, "1"_s);
314
315     auto overrideLanguages = m_processPool->configuration().overrideLanguages();
316     if (overrideLanguages.size()) {
317         StringBuilder languageString;
318         for (size_t i = 0; i < overrideLanguages.size(); ++i) {
319             if (i)
320                 languageString.append(',');
321             languageString.append(overrideLanguages[i]);
322         }
323         launchOptions.extraInitializationData.add("OverrideLanguages"_s, languageString.toString());
324     }
325
326     launchOptions.nonValidInjectedCodeAllowed = shouldAllowNonValidInjectedCode();
327
328     if (isPrewarmed())
329         launchOptions.extraInitializationData.add("is-prewarmed"_s, "1"_s);
330
331     if (processPool().shouldMakeNextWebProcessLaunchFailForTesting()) {
332         processPool().setShouldMakeNextWebProcessLaunchFailForTesting(false);
333         launchOptions.shouldMakeProcessLaunchFailForTesting = true;
334     }
335
336     if (m_serviceWorkerInformation) {
337         launchOptions.extraInitializationData.add("service-worker-process"_s, "1"_s);
338         launchOptions.extraInitializationData.add("registrable-domain"_s, m_registrableDomain->string());
339     }
340 }
341
342 #if !PLATFORM(GTK) && !PLATFORM(WPE)
343 void WebProcessProxy::platformGetLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
344 {
345 }
346 #endif
347
348 bool WebProcessProxy::shouldSendPendingMessage(const PendingMessage& message)
349 {
350 #if HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_AUDIT_TOKEN)
351     if (message.encoder->messageName() == "LoadRequestWaitingForProcessLaunch") {
352         auto buffer = message.encoder->buffer();
353         auto bufferSize = message.encoder->bufferSize();
354         std::unique_ptr<IPC::Decoder> decoder = makeUnique<IPC::Decoder>(buffer, bufferSize, nullptr, Vector<IPC::Attachment> { });
355         LoadParameters loadParameters;
356         URL resourceDirectoryURL;
357         WebPageProxyIdentifier pageID;
358         bool checkAssumedReadAccessToResourceURL;
359         if (decoder->decode(loadParameters) && decoder->decode(resourceDirectoryURL) && decoder->decode(pageID) && decoder->decode(checkAssumedReadAccessToResourceURL)) {
360             if (auto* page = WebProcessProxy::webPage(pageID)) {
361                 page->maybeInitializeSandboxExtensionHandle(static_cast<WebProcessProxy&>(*this), loadParameters.request.url(), resourceDirectoryURL, loadParameters.sandboxExtensionHandle, checkAssumedReadAccessToResourceURL);
362                 send(Messages::WebPage::LoadRequest(loadParameters), decoder->destinationID());
363             }
364         } else
365             ASSERT_NOT_REACHED();
366         return false;
367     }
368 #endif
369     return true;
370 }
371
372 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
373 {
374     ASSERT(this->connection() == &connection);
375
376     // Throttling IPC messages coming from the WebProcesses so that the UIProcess stays responsive, even
377     // if one of the WebProcesses misbehaves.
378     connection.enableIncomingMessagesThrottling();
379
380     // Use this flag to force synchronous messages to be treated as asynchronous messages in the WebProcess.
381     // Otherwise, the WebProcess would process incoming synchronous IPC while waiting for a synchronous IPC
382     // reply from the UIProcess, which would be unsafe.
383     connection.setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
384
385 #if ENABLE(SEC_ITEM_SHIM)
386     SecItemShimProxy::singleton().initializeConnection(connection);
387 #endif
388 }
389
390 void WebProcessProxy::processWillShutDown(IPC::Connection& connection)
391 {
392     ASSERT_UNUSED(connection, this->connection() == &connection);
393
394 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
395     processPool().stopDisplayLinks(connection);
396 #endif
397 }
398
399 void WebProcessProxy::shutDown()
400 {
401     RELEASE_ASSERT(isMainThreadOrCheckDisabled());
402
403     shutDownProcess();
404
405     if (m_webConnection) {
406         m_webConnection->invalidate();
407         m_webConnection = nullptr;
408     }
409
410     m_responsivenessTimer.invalidate();
411     m_backgroundResponsivenessTimer.invalidate();
412     m_activityForHoldingLockedFiles = nullptr;
413
414     for (auto& frame : copyToVector(m_frameMap.values()))
415         frame->webProcessWillShutDown();
416     m_frameMap.clear();
417
418     for (auto* webUserContentControllerProxy : m_webUserContentControllerProxies)
419         webUserContentControllerProxy->removeProcess(*this);
420     m_webUserContentControllerProxies.clear();
421
422     m_userInitiatedActionMap.clear();
423
424     m_processPool->disconnectProcess(this);
425 }
426
427 WebPageProxy* WebProcessProxy::webPage(WebPageProxyIdentifier pageID)
428 {
429     return globalPageMap().get(pageID);
430 }
431
432 #if ENABLE(RESOURCE_LOAD_STATISTICS)
433 void WebProcessProxy::notifyPageStatisticsAndDataRecordsProcessed()
434 {
435     for (auto& page : globalPageMap())
436         page.value->postMessageToInjectedBundle("WebsiteDataScanForRegistrableDomainsFinished", nullptr);
437 }
438
439 void WebProcessProxy::notifyWebsiteDataScanForRegistrableDomainsFinished()
440 {
441     for (auto& page : globalPageMap())
442         page.value->postMessageToInjectedBundle("WebsiteDataScanForRegistrableDomainsFinished", nullptr);
443 }
444
445 void WebProcessProxy::notifyWebsiteDataDeletionForRegistrableDomainsFinished()
446 {
447     for (auto& page : globalPageMap())
448         page.value->postMessageToInjectedBundle("WebsiteDataDeletionForRegistrableDomainsFinished", nullptr);
449 }
450
451 void WebProcessProxy::notifyPageStatisticsTelemetryFinished(API::Object* messageBody)
452 {
453     for (auto& page : globalPageMap())
454         page.value->postMessageToInjectedBundle("ResourceLoadStatisticsTelemetryFinished", messageBody);
455 }
456
457 void WebProcessProxy::setShouldBlockThirdPartyCookiesForTesting(ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode, CompletionHandler<void()>&& completionHandler)
458 {
459     sendWithAsyncReply(Messages::WebProcess::SetShouldBlockThirdPartyCookiesForTesting(thirdPartyCookieBlockingMode), WTFMove(completionHandler));
460 }
461 #endif
462
463 Ref<WebPageProxy> WebProcessProxy::createWebPage(PageClient& pageClient, Ref<API::PageConfiguration>&& pageConfiguration)
464 {
465     Ref<WebPageProxy> webPage = WebPageProxy::create(pageClient, *this, WTFMove(pageConfiguration));
466
467     addExistingWebPage(webPage.get(), BeginsUsingDataStore::Yes);
468
469     return webPage;
470 }
471
472 void WebProcessProxy::addExistingWebPage(WebPageProxy& webPage, BeginsUsingDataStore beginsUsingDataStore)
473 {
474     ASSERT(!m_pageMap.contains(webPage.identifier()));
475     ASSERT(!globalPageMap().contains(webPage.identifier()));
476     RELEASE_ASSERT(!m_isInProcessCache);
477     ASSERT(!m_websiteDataStore || m_websiteDataStore == &webPage.websiteDataStore());
478
479     if (beginsUsingDataStore == BeginsUsingDataStore::Yes)
480         m_processPool->pageBeginUsingWebsiteDataStore(webPage.identifier(), webPage.websiteDataStore());
481
482     m_pageMap.set(webPage.identifier(), &webPage);
483     globalPageMap().set(webPage.identifier(), &webPage);
484
485     updateRegistrationWithDataStore();
486     updateBackgroundResponsivenessTimer();
487 }
488
489 void WebProcessProxy::markIsNoLongerInPrewarmedPool()
490 {
491     ASSERT(m_isPrewarmed);
492
493     m_isPrewarmed = false;
494     RELEASE_ASSERT(m_processPool);
495     m_processPool.setIsWeak(IsWeak::No);
496
497     send(Messages::WebProcess::MarkIsNoLongerPrewarmed(), 0);
498 }
499
500 void WebProcessProxy::removeWebPage(WebPageProxy& webPage, EndsUsingDataStore endsUsingDataStore)
501 {
502     auto* removedPage = m_pageMap.take(webPage.identifier());
503     ASSERT_UNUSED(removedPage, removedPage == &webPage);
504     removedPage = globalPageMap().take(webPage.identifier());
505     ASSERT_UNUSED(removedPage, removedPage == &webPage);
506
507     if (endsUsingDataStore == EndsUsingDataStore::Yes)
508         m_processPool->pageEndUsingWebsiteDataStore(webPage.identifier(), webPage.websiteDataStore());
509
510     removeVisitedLinkStoreUser(webPage.visitedLinkStore(), webPage.identifier());
511     updateRegistrationWithDataStore();
512
513     updateBackgroundResponsivenessTimer();
514
515     maybeShutDown();
516 }
517
518 void WebProcessProxy::addVisitedLinkStoreUser(VisitedLinkStore& visitedLinkStore, WebPageProxyIdentifier pageID)
519 {
520     auto& users = m_visitedLinkStoresWithUsers.ensure(&visitedLinkStore, [] {
521         return HashSet<WebPageProxyIdentifier> { };
522     }).iterator->value;
523
524     ASSERT(!users.contains(pageID));
525     users.add(pageID);
526
527     if (users.size() == 1)
528         visitedLinkStore.addProcess(*this);
529 }
530
531 void WebProcessProxy::removeVisitedLinkStoreUser(VisitedLinkStore& visitedLinkStore, WebPageProxyIdentifier pageID)
532 {
533     auto it = m_visitedLinkStoresWithUsers.find(&visitedLinkStore);
534     if (it == m_visitedLinkStoresWithUsers.end())
535         return;
536
537     auto& users = it->value;
538     users.remove(pageID);
539     if (users.isEmpty()) {
540         m_visitedLinkStoresWithUsers.remove(it);
541         visitedLinkStore.removeProcess(*this);
542     }
543 }
544
545 void WebProcessProxy::addWebUserContentControllerProxy(WebUserContentControllerProxy& proxy, WebPageCreationParameters& parameters)
546 {
547     m_webUserContentControllerProxies.add(&proxy);
548     proxy.addProcess(*this, parameters);
549 }
550
551 void WebProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
552 {
553     ASSERT(m_webUserContentControllerProxies.contains(&proxy));
554     m_webUserContentControllerProxies.remove(&proxy);
555 }
556
557 void WebProcessProxy::assumeReadAccessToBaseURL(WebPageProxy& page, const String& urlString)
558 {
559     URL url(URL(), urlString);
560     if (!url.isLocalFile())
561         return;
562
563     // There's a chance that urlString does not point to a directory.
564     // Get url's base URL to add to m_localPathsWithAssumedReadAccess.
565     URL baseURL(URL(), url.baseAsString());
566     String path = baseURL.fileSystemPath();
567     if (path.isNull())
568         return;
569     
570     // Client loads an alternate string. This doesn't grant universal file read, but the web process is assumed
571     // to have read access to this directory already.
572     m_localPathsWithAssumedReadAccess.add(path);
573     page.addPreviouslyVisitedPath(path);
574 }
575
576 bool WebProcessProxy::hasAssumedReadAccessToURL(const URL& url) const
577 {
578     if (!url.isLocalFile())
579         return false;
580
581     String path = url.fileSystemPath();
582     auto startsWithURLPath = [&path](const String& assumedAccessPath) {
583         // There are no ".." components, because URL removes those.
584         return path.startsWith(assumedAccessPath);
585     };
586
587     auto& platformPaths = platformPathsWithAssumedReadAccess();
588     auto platformPathsEnd = platformPaths.end();
589     if (std::find_if(platformPaths.begin(), platformPathsEnd, startsWithURLPath) != platformPathsEnd)
590         return true;
591
592     auto localPathsEnd = m_localPathsWithAssumedReadAccess.end();
593     if (std::find_if(m_localPathsWithAssumedReadAccess.begin(), localPathsEnd, startsWithURLPath) != localPathsEnd)
594         return true;
595
596     return false;
597 }
598
599 bool WebProcessProxy::checkURLReceivedFromWebProcess(const String& urlString)
600 {
601     return checkURLReceivedFromWebProcess(URL(URL(), urlString));
602 }
603
604 bool WebProcessProxy::checkURLReceivedFromWebProcess(const URL& url)
605 {
606     // 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.
607
608     // Any other non-file URL is OK.
609     if (!url.isLocalFile())
610         return true;
611
612     // Any file URL is also OK if we've loaded a file URL through API before, granting universal read access.
613     if (m_mayHaveUniversalFileReadSandboxExtension)
614         return true;
615
616     // If we loaded a string with a file base URL before, loading resources from that subdirectory is fine.
617     if (hasAssumedReadAccessToURL(url))
618         return true;
619
620     // Items in back/forward list have been already checked.
621     // 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.
622     String path = url.fileSystemPath();
623     for (auto& item : WebBackForwardListItem::allItems().values()) {
624         URL itemURL(URL(), item->url());
625         if (itemURL.isLocalFile() && itemURL.fileSystemPath() == path)
626             return true;
627         URL itemOriginalURL(URL(), item->originalURL());
628         if (itemOriginalURL.isLocalFile() && itemOriginalURL.fileSystemPath() == path)
629             return true;
630     }
631
632     // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL.
633     RELEASE_LOG_ERROR(Loading, "Received an unexpected URL from the web process");
634     return false;
635 }
636
637 #if !PLATFORM(COCOA)
638 bool WebProcessProxy::fullKeyboardAccessEnabled()
639 {
640     return false;
641 }
642 #endif
643
644 bool WebProcessProxy::hasProvisionalPageWithID(WebPageProxyIdentifier pageID) const
645 {
646     for (auto* provisionalPage : m_provisionalPages) {
647         if (provisionalPage->page().identifier() == pageID)
648             return true;
649     }
650     return false;
651 }
652
653 bool WebProcessProxy::isAllowedToUpdateBackForwardItem(WebBackForwardListItem& item) const
654 {
655     if (m_pageMap.contains(item.pageID()))
656         return true;
657
658     if (hasProvisionalPageWithID(item.pageID()))
659         return true;
660
661     if (item.suspendedPage() && item.suspendedPage()->page().identifier() == item.pageID() && &item.suspendedPage()->process() == this)
662         return true;
663
664     return false;
665 }
666
667 void WebProcessProxy::updateBackForwardItem(const BackForwardListItemState& itemState)
668 {
669     auto* item = WebBackForwardListItem::itemForID(itemState.identifier);
670     if (!item || !isAllowedToUpdateBackForwardItem(*item))
671         return;
672
673     item->setPageState(PageState { itemState.pageState });
674
675     if (!!item->backForwardCacheEntry() != itemState.hasCachedPage) {
676         if (itemState.hasCachedPage)
677             processPool().backForwardCache().addEntry(*item, coreProcessIdentifier());
678         else if (!item->suspendedPage())
679             processPool().backForwardCache().removeEntry(*item);
680     }
681 }
682
683 #if ENABLE(NETSCAPE_PLUGIN_API)
684 void WebProcessProxy::getPlugins(bool refresh, CompletionHandler<void(Vector<PluginInfo>&& plugins, Vector<PluginInfo>&& applicationPlugins, Optional<Vector<WebCore::SupportedPluginIdentifier>>&& supportedPluginIdentifiers)>&& completionHandler)
685 {
686     if (refresh)
687         m_processPool->pluginInfoStore().refresh();
688
689     auto supportedPluginIdentifiers = m_processPool->pluginInfoStore().supportedPluginIdentifiers();
690
691     Vector<PluginInfo> plugins;
692     Vector<PluginModuleInfo> pluginModules = m_processPool->pluginInfoStore().plugins();
693     for (size_t i = 0; i < pluginModules.size(); ++i)
694         plugins.append(pluginModules[i].info);
695
696     Vector<PluginInfo> applicationPlugins;
697 #if ENABLE(PDFKIT_PLUGIN)
698     // Add built-in PDF last, so that it's not used when a real plug-in is installed.
699     if (!m_processPool->omitPDFSupport()) {
700         plugins.append(PDFPlugin::pluginInfo());
701         applicationPlugins.append(PDFPlugin::pluginInfo());
702     }
703 #endif
704     completionHandler(WTFMove(plugins), WTFMove(applicationPlugins), WTFMove(supportedPluginIdentifiers));
705 }
706 #endif // ENABLE(NETSCAPE_PLUGIN_API)
707
708 #if ENABLE(NETSCAPE_PLUGIN_API)
709 void WebProcessProxy::getPluginProcessConnection(uint64_t pluginProcessToken, Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply&& reply)
710 {
711     MESSAGE_CHECK(HashSet<uint64_t>::isValidValue(pluginProcessToken));
712     bool success = PluginProcessManager::singleton().getPluginProcessConnection(pluginProcessToken, WTFMove(reply));
713     MESSAGE_CHECK(success);
714 }
715 #endif
716
717 void WebProcessProxy::getNetworkProcessConnection(Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&& reply)
718 {
719     m_processPool->getNetworkProcessConnection(*this, WTFMove(reply));
720 }
721
722 #if ENABLE(GPU_PROCESS)
723 void WebProcessProxy::getGPUProcessConnection(Messages::WebProcessProxy::GetGPUProcessConnection::DelayedReply&& reply)
724 {
725     m_processPool->getGPUProcessConnection(*this, WTFMove(reply));
726 }
727
728 void WebProcessProxy::gpuProcessCrashed()
729 {
730     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
731         page->gpuProcessCrashed();
732 }
733 #endif
734
735 #if !PLATFORM(COCOA)
736 bool WebProcessProxy::platformIsBeingDebugged() const
737 {
738     return false;
739 }
740 #endif
741
742 #if !PLATFORM(MAC)
743 bool WebProcessProxy::shouldAllowNonValidInjectedCode() const
744 {
745     return false;
746 }
747 #endif
748
749 void WebProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
750 {
751     if (dispatchMessage(connection, decoder))
752         return;
753
754     if (m_processPool->dispatchMessage(connection, decoder))
755         return;
756
757     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
758         didReceiveWebProcessProxyMessage(connection, decoder);
759         return;
760     }
761
762     // FIXME: Add unhandled message logging.
763 }
764
765 void WebProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
766 {
767     if (dispatchSyncMessage(connection, decoder, replyEncoder))
768         return;
769
770     if (m_processPool->dispatchSyncMessage(connection, decoder, replyEncoder))
771         return;
772
773     if (decoder.messageReceiverName() == Messages::WebProcessProxy::messageReceiverName()) {
774         didReceiveSyncWebProcessProxyMessage(connection, decoder, replyEncoder);
775         return;
776     }
777
778     // FIXME: Add unhandled message logging.
779 }
780
781 void WebProcessProxy::didClose(IPC::Connection&)
782 {
783     RELEASE_LOG_IF(isReleaseLoggingAllowed(), Process, "%p - WebProcessProxy didClose (web process crash)", this);
784     processDidTerminateOrFailedToLaunch();
785 }
786
787 void WebProcessProxy::processDidTerminateOrFailedToLaunch()
788 {
789     // Protect ourselves, as the call to disconnect() below may otherwise cause us
790     // to be deleted before we can finish our work.
791     Ref<WebProcessProxy> protect(*this);
792
793 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
794     m_userMediaCaptureManagerProxy->clear();
795 #endif
796
797     if (auto* webConnection = this->webConnection())
798         webConnection->didClose();
799
800     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
801     auto provisionalPages = WTF::map(m_provisionalPages, [](auto* provisionalPage) { return makeWeakPtr(provisionalPage); });
802
803     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
804     for (auto& callback : isResponsiveCallbacks)
805         callback(false);
806
807     if (m_isInProcessCache) {
808         processPool().webProcessCache().removeProcess(*this, WebProcessCache::ShouldShutDownProcess::No);
809         ASSERT(!m_isInProcessCache);
810     }
811
812     if (isStandaloneServiceWorkerProcess())
813         processPool().serviceWorkerProcessCrashed(*this);
814
815     shutDown();
816
817 #if ENABLE(PUBLIC_SUFFIX_LIST)
818     if (pages.size() == 1) {
819         auto& page = *pages[0];
820         String domain = topPrivatelyControlledDomain(URL({ }, page.currentURL()).host().toString());
821         if (!domain.isEmpty())
822             page.logDiagnosticMessageWithEnhancedPrivacy(WebCore::DiagnosticLoggingKeys::domainCausingCrashKey(), domain, WebCore::ShouldSample::No);
823     }
824 #endif
825
826     for (auto& page : pages)
827         page->processDidTerminate(ProcessTerminationReason::Crash);
828
829     for (auto& provisionalPage : provisionalPages) {
830         if (provisionalPage)
831             provisionalPage->processDidTerminate();
832     }
833 }
834
835 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
836 {
837     logInvalidMessage(connection, messageReceiverName, messageName);
838
839     WebProcessPool::didReceiveInvalidMessage(messageReceiverName, messageName);
840
841     // Terminate the WebContent process.
842     terminate();
843
844     // Since we've invalidated the connection we'll never get a IPC::Connection::Client::didClose
845     // callback so we'll explicitly call it here instead.
846     didClose(connection);
847 }
848
849 void WebProcessProxy::didBecomeUnresponsive()
850 {
851     auto protectedThis = makeRef(*this);
852
853     m_isResponsive = NoOrMaybe::No;
854
855     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
856
857     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
858         page->processDidBecomeUnresponsive();
859
860     bool isWebProcessResponsive = false;
861     for (auto& callback : isResponsiveCallbacks)
862         callback(isWebProcessResponsive);
863
864     // If the web process becomes unresponsive and only runs service workers, kill it ourselves since there are no native clients to do it.
865     if (isRunningServiceWorkers() && m_pageMap.isEmpty()) {
866         RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didBecomeUnresponsive() Terminating service worker-only web process with pid %d because it is unresponsive", this, processIdentifier());
867         disableServiceWorkers();
868         terminate();
869     }
870 }
871
872 void WebProcessProxy::didBecomeResponsive()
873 {
874     m_isResponsive = NoOrMaybe::Maybe;
875
876     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
877         page->processDidBecomeResponsive();
878 }
879
880 void WebProcessProxy::willChangeIsResponsive()
881 {
882     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
883         page->willChangeProcessIsResponsive();
884 }
885
886 void WebProcessProxy::didChangeIsResponsive()
887 {
888     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
889         page->didChangeProcessIsResponsive();
890 }
891
892 bool WebProcessProxy::mayBecomeUnresponsive()
893 {
894 #if !defined(NDEBUG) || ASAN_ENABLED
895     // Disable responsiveness checks in slow builds to avoid false positives.
896     return false;
897 #else
898     if (platformIsBeingDebugged())
899         return false;
900
901     static bool isLibgmallocEnabled = [] {
902         char* variable = getenv("DYLD_INSERT_LIBRARIES");
903         if (!variable)
904             return false;
905         if (!strstr(variable, "libgmalloc"))
906             return false;
907         return true;
908     }();
909     if (isLibgmallocEnabled)
910         return false;
911
912     return true;
913 #endif
914 }
915
916 void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
917 {
918     RELEASE_ASSERT(isMainThreadOrCheckDisabled());
919
920     auto protectedThis = makeRef(*this);
921     AuxiliaryProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
922
923     if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
924         RELEASE_LOG_IF(isReleaseLoggingAllowed(), Process, "%p - WebProcessProxy didFinishLaunching - invalid connection identifier (web process failed to launch)", this);
925         processDidTerminateOrFailedToLaunch();
926         return;
927     }
928
929     RELEASE_ASSERT(!m_webConnection);
930     m_webConnection = WebConnectionToWebProcess::create(this);
931
932     m_processPool->processDidFinishLaunching(this);
933     m_backgroundResponsivenessTimer.updateState();
934
935 #if PLATFORM(IOS_FAMILY)
936     if (connection()) {
937         if (xpc_connection_t xpcConnection = connection()->xpcConnection())
938             m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection));
939     }
940 #endif
941
942 #if PLATFORM(COCOA)
943     unblockAccessibilityServerIfNeeded();
944 #if ENABLE(REMOTE_INSPECTOR)
945     enableRemoteInspectorIfNeeded();
946 #endif
947 #endif
948
949     if (m_shouldStartResponsivenessTimerWhenLaunched) {
950         auto useLazyStop = *std::exchange(m_shouldStartResponsivenessTimerWhenLaunched, WTF::nullopt);
951         startResponsivenessTimer(useLazyStop);
952     }
953 }
954
955 WebFrameProxy* WebProcessProxy::webFrame(FrameIdentifier frameID) const
956 {
957     if (!WebFrameProxyMap::isValidKey(frameID))
958         return nullptr;
959
960     return m_frameMap.get(frameID);
961 }
962
963 bool WebProcessProxy::canCreateFrame(FrameIdentifier frameID) const
964 {
965     return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
966 }
967
968 void WebProcessProxy::frameCreated(FrameIdentifier frameID, WebFrameProxy& frameProxy)
969 {
970     m_frameMap.set(frameID, &frameProxy);
971 }
972
973 void WebProcessProxy::didDestroyFrame(FrameIdentifier frameID)
974 {
975     // If the page is closed before it has had the chance to send the DidCreateMainFrame message
976     // back to the UIProcess, then the frameDestroyed message will still be received because it
977     // gets sent directly to the WebProcessProxy.
978     ASSERT(WebFrameProxyMap::isValidKey(frameID));
979 #if ENABLE(WEB_AUTHN)
980     if (auto* frame = webFrame(frameID)) {
981         if (auto* page = frame->page())
982             page->websiteDataStore().authenticatorManager().cancelRequest(page->webPageID(), frameID);
983     }
984 #endif
985     m_frameMap.remove(frameID);
986 }
987
988 void WebProcessProxy::disconnectFramesFromPage(WebPageProxy* page)
989 {
990     for (auto& frame : copyToVector(m_frameMap.values())) {
991         if (frame->page() == page)
992             frame->webProcessWillShutDown();
993     }
994 }
995
996 size_t WebProcessProxy::frameCountInPage(WebPageProxy* page) const
997 {
998     size_t result = 0;
999     for (auto& frame : m_frameMap.values()) {
1000         if (frame->page() == page)
1001             ++result;
1002     }
1003     return result;
1004 }
1005
1006 auto WebProcessProxy::visiblePageToken() const -> VisibleWebPageToken
1007 {
1008     return m_visiblePageCounter.count();
1009 }
1010
1011 RefPtr<API::UserInitiatedAction> WebProcessProxy::userInitiatedActivity(uint64_t identifier)
1012 {
1013     if (!UserInitiatedActionMap::isValidKey(identifier) || !identifier)
1014         return nullptr;
1015
1016     auto result = m_userInitiatedActionMap.ensure(identifier, [] { return API::UserInitiatedAction::create(); });
1017     return result.iterator->value;
1018 }
1019
1020 bool WebProcessProxy::isResponsive() const
1021 {
1022     return m_responsivenessTimer.isResponsive() && m_backgroundResponsivenessTimer.isResponsive();
1023 }
1024
1025 void WebProcessProxy::didDestroyUserGestureToken(uint64_t identifier)
1026 {
1027     ASSERT(UserInitiatedActionMap::isValidKey(identifier));
1028     m_userInitiatedActionMap.remove(identifier);
1029 }
1030
1031 bool WebProcessProxy::canBeAddedToWebProcessCache() const
1032 {
1033     if (isRunningServiceWorkers())
1034         return false;
1035
1036     if (WebKit::isInspectorProcessPool(processPool()))
1037         return false;
1038
1039     return true;
1040 }
1041
1042 void WebProcessProxy::maybeShutDown()
1043 {
1044     if (isDummyProcessProxy() && m_pageMap.isEmpty()) {
1045         ASSERT(state() == State::Terminated);
1046         m_processPool->disconnectProcess(this);
1047         return;
1048     }
1049
1050     if (state() == State::Terminated || !canTerminateAuxiliaryProcess())
1051         return;
1052
1053     if (canBeAddedToWebProcessCache() && processPool().webProcessCache().addProcessIfPossible(*this))
1054         return;
1055
1056     shutDown();
1057 }
1058
1059 bool WebProcessProxy::canTerminateAuxiliaryProcess()
1060 {
1061     if (!m_pageMap.isEmpty() || m_suspendedPageCount || !m_provisionalPages.isEmpty() || m_isInProcessCache || m_shutdownPreventingScopeCount)
1062         return false;
1063
1064     if (isRunningServiceWorkers())
1065         return false;
1066
1067     if (!m_processPool->shouldTerminate(this))
1068         return false;
1069
1070     return true;
1071 }
1072
1073 void WebProcessProxy::shouldTerminate(CompletionHandler<void(bool)>&& completionHandler)
1074 {
1075     bool shouldTerminate = canTerminateAuxiliaryProcess();
1076     if (shouldTerminate) {
1077         // We know that the web process is going to terminate so start shutting it down in the UI process.
1078         shutDown();
1079     }
1080     completionHandler(shouldTerminate);
1081 }
1082
1083 void WebProcessProxy::updateTextCheckerState()
1084 {
1085     if (canSendMessage())
1086         send(Messages::WebProcess::SetTextCheckerState(TextChecker::state()), 0);
1087 }
1088
1089 void WebProcessProxy::windowServerConnectionStateChanged()
1090 {
1091     for (const auto& page : m_pageMap.values())
1092         page->activityStateDidChange(ActivityState::IsVisuallyIdle);
1093 }
1094
1095 void WebProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, CompletionHandler<void(WebsiteData)>&& completionHandler)
1096 {
1097     ASSERT(canSendMessage());
1098     ASSERT_UNUSED(sessionID, sessionID == this->sessionID());
1099
1100     auto activity = throttler().backgroundActivity("WebProcessProxy::fetchWebsiteData"_s);
1101     RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is fetching Website data", this);
1102
1103     connection()->sendWithAsyncReply(Messages::WebProcess::FetchWebsiteData(dataTypes), [this, protectedThis = makeRef(*this), activity = WTFMove(activity), completionHandler = WTFMove(completionHandler)] (auto reply) mutable {
1104 #if RELEASE_LOG_DISABLED
1105         UNUSED_PARAM(this);
1106 #endif
1107         completionHandler(WTFMove(reply));
1108         RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done fetching Website data", this);
1109     });
1110 }
1111
1112 void WebProcessProxy::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler)
1113 {
1114     ASSERT(canSendMessage());
1115     ASSERT_UNUSED(sessionID, sessionID == this->sessionID());
1116
1117     auto activity = throttler().backgroundActivity("WebProcessProxy::deleteWebsiteData"_s);
1118     RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is deleting Website data", this);
1119
1120     connection()->sendWithAsyncReply(Messages::WebProcess::DeleteWebsiteData(dataTypes, modifiedSince), [this, protectedThis = makeRef(*this), activity = WTFMove(activity), completionHandler = WTFMove(completionHandler)] () mutable {
1121 #if RELEASE_LOG_DISABLED
1122         UNUSED_PARAM(this);
1123 #endif
1124         completionHandler();
1125         RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done deleting Website data", this);
1126     });
1127 }
1128
1129 void WebProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
1130 {
1131     ASSERT(canSendMessage());
1132     ASSERT_UNUSED(sessionID, sessionID == this->sessionID());
1133
1134     auto activity = throttler().backgroundActivity("WebProcessProxy::deleteWebsiteDataForOrigins"_s);
1135     RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is taking a background assertion because the Web process is deleting Website data for several origins", this);
1136
1137     connection()->sendWithAsyncReply(Messages::WebProcess::DeleteWebsiteDataForOrigins(dataTypes, origins), [this, protectedThis = makeRef(*this), activity = WTFMove(activity), completionHandler = WTFMove(completionHandler)] () mutable {
1138 #if RELEASE_LOG_DISABLED
1139         UNUSED_PARAM(this);
1140 #endif
1141         completionHandler();
1142         RELEASE_LOG_IF(isReleaseLoggingAllowed(), ProcessSuspension, "%p - WebProcessProxy is releasing a background assertion because the Web process is done deleting Website data for several origins", this);
1143     });
1144 }
1145
1146 void WebProcessProxy::requestTermination(ProcessTerminationReason reason)
1147 {
1148     if (state() == State::Terminated)
1149         return;
1150
1151     auto protectedThis = makeRef(*this);
1152     RELEASE_LOG_ERROR_IF(isReleaseLoggingAllowed(), Process, "%p - WebProcessProxy::requestTermination - PID %d - reason %d", this, processIdentifier(), reason);
1153
1154     AuxiliaryProcessProxy::terminate();
1155
1156     if (webConnection())
1157         webConnection()->didClose();
1158
1159     auto provisionalPages = WTF::map(m_provisionalPages, [](auto* provisionalPage) { return makeWeakPtr(provisionalPage); });
1160     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
1161
1162     shutDown();
1163
1164     for (auto& page : pages)
1165         page->processDidTerminate(reason);
1166         
1167     for (auto& provisionalPage : provisionalPages) {
1168         if (provisionalPage)
1169             provisionalPage->processDidTerminate();
1170     }
1171 }
1172
1173 bool WebProcessProxy::isReleaseLoggingAllowed() const
1174 {
1175     return !m_websiteDataStore || m_websiteDataStore->sessionID().isAlwaysOnLoggingAllowed();
1176 }
1177
1178 void WebProcessProxy::stopResponsivenessTimer()
1179 {
1180     responsivenessTimer().stop();
1181 }
1182
1183 void WebProcessProxy::startResponsivenessTimer(UseLazyStop useLazyStop)
1184 {
1185     if (isLaunching()) {
1186         m_shouldStartResponsivenessTimerWhenLaunched = useLazyStop;
1187         return;
1188     }
1189
1190     if (useLazyStop == UseLazyStop::Yes)
1191         responsivenessTimer().startWithLazyStop();
1192     else
1193         responsivenessTimer().start();
1194 }
1195
1196 void WebProcessProxy::enableSuddenTermination()
1197 {
1198     if (state() != State::Running)
1199         return;
1200
1201     ASSERT(m_numberOfTimesSuddenTerminationWasDisabled);
1202     WebCore::enableSuddenTermination();
1203     --m_numberOfTimesSuddenTerminationWasDisabled;
1204 }
1205
1206 void WebProcessProxy::disableSuddenTermination()
1207 {
1208     if (state() != State::Running)
1209         return;
1210
1211     WebCore::disableSuddenTermination();
1212     ++m_numberOfTimesSuddenTerminationWasDisabled;
1213 }
1214
1215 RefPtr<API::Object> WebProcessProxy::transformHandlesToObjects(API::Object* object)
1216 {
1217     struct Transformer final : UserData::Transformer {
1218         Transformer(WebProcessProxy& webProcessProxy)
1219             : m_webProcessProxy(webProcessProxy)
1220         {
1221         }
1222
1223         bool shouldTransformObject(const API::Object& object) const override
1224         {
1225             switch (object.type()) {
1226             case API::Object::Type::FrameHandle:
1227                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1228
1229             case API::Object::Type::PageHandle:
1230                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1231
1232             case API::Object::Type::PageGroupHandle:
1233 #if PLATFORM(COCOA)
1234             case API::Object::Type::ObjCObjectGraph:
1235 #endif
1236                 return true;
1237
1238             default:
1239                 return false;
1240             }
1241         }
1242
1243         RefPtr<API::Object> transformObject(API::Object& object) const override
1244         {
1245             switch (object.type()) {
1246             case API::Object::Type::FrameHandle:
1247                 ASSERT(static_cast<API::FrameHandle&>(object).isAutoconverting());
1248                 return m_webProcessProxy.webFrame(static_cast<API::FrameHandle&>(object).frameID());
1249
1250             case API::Object::Type::PageGroupHandle:
1251                 return WebPageGroup::get(static_cast<API::PageGroupHandle&>(object).webPageGroupData().pageGroupID);
1252
1253             case API::Object::Type::PageHandle:
1254                 ASSERT(static_cast<API::PageHandle&>(object).isAutoconverting());
1255                 return m_webProcessProxy.webPage(static_cast<API::PageHandle&>(object).pageProxyID());
1256
1257 #if PLATFORM(COCOA)
1258             case API::Object::Type::ObjCObjectGraph:
1259                 return m_webProcessProxy.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1260 #endif
1261             default:
1262                 return &object;
1263             }
1264         }
1265
1266         WebProcessProxy& m_webProcessProxy;
1267     };
1268
1269     return UserData::transform(object, Transformer(*this));
1270 }
1271
1272 RefPtr<API::Object> WebProcessProxy::transformObjectsToHandles(API::Object* object)
1273 {
1274     struct Transformer final : UserData::Transformer {
1275         bool shouldTransformObject(const API::Object& object) const override
1276         {
1277             switch (object.type()) {
1278             case API::Object::Type::Frame:
1279             case API::Object::Type::Page:
1280             case API::Object::Type::PageGroup:
1281 #if PLATFORM(COCOA)
1282             case API::Object::Type::ObjCObjectGraph:
1283 #endif
1284                 return true;
1285
1286             default:
1287                 return false;
1288             }
1289         }
1290
1291         RefPtr<API::Object> transformObject(API::Object& object) const override
1292         {
1293             switch (object.type()) {
1294             case API::Object::Type::Frame:
1295                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrameProxy&>(object).frameID());
1296
1297             case API::Object::Type::Page:
1298                 return API::PageHandle::createAutoconverting(static_cast<const WebPageProxy&>(object).identifier(), static_cast<const WebPageProxy&>(object).webPageID());
1299
1300             case API::Object::Type::PageGroup:
1301                 return API::PageGroupHandle::create(WebPageGroupData(static_cast<const WebPageGroup&>(object).data()));
1302
1303 #if PLATFORM(COCOA)
1304             case API::Object::Type::ObjCObjectGraph:
1305                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1306 #endif
1307
1308             default:
1309                 return &object;
1310             }
1311         }
1312     };
1313
1314     return UserData::transform(object, Transformer());
1315 }
1316
1317 void WebProcessProxy::sendPrepareToSuspend(IsSuspensionImminent isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
1318 {
1319     sendWithAsyncReply(Messages::WebProcess::PrepareToSuspend(isSuspensionImminent == IsSuspensionImminent::Yes), WTFMove(completionHandler));
1320 }
1321
1322 void WebProcessProxy::sendProcessDidResume()
1323 {
1324     if (canSendMessage())
1325         send(Messages::WebProcess::ProcessDidResume(), 0);
1326 }
1327
1328 void WebProcessProxy::didSetAssertionState(AssertionState state)
1329 {
1330     RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(%u)", this, state);
1331
1332     if (isStandaloneServiceWorkerProcess()) {
1333         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState() release all assertions for network process because this is a service worker process without page", this);
1334         m_foregroundToken = nullptr;
1335         m_backgroundToken = nullptr;
1336         return;
1337     }
1338
1339     ASSERT(!m_backgroundToken || !m_foregroundToken);
1340
1341     switch (state) {
1342     case AssertionState::Suspended:
1343         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Suspended) release all assertions for network process", this);
1344         m_foregroundToken = nullptr;
1345         m_backgroundToken = nullptr;
1346 #if PLATFORM(IOS_FAMILY)
1347         for (auto& page : m_pageMap.values())
1348             page->processWillBecomeSuspended();
1349 #endif
1350         break;
1351
1352     case AssertionState::Background:
1353         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Background) taking background assertion for network process", this);
1354         m_backgroundToken = processPool().backgroundWebProcessToken();
1355         m_foregroundToken = nullptr;
1356         break;
1357     
1358     case AssertionState::Foreground:
1359         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::didSetAssertionState(Foreground) taking foreground assertion for network process", this);
1360         m_foregroundToken = processPool().foregroundWebProcessToken();
1361         m_backgroundToken = nullptr;
1362 #if PLATFORM(IOS_FAMILY)
1363         for (auto& page : m_pageMap.values())
1364             page->processWillBecomeForeground();
1365 #endif
1366         break;
1367     
1368     case AssertionState::UnboundedNetworking:
1369         ASSERT_NOT_REACHED();
1370     }
1371
1372     ASSERT(!m_backgroundToken || !m_foregroundToken);
1373 }
1374
1375 void WebProcessProxy::webPageMediaStateDidChange(WebPageProxy&)
1376 {
1377     bool newHasAudibleWebPage = WTF::anyOf(m_pageMap.values(), [] (auto& page) { return page->isPlayingAudio(); });
1378     if (m_hasAudibleWebPage == newHasAudibleWebPage)
1379         return;
1380     m_hasAudibleWebPage = newHasAudibleWebPage;
1381
1382     if (m_hasAudibleWebPage)
1383         processPool().setWebProcessIsPlayingAudibleMedia(coreProcessIdentifier());
1384     else
1385         processPool().clearWebProcessIsPlayingAudibleMedia(coreProcessIdentifier());
1386 }
1387
1388 void WebProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
1389 {
1390     if (!isHoldingLockedFiles) {
1391         RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the WebContent process is no longer holding locked files");
1392         m_activityForHoldingLockedFiles = nullptr;
1393         return;
1394     }
1395     if (!m_activityForHoldingLockedFiles) {
1396         RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the WebContent process is holding locked files");
1397         m_activityForHoldingLockedFiles = m_throttler.backgroundActivity("Holding locked files"_s).moveToUniquePtr();
1398     }
1399 }
1400
1401 void WebProcessProxy::isResponsive(CompletionHandler<void(bool isWebProcessResponsive)>&& callback)
1402 {
1403     if (m_isResponsive == NoOrMaybe::No) {
1404         if (callback) {
1405             RunLoop::main().dispatch([callback = WTFMove(callback)]() mutable {
1406                 bool isWebProcessResponsive = false;
1407                 callback(isWebProcessResponsive);
1408             });
1409         }
1410         return;
1411     }
1412
1413     if (callback)
1414         m_isResponsiveCallbacks.append(WTFMove(callback));
1415
1416     startResponsivenessTimer();
1417     send(Messages::WebProcess::MainThreadPing(), 0);
1418 }
1419
1420 void WebProcessProxy::isResponsiveWithLazyStop()
1421 {
1422     if (m_isResponsive == NoOrMaybe::No)
1423         return;
1424
1425     if (!responsivenessTimer().hasActiveTimer()) {
1426         // We do not send a ping if we are already waiting for the WebProcess.
1427         // Spamming pings on a slow web process is not helpful.
1428         responsivenessTimer().startWithLazyStop();
1429         send(Messages::WebProcess::MainThreadPing(), 0);
1430     }
1431 }
1432
1433 bool WebProcessProxy::shouldConfigureJSCForTesting() const
1434 {
1435     return processPool().configuration().shouldConfigureJSCForTesting();
1436 }
1437
1438 bool WebProcessProxy::isJITEnabled() const
1439 {
1440     return processPool().configuration().isJITEnabled();
1441 }
1442
1443 void WebProcessProxy::didReceiveMainThreadPing()
1444 {
1445     responsivenessTimer().stop();
1446
1447     auto isResponsiveCallbacks = WTFMove(m_isResponsiveCallbacks);
1448     bool isWebProcessResponsive = true;
1449     for (auto& callback : isResponsiveCallbacks)
1450         callback(isWebProcessResponsive);
1451 }
1452
1453 void WebProcessProxy::didReceiveBackgroundResponsivenessPing()
1454 {
1455     m_backgroundResponsivenessTimer.didReceiveBackgroundResponsivenessPong();
1456 }
1457
1458 void WebProcessProxy::processTerminated()
1459 {
1460     m_responsivenessTimer.processTerminated();
1461     m_backgroundResponsivenessTimer.processTerminated();
1462 }
1463
1464 void WebProcessProxy::logDiagnosticMessageForResourceLimitTermination(const String& limitKey)
1465 {
1466     if (pageCount())
1467         (*pages().begin())->logDiagnosticMessage(DiagnosticLoggingKeys::simulatedPageCrashKey(), limitKey, ShouldSample::No);
1468 }
1469
1470 void WebProcessProxy::didExceedInactiveMemoryLimitWhileActive()
1471 {
1472     for (auto& page : pages())
1473         page->didExceedInactiveMemoryLimitWhileActive();
1474 }
1475
1476 void WebProcessProxy::didExceedActiveMemoryLimit()
1477 {
1478     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedActiveMemoryLimit() Terminating WebProcess with pid %d that has exceeded the active memory limit", this, processIdentifier());
1479     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededActiveMemoryLimitKey());
1480     requestTermination(ProcessTerminationReason::ExceededMemoryLimit);
1481 }
1482
1483 void WebProcessProxy::didExceedInactiveMemoryLimit()
1484 {
1485     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedInactiveMemoryLimit() Terminating WebProcess with pid %d that has exceeded the inactive memory limit", this, processIdentifier());
1486     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededInactiveMemoryLimitKey());
1487     requestTermination(ProcessTerminationReason::ExceededMemoryLimit);
1488 }
1489
1490 void WebProcessProxy::didExceedCPULimit()
1491 {
1492     auto protectedThis = makeRef(*this);
1493
1494     for (auto& page : pages()) {
1495         if (page->isPlayingAudio()) {
1496             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());
1497             return;
1498         }
1499
1500         if (page->hasActiveAudioStream() || page->hasActiveVideoStream()) {
1501             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());
1502             return;
1503         }
1504     }
1505
1506     bool hasVisiblePage = false;
1507     for (auto& page : pages()) {
1508         if (page->isViewVisible()) {
1509             page->didExceedBackgroundCPULimitWhileInForeground();
1510             hasVisiblePage = true;
1511         }
1512     }
1513
1514     // We only notify the client that the process exceeded the CPU limit when it is visible, we do not terminate it.
1515     if (hasVisiblePage)
1516         return;
1517
1518     RELEASE_LOG_ERROR(PerformanceLogging, "%p - WebProcessProxy::didExceedCPULimit() Terminating background WebProcess with pid %d that has exceeded the background CPU limit", this, processIdentifier());
1519     logDiagnosticMessageForResourceLimitTermination(DiagnosticLoggingKeys::exceededBackgroundCPULimitKey());
1520     requestTermination(ProcessTerminationReason::ExceededCPULimit);
1521 }
1522
1523 void WebProcessProxy::updateBackgroundResponsivenessTimer()
1524 {
1525     m_backgroundResponsivenessTimer.updateState();
1526 }
1527
1528 #if !PLATFORM(COCOA)
1529 const HashSet<String>& WebProcessProxy::platformPathsWithAssumedReadAccess()
1530 {
1531     static NeverDestroyed<HashSet<String>> platformPathsWithAssumedReadAccess;
1532     return platformPathsWithAssumedReadAccess;
1533 }
1534 #endif
1535
1536 void WebProcessProxy::didCollectPrewarmInformation(const WebCore::RegistrableDomain& domain, const WebCore::PrewarmInformation& prewarmInformation)
1537 {
1538     MESSAGE_CHECK(!domain.isEmpty());
1539     processPool().didCollectPrewarmInformation(domain, prewarmInformation);
1540 }
1541
1542 void WebProcessProxy::activePagesDomainsForTesting(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
1543 {
1544     connection()->sendWithAsyncReply(Messages::WebProcess::GetActivePagesOriginsForTesting(), WTFMove(completionHandler));
1545 }
1546
1547 void WebProcessProxy::didStartProvisionalLoadForMainFrame(const URL& url)
1548 {
1549     RELEASE_ASSERT(!isInProcessCache());
1550
1551     // This process has been used for several registrable domains already.
1552     if (m_registrableDomain && m_registrableDomain->isEmpty())
1553         return;
1554
1555     auto registrableDomain = WebCore::RegistrableDomain { url };
1556     if (m_registrableDomain && *m_registrableDomain != registrableDomain) {
1557 #if ENABLE(SERVICE_WORKER)
1558         disableServiceWorkers();
1559 #endif
1560         // Null out registrable domain since this process has now been used for several domains.
1561         m_registrableDomain = WebCore::RegistrableDomain { };
1562         return;
1563     }
1564
1565     // Associate the process with this registrable domain.
1566     m_registrableDomain = WTFMove(registrableDomain);
1567 }
1568
1569 void WebProcessProxy::incrementSuspendedPageCount()
1570 {
1571     ++m_suspendedPageCount;
1572     if (m_suspendedPageCount == 1)
1573         send(Messages::WebProcess::SetHasSuspendedPageProxy(true), 0);
1574 }
1575
1576 void WebProcessProxy::decrementSuspendedPageCount()
1577 {
1578     ASSERT(m_suspendedPageCount);
1579     --m_suspendedPageCount;
1580     if (!m_suspendedPageCount) {
1581         send(Messages::WebProcess::SetHasSuspendedPageProxy(false), 0);
1582         maybeShutDown();
1583     }
1584 }
1585
1586 WebProcessPool* WebProcessProxy::processPoolIfExists() const
1587 {
1588     if (m_isPrewarmed || m_isInProcessCache)
1589         RELEASE_LOG_ERROR(Process, "%p - WebProcessProxy::processPoolIfExists: trying to get WebProcessPool from an inactive WebProcessProxy %i", this, processIdentifier());
1590     else
1591         ASSERT(m_processPool);
1592     return m_processPool.get();
1593 }
1594
1595 WebProcessPool& WebProcessProxy::processPool() const
1596 {
1597     ASSERT(m_processPool);
1598     return *m_processPool.get();
1599 }
1600
1601 PAL::SessionID WebProcessProxy::sessionID() const
1602 {
1603     ASSERT(m_websiteDataStore);
1604     return m_websiteDataStore->sessionID();
1605 }
1606
1607 void WebProcessProxy::addPlugInAutoStartOriginHash(String&& pageOrigin, uint32_t hash)
1608 {
1609     MESSAGE_CHECK(PlugInAutoStartProvider::AutoStartTable::isValidKey(pageOrigin));
1610     MESSAGE_CHECK(PlugInAutoStartProvider::HashToOriginMap::isValidKey(hash));
1611     processPool().plugInAutoStartProvider().addAutoStartOriginHash(WTFMove(pageOrigin), hash, sessionID());
1612 }
1613
1614 void WebProcessProxy::plugInDidReceiveUserInteraction(uint32_t hash)
1615 {
1616     MESSAGE_CHECK(PlugInAutoStartProvider::HashToOriginMap::isValidKey(hash));
1617     processPool().plugInAutoStartProvider().didReceiveUserInteraction(hash, sessionID());
1618 }
1619
1620 #if PLATFORM(WATCHOS)
1621
1622 void WebProcessProxy::startBackgroundActivityForFullscreenInput()
1623 {
1624     if (m_backgroundActivityForFullscreenFormControls)
1625         return;
1626
1627     m_backgroundActivityForFullscreenFormControls = m_throttler.backgroundActivity("Fullscreen input"_s).moveToUniquePtr();
1628     RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because it is presenting fullscreen UI for form controls.");
1629 }
1630
1631 void WebProcessProxy::endBackgroundActivityForFullscreenInput()
1632 {
1633     if (!m_backgroundActivityForFullscreenFormControls)
1634         return;
1635
1636     m_backgroundActivityForFullscreenFormControls = nullptr;
1637     RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because it has dismissed fullscreen UI for form controls.");
1638 }
1639
1640 #endif
1641
1642 #if ENABLE(SERVICE_WORKER)
1643 void WebProcessProxy::establishServiceWorkerContext(const WebPreferencesStore& store, CompletionHandler<void()>&& completionHandler)
1644 {
1645     sendWithAsyncReply(Messages::WebProcess::EstablishWorkerContextConnectionToNetworkProcess { processPool().defaultPageGroup().pageGroupID(), m_serviceWorkerInformation->serviceWorkerPageProxyID, m_serviceWorkerInformation->serviceWorkerPageID, store, *m_registrableDomain, m_serviceWorkerInformation->initializationData }, [activity = m_throttler.backgroundActivity("Establish Service Worker"_s), completionHandler = WTFMove(completionHandler)]() mutable {
1646         RELEASE_LOG(Loading, "WebProcessProxy::establishServiceWorkerContext finished");
1647         completionHandler();
1648     }, 0);
1649 }
1650
1651 void WebProcessProxy::setServiceWorkerUserAgent(const String& userAgent)
1652 {
1653     ASSERT(m_serviceWorkerInformation);
1654     send(Messages::WebSWContextManagerConnection::SetUserAgent { userAgent }, 0);
1655 }
1656
1657 void WebProcessProxy::updateServiceWorkerPreferencesStore(const WebPreferencesStore& store)
1658 {
1659     ASSERT(m_serviceWorkerInformation);
1660     send(Messages::WebSWContextManagerConnection::UpdatePreferencesStore { store }, 0);
1661 }
1662
1663 void WebProcessProxy::updateServiceWorkerProcessAssertion()
1664 {
1665     RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::updateServiceWorkerProcessAssertion() PID: %d", this, processIdentifier());
1666     ASSERT(m_serviceWorkerInformation);
1667     if (!m_serviceWorkerInformation)
1668         return;
1669
1670     bool shouldTakeForegroundActivity = WTF::anyOf(m_serviceWorkerInformation->clientProcesses, [](auto& process) {
1671         return !!process.m_foregroundToken;
1672     });
1673     if (shouldTakeForegroundActivity) {
1674         if (!ProcessThrottler::isValidForegroundActivity(m_serviceWorkerInformation->activity))
1675             m_serviceWorkerInformation->activity = m_throttler.foregroundActivity("Service Worker for foreground view(s)"_s);
1676         return;
1677     }
1678
1679     bool shouldTakeBackgroundActivity = WTF::anyOf(m_serviceWorkerInformation->clientProcesses, [](auto& process) {
1680         return !!process.m_backgroundToken;
1681     });
1682     if (shouldTakeBackgroundActivity) {
1683         if (!ProcessThrottler::isValidBackgroundActivity(m_serviceWorkerInformation->activity))
1684             m_serviceWorkerInformation->activity = m_throttler.backgroundActivity("Service Worker for background view(s)"_s);
1685         return;
1686     }
1687     m_serviceWorkerInformation->activity = nullptr;
1688 }
1689
1690 void WebProcessProxy::registerServiceWorkerClientProcess(WebProcessProxy& proxy)
1691 {
1692     if (!m_serviceWorkerInformation)
1693         return;
1694
1695     m_serviceWorkerInformation->clientProcesses.add(proxy);
1696     updateServiceWorkerProcessAssertion();
1697 }
1698
1699 void WebProcessProxy::unregisterServiceWorkerClientProcess(WebProcessProxy& proxy)
1700 {
1701     if (!m_serviceWorkerInformation)
1702         return;
1703
1704     m_serviceWorkerInformation->clientProcesses.remove(proxy);
1705     updateServiceWorkerProcessAssertion();
1706 }
1707
1708 bool WebProcessProxy::hasServiceWorkerForegroundActivityForTesting() const
1709 {
1710     return m_serviceWorkerInformation ? ProcessThrottler::isValidForegroundActivity(m_serviceWorkerInformation->activity) : false;
1711 }
1712
1713 bool WebProcessProxy::hasServiceWorkerBackgroundActivityForTesting() const
1714 {
1715     return m_serviceWorkerInformation ? ProcessThrottler::isValidBackgroundActivity(m_serviceWorkerInformation->activity) : false;
1716 }
1717 #endif // ENABLE(SERVICE_WORKER)
1718
1719 void WebProcessProxy::disableServiceWorkers()
1720 {
1721     if (!m_serviceWorkerInformation)
1722         return;
1723
1724     m_serviceWorkerInformation = { };
1725     updateBackgroundResponsivenessTimer();
1726
1727 #if ENABLE(SERVICE_WORKER)
1728     processPool().removeFromServiceWorkerProcesses(*this);
1729     send(Messages::WebSWContextManagerConnection::Close { }, 0);
1730 #endif
1731
1732     maybeShutDown();
1733 }
1734
1735 #if ENABLE(CONTENT_EXTENSIONS)
1736 static Vector<std::pair<String, WebCompiledContentRuleListData>> contentRuleListsFromIdentifier(const Optional<UserContentControllerIdentifier>& userContentControllerIdentifier)
1737 {
1738     if (!userContentControllerIdentifier) {
1739         ASSERT_NOT_REACHED();
1740         return { };
1741     }
1742
1743     auto* userContentController = WebUserContentControllerProxy::get(*userContentControllerIdentifier);
1744     if (!userContentController) {
1745         ASSERT_NOT_REACHED();
1746         return { };
1747     }
1748
1749     return userContentController->contentRuleListData();
1750 }
1751 #endif
1752
1753 void WebProcessProxy::enableServiceWorkers(const Optional<UserContentControllerIdentifier>& userContentControllerIdentifier)
1754 {
1755     ASSERT(m_registrableDomain && !m_registrableDomain->isEmpty());
1756     ASSERT(!m_serviceWorkerInformation);
1757     m_serviceWorkerInformation = ServiceWorkerInformation {
1758         WebPageProxyIdentifier::generate(),
1759         PageIdentifier::generate(),
1760         ServiceWorkerInitializationData {
1761             userContentControllerIdentifier,
1762 #if ENABLE(CONTENT_EXTENSIONS)
1763             contentRuleListsFromIdentifier(userContentControllerIdentifier),
1764 #endif
1765         },
1766         nullptr,
1767         { }
1768     };
1769     updateBackgroundResponsivenessTimer();
1770 #if ENABLE(SERVICE_WORKER)
1771     updateServiceWorkerProcessAssertion();
1772 #endif
1773 }
1774
1775 #if HAVE(VISIBILITY_PROPAGATION_VIEW)
1776 void WebProcessProxy::didCreateContextInGPUProcessForVisibilityPropagation(LayerHostingContextID contextID)
1777 {
1778     for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
1779         page->didCreateContextInGPUProcessForVisibilityPropagation(contextID);
1780 }
1781 #endif
1782
1783 } // namespace WebKit
1784
1785 #undef MESSAGE_CHECK
1786 #undef MESSAGE_CHECK_URL