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