Fix occasional null-dereference crash in WebPageProxy::didReceiveServerRedirectForPro...
[WebKit-https.git] / Source / WebKit / UIProcess / WebPageProxy.cpp
1 /*
2  * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebPageProxy.h"
29
30 #include "APIArray.h"
31 #include "APIAttachment.h"
32 #include "APIContextMenuClient.h"
33 #include "APIFindClient.h"
34 #include "APIFindMatchesClient.h"
35 #include "APIFormClient.h"
36 #include "APIFrameInfo.h"
37 #include "APIFullscreenClient.h"
38 #include "APIGeometry.h"
39 #include "APIHistoryClient.h"
40 #include "APIHitTestResult.h"
41 #include "APIIconLoadingClient.h"
42 #include "APILegacyContextHistoryClient.h"
43 #include "APILoaderClient.h"
44 #include "APINavigation.h"
45 #include "APINavigationAction.h"
46 #include "APINavigationClient.h"
47 #include "APINavigationResponse.h"
48 #include "APIOpenPanelParameters.h"
49 #include "APIPageConfiguration.h"
50 #include "APIPolicyClient.h"
51 #include "APISecurityOrigin.h"
52 #include "APIUIClient.h"
53 #include "APIURLRequest.h"
54 #include "APIWebsitePolicies.h"
55 #include "AuthenticationChallengeProxy.h"
56 #include "AuthenticationDecisionListener.h"
57 #include "DataReference.h"
58 #include "DownloadProxy.h"
59 #include "DrawingAreaMessages.h"
60 #include "DrawingAreaProxy.h"
61 #include "EventDispatcherMessages.h"
62 #include "FormDataReference.h"
63 #include "FrameInfoData.h"
64 #include "LoadParameters.h"
65 #include "Logging.h"
66 #include "NativeWebGestureEvent.h"
67 #include "NativeWebKeyboardEvent.h"
68 #include "NativeWebMouseEvent.h"
69 #include "NativeWebWheelEvent.h"
70 #include "NavigationActionData.h"
71 #include "NetworkProcessMessages.h"
72 #include "NetworkProcessProxy.h"
73 #include "NotificationPermissionRequest.h"
74 #include "NotificationPermissionRequestManager.h"
75 #include "OptionalCallbackID.h"
76 #include "PageClient.h"
77 #include "PluginInformation.h"
78 #include "PluginProcessManager.h"
79 #include "PrintInfo.h"
80 #include "SafeBrowsingWarning.h"
81 #include "ShareSheetCallbackID.h"
82 #include "SharedBufferDataReference.h"
83 #include "TextChecker.h"
84 #include "TextCheckerState.h"
85 #include "UIMessagePortChannelProvider.h"
86 #include "URLSchemeTaskParameters.h"
87 #include "UndoOrRedo.h"
88 #include "UserMediaPermissionRequestProxy.h"
89 #include "UserMediaProcessManager.h"
90 #include "WKContextPrivate.h"
91 #include "WebAutomationSession.h"
92 #include "WebBackForwardList.h"
93 #include "WebBackForwardListItem.h"
94 #include "WebCertificateInfo.h"
95 #include "WebContextMenuItem.h"
96 #include "WebContextMenuProxy.h"
97 #include "WebCoreArgumentCoders.h"
98 #include "WebEditCommandProxy.h"
99 #include "WebEvent.h"
100 #include "WebEventConversion.h"
101 #include "WebFramePolicyListenerProxy.h"
102 #include "WebFullScreenManagerProxy.h"
103 #include "WebFullScreenManagerProxyMessages.h"
104 #include "WebImage.h"
105 #include "WebInspectorProxy.h"
106 #include "WebInspectorUtilities.h"
107 #include "WebNavigationDataStore.h"
108 #include "WebNavigationState.h"
109 #include "WebNotificationManagerProxy.h"
110 #include "WebOpenPanelResultListenerProxy.h"
111 #include "WebPageCreationParameters.h"
112 #include "WebPageDebuggable.h"
113 #include "WebPageGroup.h"
114 #include "WebPageGroupData.h"
115 #include "WebPageInspectorController.h"
116 #include "WebPageMessages.h"
117 #include "WebPageProxyMessages.h"
118 #include "WebPaymentCoordinatorProxy.h"
119 #include "WebPopupItem.h"
120 #include "WebPopupMenuProxy.h"
121 #include "WebPreferences.h"
122 #include "WebPreferencesKeys.h"
123 #include "WebProcessMessages.h"
124 #include "WebProcessPool.h"
125 #include "WebProcessProxy.h"
126 #include "WebProtectionSpace.h"
127 #include "WebResourceLoadStatisticsStore.h"
128 #include "WebURLSchemeHandler.h"
129 #include "WebUserContentControllerProxy.h"
130 #include "WebsiteDataStore.h"
131 #include <WebCore/BitmapImage.h>
132 #include <WebCore/DeprecatedGlobalSettings.h>
133 #include <WebCore/DiagnosticLoggingClient.h>
134 #include <WebCore/DiagnosticLoggingKeys.h>
135 #include <WebCore/DragController.h>
136 #include <WebCore/DragData.h>
137 #include <WebCore/EventNames.h>
138 #include <WebCore/FloatRect.h>
139 #include <WebCore/FocusDirection.h>
140 #include <WebCore/FontAttributeChanges.h>
141 #include <WebCore/FrameLoader.h>
142 #include <WebCore/GlobalFrameIdentifier.h>
143 #include <WebCore/GlobalWindowIdentifier.h>
144 #include <WebCore/JSDOMBinding.h>
145 #include <WebCore/JSDOMExceptionHandling.h>
146 #include <WebCore/LengthBox.h>
147 #include <WebCore/MIMETypeRegistry.h>
148 #include <WebCore/MediaStreamRequest.h>
149 #include <WebCore/PerformanceLoggingClient.h>
150 #include <WebCore/PlatformEvent.h>
151 #include <WebCore/PublicSuffix.h>
152 #include <WebCore/RenderEmbeddedObject.h>
153 #include <WebCore/ResourceLoadStatistics.h>
154 #include <WebCore/SSLKeyGenerator.h>
155 #include <WebCore/SerializedCryptoKeyWrap.h>
156 #include <WebCore/ShareData.h>
157 #include <WebCore/SharedBuffer.h>
158 #include <WebCore/ShouldTreatAsContinuingLoad.h>
159 #include <WebCore/TextCheckerClient.h>
160 #include <WebCore/TextIndicator.h>
161 #include <WebCore/ValidationBubble.h>
162 #include <WebCore/WindowFeatures.h>
163 #include <WebCore/WritingDirection.h>
164 #include <stdio.h>
165 #include <wtf/NeverDestroyed.h>
166 #include <wtf/SystemTracing.h>
167 #include <wtf/URL.h>
168 #include <wtf/URLParser.h>
169 #include <wtf/text/StringView.h>
170 #include <wtf/text/TextStream.h>
171
172 #if ENABLE(APPLICATION_MANIFEST)
173 #include "APIApplicationManifest.h"
174 #endif
175
176 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
177 #include "RemoteScrollingCoordinatorProxy.h"
178 #endif
179
180 #ifndef NDEBUG
181 #include <wtf/RefCountedLeakCounter.h>
182 #endif
183
184 #if PLATFORM(COCOA)
185 #include "RemoteLayerTreeDrawingAreaProxy.h"
186 #include "RemoteLayerTreeScrollingPerformanceData.h"
187 #include "TouchBarMenuData.h"
188 #include "TouchBarMenuItemData.h"
189 #include "VideoFullscreenManagerProxy.h"
190 #include "VideoFullscreenManagerProxyMessages.h"
191 #include "ViewSnapshotStore.h"
192 #include <WebCore/RunLoopObserver.h>
193 #include <WebCore/TextIndicatorWindow.h>
194 #include <wtf/MachSendRight.h>
195 #endif
196
197 #if PLATFORM(GTK)
198 #include "WebSelectionData.h"
199 #endif
200
201 #if USE(CAIRO)
202 #include <WebCore/CairoUtilities.h>
203 #endif
204
205 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
206 #include <WebCore/MediaPlaybackTarget.h>
207 #include <WebCore/WebMediaSessionManager.h>
208 #endif
209
210 #if ENABLE(MEDIA_SESSION)
211 #include "WebMediaSessionFocusManager.h"
212 #include "WebMediaSessionMetadata.h"
213 #include <WebCore/MediaSessionMetadata.h>
214 #endif
215
216 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
217 #include "PlaybackSessionManagerProxy.h"
218 #endif
219
220 #if ENABLE(WEB_AUTHN)
221 #include "WebAuthenticatorCoordinatorProxy.h"
222 #endif
223
224 #if ENABLE(RESOURCE_LOAD_STATISTICS)
225 #include "WebResourceLoadStatisticsStore.h"
226 #endif
227
228 #if ENABLE(REMOTE_INSPECTOR)
229 #include <JavaScriptCore/RemoteInspector.h>
230 #endif
231
232 #if HAVE(SEC_KEY_PROXY)
233 #include "SecKeyProxyStore.h"
234 #endif
235
236 #if HAVE(PENCILKIT)
237 #include "EditableImageController.h"
238 #endif
239
240 // This controls what strategy we use for mouse wheel coalescing.
241 #define MERGE_WHEEL_EVENTS 1
242
243 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
244 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(url), m_process->connection())
245
246 #define RELEASE_LOG_IF_ALLOWED(channel, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, __VA_ARGS__)
247
248 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
249 static const unsigned wheelEventQueueSizeThreshold = 10;
250
251 static const Seconds resetRecentCrashCountDelay = 30_s;
252 static unsigned maximumWebProcessRelaunchAttempts = 1;
253
254 namespace WebKit {
255 using namespace WebCore;
256
257 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
258
259 class ExceededDatabaseQuotaRecords {
260     WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
261     friend NeverDestroyed<ExceededDatabaseQuotaRecords>;
262 public:
263     struct Record {
264         uint64_t frameID;
265         String originIdentifier;
266         String databaseName;
267         String displayName;
268         uint64_t currentQuota;
269         uint64_t currentOriginUsage;
270         uint64_t currentDatabaseUsage;
271         uint64_t expectedUsage;
272         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply reply;
273     };
274
275     static ExceededDatabaseQuotaRecords& singleton();
276
277     std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
278         String databaseName, String displayName, uint64_t currentQuota,
279         uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, 
280         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&&);
281
282     void add(std::unique_ptr<Record>);
283     bool areBeingProcessed() const { return !!m_currentRecord; }
284     Record* next();
285
286 private:
287     ExceededDatabaseQuotaRecords() { }
288     ~ExceededDatabaseQuotaRecords() { }
289
290     Deque<std::unique_ptr<Record>> m_records;
291     std::unique_ptr<Record> m_currentRecord;
292 };
293
294 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
295 {
296     static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
297     return records;
298 }
299
300 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
301     uint64_t frameID, String originIdentifier, String databaseName, String displayName,
302     uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
303     uint64_t expectedUsage, Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&& reply)
304 {
305     auto record = std::make_unique<Record>();
306     record->frameID = frameID;
307     record->originIdentifier = originIdentifier;
308     record->databaseName = databaseName;
309     record->displayName = displayName;
310     record->currentQuota = currentQuota;
311     record->currentOriginUsage = currentOriginUsage;
312     record->currentDatabaseUsage = currentDatabaseUsage;
313     record->expectedUsage = expectedUsage;
314     record->reply = WTFMove(reply);
315     return record;
316 }
317
318 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
319 {
320     m_records.append(WTFMove(record));
321 }
322
323 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
324 {
325     m_currentRecord = nullptr;
326     if (!m_records.isEmpty())
327         m_currentRecord = m_records.takeFirst();
328     return m_currentRecord.get();
329 }
330
331 #if !LOG_DISABLED
332 static const char* webMouseEventTypeString(WebEvent::Type type)
333 {
334     switch (type) {
335     case WebEvent::MouseDown:
336         return "MouseDown";
337     case WebEvent::MouseUp:
338         return "MouseUp";
339     case WebEvent::MouseMove:
340         return "MouseMove";
341     case WebEvent::MouseForceChanged:
342         return "MouseForceChanged";
343     case WebEvent::MouseForceDown:
344         return "MouseForceDown";
345     case WebEvent::MouseForceUp:
346         return "MouseForceUp";
347     default:
348         ASSERT_NOT_REACHED();
349         return "<unknown>";
350     }
351 }
352
353 static const char* webKeyboardEventTypeString(WebEvent::Type type)
354 {
355     switch (type) {
356     case WebEvent::KeyDown:
357         return "KeyDown";
358     case WebEvent::KeyUp:
359         return "KeyUp";
360     case WebEvent::RawKeyDown:
361         return "RawKeyDown";
362     case WebEvent::Char:
363         return "Char";
364     default:
365         ASSERT_NOT_REACHED();
366         return "<unknown>";
367     }
368 }
369 #endif // !LOG_DISABLED
370
371 class PageClientProtector {
372     WTF_MAKE_NONCOPYABLE(PageClientProtector);
373 public:
374     PageClientProtector(PageClient& pageClient)
375         : m_pageClient(makeWeakPtr(pageClient))
376     {
377         m_pageClient->refView();
378     }
379
380     ~PageClientProtector()
381     {
382         ASSERT(m_pageClient);
383         m_pageClient->derefView();
384     }
385
386 private:
387     WeakPtr<PageClient> m_pageClient;
388 };
389
390 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
391 {
392     return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
393 }
394
395 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
396     : m_pageClient(makeWeakPtr(pageClient))
397     , m_configuration(WTFMove(configuration))
398     , m_navigationClient(makeUniqueRef<API::NavigationClient>())
399     , m_historyClient(makeUniqueRef<API::HistoryClient>())
400     , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
401     , m_formClient(std::make_unique<API::FormClient>())
402     , m_uiClient(std::make_unique<API::UIClient>())
403     , m_findClient(std::make_unique<API::FindClient>())
404     , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
405 #if ENABLE(CONTEXT_MENUS)
406     , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
407 #endif
408     , m_navigationState(std::make_unique<WebNavigationState>())
409     , m_process(process)
410     , m_pageGroup(*m_configuration->pageGroup())
411     , m_preferences(*m_configuration->preferences())
412     , m_userContentController(*m_configuration->userContentController())
413     , m_visitedLinkStore(*m_configuration->visitedLinkStore())
414     , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
415     , m_userAgent(standardUserAgent())
416     , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
417     , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
418 #if ENABLE(FULLSCREEN_API)
419     , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
420 #endif
421     , m_geolocationPermissionRequestManager(*this)
422     , m_notificationPermissionRequestManager(*this)
423 #if PLATFORM(IOS_FAMILY)
424     , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
425 #endif
426     , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
427     , m_cpuLimit(m_configuration->cpuLimit())
428     , m_backForwardList(WebBackForwardList::create(*this))
429     , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
430     , m_drawsBackground(m_configuration->drawsBackground())
431     , m_pageID(pageID)
432     , m_controlledByAutomation(m_configuration->isControlledByAutomation())
433 #if PLATFORM(COCOA)
434     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
435 #endif
436     , m_pageLoadState(*this)
437     , m_configurationPreferenceValues(m_configuration->preferenceValues())
438     , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
439 #if ENABLE(REMOTE_INSPECTOR)
440     , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
441 #endif
442     , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
443 #if HAVE(PENCILKIT)
444     , m_editableImageController(std::make_unique<EditableImageController>(*this))
445 #endif
446 {
447     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
448     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
449
450     updateActivityState();
451     updateThrottleState();
452     updateHiddenPageThrottlingAutoIncreases();
453     
454 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
455     m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
456 #endif
457
458     platformInitialize();
459
460 #ifndef NDEBUG
461     webPageProxyCounter.increment();
462 #endif
463
464     WebProcessPool::statistics().wkPageCount++;
465
466     m_preferences->addPage(*this);
467     m_pageGroup->addPage(this);
468
469     m_inspector = WebInspectorProxy::create(this);
470 #if ENABLE(FULLSCREEN_API)
471     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, WebPageProxy::pageClient().fullScreenManagerProxyClient());
472 #endif
473 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
474     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
475     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
476 #endif
477
478 #if ENABLE(APPLE_PAY)
479     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
480 #endif
481
482 #if USE(SYSTEM_PREVIEW)
483     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
484 #endif
485
486 #if ENABLE(WEB_AUTHN)
487     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
488 #endif
489
490     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
491
492 #if PLATFORM(IOS_FAMILY)
493     DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
494 #endif
495
496 #if PLATFORM(COCOA)
497     m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
498         this->dispatchActivityStateChange();
499     });
500 #endif
501
502 #if ENABLE(REMOTE_INSPECTOR)
503     m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
504     m_inspectorDebuggable->init();
505 #endif
506
507     createInspectorTargets();
508 }
509
510 WebPageProxy::~WebPageProxy()
511 {
512     ASSERT(m_process->webPage(m_pageID) != this);
513 #if !ASSERT_DISABLED
514     for (WebPageProxy* page : m_process->pages())
515         ASSERT(page != this);
516 #endif
517
518     if (!m_isClosed)
519         close();
520
521     WebProcessPool::statistics().wkPageCount--;
522
523     if (m_spellDocumentTag)
524         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
525
526     m_preferences->removePage(*this);
527     m_pageGroup->removePage(this);
528
529 #ifndef NDEBUG
530     webPageProxyCounter.decrement();
531 #endif
532 }
533
534 // FIXME: Should return a const PageClient& and add a separate non-const
535 // version of this function, but several PageClient methods will need to become
536 // const for this to be possible.
537 PageClient& WebPageProxy::pageClient() const
538 {
539     ASSERT(m_pageClient);
540     return *m_pageClient;
541 }
542
543 PAL::SessionID WebPageProxy::sessionID() const
544 {
545     return m_websiteDataStore->sessionID();
546 }
547
548 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
549 {
550     m_process->processPool().pageEndUsingWebsiteDataStore(*this);
551     m_websiteDataStore = websiteDataStore;
552     m_process->processPool().pageBeginUsingWebsiteDataStore(*this);
553 }
554
555 const API::PageConfiguration& WebPageProxy::configuration() const
556 {
557     return m_configuration.get();
558 }
559
560 ProcessID WebPageProxy::processIdentifier() const
561 {
562     if (m_isClosed)
563         return 0;
564
565     return m_process->processIdentifier();
566 }
567
568 bool WebPageProxy::isValid() const
569 {
570     // A page that has been explicitly closed is never valid.
571     if (m_isClosed)
572         return false;
573
574     return m_isValid;
575 }
576
577 void WebPageProxy::notifyProcessPoolToPrewarm()
578 {
579     m_process->processPool().didReachGoodTimeToPrewarm();
580 }
581
582 void WebPageProxy::setPreferences(WebPreferences& preferences)
583 {
584     if (&preferences == m_preferences.ptr())
585         return;
586
587     m_preferences->removePage(*this);
588     m_preferences = preferences;
589     m_preferences->addPage(*this);
590
591     preferencesDidChange();
592 }
593     
594 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
595 {
596     m_historyClient = WTFMove(historyClient);
597 }
598
599 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
600 {
601     m_navigationClient = WTFMove(navigationClient);
602 }
603
604 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
605 {
606     m_loaderClient = WTFMove(loaderClient);
607 }
608
609 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
610 {
611     m_policyClient = WTFMove(policyClient);
612 }
613
614 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
615 {
616     if (!formClient) {
617         m_formClient = std::make_unique<API::FormClient>();
618         return;
619     }
620
621     m_formClient = WTFMove(formClient);
622 }
623
624 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
625 {
626     if (!uiClient) {
627         m_uiClient = std::make_unique<API::UIClient>();
628         return;
629     }
630
631     m_uiClient = WTFMove(uiClient);
632
633     if (!isValid())
634         return;
635
636     m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
637     setCanRunModal(m_uiClient->canRunModal());
638     setNeedsFontAttributes(m_uiClient->needsFontAttributes());
639 }
640
641 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
642 {
643     bool hasClient = iconLoadingClient.get();
644     if (!iconLoadingClient)
645         m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
646     else
647         m_iconLoadingClient = WTFMove(iconLoadingClient);
648
649     if (!isValid())
650         return;
651
652     m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
653 }
654
655 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
656 {
657     if (!findClient) {
658         m_findClient = std::make_unique<API::FindClient>();
659         return;
660     }
661     
662     m_findClient = WTFMove(findClient);
663 }
664
665 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
666 {
667     if (!findMatchesClient) {
668         m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
669         return;
670     }
671
672     m_findMatchesClient = WTFMove(findMatchesClient);
673 }
674
675 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
676 {
677     m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
678 }
679
680 #if ENABLE(CONTEXT_MENUS)
681 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
682 {
683     if (!contextMenuClient) {
684         m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
685         return;
686     }
687
688     m_contextMenuClient = WTFMove(contextMenuClient);
689 }
690 #endif
691
692 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
693 {
694     if (!client) {
695         m_injectedBundleClient = nullptr;
696         return;
697     }
698
699     m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
700     m_injectedBundleClient->initialize(client);
701 }
702
703 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
704 {
705     ASSERT(m_process->connection() == &connection);
706
707     if (!m_injectedBundleClient)
708         return;
709
710     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
711 }
712
713 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
714 {
715     ASSERT(m_process->connection() == &connection);
716
717     if (!m_injectedBundleClient)
718         return;
719
720     RefPtr<API::Object> returnData;
721     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
722     returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
723 }
724
725 void WebPageProxy::reattachToWebProcess()
726 {
727     ASSERT(!m_isClosed);
728     ASSERT(!isValid());
729     RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::reattachToWebProcess\n", this);
730
731     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
732     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
733
734     auto& processPool = m_process->processPool();
735     m_process = processPool.createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
736     m_isValid = true;
737
738     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::Yes);
739     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
740
741     finishAttachingToWebProcess();
742 }
743
744 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, std::optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient)
745 {
746     if (!mainFrameID)
747         return false;
748
749     // If the client forced a swap then it may not be Web-compatible to suspend the previous page because other windows may have an opener link to the page.
750     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
751         return false;
752
753     if (isPageOpenedByDOMShowingInitialEmptyDocument())
754         return false;
755
756     auto* currentItem = navigation.fromItem();
757     if (!currentItem) {
758         LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), m_process->processIdentifier());
759         return false;
760     }
761
762     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *currentItem, *mainFrameID);
763
764     LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), currentItem->itemID().logString());
765
766     m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
767     return true;
768 }
769
770 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<SuspendedPageProxy>&& destinationSuspendedPage, ShouldDelayAttachingDrawingArea shouldDelayAttachingDrawingArea)
771 {
772     ASSERT(!m_isClosed);
773     RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::swapToWebProcess\n", this);
774
775     m_process = WTFMove(process);
776     m_isValid = true;
777
778     // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
779     // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
780     // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
781     // already exists and already has a main frame.
782     if (destinationSuspendedPage) {
783         ASSERT(!m_mainFrame);
784         ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
785         destinationSuspendedPage->unsuspend();
786         m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
787         m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
788     }
789
790     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::No);
791     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
792
793     finishAttachingToWebProcess(shouldDelayAttachingDrawingArea);
794 }
795
796 void WebPageProxy::finishAttachingToWebProcess(ShouldDelayAttachingDrawingArea shouldDelayAttachingDrawingArea)
797 {
798     ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
799
800     if (m_process->state() == ChildProcessProxy::State::Running) {
801         m_webProcessLifetimeTracker.webPageEnteringWebProcess();
802         processDidFinishLaunching();
803     }
804
805     updateActivityState();
806     updateThrottleState();
807
808 #if ENABLE(FULLSCREEN_API)
809     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
810 #endif
811 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
812     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
813     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
814 #endif
815
816 #if ENABLE(APPLE_PAY)
817     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
818 #endif
819
820 #if USE(SYSTEM_PREVIEW)
821     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
822 #endif
823
824 #if ENABLE(WEB_AUTHN)
825     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
826 #endif
827
828 #if HAVE(PENCILKIT)
829     m_editableImageController = std::make_unique<EditableImageController>(*this);
830 #endif
831
832     initializeWebPage(shouldDelayAttachingDrawingArea);
833
834     m_inspector->updateForNewPageProcess(this);
835
836 #if ENABLE(REMOTE_INSPECTOR)
837     remoteInspectorInformationDidChange();
838 #endif
839
840     clearInspectorTargets();
841     createInspectorTargets();
842
843     pageClient().didRelaunchProcess();
844     m_pageLoadState.didSwapWebProcesses();
845     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
846 }
847
848 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
849 {
850     if (m_isClosed)
851         return nullptr;
852     
853     ASSERT(!isValid());
854     reattachToWebProcess();
855
856     if (!m_backForwardList->currentItem())
857         return nullptr;
858
859     auto navigation = m_navigationState->createReloadNavigation();
860
861     // We allow stale content when reloading a WebProcess that's been killed or crashed.
862     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, std::nullopt), m_pageID);
863     m_process->responsivenessTimer().start();
864
865     return WTFMove(navigation);
866 }
867
868 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem& item)
869 {
870     if (m_isClosed)
871         return nullptr;
872
873     ASSERT(!isValid());
874     reattachToWebProcess();
875
876     if (&item != m_backForwardList->currentItem())
877         m_backForwardList->goToItem(item);
878
879     auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
880
881     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, std::nullopt), m_pageID);
882     m_process->responsivenessTimer().start();
883
884     return WTFMove(navigation);
885 }
886
887 void WebPageProxy::initializeWebPage(ShouldDelayAttachingDrawingArea shouldDelayAttachingDrawingArea)
888 {
889     ASSERT(isValid());
890
891     m_drawingArea = pageClient().createDrawingAreaProxy();
892     ASSERT(m_drawingArea);
893
894 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
895     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
896         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
897 #if PLATFORM(IOS_FAMILY)
898         // On iOS, main frame scrolls are sent in terms of visible rect updates.
899         m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
900 #endif
901     }
902 #endif
903
904     auto parameters = creationParameters();
905 #if PLATFORM(MAC)
906     parameters.shouldDelayAttachingDrawingArea = shouldDelayAttachingDrawingArea == ShouldDelayAttachingDrawingArea::Yes;
907 #else
908     UNUSED_PARAM(shouldDelayAttachingDrawingArea);
909 #endif
910
911 #if ENABLE(SERVICE_WORKER)
912     parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
913 #endif
914
915     process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0);
916
917     m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
918     finishInitializingWebPageAfterProcessLaunch();
919 }
920
921 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
922 {
923     if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
924         return;
925     if (m_process->state() != WebProcessProxy::State::Running)
926         return;
927
928     m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
929     m_process->addVisitedLinkStore(m_visitedLinkStore);
930 }
931
932 void WebPageProxy::close()
933 {
934     if (m_isClosed)
935         return;
936
937     m_isClosed = true;
938
939 #if ENABLE(MEDIA_STREAM)
940     m_userMediaPermissionRequestManager = nullptr;
941 #endif
942
943     reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
944
945     if (m_activePopupMenu)
946         m_activePopupMenu->cancelTracking();
947
948     if (m_controlledByAutomation) {
949         if (auto* automationSession = process().processPool().automationSession())
950             automationSession->willClosePage(*this);
951     }
952
953 #if ENABLE(CONTEXT_MENUS)
954     m_activeContextMenu = nullptr;
955 #endif
956
957     m_inspector->invalidate();
958
959     m_backForwardList->pageClosed();
960     m_inspectorController->pageClosed();
961 #if ENABLE(REMOTE_INSPECTOR)
962     m_inspectorDebuggable = nullptr;
963 #endif
964     pageClient().pageClosed();
965
966     m_process->disconnectFramesFromPage(this);
967
968     resetState(ResetStateReason::PageInvalidated);
969
970     m_loaderClient = nullptr;
971     m_navigationClient = makeUniqueRef<API::NavigationClient>();
972     m_policyClient = nullptr;
973     m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
974     m_formClient = std::make_unique<API::FormClient>();
975     m_uiClient = std::make_unique<API::UIClient>();
976     m_findClient = std::make_unique<API::FindClient>();
977     m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
978     m_diagnosticLoggingClient = nullptr;
979 #if ENABLE(CONTEXT_MENUS)
980     m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
981 #endif
982 #if ENABLE(FULLSCREEN_API)
983     m_fullscreenClient = std::make_unique<API::FullscreenClient>();
984 #endif
985
986     m_webProcessLifetimeTracker.pageWasInvalidated();
987
988     m_process->processPool().removeAllSuspendedPagesForPage(*this);
989
990     m_process->send(Messages::WebPage::Close(), m_pageID);
991     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
992     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
993     m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
994
995     // Null out related WebPageProxy to avoid leaks.
996     m_configuration->setRelatedPage(nullptr);
997
998 #if PLATFORM(IOS_FAMILY)
999     // Make sure we don't hold a process assertion after getting closed.
1000     m_activityToken = nullptr;
1001 #endif
1002
1003     stopAllURLSchemeTasks();
1004 }
1005
1006 bool WebPageProxy::tryClose()
1007 {
1008     if (!isValid())
1009         return true;
1010
1011     // Close without delay if the process allows it. Our goal is to terminate
1012     // the process, so we check a per-process status bit.
1013     if (m_process->isSuddenTerminationEnabled())
1014         return true;
1015
1016     m_process->send(Messages::WebPage::TryClose(), m_pageID);
1017     m_process->responsivenessTimer().start();
1018     return false;
1019 }
1020
1021 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
1022 {
1023     if (!url.isLocalFile())
1024         return false;
1025
1026     if (m_process->hasAssumedReadAccessToURL(url))
1027         return false;
1028
1029     // Inspector resources are in a directory with assumed access.
1030     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
1031
1032     SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
1033     return true;
1034 }
1035
1036 #if !PLATFORM(COCOA)
1037 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
1038 {
1039 }
1040 #endif
1041
1042 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1043 {
1044     if (m_isClosed)
1045         return nullptr;
1046
1047     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1048     loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1049     return WTFMove(navigation);
1050 }
1051
1052 void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&& websitePolicies)
1053 {
1054     ASSERT(!m_isClosed);
1055
1056     auto transaction = m_pageLoadState.transaction();
1057
1058     auto url = request.url();
1059     m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1060
1061     if (!isValid())
1062         reattachToWebProcess();
1063
1064     LoadParameters loadParameters;
1065     loadParameters.navigationID = navigation.navigationID();
1066     loadParameters.request = WTFMove(request);
1067     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
1068     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1069     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1070     loadParameters.websitePolicies = WTFMove(websitePolicies);
1071     loadParameters.lockHistory = navigation.lockHistory();
1072     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1073     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1074     bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
1075     if (createdExtension)
1076         willAcquireUniversalFileReadSandboxExtension();
1077     addPlatformLoadParameters(loadParameters);
1078
1079     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1080     m_process->responsivenessTimer().start();
1081 }
1082
1083 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1084 {
1085     if (m_isClosed)
1086         return nullptr;
1087
1088     if (!isValid())
1089         reattachToWebProcess();
1090
1091     URL fileURL = URL(URL(), fileURLString);
1092     if (!fileURL.isLocalFile())
1093         return nullptr;
1094
1095     URL resourceDirectoryURL;
1096     if (resourceDirectoryURLString.isNull())
1097         resourceDirectoryURL = URL({ }, "file:///"_s);
1098     else {
1099         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1100         if (!resourceDirectoryURL.isLocalFile())
1101             return nullptr;
1102     }
1103
1104     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1105
1106     auto transaction = m_pageLoadState.transaction();
1107
1108     m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
1109
1110     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1111
1112     LoadParameters loadParameters;
1113     loadParameters.navigationID = navigation->navigationID();
1114     loadParameters.request = fileURL;
1115     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1116     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1117     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1118     addPlatformLoadParameters(loadParameters);
1119
1120     m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1121     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1122     m_process->responsivenessTimer().start();
1123
1124     return WTFMove(navigation);
1125 }
1126
1127 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
1128 {
1129     if (m_isClosed)
1130         return nullptr;
1131
1132     auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
1133     loadDataWithNavigation(navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
1134     return WTFMove(navigation);
1135 }
1136
1137 void WebPageProxy::loadDataWithNavigation(API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&& websitePolicies)
1138 {
1139     ASSERT(!m_isClosed);
1140
1141     auto transaction = m_pageLoadState.transaction();
1142
1143     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : WTF::blankURL().string());
1144
1145     if (!isValid())
1146         reattachToWebProcess();
1147
1148     LoadParameters loadParameters;
1149     loadParameters.navigationID = navigation.navigationID();
1150     loadParameters.data = data;
1151     loadParameters.MIMEType = MIMEType;
1152     loadParameters.encodingName = encoding;
1153     loadParameters.baseURLString = baseURL;
1154     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1155     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1156     loadParameters.websitePolicies = WTFMove(websitePolicies);
1157     addPlatformLoadParameters(loadParameters);
1158
1159     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1160     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1161     m_process->responsivenessTimer().start();
1162 }
1163
1164 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1165 {
1166     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1167     // start a second alternative HTML load as this will prevent the page load state from being
1168     // handled properly.
1169     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad)
1170         return;
1171
1172     if (!m_failingProvisionalLoadURL.isEmpty())
1173         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1174
1175     if (!isValid())
1176         reattachToWebProcess();
1177
1178     auto transaction = m_pageLoadState.transaction();
1179
1180     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1181     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1182
1183     if (m_mainFrame)
1184         m_mainFrame->setUnreachableURL(unreachableURL);
1185
1186     LoadParameters loadParameters;
1187     loadParameters.navigationID = 0;
1188     loadParameters.data = htmlData;
1189     loadParameters.MIMEType = "text/html"_s;
1190     loadParameters.encodingName = encoding;
1191     loadParameters.baseURLString = baseURL;
1192     loadParameters.unreachableURLString = unreachableURL;
1193     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1194     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1195     addPlatformLoadParameters(loadParameters);
1196
1197     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1198     m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1199     m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1200     m_process->responsivenessTimer().start();
1201 }
1202
1203 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1204 {
1205     if (m_isClosed)
1206         return;
1207
1208     if (!isValid())
1209         reattachToWebProcess();
1210
1211     auto transaction = m_pageLoadState.transaction();
1212     m_pageLoadState.setPendingAPIRequestURL(transaction, WTF::blankURL().string());
1213
1214     LoadParameters loadParameters;
1215     loadParameters.navigationID = 0;
1216     loadParameters.data = webArchiveData->dataReference();
1217     loadParameters.MIMEType = "application/x-webarchive"_s;
1218     loadParameters.encodingName = "utf-16"_s;
1219     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1220     addPlatformLoadParameters(loadParameters);
1221
1222     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1223     m_process->responsivenessTimer().start();
1224 }
1225
1226 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1227 {
1228     if (m_isClosed)
1229         return;
1230
1231     if (WTF::protocolIsJavaScript(url))
1232         return;
1233
1234     if (!isValid())
1235         reattachToWebProcess();
1236
1237     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1238     m_process->responsivenessTimer().start();
1239 }
1240
1241 void WebPageProxy::stopLoading()
1242 {
1243     if (!isValid())
1244         return;
1245
1246     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1247     m_process->responsivenessTimer().start();
1248 }
1249
1250 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1251 {
1252     SandboxExtension::Handle sandboxExtensionHandle;
1253
1254     String url = currentURL();
1255     if (!url.isEmpty()) {
1256         auto transaction = m_pageLoadState.transaction();
1257         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1258
1259         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1260         bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
1261         if (createdExtension)
1262             willAcquireUniversalFileReadSandboxExtension();
1263     }
1264
1265     if (!isValid())
1266         return reattachToWebProcessForReload();
1267     
1268     auto navigation = m_navigationState->createReloadNavigation();
1269
1270     m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1271     m_process->responsivenessTimer().start();
1272
1273     return WTFMove(navigation);
1274 }
1275
1276 void WebPageProxy::recordAutomaticNavigationSnapshot()
1277 {
1278     if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1279         return;
1280
1281     if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1282         recordNavigationSnapshot(*item);
1283 }
1284
1285 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1286 {
1287     if (!m_shouldRecordNavigationSnapshots)
1288         return;
1289
1290 #if PLATFORM(COCOA)
1291     ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1292 #else
1293     UNUSED_PARAM(item);
1294 #endif
1295 }
1296
1297 RefPtr<API::Navigation> WebPageProxy::goForward()
1298 {
1299     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1300     if (!forwardItem)
1301         return nullptr;
1302
1303     return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1304 }
1305
1306 RefPtr<API::Navigation> WebPageProxy::goBack()
1307 {
1308     WebBackForwardListItem* backItem = m_backForwardList->backItem();
1309     if (!backItem)
1310         return nullptr;
1311
1312     return goToBackForwardItem(*backItem, FrameLoadType::Back);
1313 }
1314
1315 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1316 {
1317     return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1318 }
1319
1320 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1321 {
1322     LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1323
1324     if (!isValid())
1325         return reattachToWebProcessWithItem(item);
1326
1327     auto transaction = m_pageLoadState.transaction();
1328
1329     m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
1330
1331     RefPtr<API::Navigation> navigation;
1332     if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1333         navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1334
1335     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt), m_pageID);
1336     m_process->responsivenessTimer().start();
1337
1338     return navigation;
1339 }
1340
1341 void WebPageProxy::tryRestoreScrollPosition()
1342 {
1343     if (!isValid())
1344         return;
1345
1346     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1347 }
1348
1349 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1350 {
1351     PageClientProtector protector(pageClient());
1352
1353     if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1354         m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1355
1356     auto transaction = m_pageLoadState.transaction();
1357
1358     m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1359     m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1360 }
1361
1362 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1363 {
1364     PageClientProtector protector(pageClient());
1365
1366     if (auto* item = m_backForwardList->itemForID(itemID))
1367         m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1368 }
1369
1370 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1371 {
1372     PageClientProtector protector(pageClient());
1373
1374     return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1375 }
1376
1377 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1378 {
1379     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1380         return true;
1381
1382 #if ENABLE(NETSCAPE_PLUGIN_API)
1383     String newMimeType = mimeType;
1384     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1385     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1386         return true;
1387 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1388
1389 #if PLATFORM(COCOA)
1390     // On Mac, we can show PDFs.
1391     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1392         return true;
1393 #endif // PLATFORM(COCOA)
1394
1395     return false;
1396 }
1397
1398 void WebPageProxy::setControlledByAutomation(bool controlled)
1399 {
1400     if (m_controlledByAutomation == controlled)
1401         return;
1402
1403     m_controlledByAutomation = controlled;
1404
1405     if (!isValid())
1406         return;
1407
1408     m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1409     m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1410 }
1411
1412 void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
1413 {
1414     m_inspectorController->createInspectorTarget(targetId, type);
1415 }
1416
1417 void WebPageProxy::destroyInspectorTarget(const String& targetId)
1418 {
1419     m_inspectorController->destroyInspectorTarget(targetId);
1420 }
1421
1422 void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
1423 {
1424     m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
1425 }
1426
1427 #if ENABLE(REMOTE_INSPECTOR)
1428 void WebPageProxy::setIndicating(bool indicating)
1429 {
1430     if (!isValid())
1431         return;
1432
1433     m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
1434 }
1435
1436 bool WebPageProxy::allowsRemoteInspection() const
1437 {
1438     return m_inspectorDebuggable->remoteDebuggingAllowed();
1439 }
1440
1441 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1442 {
1443     m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
1444 }
1445
1446 String WebPageProxy::remoteInspectionNameOverride() const
1447 {
1448     return m_inspectorDebuggable->nameOverride();
1449 }
1450
1451 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1452 {
1453     m_inspectorDebuggable->setNameOverride(name);
1454 }
1455
1456 void WebPageProxy::remoteInspectorInformationDidChange()
1457 {
1458     m_inspectorDebuggable->update();
1459 }
1460 #endif
1461
1462 void WebPageProxy::clearInspectorTargets()
1463 {
1464     m_inspectorController->clearTargets();
1465 }
1466
1467 void WebPageProxy::createInspectorTargets()
1468 {
1469     String pageTargetId = makeString("page-", String::number(m_pageID));
1470     m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
1471 }
1472
1473 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1474 {
1475     if (m_drawsBackground == drawsBackground)
1476         return;
1477
1478     m_drawsBackground = drawsBackground;
1479
1480     if (isValid())
1481         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1482 }
1483
1484 void WebPageProxy::setTopContentInset(float contentInset)
1485 {
1486     if (m_topContentInset == contentInset)
1487         return;
1488
1489     m_topContentInset = contentInset;
1490
1491     if (!isValid())
1492         return;
1493 #if PLATFORM(COCOA)
1494     MachSendRight fence = m_drawingArea->createFence();
1495
1496     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1497     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1498 #else
1499     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1500 #endif
1501 }
1502
1503 void WebPageProxy::setUnderlayColor(const Color& color)
1504 {
1505     if (m_underlayColor == color)
1506         return;
1507
1508     m_underlayColor = color;
1509
1510     if (isValid())
1511         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1512 }
1513
1514 void WebPageProxy::viewWillStartLiveResize()
1515 {
1516     if (!isValid())
1517         return;
1518
1519     closeOverlayedViews();
1520     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1521 }
1522
1523 void WebPageProxy::viewWillEndLiveResize()
1524 {
1525     if (!isValid())
1526         return;
1527     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1528 }
1529
1530 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1531 {
1532     pageClient().setViewNeedsDisplay(region);
1533 }
1534
1535 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1536 {
1537     pageClient().requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1538 }
1539
1540 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1541 {
1542     return pageClient().viewScrollPosition();
1543 }
1544
1545 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1546 {
1547     if (m_suppressVisibilityUpdates == flag)
1548         return;
1549     m_suppressVisibilityUpdates = flag;
1550
1551     if (!m_suppressVisibilityUpdates) {
1552 #if PLATFORM(COCOA)
1553         m_activityStateChangeDispatcher->schedule();
1554 #else
1555         dispatchActivityStateChange();
1556 #endif
1557     }
1558 }
1559
1560 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1561 {
1562     m_activityState.remove(flagsToUpdate);
1563     if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1564         m_activityState.add(ActivityState::IsFocused);
1565     if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1566         m_activityState.add(ActivityState::WindowIsActive);
1567     if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1568         m_activityState.add(ActivityState::IsVisible);
1569     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1570         m_activityState.add(ActivityState::IsVisibleOrOccluded);
1571     if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1572         m_activityState.add(ActivityState::IsInWindow);
1573     if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1574         m_activityState.add(ActivityState::IsVisuallyIdle);
1575     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1576         m_activityState.add(ActivityState::IsAudible);
1577     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1578         m_activityState.add(ActivityState::IsLoading);
1579     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1580         m_activityState.add(ActivityState::IsCapturingMedia);
1581 }
1582
1583 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1584 {
1585     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1586
1587     m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1588     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1589
1590     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1591         return;
1592
1593 #if PLATFORM(COCOA)
1594     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1595     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1596         dispatchActivityStateChange();
1597         return;
1598     }
1599     m_activityStateChangeDispatcher->schedule();
1600 #else
1601     UNUSED_PARAM(dispatchMode);
1602     dispatchActivityStateChange();
1603 #endif
1604 }
1605
1606 void WebPageProxy::viewDidLeaveWindow()
1607 {
1608     closeOverlayedViews();
1609 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1610     // When leaving the current page, close the video fullscreen.
1611     if (m_videoFullscreenManager)
1612         m_videoFullscreenManager->requestHideAndExitFullscreen();
1613 #endif
1614 }
1615
1616 void WebPageProxy::viewDidEnterWindow()
1617 {
1618     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1619     if (m_layerHostingMode != layerHostingMode) {
1620         m_layerHostingMode = layerHostingMode;
1621         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1622     }
1623 }
1624
1625 void WebPageProxy::dispatchActivityStateChange()
1626 {
1627 #if PLATFORM(COCOA)
1628     m_activityStateChangeDispatcher->invalidate();
1629 #endif
1630
1631     if (!isValid())
1632         return;
1633
1634     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1635
1636     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1637     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1638         m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1639
1640     // Record the prior view state, update the flags that may have changed,
1641     // and check which flags have actually changed.
1642     auto previousActivityState = m_activityState;
1643     updateActivityState(m_potentiallyChangedActivityStateFlags);
1644     auto changed = m_activityState ^ previousActivityState;
1645
1646     if (changed)
1647         LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1648
1649     if ((changed & ActivityState::WindowIsActive) && isViewWindowActive())
1650         updateCurrentModifierState();
1651
1652     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1653         viewIsBecomingVisible();
1654
1655     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1656     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1657     if (m_viewWasEverInWindow && isNowInWindow) {
1658         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1659             m_activityStateChangeWantsSynchronousReply = true;
1660         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1661     }
1662
1663     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1664     if (!(m_activityState & ActivityState::IsVisible))
1665         m_activityStateChangeWantsSynchronousReply = false;
1666
1667     auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1668
1669     if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1670         m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1671
1672     m_nextActivityStateChangeCallbacks.clear();
1673
1674     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1675     updateThrottleState();
1676
1677 #if ENABLE(POINTER_LOCK)
1678     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1679         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1680         requestPointerUnlock();
1681 #endif
1682
1683     if (changed & ActivityState::IsVisible) {
1684         if (isViewVisible())
1685             m_visiblePageToken = m_process->visiblePageToken();
1686         else {
1687             m_visiblePageToken = nullptr;
1688
1689             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1690             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1691             // stop the unresponsiveness timer here.
1692             m_process->responsivenessTimer().stop();
1693         }
1694     }
1695
1696     if (changed & ActivityState::IsInWindow) {
1697         if (isInWindow())
1698             viewDidEnterWindow();
1699         else
1700             viewDidLeaveWindow();
1701     }
1702
1703     updateBackingStoreDiscardableState();
1704
1705     if (activityStateChangeID != ActivityStateChangeAsynchronous)
1706         waitForDidUpdateActivityState(activityStateChangeID);
1707
1708     m_potentiallyChangedActivityStateFlags = { };
1709     m_activityStateChangeWantsSynchronousReply = false;
1710     m_viewWasEverInWindow |= isNowInWindow;
1711 }
1712
1713 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1714 {
1715     return sessionID().isAlwaysOnLoggingAllowed();
1716 }
1717
1718 void WebPageProxy::updateThrottleState()
1719 {
1720     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1721
1722     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1723     if (!processSuppressionEnabled)
1724         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1725     else if (!m_preventProcessSuppressionCount)
1726         m_preventProcessSuppressionCount = nullptr;
1727
1728     if (m_activityState & ActivityState::IsVisuallyIdle)
1729         m_pageIsUserObservableCount = nullptr;
1730     else if (!m_pageIsUserObservableCount)
1731         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1732
1733 #if PLATFORM(IOS_FAMILY)
1734     bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1735     bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1736     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1737         if (m_activityToken) {
1738             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1739             m_activityToken = nullptr;
1740         }
1741     } else if (!m_activityToken) {
1742         if (isViewVisible())
1743             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1744         else if (isAudible)
1745             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1746         else if (isCapturingMedia)
1747             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1748         else
1749             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion even though the view is not visible because m_alwaysRunsAtForegroundPriority is true", this);
1750         m_activityToken = m_process->throttler().foregroundActivityToken();
1751     }
1752 #endif
1753 }
1754
1755 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1756 {
1757     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1758         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1759     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1760         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1761 }
1762
1763 void WebPageProxy::layerHostingModeDidChange()
1764 {
1765     if (!isValid())
1766         return;
1767
1768     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1769     if (m_layerHostingMode == layerHostingMode)
1770         return;
1771
1772     m_layerHostingMode = layerHostingMode;
1773     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1774 }
1775
1776 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1777 {
1778     if (!isValid())
1779         return;
1780
1781     if (m_process->state() != WebProcessProxy::State::Running)
1782         return;
1783
1784     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1785     if (m_waitingForDidUpdateActivityState)
1786         return;
1787
1788 #if PLATFORM(IOS_FAMILY)
1789     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1790     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1791     if (!m_activityToken) {
1792         ASSERT_NOT_REACHED();
1793         return;
1794     }
1795 #endif
1796
1797     m_waitingForDidUpdateActivityState = true;
1798
1799     m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1800 }
1801
1802 IntSize WebPageProxy::viewSize() const
1803 {
1804     return pageClient().viewSize();
1805 }
1806
1807 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1808 {
1809     if (!isValid()) {
1810         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1811         return;
1812     }
1813
1814     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1815     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1816 }
1817
1818 void WebPageProxy::clearSelection()
1819 {
1820     if (!isValid())
1821         return;
1822     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1823 }
1824
1825 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1826 {
1827     if (!isValid())
1828         return;
1829     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1830 }
1831
1832 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1833 {
1834     if (!isValid()) {
1835         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1836         return;
1837     }
1838
1839     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1840     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1841 }
1842
1843 void WebPageProxy::increaseListLevel()
1844 {
1845     if (!isValid())
1846         return;
1847
1848     m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
1849 }
1850
1851 void WebPageProxy::decreaseListLevel()
1852 {
1853     if (!isValid())
1854         return;
1855
1856     m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
1857 }
1858
1859 void WebPageProxy::changeListType()
1860 {
1861     if (!isValid())
1862         return;
1863
1864     m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
1865 }
1866
1867 void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
1868 {
1869     if (!isValid())
1870         return;
1871
1872     m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
1873 }
1874
1875 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
1876 {
1877     m_cachedFontAttributesAtSelectionStart.reset();
1878
1879     if (m_editorState.isMissingPostLayoutData)
1880         return;
1881
1882     if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
1883         m_uiClient->didChangeFontAttributes(*fontAttributes);
1884         m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
1885     }
1886 }
1887
1888 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
1889 {
1890     if (m_needsFontAttributes == needsFontAttributes)
1891         return;
1892
1893     m_needsFontAttributes = needsFontAttributes;
1894
1895     if (isValid())
1896         m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
1897 }
1898
1899 bool WebPageProxy::maintainsInactiveSelection() const
1900 {
1901     // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1902     // Otherwise, there is no way to use the console to inspect the state of a selection.
1903     if (inspector() && inspector()->isVisible())
1904         return true;
1905
1906     return m_maintainsInactiveSelection;
1907 }
1908
1909 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1910 {
1911     m_maintainsInactiveSelection = newValue;
1912 }
1913
1914 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1915 {
1916     if (!isValid()) {
1917         callbackFunction(CallbackBase::Error::Unknown);
1918         return;
1919     }
1920
1921     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1922     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1923 }
1924     
1925 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1926 {
1927     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1928
1929     if (!isValid())
1930         return;
1931
1932     if (commandName == ignoreSpellingCommandName)
1933         ++m_pendingLearnOrIgnoreWordMessageCount;
1934
1935     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1936 }
1937
1938 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
1939 {
1940     if (!isValid()) {
1941         callback({ }, CallbackBase::Error::Unknown);
1942         return;
1943     }
1944
1945     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1946     m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
1947 }
1948
1949 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
1950 {
1951     m_cachedFontAttributesAtSelectionStart = attributes;
1952
1953     if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
1954         callback->performCallbackWithReturnValue(attributes);
1955 }
1956
1957 void WebPageProxy::setEditable(bool editable)
1958 {
1959     if (editable == m_isEditable)
1960         return;
1961     if (!isValid())
1962         return;
1963
1964     m_isEditable = editable;
1965     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1966 }
1967     
1968 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1969 {
1970     if (muted)
1971         setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1972     else
1973         setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1974 }
1975
1976 void WebPageProxy::activateMediaStreamCaptureInPage()
1977 {
1978 #if ENABLE(MEDIA_STREAM)
1979     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1980 #endif
1981     setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1982 }
1983
1984 #if !PLATFORM(IOS_FAMILY)
1985 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1986 {
1987 }
1988
1989 void WebPageProxy::layerTreeCommitComplete()
1990 {
1991 }
1992 #endif
1993
1994 #if ENABLE(DRAG_SUPPORT)
1995 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1996 {
1997     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
1998 }
1999
2000 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
2001 {
2002     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
2003 }
2004
2005 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
2006 {
2007     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
2008 }
2009
2010 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2011 {
2012     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
2013 }
2014
2015 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2016 {
2017     if (!isValid())
2018         return;
2019 #if PLATFORM(GTK)
2020     UNUSED_PARAM(dragStorageName);
2021     UNUSED_PARAM(sandboxExtensionHandle);
2022     UNUSED_PARAM(sandboxExtensionsForUpload);
2023
2024     String url = dragData.asURL();
2025     if (!url.isEmpty())
2026         m_process->assumeReadAccessToBaseURL(*this, url);
2027
2028     ASSERT(dragData.platformData());
2029     WebSelectionData selection(*dragData.platformData());
2030     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
2031 #else
2032     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
2033 #endif
2034 }
2035
2036 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
2037 {
2038     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
2039
2040     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2041     m_currentDragHandlingMethod = dragHandlingMethod;
2042     m_currentDragIsOverFileInput = mouseIsOverFileInput;
2043     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2044     setDragCaretRect(insertionRect);
2045 }
2046
2047 #if PLATFORM(GTK)
2048 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2049 {
2050     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2051     pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2052
2053     didStartDrag();
2054 }
2055 #endif
2056
2057 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2058 {
2059     if (!isValid())
2060         return;
2061     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2062     setDragCaretRect({ });
2063 }
2064
2065 void WebPageProxy::didPerformDragOperation(bool handled)
2066 {
2067     pageClient().didPerformDragOperation(handled);
2068 }
2069
2070 void WebPageProxy::didStartDrag()
2071 {
2072     if (isValid())
2073         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2074 }
2075     
2076 void WebPageProxy::dragCancelled()
2077 {
2078     if (isValid())
2079         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2080 }
2081
2082 void WebPageProxy::didEndDragging()
2083 {
2084     resetCurrentDragInformation();
2085 }
2086
2087 void WebPageProxy::resetCurrentDragInformation()
2088 {
2089     m_currentDragOperation = WebCore::DragOperationNone;
2090     m_currentDragHandlingMethod = DragHandlingMethod::None;
2091     m_currentDragIsOverFileInput = false;
2092     m_currentDragNumberOfFilesToBeAccepted = 0;
2093     setDragCaretRect({ });
2094 }
2095
2096 #if !ENABLE(DATA_INTERACTION)
2097
2098 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2099 {
2100     m_currentDragCaretRect = dragCaretRect;
2101 }
2102
2103 #endif
2104
2105 #endif // ENABLE(DRAG_SUPPORT)
2106
2107 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2108 {
2109     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2110         return false;
2111
2112     auto it = queue.rbegin();
2113     auto end = queue.rend();
2114
2115     // Must not remove the first event in the deque, since it is already being dispatched.
2116     if (it != end)
2117         --end;
2118
2119     for (; it != end; ++it) {
2120         auto type = it->type();
2121         if (type == incomingEventType) {
2122             queue.remove(--it.base());
2123             return true;
2124         }
2125         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2126             break;
2127     }
2128     return false;
2129 }
2130
2131 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2132 {
2133     if (!isValid())
2134         return;
2135
2136     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2137     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2138     // event in the queue.
2139     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2140     m_mouseEventQueue.append(event);
2141
2142 #if LOG_DISABLED
2143     UNUSED_PARAM(didRemoveEvent);
2144 #else
2145     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2146 #endif
2147
2148     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2149         processNextQueuedMouseEvent();
2150 }
2151     
2152 void WebPageProxy::processNextQueuedMouseEvent()
2153 {
2154     if (!isValid())
2155         return;
2156
2157     ASSERT(!m_mouseEventQueue.isEmpty());
2158
2159     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2160     
2161     if (pageClient().windowIsFrontWindowUnderMouse(event))
2162         setToolTip(String());
2163
2164     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2165     if (event.type() != WebEvent::MouseMove)
2166         m_process->responsivenessTimer().start();
2167
2168     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2169     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2170 }
2171
2172 #if MERGE_WHEEL_EVENTS
2173 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2174 {
2175     if (a.position() != b.position())
2176         return false;
2177     if (a.globalPosition() != b.globalPosition())
2178         return false;
2179     if (a.modifiers() != b.modifiers())
2180         return false;
2181     if (a.granularity() != b.granularity())
2182         return false;
2183 #if PLATFORM(COCOA)
2184     if (a.phase() != b.phase())
2185         return false;
2186     if (a.momentumPhase() != b.momentumPhase())
2187         return false;
2188     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2189         return false;
2190 #endif
2191
2192     return true;
2193 }
2194
2195 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2196 {
2197     ASSERT(canCoalesce(a, b));
2198
2199     FloatSize mergedDelta = a.delta() + b.delta();
2200     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2201
2202 #if PLATFORM(COCOA)
2203     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2204
2205     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp());
2206 #else
2207     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2208 #endif
2209 }
2210 #endif // MERGE_WHEEL_EVENTS
2211
2212 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2213 {
2214     ASSERT(!queue.isEmpty());
2215     ASSERT(coalescedEvents.isEmpty());
2216
2217 #if MERGE_WHEEL_EVENTS
2218     NativeWebWheelEvent firstEvent = queue.takeFirst();
2219     coalescedEvents.append(firstEvent);
2220
2221     WebWheelEvent event = firstEvent;
2222     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2223         NativeWebWheelEvent firstEvent = queue.takeFirst();
2224         coalescedEvents.append(firstEvent);
2225         event = coalesce(event, firstEvent);
2226     }
2227
2228     return event;
2229 #else
2230     while (!queue.isEmpty())
2231         coalescedEvents.append(queue.takeFirst());
2232     return coalescedEvents.last();
2233 #endif
2234 }
2235
2236 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2237 {
2238 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2239     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2240         return;
2241 #endif
2242
2243     if (!isValid())
2244         return;
2245
2246     closeOverlayedViews();
2247
2248     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2249         m_wheelEventQueue.append(event);
2250         if (!shouldProcessWheelEventNow(event))
2251             return;
2252         // The queue has too many wheel events, so push a new event.
2253     }
2254
2255     if (!m_wheelEventQueue.isEmpty()) {
2256         processNextQueuedWheelEvent();
2257         return;
2258     }
2259
2260     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2261     coalescedWheelEvent->append(event);
2262     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2263     sendWheelEvent(event);
2264 }
2265
2266 void WebPageProxy::processNextQueuedWheelEvent()
2267 {
2268     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2269     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2270     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2271     sendWheelEvent(nextWheelEvent);
2272 }
2273
2274 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2275 {
2276     m_process->send(
2277         Messages::EventDispatcher::WheelEvent(
2278             m_pageID,
2279             event,
2280             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2281             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2282             rubberBandsAtTop(),
2283             rubberBandsAtBottom()
2284         ), 0);
2285
2286     // Manually ping the web process to check for responsiveness since our wheel
2287     // event will dispatch to a non-main thread, which always responds.
2288     m_process->isResponsive(nullptr);
2289 }
2290
2291 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2292 {
2293 #if PLATFORM(GTK)
2294     // Don't queue events representing a non-trivial scrolling phase to
2295     // avoid having them trapped in the queue, potentially preventing a
2296     // scrolling session to beginning or end correctly.
2297     // This is only needed by platforms whose WebWheelEvent has this phase
2298     // information (Cocoa and GTK+) but Cocoa was fine without it.
2299     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2300         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2301         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2302         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2303         return true;
2304 #else
2305     UNUSED_PARAM(event);
2306 #endif
2307     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2308         return true;
2309     return false;
2310 }
2311
2312 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2313 {
2314     if (!isValid())
2315         return;
2316     
2317     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2318
2319     m_keyEventQueue.append(event);
2320
2321     m_process->responsivenessTimer().start();
2322     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2323         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2324         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2325     }
2326 }
2327
2328 WebPreferencesStore WebPageProxy::preferencesStore() const
2329 {
2330     if (m_configurationPreferenceValues.isEmpty())
2331         return m_preferences->store();
2332
2333     WebPreferencesStore store = m_preferences->store();
2334     for (const auto& preference : m_configurationPreferenceValues)
2335         store.m_values.set(preference.key, preference.value);
2336
2337     return store;
2338 }
2339
2340 #if ENABLE(NETSCAPE_PLUGIN_API)
2341 void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, Messages::WebPageProxy::FindPlugin::DelayedReply&& reply)
2342 {
2343     PageClientProtector protector(pageClient());
2344
2345     MESSAGE_CHECK_URL(urlString);
2346
2347     URL pluginURL = URL { URL(), urlString };
2348     String newMimeType = mimeType.convertToASCIILowercase();
2349
2350     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2351
2352     URL pageURL = URL { URL(), pageURLString };
2353     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2354         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2355         return;
2356     }
2357
2358     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2359     if (!plugin.path) {
2360         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2361         return;
2362     }
2363
2364     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2365
2366 #if PLATFORM(COCOA)
2367     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2368 #endif
2369
2370     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2371         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2372         switch (pluginLoadPolicy) {
2373         case PluginModuleLoadNormally:
2374             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2375             break;
2376         case PluginModuleLoadUnsandboxed:
2377             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2378             break;
2379
2380         case PluginModuleBlockedForSecurity:
2381         case PluginModuleBlockedForCompatibility:
2382             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2383             return;
2384         }
2385
2386         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2387     };
2388
2389 #if PLATFORM(COCOA)
2390     m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2391 #else
2392     findPluginCompletion(pluginLoadPolicy, { });
2393 #endif
2394 }
2395
2396 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2397
2398 #if ENABLE(TOUCH_EVENTS)
2399
2400 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2401 {
2402     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2403         return b;
2404     return a;
2405 }
2406
2407 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2408 {
2409 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2410     const EventNames& names = eventNames();
2411     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2412         IntPoint location = touchPoint.location();
2413         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2414             if (trackingType == TrackingType::Synchronous)
2415                 return;
2416
2417             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2418
2419             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2420         };
2421         updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2422         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2423         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2424         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2425         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2426         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2427         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2428     }
2429 #else
2430     UNUSED_PARAM(touchStartEvent);
2431     m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2432     m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2433     m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2434     m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2435 #endif // ENABLE(ASYNC_SCROLLING)
2436 }
2437
2438 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2439 {
2440     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2441     //
2442     // Touch events define a sequence with strong dependencies. For example, we can expect
2443     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2444     // the two.
2445     //
2446     // WebCore should not have to set up its state correctly after some events were dismissed.
2447     // For example, we don't want to send a TouchMoved without a TouchPressed.
2448     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2449     TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2450
2451     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2452     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2453         switch (touchPoint.state()) {
2454         case WebPlatformTouchPoint::TouchReleased:
2455             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2456             break;
2457         case WebPlatformTouchPoint::TouchPressed:
2458             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2459             break;
2460         case WebPlatformTouchPoint::TouchMoved:
2461         case WebPlatformTouchPoint::TouchStationary:
2462             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2463             break;
2464         case WebPlatformTouchPoint::TouchCancelled:
2465             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2466             break;
2467         }
2468     }
2469
2470     return globalTrackingType;
2471 }
2472
2473 #endif
2474
2475 #if ENABLE(MAC_GESTURE_EVENTS)
2476 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2477 {
2478     if (!isValid())
2479         return;
2480
2481     m_gestureEventQueue.append(event);
2482     // FIXME: Consider doing some coalescing here.
2483     m_process->responsivenessTimer().start();
2484
2485     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2486 }
2487 #endif
2488
2489 #if ENABLE(IOS_TOUCH_EVENTS)
2490 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2491 {
2492     if (!isValid())
2493         return;
2494
2495     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2496
2497     updateTouchEventTracking(event);
2498
2499     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2500     if (touchEventsTrackingType == TrackingType::NotTracking)
2501         return;
2502
2503     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2504         // We can end up here if a native gesture has not started but the event handlers are passive.
2505         //
2506         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2507         // can prevent a native gesture.
2508         // But, here we know that all events handlers that can handle this events are passive.
2509         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2510         event.setCanPreventNativeGestures(false);
2511         handleTouchEventAsynchronously(event);
2512         didReceiveEvent(event.type(), false);
2513         return;
2514     }
2515
2516     m_process->responsivenessTimer().start();
2517     bool handled = false;
2518     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2519     // If the sync request has timed out, we should consider the event handled. The Web Process is too busy to answer any questions, so the default action is also likely to have issues.
2520     if (!replyReceived)
2521         handled = true;
2522     didReceiveEvent(event.type(), handled);
2523     pageClient().doneWithTouchEvent(event, handled);
2524     m_process->responsivenessTimer().stop();
2525
2526     if (event.allTouchPointsAreReleased())
2527         m_touchAndPointerEventTracking.reset();
2528 }
2529
2530 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2531 {
2532     if (!isValid())
2533         return;
2534
2535     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2536     if (touchEventsTrackingType == TrackingType::NotTracking)
2537         return;
2538
2539     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2540
2541     if (event.allTouchPointsAreReleased())
2542         m_touchAndPointerEventTracking.reset();
2543 }
2544
2545 #elif ENABLE(TOUCH_EVENTS)
2546 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2547 {
2548     if (!isValid())
2549         return;
2550
2551     updateTouchEventTracking(event);
2552
2553     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2554         return;
2555
2556     // If the page is suspended, which should be the case during panning, pinching
2557     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2558     // we do not send any of the events to the page even if is has listeners.
2559     if (!m_isPageSuspended) {
2560         m_touchEventQueue.append(event);
2561         m_process->responsivenessTimer().start();
2562         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2563     } else {
2564         if (m_touchEventQueue.isEmpty()) {
2565             bool isEventHandled = false;
2566             pageClient().doneWithTouchEvent(event, isEventHandled);
2567         } else {
2568             // We attach the incoming events to the newest queued event so that all
2569             // the events are delivered in the correct order when the event is dequed.
2570             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2571             lastEvent.deferredTouchEvents.append(event);
2572         }
2573     }
2574
2575     if (event.allTouchPointsAreReleased())
2576         m_touchAndPointerEventTracking.reset();
2577 }
2578 #endif // ENABLE(TOUCH_EVENTS)
2579
2580 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2581 {
2582     if (!isValid())
2583         return;
2584
2585     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2586 }
2587
2588 void WebPageProxy::centerSelectionInVisibleArea()
2589 {
2590     if (!isValid())
2591         return;
2592
2593     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2594 }
2595
2596 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2597 public:
2598     using SendFunction = CompletionHandler<void(WebPolicyAction, uint64_t newNavigationID, DownloadID, std::optional<WebsitePoliciesData>)>;
2599     static Ref<PolicyDecisionSender> create(SendFunction&& sendFunction)
2600     {
2601         return adoptRef(*new PolicyDecisionSender(WTFMove(sendFunction)));
2602     }
2603
2604     template<typename... Args> void send(Args... args)
2605     {
2606         if (m_sendFunction)
2607             m_sendFunction(std::forward<Args>(args)...);
2608     }
2609 private:
2610     PolicyDecisionSender(SendFunction sendFunction)
2611         : m_sendFunction(WTFMove(sendFunction)) { }
2612
2613     SendFunction m_sendFunction;
2614 };
2615
2616 void WebPageProxy::receivedNavigationPolicyDecision(WebPolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2617 {
2618     std::optional<WebsitePoliciesData> data;
2619     if (policies) {
2620         data = policies->data();
2621         if (policies->websiteDataStore())
2622             changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore());
2623     }
2624
2625     if (policyAction != WebPolicyAction::Use || !frame.isMainFrame() || !navigation) {
2626         receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2627         return;
2628     }
2629
2630     process().processPool().processForNavigation(*this, *navigation, processSwapRequestedByClient, [this, protectedThis = makeRef(*this), policyAction, navigation = makeRef(*navigation), data = WTFMove(data), sender = WTFMove(sender), processSwapRequestedByClient](Ref<WebProcessProxy>&& processForNavigation, SuspendedPageProxy* destinationSuspendedPage, const String& reason) mutable {
2631         // If the navigation has been destroyed, then no need to proceed.
2632         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2633             receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2634             return;
2635         }
2636
2637         if (processForNavigation.ptr() != &process()) {
2638             policyAction = isPageOpenedByDOMShowingInitialEmptyDocument() ? WebPolicyAction::Ignore : WebPolicyAction::Suspend;
2639             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "%p - WebPageProxy::decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", this, processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
2640             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2641         } else
2642             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "%p - WebPageProxy::decidePolicyForNavigationAction, keep using process %i for navigation, reason: %{public}s", this, processIdentifier(), reason.utf8().data());
2643
2644         bool shouldProcessSwap = processForNavigation.ptr() != &process();
2645         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? std::nullopt : WTFMove(data), WTFMove(sender));
2646
2647         if (shouldProcessSwap)
2648             continueNavigationInNewProcess(navigation, destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr, WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2649     });
2650 }
2651
2652 void WebPageProxy::receivedPolicyDecision(WebPolicyAction action, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
2653 {
2654     if (!isValid()) {
2655         sender->send(WebPolicyAction::Ignore, 0, DownloadID(), std::nullopt);
2656         return;
2657     }
2658
2659     auto transaction = m_pageLoadState.transaction();
2660
2661     if (action == WebPolicyAction::Ignore)
2662         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2663
2664     if (navigation && navigation->shouldForceDownload() && action == WebPolicyAction::Use)
2665         action = WebPolicyAction::Download;
2666
2667     DownloadID downloadID = { };
2668     if (action == WebPolicyAction::Download) {
2669         // Create a download proxy.
2670         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2671         if (navigation) {
2672             download->setWasUserInitiated(navigation->wasUserInitiated());
2673             download->setRedirectChain(navigation->takeRedirectChain());
2674         }
2675
2676         downloadID = download->downloadID();
2677         handleDownloadRequest(download);
2678         m_decidePolicyForResponseRequest = { };
2679     }
2680
2681     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2682 }
2683
2684 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient, std::optional<WebsitePoliciesData>&& websitePolicies)
2685 {
2686     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2687
2688     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
2689     std::optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? std::make_optional(m_mainFrame->frameID()) : std::nullopt;
2690     auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
2691
2692     ASSERT(m_process.ptr() != process.ptr());
2693
2694     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2695
2696     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2697     bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
2698     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
2699
2700     swapToWebProcess(WTFMove(process), WTFMove(suspendedPageProxy), didSuspendPreviousPage ? ShouldDelayAttachingDrawingArea::Yes : ShouldDelayAttachingDrawingArea::No);
2701
2702     if (auto* item = navigation.targetItem()) {
2703         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2704
2705         auto transaction = m_pageLoadState.transaction();
2706         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2707
2708         auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
2709             if (auto* page = item.suspendedPage()) {
2710                 if (&page->process() == m_process.ptr())
2711                     return false;
2712             }
2713             return &item != targetItem;
2714         });
2715         m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
2716         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)), m_pageID);
2717         m_process->responsivenessTimer().start();
2718
2719         return;
2720     }
2721
2722     if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
2723         // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
2724         // it instead of creating a new one.
2725         m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
2726     }
2727
2728     // FIXME: Work out timing of responding with the last policy delegate, etc
2729     ASSERT(!navigation.currentRequest().isEmpty());
2730     if (auto& substituteData = navigation.substituteData())
2731         loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
2732     else
2733         loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
2734
2735     ASSERT(!m_mainFrame);
2736     m_mainFrameCreationHandler = [this, weakThis = makeWeakPtr(*this), navigationID = navigation.navigationID(), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
2737         if (!weakThis)
2738             return;
2739
2740         ASSERT(m_mainFrame);
2741         // This navigation was destroyed so no need to notify of redirect.
2742         if (!navigationState().navigation(navigationID))
2743             return;
2744
2745         // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
2746         m_mainFrame->frameLoadState().setURL(mainFrameURL);
2747
2748         // Normally, notification of a server redirect comes from the WebContent process.
2749         // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
2750         // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
2751         if (isServerRedirect) {
2752             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
2753             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigationID, WTFMove(request), { });
2754         }
2755     };
2756
2757     if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isPageOpenedByDOMShowingInitialEmptyDocument() || !mainFrameIDInPreviousProcess) {
2758         // There is no way we'll be able to return to the page in the previous page so close it.
2759         if (!didSuspendPreviousPage)
2760             previousProcess->send(Messages::WebPage::Close(), m_pageID);
2761         return;
2762     }
2763
2764     m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
2765         ASSERT(m_mainFrame);
2766         GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
2767         previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
2768     };
2769 }
2770
2771 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
2772 {
2773     return openedByDOM() && !hasCommittedAnyProvisionalLoads();
2774 }
2775
2776 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
2777 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
2778 #if !COMPILER(MSVC)
2779 NO_RETURN_DUE_TO_ASSERT
2780 #endif
2781 void WebPageProxy::didFailToSuspendAfterProcessSwap()
2782 {
2783     // Only the SuspendedPageProxy should be getting this call.
2784     ASSERT_NOT_REACHED();
2785 }
2786
2787 #if !COMPILER(MSVC)
2788 NO_RETURN_DUE_TO_ASSERT
2789 #endif
2790 void WebPageProxy::didSuspendAfterProcessSwap()
2791 {
2792     // Only the SuspendedPageProxy should be getting this call.
2793     ASSERT_NOT_REACHED();
2794 }
2795
2796 void WebPageProxy::setUserAgent(String&& userAgent)
2797 {
2798     if (m_userAgent == userAgent)
2799         return;
2800     m_userAgent = WTFMove(userAgent);
2801
2802 #if ENABLE(SERVICE_WORKER)
2803     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2804     // FIXME: Refactor this when we have a better User-Agent story.
2805     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2806 #endif
2807
2808     if (!isValid())
2809         return;
2810     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2811 }
2812
2813 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2814 {
2815     if (m_applicationNameForUserAgent == applicationName)
2816         return;
2817
2818     m_applicationNameForUserAgent = applicationName;
2819     if (!m_customUserAgent.isEmpty())
2820         return;
2821
2822     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2823 }
2824
2825 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2826 {
2827     if (m_customUserAgent == customUserAgent)
2828         return;
2829
2830     m_customUserAgent = customUserAgent;
2831
2832     if (m_customUserAgent.isEmpty()) {
2833         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2834         return;
2835     }
2836
2837     setUserAgent(String { m_customUserAgent });
2838 }
2839
2840 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2841 {
2842     if (!isValid() || !m_isPageSuspended)
2843         return;
2844
2845     m_isPageSuspended = false;
2846
2847     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2848 }
2849
2850 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2851 {
2852     if (!isValid() || m_isPageSuspended)
2853         return;
2854
2855     m_isPageSuspended = true;
2856
2857     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2858 }
2859
2860 bool WebPageProxy::supportsTextEncoding() const
2861 {
2862     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2863     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2864 }
2865
2866 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2867 {
2868     if (m_customTextEncodingName == encodingName)
2869         return;
2870     m_customTextEncodingName = encodingName;
2871
2872     if (!isValid())
2873         return;
2874     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2875 }
2876
2877 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2878 {
2879     SessionState sessionState;
2880
2881     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2882
2883     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2884     if (provisionalURLString.isEmpty())
2885         provisionalURLString = m_pageLoadState.provisionalURL();
2886
2887     if (!provisionalURLString.isEmpty())
2888         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2889
2890     sessionState.renderTreeSize = renderTreeSize();
2891     return sessionState;
2892 }
2893
2894 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2895 {
2896     m_sessionRestorationRenderTreeSize = 0;
2897     m_hitRenderTreeSizeThreshold = false;
2898
2899     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2900
2901     if (hasBackForwardList) {
2902         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2903         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2904
2905         auto transaction = m_pageLoadState.transaction();
2906         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2907         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2908
2909         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2910         // page when navigating away. Suppress navigation snapshotting until the next load has committed
2911         suppressNextAutomaticNavigationSnapshot();
2912     }
2913
2914     // FIXME: Navigating should be separate from state restoration.
2915     if (navigate) {
2916         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2917         if (!m_sessionRestorationRenderTreeSize)
2918             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2919
2920         if (!sessionState.provisionalURL.isNull())
2921             return loadRequest(sessionState.provisionalURL);
2922
2923         if (hasBackForwardList) {
2924             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2925                 return goToBackForwardItem(*item);
2926         }
2927     }
2928
2929     return nullptr;
2930 }
2931
2932 bool WebPageProxy::supportsTextZoom() const
2933 {
2934     // FIXME (118840): This should also return false for standalone media and plug-in documents.
2935     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2936         return false;
2937
2938     return true;
2939 }
2940  
2941 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2942 {
2943     if (!isValid())
2944         return;
2945
2946     if (m_textZoomFactor == zoomFactor)
2947         return;
2948
2949     m_textZoomFactor = zoomFactor;
2950     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
2951 }
2952
2953 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2954 {
2955     if (!isValid())
2956         return;
2957
2958     if (m_pageZoomFactor == zoomFactor)
2959         return;
2960
2961     closeOverlayedViews();
2962
2963     m_pageZoomFactor = zoomFactor;
2964     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
2965 }
2966
2967 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2968 {
2969     if (!isValid())
2970         return;
2971
2972     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2973         return;
2974
2975     closeOverlayedViews();
2976
2977     m_pageZoomFactor = pageZoomFactor;
2978     m_textZoomFactor = textZoomFactor;
2979     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
2980 }
2981
2982 double WebPageProxy::pageZoomFactor() const
2983 {
2984     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2985     // zoom which ensures that we don't use the PDF zoom for a normal page.
2986     if (m_mainFramePluginHandlesPageScaleGesture)
2987         return m_pluginZoomFactor;
2988     return m_pageZoomFactor;
2989 }
2990
2991 double WebPageProxy::pageScaleFactor() const
2992 {
2993     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2994     // separately but decide which to return based on the main frame.
2995     if (m_mainFramePluginHandlesPageScaleGesture)
2996         return m_pluginScaleFactor;
2997     return m_pageScaleFactor;
2998 }
2999
3000 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3001 {
3002     ASSERT(scale > 0);
3003
3004     if (!isValid())
3005         return;
3006
3007     m_pageScaleFactor = scale;
3008     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3009 }
3010
3011 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3012 {
3013     ASSERT(scale > 0);
3014
3015     if (!isValid())
3016         return;
3017
3018     m_pageScaleFactor = scale;
3019     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3020 }
3021
3022 void WebPageProxy::scaleView(double scale)
3023 {
3024     ASSERT(scale > 0);
3025
3026     if (!isValid())
3027         return;
3028
3029     m_viewScaleFactor = scale;
3030     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3031 }
3032
3033 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3034 {
3035     if (m_intrinsicDeviceScaleFactor == scaleFactor)
3036         return;
3037
3038     m_intrinsicDeviceScaleFactor = scaleFactor;
3039
3040     if (m_drawingArea)
3041         m_drawingArea->deviceScaleFactorDidChange();
3042 }
3043
3044 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3045 {
3046     if (!isValid())
3047         return;
3048
3049     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3050 }
3051
3052 float WebPageProxy::deviceScaleFactor() const
3053 {
3054     return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
3055 }
3056
3057 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3058 {
3059     if (!isValid())
3060         return;
3061
3062     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3063     // https://bugs.webkit.org/show_bug.cgi?id=133378
3064 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3065     return;
3066 #endif
3067
3068     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3069         return;
3070
3071     float oldScaleFactor = deviceScaleFactor();
3072
3073     // A value of 0 clears the customScaleFactor.
3074     if (customScaleFactor)
3075         m_customDeviceScaleFactor = customScaleFactor;
3076     else
3077         m_customDeviceScaleFactor = std::nullopt;
3078
3079     if (deviceScaleFactor() != oldScaleFactor)
3080         m_drawingArea->deviceScaleFactorDidChange();
3081 }
3082
3083 void WebPageProxy::accessibilitySettingsDidChange()
3084 {
3085     if (!isValid())
3086         return;
3087
3088     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3089 }
3090
3091 #if ENABLE(ACCESSIBILITY_EVENTS)
3092 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
3093 {
3094     if (!isValid())
3095         return;
3096
3097     m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
3098 }
3099 #endif
3100
3101 void WebPageProxy::setUseFixedLayout(bool fixed)
3102 {
3103     if (!isValid())
3104         return;
3105
3106     // This check is fine as the value is initialized in the web
3107     // process as part of the creation parameters.
3108     if (fixed == m_useFixedLayout)
3109         return;
3110
3111     m_useFixedLayout = fixed;
3112     if (!fixed)
3113         m_fixedLayoutSize = IntSize();
3114     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3115 }
3116
3117 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3118 {
3119     if (!isValid())
3120         return;
3121
3122     if (size == m_fixedLayoutSize)
3123         return;
3124
3125     m_fixedLayoutSize = size;
3126     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3127 }
3128
3129 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3130 {
3131     if (!isValid())
3132         return;
3133
3134     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3135         return;
3136
3137     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3138     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3139 }
3140
3141 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3142 {
3143     if (!isValid())
3144         return;
3145
3146     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3147         return;
3148
3149     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3150     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3151 }
3152
3153 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3154 {
3155     if (!isValid())
3156         return;
3157     
3158     if (milestones == m_observedLayoutMilestones)
3159         return;
3160
3161     m_observedLayoutMilestones = milestones;
3162     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3163 }
3164
3165 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3166 {
3167     if (!isValid())
3168         return;
3169
3170     if (suppressAnimations == m_suppressScrollbarAnimations)
3171         return;
3172
3173     m_suppressScrollbarAnimations = suppressAnimations;
3174     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3175 }
3176
3177 bool WebPageProxy::rubberBandsAtLeft() const
3178 {
3179     return m_rubberBandsAtLeft;
3180 }
3181
3182 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3183 {
3184     m_rubberBandsAtLeft = rubberBandsAtLeft;
3185 }
3186
3187 bool WebPageProxy::rubberBandsAtRight() const
3188 {
3189     return m_rubberBandsAtRight;
3190 }
3191
3192 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3193 {
3194     m_rubberBandsAtRight = rubberBandsAtRight;
3195 }
3196
3197 bool WebPageProxy::rubberBandsAtTop() const
3198 {
3199     return m_rubberBandsAtTop;
3200 }
3201
3202 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3203 {
3204     m_rubberBandsAtTop = rubberBandsAtTop;
3205 }
3206
3207 bool WebPageProxy::rubberBandsAtBottom() const
3208 {
3209     return m_rubberBandsAtBottom;
3210 }
3211
3212 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3213 {
3214     m_rubberBandsAtBottom = rubberBandsAtBottom;
3215 }
3216     
3217 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3218 {
3219     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3220         return;
3221
3222     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3223
3224     if (!isValid())
3225         return;
3226     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3227 }
3228     
3229 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3230 {
3231     return m_enableVerticalRubberBanding;
3232 }
3233     
3234 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3235 {
3236     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3237         return;
3238
3239     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3240
3241     if (!isValid())
3242         return;
3243     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3244 }
3245     
3246 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3247 {
3248     return m_enableHorizontalRubberBanding;
3249 }
3250
3251 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3252 {
3253     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3254         return;
3255
3256     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3257
3258     if (!isValid())
3259         return;
3260     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3261 }
3262
3263 bool WebPageProxy::backgroundExtendsBeyondPage() const
3264 {
3265     return m_backgroundExtendsBeyondPage;
3266 }
3267
3268 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3269 {
3270     if (mode == m_paginationMode)
3271         return;
3272
3273     m_paginationMode = mode;
3274
3275     if (!isValid())
3276         return;
3277     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3278 }
3279
3280 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3281 {
3282     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3283         return;
3284
3285     m_paginationBehavesLikeColumns = behavesLikeColumns;
3286
3287     if (!isValid())
3288         return;
3289     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3290 }
3291
3292 void WebPageProxy::setPageLength(double pageLength)
3293 {
3294     if (pageLength == m_pageLength)
3295         return;
3296
3297     m_pageLength = pageLength;
3298
3299     if (!isValid())
3300         return;
3301     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3302 }
3303
3304 void WebPageProxy::setGapBetweenPages(double gap)
3305 {
3306     if (gap == m_gapBetweenPages)
3307         return;
3308
3309     m_gapBetweenPages = gap;
3310
3311     if (!isValid())
3312         return;
3313     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3314 }
3315
3316 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3317 {
3318     if (lineGridEnabled == m_paginationLineGridEnabled)
3319         return;
3320     
3321     m_paginationLineGridEnabled = lineGridEnabled;
3322     
3323     if (!isValid())
3324         return;
3325     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3326 }
3327
3328 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3329 {
3330     m_pageScaleFactor = scaleFactor;
3331 }
3332
3333 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3334 {
3335     m_pluginScaleFactor = pluginScaleFactor;
3336 }
3337
3338 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3339 {
3340     m_pluginZoomFactor = pluginZoomFactor;
3341 }
3342
3343 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3344 {
3345     if (string.isEmpty()) {
3346         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3347         return;
3348     }
3349
3350     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3351 }
3352
3353 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3354 {
3355     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3356 }
3357
3358 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3359 {
3360     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3361 }
3362
3363 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3364 {
3365     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3366 }
3367
3368 void WebPageProxy::hideFindUI()
3369 {
3370     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3371 }
3372
3373 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3374 {
3375     if (!isValid())
3376         return;
3377
3378     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3379 }
3380
3381 void WebPageProxy::replaceMatches(Vector<uint32_t>&& matchIndices, const String& replacementText, bool selectionOnly, Function<void(uint64_t, CallbackBase::Error)>&& callback)
3382 {
3383     if (!isValid()) {
3384         callback(0, CallbackBase::Error::Unknown);
3385         return;
3386     }
3387
3388     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
3389     m_process->send(Messages::WebPage::ReplaceMatches(WTFMove(matchIndices), replacementText, selectionOnly, callbackID), m_pageID);
3390 }
3391
3392 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3393 {
3394     if (!isValid()) {
3395         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3396         return;
3397     }
3398
3399     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3400     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3401 }
3402
3403 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3404 {
3405     if (!isValid()) {
3406         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3407         return;
3408     }
3409
3410     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3411     m_process->send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3412 }
3413
3414 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3415 {
3416     if (!isValid()) {
3417         callbackFunction(String(), CallbackBase::Error::Unknown);
3418         return;
3419     }
3420     
3421     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3422     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3423 }
3424
3425 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3426 {
3427     if (!isValid()) {
3428         callbackFunction(String(), CallbackBase::Error::Unknown);
3429         return;
3430     }
3431     
3432     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3433     m_loadDependentStringCallbackIDs.add(callbackID);
3434     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3435 }
3436
3437 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3438 {
3439     if (!isValid()) {
3440         callbackFunction(String(), CallbackBase::Error::Unknown);
3441         return;
3442     }
3443     
3444     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3445     m_loadDependentStringCallbackIDs.add(callbackID);
3446     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3447 }
3448
3449 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3450 {
3451     if (!isValid()) {
3452         callbackFunction(String(), CallbackBase::Error::Unknown);
3453         return;
3454     }
3455     
3456     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3457     m_loadDependentStringCallbackIDs.add(callbackID);
3458     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3459 }
3460
3461 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3462 {
3463     if (!isValid()) {
3464         callbackFunction(String(), CallbackBase::Error::Unknown);
3465         return;
3466     }
3467     
3468     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3469     m_loadDependentStringCallbackIDs.add(callbackID);
3470     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3471 }
3472
3473 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
3474 {
3475     if (!isValid()) {
3476         RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
3477             bool isWebProcessResponsive = true;
3478             callbackFunction(isWebProcessResponsive);
3479         });
3480         return;
3481     }
3482
3483     m_process->isResponsive(WTFMove(callbackFunction));
3484 }
3485
3486 #if ENABLE(MHTML)
3487 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3488 {
3489     if (!isValid()) {
3490         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3491         return;
3492     }
3493
3494     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3495     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3496 }
3497 #endif
3498
3499 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3500 {
3501     if (!isValid()) {
3502         callbackFunction(String(), CallbackBase::Error::Unknown);
3503         return;
3504     }
3505     
3506     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3507     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
3508 }
3509
3510 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3511 {
3512     if (!isValid()) {
3513         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3514         return;
3515     }
3516     
3517     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3518     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3519 }
3520
3521 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3522 {
3523     if (!isValid() || !frame) {
3524         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3525         return;
3526     }
3527     
3528     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3529     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3530 }
3531
3532 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3533 {
3534     if (!isValid()) {
3535         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3536         return;
3537     }
3538     
3539     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3540     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3541 }
3542
3543 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3544 {
3545     if (!isValid()) {
3546         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3547         return;
3548     }
3549     
3550     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3551     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3552 }
3553
3554 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3555 {
3556     if (!isValid()) {
3557         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3558         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3559         return;
3560     }
3561
3562     Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3563         if (error != CallbackBase::Error::None) {
3564             callback->invalidate(error);
3565             return;
3566         }
3567
3568         if (!isValid()) {
3569             callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3570             return;
3571         }
3572     
3573         callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3574             if (error != CallbackBase::Error::None) {
3575                 callback->invalidate(error);
3576                 return;
3577             }
3578
3579             callback->performCallback();
3580         });
3581     };
3582
3583     auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3584     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3585     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
3586 }
3587
3588 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3589 {
3590     if (isPerformingDOMPrintOperation)
3591         return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3592
3593     return { };
3594 }
3595
3596 void WebPageProxy::preferencesDidChange()
3597 {
3598     if (!isValid())
3599         return;
3600
3601     updateThrottleState();
3602     updateHiddenPageThrottlingAutoIncreases();
3603
3604     pageClient().preferencesDidChange();
3605
3606     // FIXME: It probably makes more sense to send individual preference changes.
3607     // However, WebKitTestRunner depends on getting a preference change notification
3608     // even if nothing changed in UI process, so that overrides get removed.
3609
3610     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3611     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3612 }
3613
3614 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3615 {
3616     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateMainFrame one.
3617     // When this happens, decidePolicyForNavigationActionSync() calls didCreateMainFrame() and we need to ignore the DidCreateMainFrame
3618     // IPC when it later gets processed.
3619     if (m_mainFrame && m_mainFrame->frameID() == frameID)
3620         return;
3621
3622     PageClientProtector protector(pageClient());
3623
3624     MESSAGE_CHECK(!m_mainFrame);
3625     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3626
3627     m_mainFrame = WebFrameProxy::create(*this, frameID);
3628
3629     // Add the frame to the process wide map.
3630     m_process->frameCreated(frameID, *m_mainFrame);
3631
3632     if (m_mainFrameCreationHandler) {
3633         m_mainFrameCreationHandler();
3634         m_mainFrameCreationHandler = nullptr;
3635     }
3636 }
3637
3638 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3639 {
3640     PageClientProtector protector(pageClient());
3641
3642     MESSAGE_CHECK(m_mainFrame);
3643
3644     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
3645     // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
3646     // IPC when it later gets processed.
3647     if (m_process->webFrame(frameID))
3648         return;
3649
3650     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3651     
3652     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(*this, frameID);
3653
3654     // Add the frame to the process wide map.
3655     m_process->frameCreated(frameID, *subFrame);
3656 }
3657
3658 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
3659 {
3660     if (m_mainFrame && m_mainFrame->frameID() == frameID) {
3661         if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
3662             mainFrameWindowCreationHandler(windowIdentifier);
3663     }
3664 }
3665
3666 double WebPageProxy::estimatedProgress() const
3667 {
3668     return m_pageLoadState.estimatedProgress();
3669 }
3670
3671 void WebPageProxy::didStartProgress()
3672 {
3673     PageClientProtector protector(pageClient());
3674
3675     auto transaction = m_pageLoadState.transaction();
3676     m_pageLoadState.didStartProgress(transaction);
3677
3678     m_pageLoadState.commitChanges();
3679 }
3680
3681 void WebPageProxy::didChangeProgress(double value)
3682 {
3683     PageClientProtector protector(pageClient());
3684
3685     auto transaction = m_pageLoadState.transaction();
3686     m_pageLoadState.didChangeProgress(transaction, value);
3687
3688     m_pageLoadState.commitChanges();
3689 }
3690
3691 void WebPageProxy::didFinishProgress()
3692 {
3693     PageClientProtector protector(pageClient());
3694
3695     auto transaction = m_pageLoadState.transaction();
3696     m_pageLoadState.didFinishProgress(transaction);
3697
3698     m_pageLoadState.commitChanges();
3699 }
3700
3701 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3702 {
3703     auto transaction = m_pageLoadState.transaction();
3704     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3705 }
3706
3707 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3708 {
3709     hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3710 }
3711
3712 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3713 {
3714     PageClientProtector protector(pageClient());
3715
3716     // FIXME: Message check the navigationID.
3717     m_navigationState->didDestroyNavigation(navigationID);
3718 }
3719
3720 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
3721 {
3722     PageClientProtector protector(pageClient());
3723
3724     WebFrameProxy* frame = m_process->webFrame(frameID);
3725     MESSAGE_CHECK(frame);
3726     MESSAGE_CHECK_URL(url);
3727
3728     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3729     RefPtr<API::Navigation> navigation;
3730     if (frame->isMainFrame() && navigationID)
3731         navigation = navigationState().navigation(navigationID);
3732
3733     // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
3734     // then we ignore this notification.
3735     if (navigation && navigation->currentRequestIsRedirect()) {
3736         auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
3737         if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
3738             return;
3739     }
3740
3741     LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
3742
3743     auto transaction = m_pageLoadState.transaction();
3744
3745     m_pageLoadState.clearPendingAPIRequestURL(transaction);
3746
3747     if (frame->isMainFrame()) {
3748         reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
3749         m_pageLoadStart = MonotonicTime::now();
3750         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
3751         pageClient().didStartProvisionalLoadForMainFrame();
3752         closeOverlayedViews();
3753     }
3754
3755     frame->setUnreachableURL(unreachableURL);
3756     frame->didStartProvisionalLoad(url);
3757
3758     m_pageLoadState.commitChanges();
3759     if (m_loaderClient)
3760         m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3761     else if (frame->isMainFrame())
3762         m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3763 }
3764
3765 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
3766 {
3767     LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data());
3768
3769     PageClientProtector protector(pageClient());
3770
3771     WebFrameProxy* frame = m_process->webFrame(frameID);
3772     MESSAGE_CHECK(frame);
3773     MESSAGE_CHECK_URL(request.url());
3774
3775     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3776     RefPtr<API::Navigation> navigation = navigationID ? navigationState().navigation(navigationID) : nullptr;
3777     if (navigation)
3778         navigation->appendRedirectionURL(request.url());
3779
3780     auto transaction = m_pageLoadState.transaction();
3781
3782     if (frame->isMainFrame())
3783         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, request.url());
3784
3785     frame->didReceiveServerRedirectForProvisionalLoad(request.url());
3786
3787     m_pageLoadState.commitChanges();
3788     if (m_loaderClient)
3789         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, m_process->transformHandlesToObjects(userData.object()).get());
3790     else if (frame->isMainFrame())
3791         m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3792 }
3793
3794 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList)
3795 {
3796     PageClientProtector protector(pageClient());
3797
3798     WebFrameProxy* frame = m_process->webFrame(frameID);
3799     MESSAGE_CHECK(frame);
3800
3801     if (frame->isMainFrame())
3802         m_navigationClient->willPerformClientRedirect(*this, url, delay);
3803 }
3804
3805 void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
3806 {
3807     PageClientProtector protector(pageClient());
3808
3809     WebFrameProxy* frame = m_process->webFrame(frameID);
3810     MESSAGE_CHECK(frame);
3811
3812     if (frame->isMainFrame())
3813         m_navigationClient->didCancelClientRedirect(*this);
3814 }
3815
3816 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, URL&& url)
3817 {
3818     PageClientProtector protector(pageClient());
3819
3820     WebFrameProxy* frame = m_process->webFrame(frameID);
3821     MESSAGE_CHECK(frame);
3822     MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
3823     MESSAGE_CHECK_URL(url);
3824
3825     auto transaction = m_pageLoadState.transaction();
3826
3827     // Internally, we handle this the same way we handle a server redirect. There are no client callbacks
3828     // for this, but if this is the main frame, clients may observe a change to the page's URL.
3829     if (frame->isMainFrame())
3830         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3831
3832     frame->didReceiveServerRedirectForProvisionalLoad(url);
3833 }
3834
3835 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
3836 {
3837     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, m_process->processIdentifier(), provisionalURL.utf8().data());
3838
3839     PageClientProtector protector(pageClient());
3840
3841     WebFrameProxy* frame = m_process->webFrame(frameID);
3842     MESSAGE_CHECK(frame);
3843
3844     if (m_controlledByAutomation) {
3845         if (auto* automationSession = process().processPool().automationSession())
3846             automationSession->navigationOccurredForFrame(*frame);
3847     }
3848
3849     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3850     RefPtr<API::Navigation> navigation;
3851     if (frame->isMainFrame() && navigationID)
3852         navigation = navigationState().takeNavigation(navigationID);
3853
3854     auto transaction = m_pageLoadState.transaction();
3855
3856     if (frame->isMainFrame()) {
3857         reportPageLoadResult(error);
3858         m_pageLoadState.didFailProvisionalLoad(transaction);
3859         pageClient().didFailProvisionalLoadForMainFrame();
3860     }
3861
3862     frame->didFailProvisionalLoad();
3863
3864     m_pageLoadState.commitChanges();
3865
3866     ASSERT(!m_failingProvisionalLoadURL);
3867     m_failingProvisionalLoadURL = provisionalURL;
3868
3869     if (m_loaderClient)
3870         m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3871     else if (frame->isMainFrame())
3872         m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3873     else {
3874             // FIXME: Get the main frame's current navigation.
3875             m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
3876     }
3877
3878     m_failingProvisionalLoadURL = { };
3879 }
3880
3881 void WebPageProxy::clearLoadDependentCallbacks()
3882 {
3883     HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);
3884     for (auto& callbackID : loadDependentStringCallbackIDs) {
3885         if (auto callback = m_callbacks.take<StringCallback>(callbackID))
3886             callback->invalidate();
3887     }
3888 }
3889
3890 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, std::optional<HasInsecureContent> hasInsecureContent, const UserData& userData)
3891 {
3892     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " didCommitLoadForFrame in navigation %" PRIu64, m_pageID, m_navigationID);
3893     LOG(BackForward, "(Back/Forward) After load commit, back/forward list is now:%s", m_backForwardList->loggingString());
3894
3895     PageClientProtector protector(pageClient());
3896
3897     WebFrameProxy* frame = m_process->webFrame(frameID);
3898     MESSAGE_CHECK(frame);
3899
3900     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3901     RefPtr<API::Navigation> navigation;
3902     if (frame->isMainFrame() && navigationID)
3903         navigation = navigationState().navigation(navigationID);
3904
3905     m_hasCommittedAnyProvisionalLoads = true;
3906     m_process->didCommitProvisionalLoad();
3907
3908 #if PLATFORM(IOS_FAMILY)
3909     if (frame->isMainFrame()) {
3910         m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
3911         m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
3912     }
3913 #endif
3914
3915     auto transaction = m_pageLoadState.transaction();
3916     Ref<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(certificateInfo);
3917     bool markPageInsecure = hasInsecureContent ? hasInsecureContent.value() == HasInsecureContent::Yes : m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
3918
3919     if (frame->isMainFrame()) {
3920         m_pageLoadState.didCommitLoad(transaction, webCertificateInfo, markPageInsecure);
3921         m_shouldSuppressNextAutomaticNavigationSnapshot = false;
3922     } else if (markPageInsecure)
3923         m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3924
3925 #if USE(APPKIT)
3926     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
3927     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
3928     pageClient().resetSecureInputState();
3929 #endif
3930
3931     clearLoadDependentCallbacks();
3932
3933     frame->didCommitLoad(mimeType, webCertificateInfo, containsPluginDocument);
3934
3935     if (frame->isMainFrame()) {
3936         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
3937
3938         if (m_mainFrameHasCustomContentProvider) {
3939             // Always assume that the main frame is pinned here, since the custom representation view will handle
3940             // any wheel events and dispatch them to the WKView when necessary.
3941             m_mainFrameIsPinnedToLeftSide = true;
3942             m_mainFrameIsPinnedToRightSide = true;
3943             m_mainFrameIsPinnedToTopSide = true;
3944             m_mainFrameIsPinnedToBottomSide = true;
3945
3946             m_uiClient->pinnedStateDidChange(*this);
3947         }
3948         pageClient().didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
3949     }
3950
3951     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
3952     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
3953     // plugin is handling page scaling itself) so we should reset it to the default
3954     // for standard main frame loads.
3955     if (frame->isMainFrame()) {
3956         if (static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
3957             m_pageScaleFactor = 1;
3958             m_pluginScaleFactor = 1;
3959             m_mainFramePluginHandlesPageScaleGesture = false;
3960         }
3961     }
3962
3963 #if ENABLE(POINTER_LOCK)
3964     if (frame->isMainFrame())
3965         requestPointerUnlock();
3966 #endif
3967
3968     m_pageLoadState.commitChanges();
3969     if (m_loaderClient)
3970         m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3971     else if (frame->isMainFrame())
3972         m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3973
3974 #if ENABLE(ATTACHMENT_ELEMENT)
3975     if (frame->isMainFrame())
3976         invalidateAllAttachments();
3977 #endif
3978
3979 #if ENABLE(REMOTE_INSPECTOR)
3980     if (frame->isMainFrame())
3981         remoteInspectorInformationDidChange();
3982 #endif
3983 }
3984
3985 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3986 {
3987     PageClientProtector protector(pageClient());
3988
3989     WebFrameProxy* frame = m_process->webFrame(frameID);
3990     MESSAGE_CHECK(frame);
3991
3992     if (m_controlledByAutomation) {
3993         if (auto* automationSession = process().processPool().automationSession())
3994             automationSession->documentLoadedForFrame(*frame);
3995     }
3996
3997     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3998     RefPtr<API::Navigation> navigation;
3999     if (frame->isMainFrame() && navigationID)
4000         navigation = navigationState().navigation(navigationID);
4001
4002     if (frame->isMainFrame())
4003         m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4004 }
4005
4006 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
4007 {
4008     LOG(Loading, "WebPageProxy::didFinishLoadForFrame - WebPageProxy %p with navigationID %" PRIu64 " didFinishLoad", this, navigationID);
4009
4010     PageClientProtector protector(pageClient());
4011
4012     WebFrameProxy* frame = m_process->webFrame(frameID);
4013     MESSAGE_CHECK(frame);
4014
4015     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4016     RefPtr<API::Navigation> navigation;
4017     if (frame->isMainFrame() && navigationID)
4018         navigation = navigationState().navigation(navigationID);
4019
4020     auto transaction = m_pageLoadState.transaction();
4021
4022     bool isMainFrame = frame->isMainFrame();
4023     if (isMainFrame)
4024         m_pageLoadState.didFinishLoad(transaction);
4025
4026     if (m_controlledByAutomation) {
4027         if (auto* automationSession = process().processPool().automationSession())
4028             automationSession->navigationOccurredForFrame(*frame);
4029     }
4030
4031     frame->didFinishLoad();
4032
4033     m_pageLoadState.commitChanges();
4034     if (m_loaderClient)
4035         m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4036     else if (isMainFrame)
4037         m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4038
4039     if (isMainFrame) {
4040         reportPageLoadResult();
4041         pageClient().didFinishLoadForMainFrame();
4042
4043         resetRecentCrashCountSoon();
4044
4045         notifyProcessPoolToPrewarm();
4046     }
4047
4048     m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = false;
4049 }
4050
4051 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
4052 {
4053     PageClientProtector protector(pageClient());
4054
4055     WebFrameProxy* frame = m_process->webFrame(frameID);
4056     MESSAGE_CHECK(frame);
4057
4058     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4059     RefPtr<API::Navigation> navigation;
4060     if (frame->isMainFrame() && navigationID)
4061         navigation = navigationState().navigation(navigationID);
4062
4063     clearLoadDependentCallbacks();
4064
4065     auto transaction = m_pageLoadState.transaction();
4066
4067     bool isMainFrame = frame->isMainFrame();
4068
4069     if (isMainFrame)
4070         m_pageLoadState.didFailLoad(transaction);
4071
4072     if (m_controlledByAutomation) {
4073         if (auto* automationSession = process().processPool().automationSession())
4074             automationSession->navigationOccurredForFrame(*frame);
4075     }
4076
4077     frame->didFailLoad();
4078
4079     m_pageLoadState.commitChanges();
4080     if (m_loaderClient)
4081         m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4082     else if (frame->isMainFrame())
4083         m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4084
4085     if (isMainFrame) {
4086         reportPageLoadResult(error);
4087         pageClient().didFailLoadForMainFrame();
4088     }
4089 }
4090
4091 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, URL&& url, const UserData& userData)
4092 {
4093     PageClientProtector protector(pageClient());
4094
4095     WebFrameProxy* frame = m_process->webFrame(frameID);
4096     MESSAGE_CHECK(frame);
4097     MESSAGE_CHECK_URL(url);
4098
4099     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4100     RefPtr<API::Navigation> navigation;
4101     if (frame->isMainFrame() && navigationID)
4102         navigation = navigationState().navigation(navigationID);
4103
4104     auto transaction = m_pageLoadState.transaction();
4105
4106     bool isMainFrame = frame->isMainFrame();
4107     if (isMainFrame)
4108         m_pageLoadState.didSameDocumentNavigation(transaction, url);
4109
4110     if (m_controlledByAutomation) {
4111         if (auto* automationSession = process().processPool().automationSession())
4112             automationSession->navigationOccurredForFrame(*frame);
4113     }
4114
4115     m_pageLoadState.clearPendingAPIRequestURL(transaction);
4116     frame->didSameDocumentNavigation(url);
4117
4118     m_pageLoadState.commitChanges();
4119
4120     SameDocumentNavigationType navigationType = static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType);
4121     if (isMainFrame)
4122         m_navigationClient->didSameDocumentNavigation(*this, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
4123
4124     if (isMainFrame)
4125         pageClient().didSameDocumentNavigationForMainFrame(navigationType);
4126 }
4127
4128 void WebPageProxy::didChangeMainDocument(uint64_t frameID)
4129 {
4130 #if ENABLE(MEDIA_STREAM)
4131     userMediaPermissionRequestManager().resetAccess(frameID);
4132 #else
4133     UNUSED_PARAM(frameID);
4134 #endif
4135 }
4136
4137 void WebPageProxy::viewIsBecomingVisible()
4138 {
4139 #if ENABLE(MEDIA_STREAM)
4140     userMediaPermissionRequestManager().viewIsBecomingVisible();
4141 #endif
4142 }
4143
4144 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
4145 {
4146     PageClientProtector protector(pageClient());
4147
4148     WebFrameProxy* frame = m_process->webFrame(frameID);
4149     MESSAGE_CHECK(frame);
4150
4151     auto transaction = m_pageLoadState.transaction();
4152
4153     if (frame->isMainFrame())
4154         m_pageLoadState.setTitle(transaction, title);
4155
4156     frame->didChangeTitle(title);
4157     
4158     m_pageLoadState.commitChanges();
4159
4160 #if ENABLE(REMOTE_INSPECTOR)
4161     if (frame->isMainFrame())
4162         remoteInspectorInformationDidChange();
4163 #endif
4164 }
4165
4166 void WebPageProxy::didFirstLayoutForFrame(uint64_t, const UserData& userData)
4167 {
4168 }
4169
4170 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData& userData)
4171 {
4172     PageClientProtector protector(pageClient());
4173
4174     WebFrameProxy* frame = m_process->webFrame(frameID);
4175     MESSAGE_CHECK(frame);
4176
4177     if (m_loaderClient)
4178         m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
4179
4180     if (frame->isMainFrame())
4181         pageClient().didFirstVisuallyNonEmptyLayoutForMainFrame();
4182 }
4183
4184 void WebPageProxy::didLayoutForCustomContentProvider()
4185 {
4186     didReachLayoutMilestone({ DidFirstLayout, DidFirstVisuallyNonEmptyLayout, DidHitRelevantRepaintedObjectsAreaThreshold });
4187 }