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