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