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