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