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