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