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