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