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