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