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