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