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