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