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