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