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