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