[PSON] WebsitePolicies are lost on process-swap
[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);
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, 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.userData = UserData(process().transformObjectsToHandles(userData).get());
1155     loadParameters.websitePolicies = WTFMove(websitePolicies);
1156     addPlatformLoadParameters(loadParameters);
1157
1158     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1159     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1160     m_process->responsivenessTimer().start();
1161 }
1162
1163 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1164 {
1165     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1166     // start a second alternative HTML load as this will prevent the page load state from being
1167     // handled properly.
1168     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad)
1169         return;
1170
1171     if (!m_failingProvisionalLoadURL.isEmpty())
1172         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1173
1174     if (!isValid())
1175         reattachToWebProcess();
1176
1177     auto transaction = m_pageLoadState.transaction();
1178
1179     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1180     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1181
1182     if (m_mainFrame)
1183         m_mainFrame->setUnreachableURL(unreachableURL);
1184
1185     LoadParameters loadParameters;
1186     loadParameters.navigationID = 0;
1187     loadParameters.data = htmlData;
1188     loadParameters.MIMEType = "text/html"_s;
1189     loadParameters.encodingName = encoding;
1190     loadParameters.baseURLString = baseURL;
1191     loadParameters.unreachableURLString = unreachableURL;
1192     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1193     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1194     addPlatformLoadParameters(loadParameters);
1195
1196     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1197     m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1198     m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1199     m_process->responsivenessTimer().start();
1200 }
1201
1202 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1203 {
1204     if (m_isClosed)
1205         return;
1206
1207     if (!isValid())
1208         reattachToWebProcess();
1209
1210     auto transaction = m_pageLoadState.transaction();
1211     m_pageLoadState.setPendingAPIRequestURL(transaction, WTF::blankURL().string());
1212
1213     LoadParameters loadParameters;
1214     loadParameters.navigationID = 0;
1215     loadParameters.data = webArchiveData->dataReference();
1216     loadParameters.MIMEType = "application/x-webarchive"_s;
1217     loadParameters.encodingName = "utf-16"_s;
1218     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1219     addPlatformLoadParameters(loadParameters);
1220
1221     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1222     m_process->responsivenessTimer().start();
1223 }
1224
1225 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1226 {
1227     if (m_isClosed)
1228         return;
1229
1230     if (WTF::protocolIsJavaScript(url))
1231         return;
1232
1233     if (!isValid())
1234         reattachToWebProcess();
1235
1236     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1237     m_process->responsivenessTimer().start();
1238 }
1239
1240 void WebPageProxy::stopLoading()
1241 {
1242     if (!isValid())
1243         return;
1244
1245     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1246     m_process->responsivenessTimer().start();
1247 }
1248
1249 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1250 {
1251     SandboxExtension::Handle sandboxExtensionHandle;
1252
1253     String url = currentURL();
1254     if (!url.isEmpty()) {
1255         auto transaction = m_pageLoadState.transaction();
1256         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1257
1258         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1259         bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
1260         if (createdExtension)
1261             willAcquireUniversalFileReadSandboxExtension();
1262     }
1263
1264     if (!isValid())
1265         return reattachToWebProcessForReload();
1266     
1267     auto navigation = m_navigationState->createReloadNavigation();
1268
1269     m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1270     m_process->responsivenessTimer().start();
1271
1272     return WTFMove(navigation);
1273 }
1274
1275 void WebPageProxy::recordAutomaticNavigationSnapshot()
1276 {
1277     if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1278         return;
1279
1280     if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1281         recordNavigationSnapshot(*item);
1282 }
1283
1284 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1285 {
1286     if (!m_shouldRecordNavigationSnapshots)
1287         return;
1288
1289 #if PLATFORM(COCOA)
1290     ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1291 #else
1292     UNUSED_PARAM(item);
1293 #endif
1294 }
1295
1296 RefPtr<API::Navigation> WebPageProxy::goForward()
1297 {
1298     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1299     if (!forwardItem)
1300         return nullptr;
1301
1302     return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1303 }
1304
1305 RefPtr<API::Navigation> WebPageProxy::goBack()
1306 {
1307     WebBackForwardListItem* backItem = m_backForwardList->backItem();
1308     if (!backItem)
1309         return nullptr;
1310
1311     return goToBackForwardItem(*backItem, FrameLoadType::Back);
1312 }
1313
1314 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1315 {
1316     return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1317 }
1318
1319 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1320 {
1321     LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1322
1323     if (!isValid())
1324         return reattachToWebProcessWithItem(item);
1325
1326     auto transaction = m_pageLoadState.transaction();
1327
1328     m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
1329
1330     RefPtr<API::Navigation> navigation;
1331     if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1332         navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1333
1334     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt), m_pageID);
1335     m_process->responsivenessTimer().start();
1336
1337     return navigation;
1338 }
1339
1340 void WebPageProxy::tryRestoreScrollPosition()
1341 {
1342     if (!isValid())
1343         return;
1344
1345     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1346 }
1347
1348 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1349 {
1350     PageClientProtector protector(pageClient());
1351
1352     if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1353         m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1354
1355     auto transaction = m_pageLoadState.transaction();
1356
1357     m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1358     m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1359 }
1360
1361 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1362 {
1363     PageClientProtector protector(pageClient());
1364
1365     if (auto* item = m_backForwardList->itemForID(itemID))
1366         m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1367 }
1368
1369 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1370 {
1371     PageClientProtector protector(pageClient());
1372
1373     return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1374 }
1375
1376 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1377 {
1378     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1379         return true;
1380
1381 #if ENABLE(NETSCAPE_PLUGIN_API)
1382     String newMimeType = mimeType;
1383     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1384     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1385         return true;
1386 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1387
1388 #if PLATFORM(COCOA)
1389     // On Mac, we can show PDFs.
1390     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1391         return true;
1392 #endif // PLATFORM(COCOA)
1393
1394     return false;
1395 }
1396
1397 void WebPageProxy::setControlledByAutomation(bool controlled)
1398 {
1399     if (m_controlledByAutomation == controlled)
1400         return;
1401
1402     m_controlledByAutomation = controlled;
1403
1404     if (!isValid())
1405         return;
1406
1407     m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1408     m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1409 }
1410
1411 void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
1412 {
1413     m_inspectorController->createInspectorTarget(targetId, type);
1414 }
1415
1416 void WebPageProxy::destroyInspectorTarget(const String& targetId)
1417 {
1418     m_inspectorController->destroyInspectorTarget(targetId);
1419 }
1420
1421 void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
1422 {
1423     m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
1424 }
1425
1426 #if ENABLE(REMOTE_INSPECTOR)
1427 void WebPageProxy::setIndicating(bool indicating)
1428 {
1429     if (!isValid())
1430         return;
1431
1432     m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
1433 }
1434
1435 bool WebPageProxy::allowsRemoteInspection() const
1436 {
1437     return m_inspectorDebuggable->remoteDebuggingAllowed();
1438 }
1439
1440 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1441 {
1442     m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
1443 }
1444
1445 String WebPageProxy::remoteInspectionNameOverride() const
1446 {
1447     return m_inspectorDebuggable->nameOverride();
1448 }
1449
1450 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1451 {
1452     m_inspectorDebuggable->setNameOverride(name);
1453 }
1454
1455 void WebPageProxy::remoteInspectorInformationDidChange()
1456 {
1457     m_inspectorDebuggable->update();
1458 }
1459 #endif
1460
1461 void WebPageProxy::clearInspectorTargets()
1462 {
1463     m_inspectorController->clearTargets();
1464 }
1465
1466 void WebPageProxy::createInspectorTargets()
1467 {
1468     String pageTargetId = makeString("page-", String::number(m_pageID));
1469     m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
1470 }
1471
1472 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1473 {
1474     if (m_drawsBackground == drawsBackground)
1475         return;
1476
1477     m_drawsBackground = drawsBackground;
1478
1479     if (isValid())
1480         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1481 }
1482
1483 void WebPageProxy::setTopContentInset(float contentInset)
1484 {
1485     if (m_topContentInset == contentInset)
1486         return;
1487
1488     m_topContentInset = contentInset;
1489
1490     if (!isValid())
1491         return;
1492 #if PLATFORM(COCOA)
1493     MachSendRight fence = m_drawingArea->createFence();
1494
1495     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1496     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1497 #else
1498     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1499 #endif
1500 }
1501
1502 void WebPageProxy::setUnderlayColor(const Color& color)
1503 {
1504     if (m_underlayColor == color)
1505         return;
1506
1507     m_underlayColor = color;
1508
1509     if (isValid())
1510         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1511 }
1512
1513 void WebPageProxy::viewWillStartLiveResize()
1514 {
1515     if (!isValid())
1516         return;
1517
1518     closeOverlayedViews();
1519     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1520 }
1521
1522 void WebPageProxy::viewWillEndLiveResize()
1523 {
1524     if (!isValid())
1525         return;
1526     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1527 }
1528
1529 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1530 {
1531     pageClient().setViewNeedsDisplay(region);
1532 }
1533
1534 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1535 {
1536     pageClient().requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1537 }
1538
1539 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1540 {
1541     return pageClient().viewScrollPosition();
1542 }
1543
1544 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1545 {
1546     if (m_suppressVisibilityUpdates == flag)
1547         return;
1548     m_suppressVisibilityUpdates = flag;
1549
1550     if (!m_suppressVisibilityUpdates) {
1551 #if PLATFORM(COCOA)
1552         m_activityStateChangeDispatcher->schedule();
1553 #else
1554         dispatchActivityStateChange();
1555 #endif
1556     }
1557 }
1558
1559 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1560 {
1561     m_activityState.remove(flagsToUpdate);
1562     if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1563         m_activityState.add(ActivityState::IsFocused);
1564     if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1565         m_activityState.add(ActivityState::WindowIsActive);
1566     if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1567         m_activityState.add(ActivityState::IsVisible);
1568     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1569         m_activityState.add(ActivityState::IsVisibleOrOccluded);
1570     if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1571         m_activityState.add(ActivityState::IsInWindow);
1572     if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1573         m_activityState.add(ActivityState::IsVisuallyIdle);
1574     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1575         m_activityState.add(ActivityState::IsAudible);
1576     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1577         m_activityState.add(ActivityState::IsLoading);
1578     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1579         m_activityState.add(ActivityState::IsCapturingMedia);
1580 }
1581
1582 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1583 {
1584     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1585
1586     m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1587     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1588
1589     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1590         return;
1591
1592 #if PLATFORM(COCOA)
1593     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1594     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1595         dispatchActivityStateChange();
1596         return;
1597     }
1598     m_activityStateChangeDispatcher->schedule();
1599 #else
1600     UNUSED_PARAM(dispatchMode);
1601     dispatchActivityStateChange();
1602 #endif
1603 }
1604
1605 void WebPageProxy::viewDidLeaveWindow()
1606 {
1607     closeOverlayedViews();
1608 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1609     // When leaving the current page, close the video fullscreen.
1610     if (m_videoFullscreenManager)
1611         m_videoFullscreenManager->requestHideAndExitFullscreen();
1612 #endif
1613 }
1614
1615 void WebPageProxy::viewDidEnterWindow()
1616 {
1617     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1618     if (m_layerHostingMode != layerHostingMode) {
1619         m_layerHostingMode = layerHostingMode;
1620         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1621     }
1622 }
1623
1624 void WebPageProxy::dispatchActivityStateChange()
1625 {
1626 #if PLATFORM(COCOA)
1627     m_activityStateChangeDispatcher->invalidate();
1628 #endif
1629
1630     if (!isValid())
1631         return;
1632
1633     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1634
1635     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1636     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1637         m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1638
1639     // Record the prior view state, update the flags that may have changed,
1640     // and check which flags have actually changed.
1641     auto previousActivityState = m_activityState;
1642     updateActivityState(m_potentiallyChangedActivityStateFlags);
1643     auto changed = m_activityState ^ previousActivityState;
1644
1645     if (changed)
1646         LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1647
1648     if ((changed & ActivityState::WindowIsActive) && isViewWindowActive())
1649         updateCurrentModifierState();
1650
1651     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1652         viewIsBecomingVisible();
1653
1654     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1655     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1656     if (m_viewWasEverInWindow && isNowInWindow) {
1657         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1658             m_activityStateChangeWantsSynchronousReply = true;
1659         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1660     }
1661
1662     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1663     if (!(m_activityState & ActivityState::IsVisible))
1664         m_activityStateChangeWantsSynchronousReply = false;
1665
1666     auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1667
1668     if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1669         m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1670
1671     m_nextActivityStateChangeCallbacks.clear();
1672
1673     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1674     updateThrottleState();
1675
1676 #if ENABLE(POINTER_LOCK)
1677     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1678         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1679         requestPointerUnlock();
1680 #endif
1681
1682     if (changed & ActivityState::IsVisible) {
1683         if (isViewVisible())
1684             m_visiblePageToken = m_process->visiblePageToken();
1685         else {
1686             m_visiblePageToken = nullptr;
1687
1688             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1689             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1690             // stop the unresponsiveness timer here.
1691             m_process->responsivenessTimer().stop();
1692         }
1693     }
1694
1695     if (changed & ActivityState::IsInWindow) {
1696         if (isInWindow())
1697             viewDidEnterWindow();
1698         else
1699             viewDidLeaveWindow();
1700     }
1701
1702     updateBackingStoreDiscardableState();
1703
1704     if (activityStateChangeID != ActivityStateChangeAsynchronous)
1705         waitForDidUpdateActivityState(activityStateChangeID);
1706
1707     m_potentiallyChangedActivityStateFlags = { };
1708     m_activityStateChangeWantsSynchronousReply = false;
1709     m_viewWasEverInWindow |= isNowInWindow;
1710 }
1711
1712 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1713 {
1714     return sessionID().isAlwaysOnLoggingAllowed();
1715 }
1716
1717 void WebPageProxy::updateThrottleState()
1718 {
1719     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1720
1721     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1722     if (!processSuppressionEnabled)
1723         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1724     else if (!m_preventProcessSuppressionCount)
1725         m_preventProcessSuppressionCount = nullptr;
1726
1727     if (m_activityState & ActivityState::IsVisuallyIdle)
1728         m_pageIsUserObservableCount = nullptr;
1729     else if (!m_pageIsUserObservableCount)
1730         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1731
1732 #if PLATFORM(IOS_FAMILY)
1733     bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1734     bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1735     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1736         if (m_activityToken) {
1737             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1738             m_activityToken = nullptr;
1739         }
1740     } else if (!m_activityToken) {
1741         if (isViewVisible())
1742             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1743         else if (isAudible)
1744             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1745         else if (isCapturingMedia)
1746             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1747         else
1748             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);
1749         m_activityToken = m_process->throttler().foregroundActivityToken();
1750     }
1751 #endif
1752 }
1753
1754 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1755 {
1756     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1757         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1758     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1759         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1760 }
1761
1762 void WebPageProxy::layerHostingModeDidChange()
1763 {
1764     if (!isValid())
1765         return;
1766
1767     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1768     if (m_layerHostingMode == layerHostingMode)
1769         return;
1770
1771     m_layerHostingMode = layerHostingMode;
1772     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1773 }
1774
1775 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1776 {
1777     if (!isValid())
1778         return;
1779
1780     if (m_process->state() != WebProcessProxy::State::Running)
1781         return;
1782
1783     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1784     if (m_waitingForDidUpdateActivityState)
1785         return;
1786
1787 #if PLATFORM(IOS_FAMILY)
1788     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1789     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1790     if (!m_activityToken) {
1791         ASSERT_NOT_REACHED();
1792         return;
1793     }
1794 #endif
1795
1796     m_waitingForDidUpdateActivityState = true;
1797
1798     m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1799 }
1800
1801 IntSize WebPageProxy::viewSize() const
1802 {
1803     return pageClient().viewSize();
1804 }
1805
1806 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1807 {
1808     if (!isValid()) {
1809         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1810         return;
1811     }
1812
1813     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1814     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1815 }
1816
1817 void WebPageProxy::clearSelection()
1818 {
1819     if (!isValid())
1820         return;
1821     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1822 }
1823
1824 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1825 {
1826     if (!isValid())
1827         return;
1828     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1829 }
1830
1831 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1832 {
1833     if (!isValid()) {
1834         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1835         return;
1836     }
1837
1838     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1839     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1840 }
1841
1842 void WebPageProxy::increaseListLevel()
1843 {
1844     if (!isValid())
1845         return;
1846
1847     m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
1848 }
1849
1850 void WebPageProxy::decreaseListLevel()
1851 {
1852     if (!isValid())
1853         return;
1854
1855     m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
1856 }
1857
1858 void WebPageProxy::changeListType()
1859 {
1860     if (!isValid())
1861         return;
1862
1863     m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
1864 }
1865
1866 void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
1867 {
1868     if (!isValid())
1869         return;
1870
1871     m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
1872 }
1873
1874 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
1875 {
1876     m_cachedFontAttributesAtSelectionStart.reset();
1877
1878     if (m_editorState.isMissingPostLayoutData)
1879         return;
1880
1881     if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
1882         m_uiClient->didChangeFontAttributes(*fontAttributes);
1883         m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
1884     }
1885 }
1886
1887 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
1888 {
1889     if (m_needsFontAttributes == needsFontAttributes)
1890         return;
1891
1892     m_needsFontAttributes = needsFontAttributes;
1893
1894     if (isValid())
1895         m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
1896 }
1897
1898 bool WebPageProxy::maintainsInactiveSelection() const
1899 {
1900     // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1901     // Otherwise, there is no way to use the console to inspect the state of a selection.
1902     if (inspector() && inspector()->isVisible())
1903         return true;
1904
1905     return m_maintainsInactiveSelection;
1906 }
1907
1908 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1909 {
1910     m_maintainsInactiveSelection = newValue;
1911 }
1912
1913 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1914 {
1915     if (!isValid()) {
1916         callbackFunction(CallbackBase::Error::Unknown);
1917         return;
1918     }
1919
1920     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1921     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1922 }
1923     
1924 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1925 {
1926     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1927
1928     if (!isValid())
1929         return;
1930
1931     if (commandName == ignoreSpellingCommandName)
1932         ++m_pendingLearnOrIgnoreWordMessageCount;
1933
1934     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1935 }
1936
1937 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
1938 {
1939     if (!isValid()) {
1940         callback({ }, CallbackBase::Error::Unknown);
1941         return;
1942     }
1943
1944     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1945     m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
1946 }
1947
1948 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
1949 {
1950     m_cachedFontAttributesAtSelectionStart = attributes;
1951
1952     if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
1953         callback->performCallbackWithReturnValue(attributes);
1954 }
1955
1956 void WebPageProxy::setEditable(bool editable)
1957 {
1958     if (editable == m_isEditable)
1959         return;
1960     if (!isValid())
1961         return;
1962
1963     m_isEditable = editable;
1964     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1965 }
1966     
1967 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1968 {
1969     if (muted)
1970         setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1971     else
1972         setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1973 }
1974
1975 void WebPageProxy::activateMediaStreamCaptureInPage()
1976 {
1977 #if ENABLE(MEDIA_STREAM)
1978     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1979 #endif
1980     setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1981 }
1982
1983 #if !PLATFORM(IOS_FAMILY)
1984 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1985 {
1986 }
1987
1988 void WebPageProxy::layerTreeCommitComplete()
1989 {
1990 }
1991 #endif
1992
1993 #if ENABLE(DRAG_SUPPORT)
1994 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1995 {
1996     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
1997 }
1998
1999 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
2000 {
2001     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
2002 }
2003
2004 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
2005 {
2006     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
2007 }
2008
2009 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2010 {
2011     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
2012 }
2013
2014 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2015 {
2016     if (!isValid())
2017         return;
2018 #if PLATFORM(GTK)
2019     UNUSED_PARAM(dragStorageName);
2020     UNUSED_PARAM(sandboxExtensionHandle);
2021     UNUSED_PARAM(sandboxExtensionsForUpload);
2022
2023     String url = dragData.asURL();
2024     if (!url.isEmpty())
2025         m_process->assumeReadAccessToBaseURL(*this, url);
2026
2027     ASSERT(dragData.platformData());
2028     WebSelectionData selection(*dragData.platformData());
2029     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
2030 #else
2031     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
2032 #endif
2033 }
2034
2035 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
2036 {
2037     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
2038
2039     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2040     m_currentDragHandlingMethod = dragHandlingMethod;
2041     m_currentDragIsOverFileInput = mouseIsOverFileInput;
2042     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2043     setDragCaretRect(insertionRect);
2044 }
2045
2046 #if PLATFORM(GTK)
2047 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2048 {
2049     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2050     pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2051
2052     didStartDrag();
2053 }
2054 #endif
2055
2056 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2057 {
2058     if (!isValid())
2059         return;
2060     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2061     setDragCaretRect({ });
2062 }
2063
2064 void WebPageProxy::didPerformDragOperation(bool handled)
2065 {
2066     pageClient().didPerformDragOperation(handled);
2067 }
2068
2069 void WebPageProxy::didStartDrag()
2070 {
2071     if (isValid())
2072         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2073 }
2074     
2075 void WebPageProxy::dragCancelled()
2076 {
2077     if (isValid())
2078         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2079 }
2080
2081 void WebPageProxy::didEndDragging()
2082 {
2083     resetCurrentDragInformation();
2084 }
2085
2086 void WebPageProxy::resetCurrentDragInformation()
2087 {
2088     m_currentDragOperation = WebCore::DragOperationNone;
2089     m_currentDragHandlingMethod = DragHandlingMethod::None;
2090     m_currentDragIsOverFileInput = false;
2091     m_currentDragNumberOfFilesToBeAccepted = 0;
2092     setDragCaretRect({ });
2093 }
2094
2095 #if !ENABLE(DATA_INTERACTION)
2096
2097 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2098 {
2099     m_currentDragCaretRect = dragCaretRect;
2100 }
2101
2102 #endif
2103
2104 #endif // ENABLE(DRAG_SUPPORT)
2105
2106 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2107 {
2108     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2109         return false;
2110
2111     auto it = queue.rbegin();
2112     auto end = queue.rend();
2113
2114     // Must not remove the first event in the deque, since it is already being dispatched.
2115     if (it != end)
2116         --end;
2117
2118     for (; it != end; ++it) {
2119         auto type = it->type();
2120         if (type == incomingEventType) {
2121             queue.remove(--it.base());
2122             return true;
2123         }
2124         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2125             break;
2126     }
2127     return false;
2128 }
2129
2130 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2131 {
2132     if (!isValid())
2133         return;
2134
2135     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2136     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2137     // event in the queue.
2138     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2139     m_mouseEventQueue.append(event);
2140
2141 #if LOG_DISABLED
2142     UNUSED_PARAM(didRemoveEvent);
2143 #else
2144     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2145 #endif
2146
2147     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2148         processNextQueuedMouseEvent();
2149 }
2150     
2151 void WebPageProxy::processNextQueuedMouseEvent()
2152 {
2153     if (!isValid())
2154         return;
2155
2156     ASSERT(!m_mouseEventQueue.isEmpty());
2157
2158     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2159     
2160     if (pageClient().windowIsFrontWindowUnderMouse(event))
2161         setToolTip(String());
2162
2163     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2164     if (event.type() != WebEvent::MouseMove)
2165         m_process->responsivenessTimer().start();
2166
2167     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2168     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2169 }
2170
2171 #if MERGE_WHEEL_EVENTS
2172 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2173 {
2174     if (a.position() != b.position())
2175         return false;
2176     if (a.globalPosition() != b.globalPosition())
2177         return false;
2178     if (a.modifiers() != b.modifiers())
2179         return false;
2180     if (a.granularity() != b.granularity())
2181         return false;
2182 #if PLATFORM(COCOA)
2183     if (a.phase() != b.phase())
2184         return false;
2185     if (a.momentumPhase() != b.momentumPhase())
2186         return false;
2187     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2188         return false;
2189 #endif
2190
2191     return true;
2192 }
2193
2194 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2195 {
2196     ASSERT(canCoalesce(a, b));
2197
2198     FloatSize mergedDelta = a.delta() + b.delta();
2199     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2200
2201 #if PLATFORM(COCOA)
2202     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2203
2204     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());
2205 #else
2206     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2207 #endif
2208 }
2209 #endif // MERGE_WHEEL_EVENTS
2210
2211 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2212 {
2213     ASSERT(!queue.isEmpty());
2214     ASSERT(coalescedEvents.isEmpty());
2215
2216 #if MERGE_WHEEL_EVENTS
2217     NativeWebWheelEvent firstEvent = queue.takeFirst();
2218     coalescedEvents.append(firstEvent);
2219
2220     WebWheelEvent event = firstEvent;
2221     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2222         NativeWebWheelEvent firstEvent = queue.takeFirst();
2223         coalescedEvents.append(firstEvent);
2224         event = coalesce(event, firstEvent);
2225     }
2226
2227     return event;
2228 #else
2229     while (!queue.isEmpty())
2230         coalescedEvents.append(queue.takeFirst());
2231     return coalescedEvents.last();
2232 #endif
2233 }
2234
2235 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2236 {
2237 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2238     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2239         return;
2240 #endif
2241
2242     if (!isValid())
2243         return;
2244
2245     closeOverlayedViews();
2246
2247     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2248         m_wheelEventQueue.append(event);
2249         if (!shouldProcessWheelEventNow(event))
2250             return;
2251         // The queue has too many wheel events, so push a new event.
2252     }
2253
2254     if (!m_wheelEventQueue.isEmpty()) {
2255         processNextQueuedWheelEvent();
2256         return;
2257     }
2258
2259     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2260     coalescedWheelEvent->append(event);
2261     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2262     sendWheelEvent(event);
2263 }
2264
2265 void WebPageProxy::processNextQueuedWheelEvent()
2266 {
2267     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2268     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2269     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2270     sendWheelEvent(nextWheelEvent);
2271 }
2272
2273 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2274 {
2275     m_process->send(
2276         Messages::EventDispatcher::WheelEvent(
2277             m_pageID,
2278             event,
2279             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2280             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2281             rubberBandsAtTop(),
2282             rubberBandsAtBottom()
2283         ), 0);
2284
2285     // Manually ping the web process to check for responsiveness since our wheel
2286     // event will dispatch to a non-main thread, which always responds.
2287     m_process->isResponsive(nullptr);
2288 }
2289
2290 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2291 {
2292 #if PLATFORM(GTK)
2293     // Don't queue events representing a non-trivial scrolling phase to
2294     // avoid having them trapped in the queue, potentially preventing a
2295     // scrolling session to beginning or end correctly.
2296     // This is only needed by platforms whose WebWheelEvent has this phase
2297     // information (Cocoa and GTK+) but Cocoa was fine without it.
2298     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2299         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2300         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2301         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2302         return true;
2303 #else
2304     UNUSED_PARAM(event);
2305 #endif
2306     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2307         return true;
2308     return false;
2309 }
2310
2311 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2312 {
2313     if (!isValid())
2314         return;
2315     
2316     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2317
2318     m_keyEventQueue.append(event);
2319
2320     m_process->responsivenessTimer().start();
2321     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2322         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2323         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2324     }
2325 }
2326
2327 WebPreferencesStore WebPageProxy::preferencesStore() const
2328 {
2329     if (m_configurationPreferenceValues.isEmpty())
2330         return m_preferences->store();
2331
2332     WebPreferencesStore store = m_preferences->store();
2333     for (const auto& preference : m_configurationPreferenceValues)
2334         store.m_values.set(preference.key, preference.value);
2335
2336     return store;
2337 }
2338
2339 #if ENABLE(NETSCAPE_PLUGIN_API)
2340 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)
2341 {
2342     PageClientProtector protector(pageClient());
2343
2344     MESSAGE_CHECK_URL(urlString);
2345
2346     URL pluginURL = URL { URL(), urlString };
2347     String newMimeType = mimeType.convertToASCIILowercase();
2348
2349     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2350
2351     URL pageURL = URL { URL(), pageURLString };
2352     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2353         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2354         return;
2355     }
2356
2357     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2358     if (!plugin.path) {
2359         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2360         return;
2361     }
2362
2363     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2364
2365 #if PLATFORM(COCOA)
2366     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2367 #endif
2368
2369     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2370         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2371         switch (pluginLoadPolicy) {
2372         case PluginModuleLoadNormally:
2373             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2374             break;
2375         case PluginModuleLoadUnsandboxed:
2376             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2377             break;
2378
2379         case PluginModuleBlockedForSecurity:
2380         case PluginModuleBlockedForCompatibility:
2381             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2382             return;
2383         }
2384
2385         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2386     };
2387
2388 #if PLATFORM(COCOA)
2389     m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2390 #else
2391     findPluginCompletion(pluginLoadPolicy, { });
2392 #endif
2393 }
2394
2395 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2396
2397 #if ENABLE(TOUCH_EVENTS)
2398
2399 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2400 {
2401     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2402         return b;
2403     return a;
2404 }
2405
2406 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2407 {
2408 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2409     const EventNames& names = eventNames();
2410     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2411         IntPoint location = touchPoint.location();
2412         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2413             if (trackingType == TrackingType::Synchronous)
2414                 return;
2415
2416             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2417
2418             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2419         };
2420         updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2421         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2422         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2423         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2424         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2425         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2426         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2427     }
2428 #else
2429     UNUSED_PARAM(touchStartEvent);
2430     m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2431     m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2432     m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2433     m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2434 #endif // ENABLE(ASYNC_SCROLLING)
2435 }
2436
2437 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2438 {
2439     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2440     //
2441     // Touch events define a sequence with strong dependencies. For example, we can expect
2442     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2443     // the two.
2444     //
2445     // WebCore should not have to set up its state correctly after some events were dismissed.
2446     // For example, we don't want to send a TouchMoved without a TouchPressed.
2447     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2448     TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2449
2450     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2451     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2452         switch (touchPoint.state()) {
2453         case WebPlatformTouchPoint::TouchReleased:
2454             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2455             break;
2456         case WebPlatformTouchPoint::TouchPressed:
2457             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2458             break;
2459         case WebPlatformTouchPoint::TouchMoved:
2460         case WebPlatformTouchPoint::TouchStationary:
2461             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2462             break;
2463         case WebPlatformTouchPoint::TouchCancelled:
2464             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2465             break;
2466         }
2467     }
2468
2469     return globalTrackingType;
2470 }
2471
2472 #endif
2473
2474 #if ENABLE(MAC_GESTURE_EVENTS)
2475 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2476 {
2477     if (!isValid())
2478         return;
2479
2480     m_gestureEventQueue.append(event);
2481     // FIXME: Consider doing some coalescing here.
2482     m_process->responsivenessTimer().start();
2483
2484     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2485 }
2486 #endif
2487
2488 #if ENABLE(IOS_TOUCH_EVENTS)
2489 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2490 {
2491     if (!isValid())
2492         return;
2493
2494     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2495
2496     updateTouchEventTracking(event);
2497
2498     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2499     if (touchEventsTrackingType == TrackingType::NotTracking)
2500         return;
2501
2502     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2503         // We can end up here if a native gesture has not started but the event handlers are passive.
2504         //
2505         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2506         // can prevent a native gesture.
2507         // But, here we know that all events handlers that can handle this events are passive.
2508         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2509         event.setCanPreventNativeGestures(false);
2510         handleTouchEventAsynchronously(event);
2511         didReceiveEvent(event.type(), false);
2512         return;
2513     }
2514
2515     m_process->responsivenessTimer().start();
2516     bool handled = false;
2517     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2518     // 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.
2519     if (!replyReceived)
2520         handled = true;
2521     didReceiveEvent(event.type(), handled);
2522     pageClient().doneWithTouchEvent(event, handled);
2523     m_process->responsivenessTimer().stop();
2524
2525     if (event.allTouchPointsAreReleased())
2526         m_touchAndPointerEventTracking.reset();
2527 }
2528
2529 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2530 {
2531     if (!isValid())
2532         return;
2533
2534     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2535     if (touchEventsTrackingType == TrackingType::NotTracking)
2536         return;
2537
2538     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2539
2540     if (event.allTouchPointsAreReleased())
2541         m_touchAndPointerEventTracking.reset();
2542 }
2543
2544 #elif ENABLE(TOUCH_EVENTS)
2545 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2546 {
2547     if (!isValid())
2548         return;
2549
2550     updateTouchEventTracking(event);
2551
2552     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2553         return;
2554
2555     // If the page is suspended, which should be the case during panning, pinching
2556     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2557     // we do not send any of the events to the page even if is has listeners.
2558     if (!m_isPageSuspended) {
2559         m_touchEventQueue.append(event);
2560         m_process->responsivenessTimer().start();
2561         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2562     } else {
2563         if (m_touchEventQueue.isEmpty()) {
2564             bool isEventHandled = false;
2565             pageClient().doneWithTouchEvent(event, isEventHandled);
2566         } else {
2567             // We attach the incoming events to the newest queued event so that all
2568             // the events are delivered in the correct order when the event is dequed.
2569             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2570             lastEvent.deferredTouchEvents.append(event);
2571         }
2572     }
2573
2574     if (event.allTouchPointsAreReleased())
2575         m_touchAndPointerEventTracking.reset();
2576 }
2577 #endif // ENABLE(TOUCH_EVENTS)
2578
2579 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2580 {
2581     if (!isValid())
2582         return;
2583
2584     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2585 }
2586
2587 void WebPageProxy::centerSelectionInVisibleArea()
2588 {
2589     if (!isValid())
2590         return;
2591
2592     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2593 }
2594
2595 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2596 public:
2597     using SendFunction = CompletionHandler<void(WebCore::PolicyAction, uint64_t newNavigationID, DownloadID, std::optional<WebsitePoliciesData>)>;
2598     static Ref<PolicyDecisionSender> create(SendFunction&& sendFunction)
2599     {
2600         return adoptRef(*new PolicyDecisionSender(WTFMove(sendFunction)));
2601     }
2602
2603     template<typename... Args> void send(Args... args)
2604     {
2605         if (m_sendFunction)
2606             m_sendFunction(std::forward<Args>(args)...);
2607     }
2608 private:
2609     PolicyDecisionSender(SendFunction sendFunction)
2610         : m_sendFunction(WTFMove(sendFunction)) { }
2611
2612     SendFunction m_sendFunction;
2613 };
2614
2615 void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2616 {
2617     std::optional<WebsitePoliciesData> data;
2618     if (policies) {
2619         data = policies->data();
2620         if (policies->websiteDataStore())
2621             changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore());
2622     }
2623
2624     if (policyAction != PolicyAction::Use || !frame.isMainFrame() || !navigation) {
2625         receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2626         return;
2627     }
2628
2629     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 {
2630         // If the navigation has been destroyed, then no need to proceed.
2631         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2632             receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2633             return;
2634         }
2635
2636         if (processForNavigation.ptr() != &process()) {
2637             policyAction = isPageOpenedByDOMShowingInitialEmptyDocument() ? PolicyAction::Ignore : PolicyAction::Suspend;
2638             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());
2639             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2640         } else
2641             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "%p - WebPageProxy::decidePolicyForNavigationAction, keep using process %i for navigation, reason: %{public}s", this, processIdentifier(), reason.utf8().data());
2642
2643         bool shouldProcessSwap = processForNavigation.ptr() != &process();
2644         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? std::nullopt : WTFMove(data), WTFMove(sender));
2645
2646         if (shouldProcessSwap)
2647             continueNavigationInNewProcess(navigation, destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr, WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2648     });
2649 }
2650
2651 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
2652 {
2653     if (!isValid()) {
2654         sender->send(PolicyAction::Ignore, 0, DownloadID(), std::nullopt);
2655         return;
2656     }
2657
2658     auto transaction = m_pageLoadState.transaction();
2659
2660     if (action == PolicyAction::Ignore)
2661         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2662
2663     if (navigation && navigation->shouldForceDownload() && action == PolicyAction::Use)
2664         action = PolicyAction::Download;
2665
2666     DownloadID downloadID = { };
2667     if (action == PolicyAction::Download) {
2668         // Create a download proxy.
2669         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2670         if (navigation) {
2671             download->setWasUserInitiated(navigation->wasUserInitiated());
2672             download->setRedirectChain(navigation->takeRedirectChain());
2673         }
2674
2675         downloadID = download->downloadID();
2676         handleDownloadRequest(download);
2677         m_decidePolicyForResponseRequest = { };
2678     }
2679
2680     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2681 }
2682
2683 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient, std::optional<WebsitePoliciesData>&& websitePolicies)
2684 {
2685     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2686
2687     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
2688     std::optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? std::make_optional(m_mainFrame->frameID()) : std::nullopt;
2689     auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
2690
2691     ASSERT(m_process.ptr() != process.ptr());
2692
2693     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2694
2695     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2696     bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
2697     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
2698
2699     swapToWebProcess(WTFMove(process), WTFMove(suspendedPageProxy), didSuspendPreviousPage ? ShouldDelayAttachingDrawingArea::Yes : ShouldDelayAttachingDrawingArea::No);
2700
2701     if (auto* item = navigation.targetItem()) {
2702         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2703
2704         auto transaction = m_pageLoadState.transaction();
2705         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2706
2707         auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
2708             if (auto* page = item.suspendedPage()) {
2709                 if (&page->process() == m_process.ptr())
2710                     return false;
2711             }
2712             return &item != targetItem;
2713         });
2714         m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
2715         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)), m_pageID);
2716         m_process->responsivenessTimer().start();
2717
2718         return;
2719     }
2720
2721     if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
2722         // 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
2723         // it instead of creating a new one.
2724         m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
2725     }
2726
2727     // FIXME: Work out timing of responding with the last policy delegate, etc
2728     ASSERT(!navigation.currentRequest().isEmpty());
2729     if (auto& substituteData = navigation.substituteData())
2730         loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
2731     else
2732         loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
2733
2734     ASSERT(!m_mainFrame);
2735     m_mainFrameCreationHandler = [this, weakThis = makeWeakPtr(*this), navigationID = navigation.navigationID(), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
2736         if (!weakThis)
2737             return;
2738
2739         ASSERT(m_mainFrame);
2740         // This navigation was destroyed so no need to notify of redirect.
2741         if (!navigationState().navigation(navigationID))
2742             return;
2743
2744         // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
2745         m_mainFrame->frameLoadState().setURL(mainFrameURL);
2746
2747         // Normally, notification of a server redirect comes from the WebContent process.
2748         // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
2749         // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
2750         if (isServerRedirect) {
2751             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
2752             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigationID, WTFMove(request), { });
2753         }
2754     };
2755
2756     if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isPageOpenedByDOMShowingInitialEmptyDocument() || !mainFrameIDInPreviousProcess) {
2757         // There is no way we'll be able to return to the page in the previous page so close it.
2758         if (!didSuspendPreviousPage)
2759             previousProcess->send(Messages::WebPage::Close(), m_pageID);
2760         return;
2761     }
2762
2763     m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
2764         ASSERT(m_mainFrame);
2765         GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
2766         previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
2767     };
2768 }
2769
2770 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
2771 {
2772     return openedByDOM() && !hasCommittedAnyProvisionalLoads();
2773 }
2774
2775 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
2776 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
2777 #if !COMPILER(MSVC)
2778 NO_RETURN_DUE_TO_ASSERT
2779 #endif
2780 void WebPageProxy::didFailToSuspendAfterProcessSwap()
2781 {
2782     // Only the SuspendedPageProxy should be getting this call.
2783     ASSERT_NOT_REACHED();
2784 }
2785
2786 #if !COMPILER(MSVC)
2787 NO_RETURN_DUE_TO_ASSERT
2788 #endif
2789 void WebPageProxy::didSuspendAfterProcessSwap()
2790 {
2791     // Only the SuspendedPageProxy should be getting this call.
2792     ASSERT_NOT_REACHED();
2793 }
2794
2795 void WebPageProxy::setUserAgent(String&& userAgent)
2796 {
2797     if (m_userAgent == userAgent)
2798         return;
2799     m_userAgent = WTFMove(userAgent);
2800
2801 #if ENABLE(SERVICE_WORKER)
2802     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2803     // FIXME: Refactor this when we have a better User-Agent story.
2804     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2805 #endif
2806
2807     if (!isValid())
2808         return;
2809     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2810 }
2811
2812 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2813 {
2814     if (m_applicationNameForUserAgent == applicationName)
2815         return;
2816
2817     m_applicationNameForUserAgent = applicationName;
2818     if (!m_customUserAgent.isEmpty())
2819         return;
2820
2821     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2822 }
2823
2824 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2825 {
2826     if (m_customUserAgent == customUserAgent)
2827         return;
2828
2829     m_customUserAgent = customUserAgent;
2830
2831     if (m_customUserAgent.isEmpty()) {
2832         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2833         return;
2834     }
2835
2836     setUserAgent(String { m_customUserAgent });
2837 }
2838
2839 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2840 {
2841     if (!isValid() || !m_isPageSuspended)
2842         return;
2843
2844     m_isPageSuspended = false;
2845
2846     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2847 }
2848
2849 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2850 {
2851     if (!isValid() || m_isPageSuspended)
2852         return;
2853
2854     m_isPageSuspended = true;
2855
2856     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2857 }
2858
2859 bool WebPageProxy::supportsTextEncoding() const
2860 {
2861     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2862     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2863 }
2864
2865 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2866 {
2867     if (m_customTextEncodingName == encodingName)
2868         return;
2869     m_customTextEncodingName = encodingName;
2870
2871     if (!isValid())
2872         return;
2873     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2874 }
2875
2876 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2877 {
2878     SessionState sessionState;
2879
2880     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2881
2882     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2883     if (provisionalURLString.isEmpty())
2884         provisionalURLString = m_pageLoadState.provisionalURL();
2885
2886     if (!provisionalURLString.isEmpty())
2887         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2888
2889     sessionState.renderTreeSize = renderTreeSize();
2890     return sessionState;
2891 }
2892
2893 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2894 {
2895     m_sessionRestorationRenderTreeSize = 0;
2896     m_hitRenderTreeSizeThreshold = false;
2897
2898     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2899
2900     if (hasBackForwardList) {
2901         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2902         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2903
2904         auto transaction = m_pageLoadState.transaction();
2905         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2906         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2907
2908         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2909         // page when navigating away. Suppress navigation snapshotting until the next load has committed
2910         suppressNextAutomaticNavigationSnapshot();
2911     }
2912
2913     // FIXME: Navigating should be separate from state restoration.
2914     if (navigate) {
2915         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2916         if (!m_sessionRestorationRenderTreeSize)
2917             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2918
2919         if (!sessionState.provisionalURL.isNull())
2920             return loadRequest(sessionState.provisionalURL);
2921
2922         if (hasBackForwardList) {
2923             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2924                 return goToBackForwardItem(*item);
2925         }
2926     }
2927
2928     return nullptr;
2929 }
2930
2931 bool WebPageProxy::supportsTextZoom() const
2932 {
2933     // FIXME (118840): This should also return false for standalone media and plug-in documents.
2934     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2935         return false;
2936
2937     return true;
2938 }
2939  
2940 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2941 {
2942     if (!isValid())
2943         return;
2944
2945     if (m_textZoomFactor == zoomFactor)
2946         return;
2947
2948     m_textZoomFactor = zoomFactor;
2949     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
2950 }
2951
2952 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2953 {
2954     if (!isValid())
2955         return;
2956
2957     if (m_pageZoomFactor == zoomFactor)
2958         return;
2959
2960     closeOverlayedViews();
2961
2962     m_pageZoomFactor = zoomFactor;
2963     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
2964 }
2965
2966 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2967 {
2968     if (!isValid())
2969         return;
2970
2971     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2972         return;
2973
2974     closeOverlayedViews();
2975
2976     m_pageZoomFactor = pageZoomFactor;
2977     m_textZoomFactor = textZoomFactor;
2978     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
2979 }
2980
2981 double WebPageProxy::pageZoomFactor() const
2982 {
2983     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2984     // zoom which ensures that we don't use the PDF zoom for a normal page.
2985     if (m_mainFramePluginHandlesPageScaleGesture)
2986         return m_pluginZoomFactor;
2987     return m_pageZoomFactor;
2988 }
2989
2990 double WebPageProxy::pageScaleFactor() const
2991 {
2992     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2993     // separately but decide which to return based on the main frame.
2994     if (m_mainFramePluginHandlesPageScaleGesture)
2995         return m_pluginScaleFactor;
2996     return m_pageScaleFactor;
2997 }
2998
2999 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3000 {
3001     ASSERT(scale > 0);
3002
3003     if (!isValid())
3004         return;
3005
3006     m_pageScaleFactor = scale;
3007     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3008 }
3009
3010 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3011 {
3012     ASSERT(scale > 0);
3013
3014     if (!isValid())
3015         return;
3016
3017     m_pageScaleFactor = scale;
3018     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3019 }
3020
3021 void WebPageProxy::scaleView(double scale)
3022 {
3023     ASSERT(scale > 0);
3024
3025     if (!isValid())
3026         return;
3027
3028     m_viewScaleFactor = scale;
3029     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3030 }
3031
3032 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3033 {
3034     if (m_intrinsicDeviceScaleFactor == scaleFactor)
3035         return;
3036
3037     m_intrinsicDeviceScaleFactor = scaleFactor;
3038
3039     if (m_drawingArea)
3040         m_drawingArea->deviceScaleFactorDidChange();
3041 }
3042
3043 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3044 {
3045     if (!isValid())
3046         return;
3047
3048     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3049 }
3050
3051 float WebPageProxy::deviceScaleFactor() const
3052 {
3053     return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
3054 }
3055
3056 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3057 {
3058     if (!isValid())
3059         return;
3060
3061     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3062     // https://bugs.webkit.org/show_bug.cgi?id=133378
3063 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3064     return;
3065 #endif
3066
3067     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3068         return;
3069
3070     float oldScaleFactor = deviceScaleFactor();
3071
3072     // A value of 0 clears the customScaleFactor.
3073     if (customScaleFactor)
3074         m_customDeviceScaleFactor = customScaleFactor;
3075     else
3076         m_customDeviceScaleFactor = std::nullopt;
3077
3078     if (deviceScaleFactor() != oldScaleFactor)
3079         m_drawingArea->deviceScaleFactorDidChange();
3080 }
3081
3082 void WebPageProxy::accessibilitySettingsDidChange()
3083 {
3084     if (!isValid())
3085         return;
3086
3087     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3088 }
3089
3090 #if ENABLE(ACCESSIBILITY_EVENTS)
3091 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
3092 {
3093     if (!isValid())
3094         return;
3095
3096     m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
3097 }
3098 #endif
3099
3100 void WebPageProxy::setUseFixedLayout(bool fixed)
3101 {
3102     if (!isValid())
3103         return;
3104
3105     // This check is fine as the value is initialized in the web
3106     // process as part of the creation parameters.
3107     if (fixed == m_useFixedLayout)
3108         return;
3109
3110     m_useFixedLayout = fixed;
3111     if (!fixed)
3112         m_fixedLayoutSize = IntSize();
3113     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3114 }
3115
3116 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3117 {
3118     if (!isValid())
3119         return;
3120
3121     if (size == m_fixedLayoutSize)
3122         return;
3123
3124     m_fixedLayoutSize = size;
3125     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3126 }
3127
3128 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3129 {
3130     if (!isValid())
3131         return;
3132
3133     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3134         return;
3135
3136     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3137     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3138 }
3139
3140 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3141 {
3142     if (!isValid())
3143         return;
3144
3145     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3146         return;
3147
3148     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3149     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3150 }
3151
3152 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3153 {
3154     if (!isValid())
3155         return;
3156     
3157     if (milestones == m_observedLayoutMilestones)
3158         return;
3159
3160     m_observedLayoutMilestones = milestones;
3161     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3162 }
3163
3164 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3165 {
3166     if (!isValid())
3167         return;
3168
3169     if (suppressAnimations == m_suppressScrollbarAnimations)
3170         return;
3171
3172     m_suppressScrollbarAnimations = suppressAnimations;
3173     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3174 }
3175
3176 bool WebPageProxy::rubberBandsAtLeft() const
3177 {
3178     return m_rubberBandsAtLeft;
3179 }
3180
3181 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3182 {
3183     m_rubberBandsAtLeft = rubberBandsAtLeft;
3184 }
3185
3186 bool WebPageProxy::rubberBandsAtRight() const
3187 {
3188     return m_rubberBandsAtRight;
3189 }
3190
3191 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3192 {
3193     m_rubberBandsAtRight = rubberBandsAtRight;
3194 }
3195
3196 bool WebPageProxy::rubberBandsAtTop() const
3197 {
3198     return m_rubberBandsAtTop;
3199 }
3200
3201 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3202 {
3203     m_rubberBandsAtTop = rubberBandsAtTop;
3204 }
3205
3206 bool WebPageProxy::rubberBandsAtBottom() const
3207 {
3208     return m_rubberBandsAtBottom;
3209 }
3210
3211 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3212 {
3213     m_rubberBandsAtBottom = rubberBandsAtBottom;
3214 }
3215     
3216 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3217 {
3218     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3219         return;
3220
3221     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3222
3223     if (!isValid())
3224         return;
3225     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3226 }
3227     
3228 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3229 {
3230     return m_enableVerticalRubberBanding;
3231 }
3232     
3233 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3234 {
3235     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3236         return;
3237
3238     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3239
3240     if (!isValid())
3241         return;
3242     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3243 }
3244     
3245 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3246 {
3247     return m_enableHorizontalRubberBanding;
3248 }
3249
3250 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3251 {
3252     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3253         return;
3254
3255     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3256
3257     if (!isValid())
3258         return;
3259     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3260 }
3261
3262 bool WebPageProxy::backgroundExtendsBeyondPage() const
3263 {
3264     return m_backgroundExtendsBeyondPage;
3265 }
3266
3267 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3268 {
3269     if (mode == m_paginationMode)
3270         return;
3271
3272     m_paginationMode = mode;
3273
3274     if (!isValid())
3275         return;
3276     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3277 }
3278
3279 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3280 {
3281     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3282         return;
3283
3284     m_paginationBehavesLikeColumns = behavesLikeColumns;
3285
3286     if (!isValid())
3287         return;
3288     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3289 }
3290
3291 void WebPageProxy::setPageLength(double pageLength)
3292 {
3293     if (pageLength == m_pageLength)
3294         return;
3295
3296     m_pageLength = pageLength;
3297
3298     if (!isValid())
3299         return;
3300     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3301 }
3302
3303 void WebPageProxy::setGapBetweenPages(double gap)
3304 {
3305     if (gap == m_gapBetweenPages)
3306         return;
3307
3308     m_gapBetweenPages = gap;
3309
3310     if (!isValid())
3311         return;
3312     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3313 }
3314
3315 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3316 {
3317     if (lineGridEnabled == m_paginationLineGridEnabled)
3318         return;
3319     
3320     m_paginationLineGridEnabled = lineGridEnabled;
3321     
3322     if (!isValid())
3323         return;
3324     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3325 }
3326
3327 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3328 {
3329     m_pageScaleFactor = scaleFactor;
3330 }
3331
3332 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3333 {
3334     m_pluginScaleFactor = pluginScaleFactor;
3335 }
3336
3337 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3338 {
3339     m_pluginZoomFactor = pluginZoomFactor;
3340 }
3341
3342 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3343 {
3344     if (string.isEmpty()) {
3345         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3346         return;
3347     }
3348
3349     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3350 }
3351
3352 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3353 {
3354     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3355 }
3356
3357 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3358 {
3359     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3360 }
3361
3362 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3363 {
3364     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3365 }
3366
3367 void WebPageProxy::hideFindUI()
3368 {
3369     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3370 }
3371
3372 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3373 {
3374     if (!isValid())
3375         return;
3376
3377     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3378 }
3379
3380 void WebPageProxy::replaceMatches(Vector<uint32_t>&& matchIndices, const String& replacementText, bool selectionOnly, Function<void(uint64_t, CallbackBase::Error)>&& callback)
3381 {
3382     if (!isValid()) {
3383         callback(0, CallbackBase::Error::Unknown);
3384         return;
3385     }
3386
3387     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
3388     m_process->send(Messages::WebPage::ReplaceMatches(WTFMove(matchIndices), replacementText, selectionOnly, callbackID), m_pageID);
3389 }
3390
3391 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3392 {
3393     if (!isValid()) {
3394         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3395         return;
3396     }
3397
3398     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3399     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3400 }
3401
3402 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3403 {
3404     if (!isValid()) {
3405         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3406         return;
3407     }
3408
3409     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3410     m_process->send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3411 }
3412
3413 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3414 {
3415     if (!isValid()) {
3416         callbackFunction(String(), CallbackBase::Error::Unknown);
3417         return;
3418     }
3419     
3420     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3421     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3422 }
3423
3424 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3425 {
3426     if (!isValid()) {
3427         callbackFunction(String(), CallbackBase::Error::Unknown);
3428         return;
3429     }
3430     
3431     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3432     m_loadDependentStringCallbackIDs.add(callbackID);
3433     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3434 }
3435
3436 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3437 {
3438     if (!isValid()) {
3439         callbackFunction(String(), CallbackBase::Error::Unknown);
3440         return;
3441     }
3442     
3443     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3444     m_loadDependentStringCallbackIDs.add(callbackID);
3445     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3446 }
3447
3448 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3449 {
3450     if (!isValid()) {
3451         callbackFunction(String(), CallbackBase::Error::Unknown);
3452         return;
3453     }
3454     
3455     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3456     m_loadDependentStringCallbackIDs.add(callbackID);
3457     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3458 }
3459
3460 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3461 {
3462     if (!isValid()) {
3463         callbackFunction(String(), CallbackBase::Error::Unknown);
3464         return;
3465     }
3466     
3467     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3468     m_loadDependentStringCallbackIDs.add(callbackID);
3469     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3470 }
3471
3472 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
3473 {
3474     if (!isValid()) {
3475         RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
3476             bool isWebProcessResponsive = true;
3477             callbackFunction(isWebProcessResponsive);
3478         });
3479         return;
3480     }
3481
3482     m_process->isResponsive(WTFMove(callbackFunction));
3483 }
3484
3485 #if ENABLE(MHTML)
3486 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3487 {
3488     if (!isValid()) {
3489         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3490         return;
3491     }
3492
3493     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3494     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3495 }
3496 #endif
3497
3498 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3499 {
3500     if (!isValid()) {
3501         callbackFunction(String(), CallbackBase::Error::Unknown);
3502         return;
3503     }
3504     
3505     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3506     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
3507 }
3508
3509 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3510 {
3511     if (!isValid()) {
3512         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3513         return;
3514     }
3515     
3516     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3517     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3518 }
3519
3520 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3521 {
3522     if (!isValid() || !frame) {
3523         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3524         return;
3525     }
3526     
3527     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3528     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3529 }
3530
3531 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3532 {
3533     if (!isValid()) {
3534         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3535         return;
3536     }
3537     
3538     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3539     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3540 }
3541
3542 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3543 {
3544     if (!isValid()) {
3545         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3546         return;
3547     }
3548     
3549     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3550     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3551 }
3552
3553 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3554 {
3555     if (!isValid()) {
3556         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3557         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3558         return;
3559     }
3560
3561     Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3562         if (error != CallbackBase::Error::None) {
3563             callback->invalidate(error);
3564             return;
3565         }
3566
3567         if (!isValid()) {
3568             callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3569             return;
3570         }
3571     
3572         callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3573             if (error != CallbackBase::Error::None) {
3574                 callback->invalidate(error);
3575                 return;
3576             }
3577
3578             callback->performCallback();
3579         });
3580     };
3581
3582     auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3583     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3584     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
3585 }
3586
3587 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3588 {
3589     if (isPerformingDOMPrintOperation)
3590         return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3591
3592     return { };
3593 }
3594
3595 void WebPageProxy::preferencesDidChange()
3596 {
3597     if (!isValid())
3598         return;
3599
3600     updateThrottleState();
3601     updateHiddenPageThrottlingAutoIncreases();
3602
3603     pageClient().preferencesDidChange();
3604
3605     // FIXME: It probably makes more sense to send individual preference changes.
3606     // However, WebKitTestRunner depends on getting a preference change notification
3607     // even if nothing changed in UI process, so that overrides get removed.
3608
3609     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3610     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3611 }
3612
3613 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3614 {
3615     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateMainFrame one.
3616     // When this happens, decidePolicyForNavigationActionSync() calls didCreateMainFrame() and we need to ignore the DidCreateMainFrame
3617     // IPC when it later gets processed.
3618     if (m_mainFrame && m_mainFrame->frameID() == frameID)
3619         return;
3620
3621     PageClientProtector protector(pageClient());
3622
3623     MESSAGE_CHECK(!m_mainFrame);
3624     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3625
3626     m_mainFrame = WebFrameProxy::create(*this, frameID);
3627
3628     // Add the frame to the process wide map.
3629     m_process->frameCreated(frameID, *m_mainFrame);
3630
3631     if (m_mainFrameCreationHandler) {
3632         m_mainFrameCreationHandler();
3633         m_mainFrameCreationHandler = nullptr;
3634     }
3635 }
3636
3637 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3638 {
3639     PageClientProtector protector(pageClient());
3640
3641     MESSAGE_CHECK(m_mainFrame);
3642
3643     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
3644     // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
3645     // IPC when it later gets processed.
3646     if (m_process->webFrame(frameID))
3647         return;
3648
3649     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3650     
3651     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(*this, frameID);
3652
3653     // Add the frame to the process wide map.
3654     m_process->frameCreated(frameID, *subFrame);
3655 }
3656
3657 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
3658 {
3659     if (m_mainFrame && m_mainFrame->frameID() == frameID) {
3660         if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
3661             mainFrameWindowCreationHandler(windowIdentifier);
3662     }
3663 }
3664
3665 double WebPageProxy::estimatedProgress() const
3666 {
3667     return m_pageLoadState.estimatedProgress();
3668 }
3669
3670 void WebPageProxy::didStartProgress()
3671 {
3672     PageClientProtector protector(pageClient());
3673
3674     auto transaction = m_pageLoadState.transaction();
3675     m_pageLoadState.didStartProgress(transaction);
3676
3677     m_pageLoadState.commitChanges();
3678 }
3679
3680 void WebPageProxy::didChangeProgress(double value)
3681 {
3682     PageClientProtector protector(pageClient());
3683
3684     auto transaction = m_pageLoadState.transaction();
3685     m_pageLoadState.didChangeProgress(transaction, value);
3686
3687     m_pageLoadState.commitChanges();
3688 }
3689
3690 void WebPageProxy::didFinishProgress()
3691 {
3692     PageClientProtector protector(pageClient());
3693
3694     auto transaction = m_pageLoadState.transaction();
3695     m_pageLoadState.didFinishProgress(transaction);
3696
3697     m_pageLoadState.commitChanges();
3698 }
3699
3700 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3701 {
3702     auto transaction = m_pageLoadState.transaction();
3703     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3704 }
3705
3706 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3707 {
3708     hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3709 }
3710
3711 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3712 {
3713     PageClientProtector protector(pageClient());
3714
3715     // FIXME: Message check the navigationID.
3716     m_navigationState->didDestroyNavigation(navigationID);
3717 }
3718
3719 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
3720 {
3721     PageClientProtector protector(pageClient());
3722
3723     WebFrameProxy* frame = m_process->webFrame(frameID);
3724     MESSAGE_CHECK(frame);
3725     MESSAGE_CHECK_URL(url);
3726
3727     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3728     RefPtr<API::Navigation> navigation;
3729     if (frame->isMainFrame() && navigationID)
3730         navigation = navigationState().navigation(navigationID);
3731
3732     // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
3733     // then we ignore this notification.
3734     if (navigation && navigation->currentRequestIsRedirect()) {
3735         auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
3736         if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
3737             return;
3738     }
3739
3740     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());
3741
3742     auto transaction = m_pageLoadState.transaction();
3743
3744     m_pageLoadState.clearPendingAPIRequestURL(transaction);
3745
3746     if (frame->isMainFrame()) {
3747         reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
3748         m_pageLoadStart = MonotonicTime::now();
3749         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
3750         pageClient().didStartProvisionalLoadForMainFrame();
3751         closeOverlayedViews();
3752     }
3753
3754     frame->setUnreachableURL(unreachableURL);
3755     frame->didStartProvisionalLoad(url);
3756
3757     m_pageLoadState.commitChanges();
3758     if (m_loaderClient)
3759         m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3760     else if (frame->isMainFrame())
3761         m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3762 }
3763
3764 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
3765 {
3766     LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data());
3767
3768     PageClientProtector protector(pageClient());
3769
3770     WebFrameProxy* frame = m_process->webFrame(frameID);
3771     MESSAGE_CHECK(frame);
3772     MESSAGE_CHECK_URL(request.url());
3773
3774     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3775     RefPtr<API::Navigation> navigation;
3776     if (navigationID) {
3777         navigation = navigationState().navigation(navigationID);
3778         navigation->appendRedirectionURL(request.url());
3779     }
3780
3781     auto transaction = m_pageLoadState.transaction();
3782
3783     if (frame->isMainFrame())
3784         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, request.url());
3785
3786     frame->didReceiveServerRedirectForProvisionalLoad(request.url());
3787
3788     m_pageLoadState.commitChanges();
3789     if (m_loaderClient)
3790         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, m_process->transformHandlesToObjects(userData.object()).get());
3791     else if (frame->isMainFrame())
3792         m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3793 }
3794
3795 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList)
3796 {
3797     PageClientProtector protector(pageClient());
3798
3799     WebFrameProxy* frame = m_process->webFrame(frameID);
3800     MESSAGE_CHECK(frame);
3801
3802     if (frame->isMainFrame())
3803         m_navigationClient->willPerformClientRedirect(*this, url, delay);
3804 }
3805
3806 void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
3807 {
3808     PageClientProtector protector(pageClient());
3809
3810     WebFrameProxy* frame = m_process->webFrame(frameID);
3811     MESSAGE_CHECK(frame);
3812
3813     if (frame->isMainFrame())
3814         m_navigationClient->didCancelClientRedirect(*this);
3815 }
3816
3817 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, URL&& url)
3818 {
3819     PageClientProtector protector(pageClient());
3820
3821     WebFrameProxy* frame = m_process->webFrame(frameID);
3822     MESSAGE_CHECK(frame);
3823     MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
3824     MESSAGE_CHECK_URL(url);
3825
3826     auto transaction = m_pageLoadState.transaction();
3827
3828     // Internally, we handle this the same way we handle a server redirect. There are no client callbacks
3829     // for this, but if this is the main frame, clients may observe a change to the page's URL.
3830     if (frame->isMainFrame())
3831         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3832
3833     frame->didReceiveServerRedirectForProvisionalLoad(url);
3834 }
3835
3836 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
3837 {
3838     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, m_process->processIdentifier(), provisionalURL.utf8().data());
3839
3840     PageClientProtector protector(pageClient());
3841
3842     WebFrameProxy* frame = m_process->webFrame(frameID);
3843     MESSAGE_CHECK(frame);
3844
3845     if (m_controlledByAutomation) {
3846         if (auto* automationSession = process().processPool().automationSession())
3847             automationSession->navigationOccurredForFrame(*frame);
3848     }
3849
3850     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3851     RefPtr<API::Navigation> navigation;
3852     if (frame->isMainFrame() && navigationID)
3853         navigation = navigationState().takeNavigation(navigationID);
3854
3855     auto transaction = m_pageLoadState.transaction();
3856
3857     if (frame->isMainFrame()) {
3858         reportPageLoadResult(error);
3859         m_pageLoadState.didFailProvisionalLoad(transaction);
3860         pageClient().didFailProvisionalLoadForMainFrame();
3861     }
3862
3863     frame->didFailProvisionalLoad();
3864
3865     m_pageLoadState.commitChanges();
3866
3867     ASSERT(!m_failingProvisionalLoadURL);
3868     m_failingProvisionalLoadURL = provisionalURL;
3869
3870     if (m_loaderClient)
3871         m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3872     else if (frame->isMainFrame())
3873         m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3874     else {
3875             // FIXME: Get the main frame's current navigation.
3876             m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
3877     }
3878
3879     m_failingProvisionalLoadURL = { };
3880 }
3881
3882 void WebPageProxy::clearLoadDependentCallbacks()
3883 {
3884     HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);
3885     for (auto& callbackID : loadDependentStringCallbackIDs) {
3886         if (auto callback = m_callbacks.take<StringCallback>(callbackID))
3887             callback->invalidate();
3888     }
3889 }
3890
3891 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)
3892 {
3893     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " didCommitLoadForFrame in navigation %" PRIu64, m_pageID, m_navigationID);
3894     LOG(BackForward, "(Back/Forward) After load commit, back/forward list is now:%s", m_backForwardList->loggingString());
3895
3896     PageClientProtector protector(pageClient());
3897
3898     WebFrameProxy* frame = m_process->webFrame(frameID);
3899     MESSAGE_CHECK(frame);
3900
3901     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3902     RefPtr<API::Navigation> navigation;
3903     if (frame->isMainFrame() && navigationID)
3904         navigation = navigationState().navigation(navigationID);
3905
3906     m_hasCommittedAnyProvisionalLoads = true;
3907     m_process->didCommitProvisionalLoad();
3908
3909 #if PLATFORM(IOS_FAMILY)
3910     if (frame->isMainFrame()) {
3911         m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
3912         m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
3913     }
3914 #endif
3915
3916     auto transaction = m_pageLoadState.transaction();
3917     Ref<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(certificateInfo);
3918     bool markPageInsecure = hasInsecureContent ? hasInsecureContent.value() == HasInsecureContent::Yes : m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
3919
3920     if (frame->isMainFrame()) {
3921         m_pageLoadState.didCommitLoad(transaction, webCertificateInfo, markPageInsecure);
3922         m_shouldSuppressNextAutomaticNavigationSnapshot = false;
3923     } else if (markPageInsecure)
3924         m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3925
3926 #if USE(APPKIT)
3927     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
3928     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
3929     pageClient().resetSecureInputState();
3930 #endif
3931
3932     clearLoadDependentCallbacks();
3933
3934     frame->didCommitLoad(mimeType, webCertificateInfo, containsPluginDocument);
3935
3936     if (frame->isMainFrame()) {
3937         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
3938
3939         if (m_mainFrameHasCustomContentProvider) {
3940             // Always assume that the main frame is pinned here, since the custom representation view will handle
3941             // any wheel events and dispatch them to the WKView when necessary.
3942             m_mainFrameIsPinnedToLeftSide = true;
3943             m_mainFrameIsPinnedToRightSide = true;
3944             m_mainFrameIsPinnedToTopSide = true;
3945             m_mainFrameIsPinnedToBottomSide = true;
3946
3947             m_uiClient->pinnedStateDidChange(*this);
3948         }
3949         pageClient().didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
3950     }
3951
3952     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
3953     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
3954     // plugin is handling page scaling itself) so we should reset it to the default
3955     // for standard main frame loads.
3956     if (frame->isMainFrame()) {
3957         if (static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
3958             m_pageScaleFactor = 1;
3959             m_pluginScaleFactor = 1;
3960             m_mainFramePluginHandlesPageScaleGesture = false;
3961         }
3962     }
3963
3964 #if ENABLE(POINTER_LOCK)
3965     if (frame->isMainFrame())
3966         requestPointerUnlock();
3967 #endif
3968
3969     m_pageLoadState.commitChanges();
3970     if (m_loaderClient)
3971         m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3972     else if (frame->isMainFrame())
3973         m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3974
3975 #if ENABLE(ATTACHMENT_ELEMENT)
3976     if (frame->isMainFrame())
3977         invalidateAllAttachments();
3978 #endif
3979
3980 #if ENABLE(REMOTE_INSPECTOR)
3981     if (frame->isMainFrame())
3982         remoteInspectorInformationDidChange();
3983 #endif
3984 }
3985
3986 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3987 {
3988     PageClientProtector protector(pageClient());
3989
3990     WebFrameProxy* frame = m_process->webFrame(frameID);
3991     MESSAGE_CHECK(frame);
3992
3993     if (m_controlledByAutomation) {
3994         if (auto* automationSession = process().processPool().automationSession())
3995             automationSession->documentLoadedForFrame(*frame);
3996     }
3997
3998     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3999     RefPtr<API::Navigation> navigation;
4000     if (frame->isMainFrame() && navigationID)
4001         navigation = navigationState().navigation(navigationID);
4002
4003     if (frame->isMainFrame())
4004         m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4005 }
4006
4007 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
4008 {
4009     LOG(Loading, "WebPageProxy::didFinishLoadForFrame - WebPageProxy %p with navigationID %" PRIu64 " didFinishLoad", this, navigationID);
4010
4011     PageClientProtector protector(pageClient());
4012
4013     WebFrameProxy* frame = m_process->webFrame(frameID);
4014     MESSAGE_CHECK(frame);
4015
4016     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4017     RefPtr<API::Navigation> navigation;
4018     if (frame->isMainFrame() && navigationID)
4019         navigation = navigationState().navigation(navigationID);
4020
4021     auto transaction = m_pageLoadState.transaction();
4022
4023     bool isMainFrame = frame->isMainFrame();
4024     if (isMainFrame)
4025         m_pageLoadState.didFinishLoad(transaction);
4026
4027     if (m_controlledByAutomation) {
4028         if (auto* automationSession = process().processPool().automationSession())
4029             automationSession->navigationOccurredForFrame(*frame);
4030     }
4031
4032     frame->didFinishLoad();
4033
4034     m_pageLoadState.commitChanges();
4035     if (m_loaderClient)
4036         m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4037     else if (isMainFrame)
4038         m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4039
4040     if (isMainFrame) {
4041         reportPageLoadResult();
4042         pageClient().didFinishLoadForMainFrame();
4043
4044         resetRecentCrashCountSoon();
4045
4046         notifyProcessPoolToPrewarm();
4047     }
4048
4049     m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = false;
4050 }
4051
4052 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
4053 {
4054     PageClientProtector protector(pageClient());
4055
4056     WebFrameProxy* frame = m_process->webFrame(frameID);
4057     MESSAGE_CHECK(frame);
4058
4059     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4060     RefPtr<API::Navigation> navigation;
4061     if (frame->isMainFrame() && navigationID)
4062         navigation = navigationState().navigation(navigationID);
4063
4064     clearLoadDependentCallbacks();
4065
4066     auto transaction = m_pageLoadState.transaction();
4067
4068     bool isMainFrame = frame->isMainFrame();
4069
4070     if (isMainFrame)
4071         m_pageLoadState.didFailLoad(transaction);
4072
4073     if (m_controlledByAutomation) {
4074         if (auto* automationSession = process().processPool().automationSession())
4075             automationSession->navigationOccurredForFrame(*frame);
4076     }
4077
4078     frame->didFailLoad();
4079
4080     m_pageLoadState.commitChanges();
4081     if (m_loaderClient)
4082         m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4083     else if (frame->isMainFrame())
4084         m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4085
4086     if (isMainFrame) {
4087         reportPageLoadResult(error);
4088         pageClient().didFailLoadForMainFrame();
4089     }
4090 }
4091
4092 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, URL&& url, const UserData& userData)
4093 {
4094     PageClientProtector protector(pageClient());
4095
4096     WebFrameProxy* frame = m_process->webFrame(frameID);
4097     MESSAGE_CHECK(frame);
4098     MESSAGE_CHECK_URL(url);
4099
4100     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4101     RefPtr<API::Navigation> navigation;
4102     if (frame->isMainFrame() && navigationID)
4103         navigation = navigationState().navigation(navigationID);
4104
4105     auto transaction = m_pageLoadState.transaction();
4106
4107     bool isMainFrame = frame->isMainFrame();
4108     if (isMainFrame)
4109         m_pageLoadState.didSameDocumentNavigation(transaction, url);
4110
4111     if (m_controlledByAutomation) {
4112         if (auto* automationSession = process().processPool().automationSession())
4113             automationSession->navigationOccurredForFrame(*frame);
4114     }
4115
4116     m_pageLoadState.clearPendingAPIRequestURL(transaction);
4117     frame->didSameDocumentNavigation(url);
4118
4119     m_pageLoadState.commitChanges();
4120
4121     SameDocumentNavigationType navigationType = static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType);
4122     if (isMainFrame)
4123         m_navigationClient->didSameDocumentNavigation(*this, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
4124
4125     if (isMainFrame)
4126         pageClient().didSameDocumentNavigationForMainFrame(navigationType);
4127 }
4128
4129 void WebPageProxy::didChangeMainDocument(uint64_t frameID)
4130 {
4131 #if ENABLE(MEDIA_STREAM)
4132     userMediaPermissionRequestManager().resetAccess(frameID);
4133 #else
4134     UNUSED_PARAM(frameID);
4135 #endif
4136 }
4137
4138 void WebPageProxy::viewIsBecomingVisible()
4139 {
4140 #if ENABLE(MEDIA_STREAM)
4141     userMediaPermissionRequestManager().viewIsBecomingVisible();
4142 #endif
4143 }
4144
4145 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
4146 {
4147     PageClientProtector protector(pageClient());
4148
4149     WebFrameProxy* frame = m_process->webFrame(frameID);
4150     MESSAGE_CHECK(frame);
4151
4152     auto transaction = m_pageLoadState.transaction();
4153
4154     if (frame->isMainFrame())
4155         m_pageLoadState.setTitle(transaction, title);
4156
4157     frame->didChangeTitle(title);
4158     
4159     m_pageLoadState.commitChanges();
4160
4161 #if ENABLE(REMOTE_INSPECTOR)
4162     if (frame->isMainFrame())
4163         remoteInspectorInformationDidChange();
4164 #endif
4165 }
4166
4167 void WebPageProxy::didFirstLayoutForFrame(uint64_t, const UserData& userData)
4168 {
4169 }
4170
4171 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData& userData)
4172 {
4173     PageClientProtector protector(pageClient());
4174
4175     WebFrameProxy* frame = m_process->webFrame(frameID);
4176     MESSAGE_CHECK(frame);
4177
4178     if (m_loaderClient)
4179         m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
4180
4181     if (frame->isMainFrame())
4182         pageClient().didFirstVisuallyNonEmptyLayoutForMainFrame();
4183 }
4184
4185 void WebPageProxy::didLayoutForCustomContentProvider()
4186 {
4187     didReachLayoutMilestone({ DidFirstLayout, DidFirstVisuallyNonEmptyLayout, DidHitRelevantRepaintedObjectsAreaThreshold });
4188 }
4189