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