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