2a7f60575139f8049bf035f475ce7654d3776e9f
[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 "WebFramePolicyListenerProxy.h"
92 #include "WebFullScreenManagerProxy.h"
93 #include "WebFullScreenManagerProxyMessages.h"
94 #include "WebImage.h"
95 #include "WebInspectorProxy.h"
96 #include "WebInspectorUtilities.h"
97 #include "WebNavigationState.h"
98 #include "WebNotificationManagerProxy.h"
99 #include "WebOpenPanelResultListenerProxy.h"
100 #include "WebPageCreationParameters.h"
101 #include "WebPageGroup.h"
102 #include "WebPageGroupData.h"
103 #include "WebPageMessages.h"
104 #include "WebPageProxyMessages.h"
105 #include "WebPaymentCoordinatorProxy.h"
106 #include "WebPopupItem.h"
107 #include "WebPopupMenuProxy.h"
108 #include "WebPreferences.h"
109 #include "WebProcessMessages.h"
110 #include "WebProcessPool.h"
111 #include "WebProcessProxy.h"
112 #include "WebProtectionSpace.h"
113 #include "WebURLSchemeHandler.h"
114 #include "WebUserContentControllerProxy.h"
115 #include "WebsiteDataStore.h"
116 #include <WebCore/BitmapImage.h>
117 #include <WebCore/DiagnosticLoggingClient.h>
118 #include <WebCore/DiagnosticLoggingKeys.h>
119 #include <WebCore/DragController.h>
120 #include <WebCore/DragData.h>
121 #include <WebCore/EventNames.h>
122 #include <WebCore/FloatRect.h>
123 #include <WebCore/FocusDirection.h>
124 #include <WebCore/JSDOMBinding.h>
125 #include <WebCore/JSDOMExceptionHandling.h>
126 #include <WebCore/LengthBox.h>
127 #include <WebCore/MIMETypeRegistry.h>
128 #include <WebCore/PerformanceLoggingClient.h>
129 #include <WebCore/PublicSuffix.h>
130 #include <WebCore/RenderEmbeddedObject.h>
131 #include <WebCore/SerializedCryptoKeyWrap.h>
132 #include <WebCore/TextCheckerClient.h>
133 #include <WebCore/TextIndicator.h>
134 #include <WebCore/URL.h>
135 #include <WebCore/URLParser.h>
136 #include <WebCore/ValidationBubble.h>
137 #include <WebCore/WindowFeatures.h>
138 #include <stdio.h>
139 #include <wtf/NeverDestroyed.h>
140 #include <wtf/SystemTracing.h>
141 #include <wtf/text/StringView.h>
142
143 #if ENABLE(ASYNC_SCROLLING)
144 #include "RemoteScrollingCoordinatorProxy.h"
145 #endif
146
147 #ifndef NDEBUG
148 #include <wtf/RefCountedLeakCounter.h>
149 #endif
150
151 #if PLATFORM(COCOA)
152 #include "RemoteLayerTreeDrawingAreaProxy.h"
153 #include "RemoteLayerTreeScrollingPerformanceData.h"
154 #include "VideoFullscreenManagerProxy.h"
155 #include "VideoFullscreenManagerProxyMessages.h"
156 #include "ViewSnapshotStore.h"
157 #include <WebCore/MachSendRight.h>
158 #include <WebCore/RunLoopObserver.h>
159 #include <WebCore/TextIndicatorWindow.h>
160 #endif
161
162 #if PLATFORM(GTK)
163 #include "WebSelectionData.h"
164 #endif
165
166 #if USE(CAIRO)
167 #include <WebCore/CairoUtilities.h>
168 #endif
169
170 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
171 #include <WebCore/MediaPlaybackTarget.h>
172 #include <WebCore/WebMediaSessionManager.h>
173 #endif
174
175 #if ENABLE(MEDIA_SESSION)
176 #include "WebMediaSessionFocusManager.h"
177 #include "WebMediaSessionMetadata.h"
178 #include <WebCore/MediaSessionMetadata.h>
179 #endif
180
181 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
182 #include "PlaybackSessionManagerProxy.h"
183 #endif
184
185 #if ENABLE(MEDIA_STREAM)
186 #include <WebCore/MediaConstraints.h>
187 #endif
188
189 // This controls what strategy we use for mouse wheel coalescing.
190 #define MERGE_WHEEL_EVENTS 1
191
192 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
193 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
194
195 #define RELEASE_LOG_IF_ALLOWED(channel, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, __VA_ARGS__)
196
197 using namespace WebCore;
198
199 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
200 static const unsigned wheelEventQueueSizeThreshold = 10;
201
202 namespace WebKit {
203
204 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
205
206 class ExceededDatabaseQuotaRecords {
207     WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
208     friend class NeverDestroyed<ExceededDatabaseQuotaRecords>;
209 public:
210     struct Record {
211         uint64_t frameID;
212         String originIdentifier;
213         String databaseName;
214         String displayName;
215         uint64_t currentQuota;
216         uint64_t currentOriginUsage;
217         uint64_t currentDatabaseUsage;
218         uint64_t expectedUsage;
219         RefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply;
220     };
221
222     static ExceededDatabaseQuotaRecords& singleton();
223
224     std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
225         String databaseName, String displayName, uint64_t currentQuota,
226         uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, 
227         Ref<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>&&);
228
229     void add(std::unique_ptr<Record>);
230     bool areBeingProcessed() const { return !!m_currentRecord; }
231     Record* next();
232
233 private:
234     ExceededDatabaseQuotaRecords() { }
235     ~ExceededDatabaseQuotaRecords() { }
236
237     Deque<std::unique_ptr<Record>> m_records;
238     std::unique_ptr<Record> m_currentRecord;
239 };
240
241 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
242 {
243     static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
244     return records;
245 }
246
247 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
248     uint64_t frameID, String originIdentifier, String databaseName, String displayName,
249     uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
250     uint64_t expectedUsage, Ref<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>&& reply)
251 {
252     auto record = std::make_unique<Record>();
253     record->frameID = frameID;
254     record->originIdentifier = originIdentifier;
255     record->databaseName = databaseName;
256     record->displayName = displayName;
257     record->currentQuota = currentQuota;
258     record->currentOriginUsage = currentOriginUsage;
259     record->currentDatabaseUsage = currentDatabaseUsage;
260     record->expectedUsage = expectedUsage;
261     record->reply = WTFMove(reply);
262     return record;
263 }
264
265 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
266 {
267     m_records.append(WTFMove(record));
268 }
269
270 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
271 {
272     m_currentRecord = nullptr;
273     if (!m_records.isEmpty())
274         m_currentRecord = m_records.takeFirst();
275     return m_currentRecord.get();
276 }
277
278 #if !LOG_DISABLED
279 static const char* webKeyboardEventTypeString(WebEvent::Type type)
280 {
281     switch (type) {
282     case WebEvent::KeyDown:
283         return "KeyDown";
284     
285     case WebEvent::KeyUp:
286         return "KeyUp";
287     
288     case WebEvent::RawKeyDown:
289         return "RawKeyDown";
290     
291     case WebEvent::Char:
292         return "Char";
293     
294     default:
295         ASSERT_NOT_REACHED();
296         return "<unknown>";
297     }
298 }
299 #endif // !LOG_DISABLED
300
301 class PageClientProtector {
302     WTF_MAKE_NONCOPYABLE(PageClientProtector);
303 public:
304     PageClientProtector(PageClient& pageClient)
305         : m_pageClient(pageClient)
306     {
307         m_pageClient.refView();
308     }
309
310     ~PageClientProtector()
311     {
312         m_pageClient.derefView();
313     }
314
315 private:
316     PageClient& m_pageClient;
317 };
318
319 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
320 {
321     return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
322 }
323
324 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
325     : m_pageClient(pageClient)
326     , m_configuration(WTFMove(configuration))
327     , m_loaderClient(std::make_unique<API::LoaderClient>())
328     , m_policyClient(std::make_unique<API::PolicyClient>())
329     , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
330     , m_formClient(std::make_unique<API::FormClient>())
331     , m_uiClient(std::make_unique<API::UIClient>())
332     , m_findClient(std::make_unique<API::FindClient>())
333     , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
334 #if ENABLE(CONTEXT_MENUS)
335     , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
336 #endif
337     , m_navigationState(std::make_unique<WebNavigationState>())
338     , m_process(process)
339     , m_pageGroup(*m_configuration->pageGroup())
340     , m_preferences(*m_configuration->preferences())
341     , m_userContentController(*m_configuration->userContentController())
342     , m_visitedLinkStore(*m_configuration->visitedLinkStore())
343     , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
344     , m_userAgent(standardUserAgent())
345     , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
346     , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
347 #if ENABLE(FULLSCREEN_API)
348     , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
349 #endif
350     , m_geolocationPermissionRequestManager(*this)
351     , m_notificationPermissionRequestManager(*this)
352 #if PLATFORM(IOS)
353     , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
354 #endif
355     , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
356     , m_cpuLimit(m_configuration->cpuLimit())
357     , m_backForwardList(WebBackForwardList::create(*this))
358     , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
359     , m_pageID(pageID)
360     , m_sessionID(m_configuration->sessionID())
361     , m_controlledByAutomation(m_configuration->isControlledByAutomation())
362 #if PLATFORM(COCOA)
363     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
364 #endif
365     , m_pageLoadState(*this)
366     , m_configurationPreferenceValues(m_configuration->preferenceValues())
367 {
368     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
369     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
370
371     updateActivityState();
372     updateThrottleState();
373     updateHiddenPageThrottlingAutoIncreases();
374     
375 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
376     m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? m_pageClient.viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
377 #endif
378
379     platformInitialize();
380
381 #ifndef NDEBUG
382     webPageProxyCounter.increment();
383 #endif
384
385     WebProcessPool::statistics().wkPageCount++;
386
387     m_preferences->addPage(*this);
388     m_pageGroup->addPage(this);
389
390     m_inspector = WebInspectorProxy::create(this);
391 #if ENABLE(FULLSCREEN_API)
392     m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
393 #endif
394 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
395     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
396     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
397 #endif
398
399 #if ENABLE(APPLE_PAY)
400     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
401 #endif
402
403     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
404
405 #if PLATFORM(COCOA)
406     const CFIndex activityStateChangeRunLoopOrder = (CFIndex)RunLoopObserver::WellKnownRunLoopOrders::CoreAnimationCommit - 1;
407     m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(activityStateChangeRunLoopOrder, [this] {
408         this->dispatchActivityStateChange();
409     });
410 #endif
411 }
412
413 WebPageProxy::~WebPageProxy()
414 {
415     ASSERT(m_process->webPage(m_pageID) != this);
416 #if !ASSERT_DISABLED
417     for (WebPageProxy* page : m_process->pages())
418         ASSERT(page != this);
419 #endif
420
421     if (!m_isClosed)
422         close();
423
424     WebProcessPool::statistics().wkPageCount--;
425
426     if (m_hasSpellDocumentTag)
427         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag);
428
429     m_preferences->removePage(*this);
430     m_pageGroup->removePage(this);
431
432 #ifndef NDEBUG
433     webPageProxyCounter.decrement();
434 #endif
435 }
436
437 const API::PageConfiguration& WebPageProxy::configuration() const
438 {
439     return m_configuration.get();
440 }
441
442 ProcessID WebPageProxy::processIdentifier() const
443 {
444     if (m_isClosed)
445         return 0;
446
447     return m_process->processIdentifier();
448 }
449
450 bool WebPageProxy::isValid() const
451 {
452     // A page that has been explicitly closed is never valid.
453     if (m_isClosed)
454         return false;
455
456     return m_isValid;
457 }
458
459 void WebPageProxy::setPreferences(WebPreferences& preferences)
460 {
461     if (&preferences == m_preferences.ptr())
462         return;
463
464     m_preferences->removePage(*this);
465     m_preferences = preferences;
466     m_preferences->addPage(*this);
467
468     preferencesDidChange();
469 }
470     
471 void WebPageProxy::setHistoryClient(std::unique_ptr<API::HistoryClient>&& historyClient)
472 {
473     m_historyClient = WTFMove(historyClient);
474 }
475
476 void WebPageProxy::setNavigationClient(std::unique_ptr<API::NavigationClient>&& navigationClient)
477 {
478     m_navigationClient = WTFMove(navigationClient);
479 }
480
481 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
482 {
483     if (!loaderClient) {
484         m_loaderClient = std::make_unique<API::LoaderClient>();
485         return;
486     }
487
488     m_loaderClient = WTFMove(loaderClient);
489 }
490
491 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
492 {
493     if (!policyClient) {
494         m_policyClient = std::make_unique<API::PolicyClient>();
495         return;
496     }
497
498     m_policyClient = WTFMove(policyClient);
499 }
500
501 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
502 {
503     if (!formClient) {
504         m_formClient = std::make_unique<API::FormClient>();
505         return;
506     }
507
508     m_formClient = WTFMove(formClient);
509 }
510
511 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
512 {
513     if (!uiClient) {
514         m_uiClient = std::make_unique<API::UIClient>();
515         return;
516     }
517
518     m_uiClient = WTFMove(uiClient);
519
520     if (!isValid())
521         return;
522
523     m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
524     setCanRunModal(m_uiClient->canRunModal());
525 }
526
527 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
528 {
529     bool hasClient = iconLoadingClient.get();
530     if (!iconLoadingClient)
531         m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
532     else
533         m_iconLoadingClient = WTFMove(iconLoadingClient);
534
535     if (!isValid())
536         return;
537
538     m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
539 }
540
541 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
542 {
543     if (!findClient) {
544         m_findClient = std::make_unique<API::FindClient>();
545         return;
546     }
547     
548     m_findClient = WTFMove(findClient);
549 }
550
551 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
552 {
553     if (!findMatchesClient) {
554         m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
555         return;
556     }
557
558     m_findMatchesClient = WTFMove(findMatchesClient);
559 }
560
561 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
562 {
563     m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
564 }
565
566 #if ENABLE(CONTEXT_MENUS)
567 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
568 {
569     if (!contextMenuClient) {
570         m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
571         return;
572     }
573
574     m_contextMenuClient = WTFMove(contextMenuClient);
575 }
576 #endif
577
578 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
579 {
580     if (!client) {
581         m_injectedBundleClient = nullptr;
582         return;
583     }
584
585     m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
586     m_injectedBundleClient->initialize(client);
587 }
588
589 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
590 {
591     ASSERT(m_process->connection() == &connection);
592
593     if (!m_injectedBundleClient)
594         return;
595
596     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
597 }
598
599 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
600 {
601     ASSERT(m_process->connection() == &connection);
602
603     if (!m_injectedBundleClient)
604         return;
605
606     RefPtr<API::Object> returnData;
607     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
608     returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
609 }
610
611 void WebPageProxy::reattachToWebProcess()
612 {
613     ASSERT(!m_isClosed);
614     ASSERT(!isValid());
615     ASSERT(m_process->state() == WebProcessProxy::State::Terminated);
616
617     m_isValid = true;
618     m_process->removeWebPage(*this, m_pageID);
619     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
620
621     m_process = m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
622
623     ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
624     if (m_process->state() == ChildProcessProxy::State::Running)
625         processDidFinishLaunching();
626     m_process->addExistingWebPage(*this, m_pageID);
627     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
628
629     updateActivityState();
630     updateThrottleState();
631
632     m_inspector = WebInspectorProxy::create(this);
633 #if ENABLE(FULLSCREEN_API)
634     m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
635 #endif
636 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
637     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
638     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
639 #endif
640
641 #if ENABLE(APPLE_PAY)
642     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
643 #endif
644
645     initializeWebPage();
646
647     m_pageClient.didRelaunchProcess();
648     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
649 }
650
651 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
652 {
653     if (m_isClosed)
654         return nullptr;
655     
656     ASSERT(!isValid());
657     reattachToWebProcess();
658
659     if (!m_backForwardList->currentItem())
660         return nullptr;
661
662     auto navigation = m_navigationState->createReloadNavigation();
663
664     // We allow stale content when reloading a WebProcess that's been killed or crashed.
665     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID()), m_pageID);
666     m_process->responsivenessTimer().start();
667
668     return WTFMove(navigation);
669 }
670
671 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
672 {
673     if (m_isClosed)
674         return nullptr;
675
676     ASSERT(!isValid());
677     reattachToWebProcess();
678
679     if (!item)
680         return nullptr;
681
682     if (item != m_backForwardList->currentItem())
683         m_backForwardList->goToItem(item);
684
685     auto navigation = m_navigationState->createBackForwardNavigation();
686
687     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item->itemID()), m_pageID);
688     m_process->responsivenessTimer().start();
689
690     return WTFMove(navigation);
691 }
692
693 void WebPageProxy::initializeWebPage()
694 {
695     ASSERT(isValid());
696
697     BackForwardListItemVector items = m_backForwardList->entries();
698     for (size_t i = 0; i < items.size(); ++i)
699         m_process->registerNewWebBackForwardListItem(items[i].get());
700
701     m_drawingArea = m_pageClient.createDrawingAreaProxy();
702     ASSERT(m_drawingArea);
703
704 #if ENABLE(ASYNC_SCROLLING)
705     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
706         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
707 #if PLATFORM(IOS)
708         // On iOS, main frame scrolls are sent in terms of visible rect updates.
709         m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
710 #endif
711     }
712 #endif
713
714     process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
715
716     m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
717     finishInitializingWebPageAfterProcessLaunch();
718 }
719
720 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
721 {
722     if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
723         return;
724     if (m_process->state() != WebProcessProxy::State::Running)
725         return;
726
727     m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
728     m_process->addVisitedLinkStore(m_visitedLinkStore);
729 }
730
731 void WebPageProxy::close()
732 {
733     if (m_isClosed)
734         return;
735
736     m_isClosed = true;
737
738     if (m_activePopupMenu)
739         m_activePopupMenu->cancelTracking();
740
741     if (m_controlledByAutomation) {
742         if (auto* automationSession = process().processPool().automationSession())
743             automationSession->willClosePage(*this);
744     }
745
746 #if ENABLE(CONTEXT_MENUS)
747     m_activeContextMenu = nullptr;
748 #endif
749
750     m_backForwardList->pageClosed();
751     m_pageClient.pageClosed();
752
753     m_process->disconnectFramesFromPage(this);
754
755     resetState(ResetStateReason::PageInvalidated);
756
757     m_loaderClient = std::make_unique<API::LoaderClient>();
758     m_navigationClient = nullptr;
759     m_policyClient = std::make_unique<API::PolicyClient>();
760     m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
761     m_formClient = std::make_unique<API::FormClient>();
762     m_uiClient = std::make_unique<API::UIClient>();
763     m_findClient = std::make_unique<API::FindClient>();
764     m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
765     m_diagnosticLoggingClient = nullptr;
766 #if ENABLE(CONTEXT_MENUS)
767     m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
768 #endif
769 #if ENABLE(FULLSCREEN_API)
770     m_fullscreenClient = std::make_unique<API::FullscreenClient>();
771 #endif
772
773     m_webProcessLifetimeTracker.pageWasInvalidated();
774
775     m_process->send(Messages::WebPage::Close(), m_pageID);
776     m_process->removeWebPage(*this, m_pageID);
777     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
778     m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
779
780     // Null out related WebPageProxy to avoid leaks.
781     m_configuration->setRelatedPage(nullptr);
782
783 #if PLATFORM(IOS)
784     // Make sure we don't hold a process assertion after getting closed.
785     m_activityToken = nullptr;
786 #endif
787
788     stopAllURLSchemeTasks();
789 }
790
791 bool WebPageProxy::tryClose()
792 {
793     if (!isValid())
794         return true;
795
796     // Close without delay if the process allows it. Our goal is to terminate
797     // the process, so we check a per-process status bit.
798     if (m_process->isSuddenTerminationEnabled())
799         return true;
800
801     m_process->send(Messages::WebPage::TryClose(), m_pageID);
802     m_process->responsivenessTimer().start();
803     return false;
804 }
805
806 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
807 {
808     if (!url.isLocalFile())
809         return false;
810
811     if (m_process->hasAssumedReadAccessToURL(url))
812         return false;
813
814     // Inspector resources are in a directory with assumed access.
815     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
816
817     SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
818     return true;
819 }
820
821 #if !PLATFORM(COCOA)
822 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
823 {
824 }
825 #endif
826
827 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
828 {
829     if (m_isClosed)
830         return nullptr;
831
832     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
833
834     auto transaction = m_pageLoadState.transaction();
835
836     auto url = request.url();
837     m_pageLoadState.setPendingAPIRequestURL(transaction, url);
838
839     if (!isValid())
840         reattachToWebProcess();
841
842     LoadParameters loadParameters;
843     loadParameters.navigationID = navigation->navigationID();
844     loadParameters.request = WTFMove(request);
845     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
846     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
847     bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
848     if (createdExtension)
849         m_process->willAcquireUniversalFileReadSandboxExtension();
850     addPlatformLoadParameters(loadParameters);
851
852     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
853     m_process->responsivenessTimer().start();
854
855     return WTFMove(navigation);
856 }
857
858 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
859 {
860     if (m_isClosed)
861         return nullptr;
862
863     if (!isValid())
864         reattachToWebProcess();
865
866     URL fileURL = URL(URL(), fileURLString);
867     if (!fileURL.isLocalFile())
868         return nullptr;
869
870     URL resourceDirectoryURL;
871     if (resourceDirectoryURLString.isNull())
872         resourceDirectoryURL = URL(ParsedURLString, ASCIILiteral("file:///"));
873     else {
874         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
875         if (!resourceDirectoryURL.isLocalFile())
876             return nullptr;
877     }
878
879     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL));
880
881     auto transaction = m_pageLoadState.transaction();
882
883     m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
884
885     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
886
887     LoadParameters loadParameters;
888     loadParameters.navigationID = navigation->navigationID();
889     loadParameters.request = fileURL;
890     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
891     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
892     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
893     addPlatformLoadParameters(loadParameters);
894
895     m_process->assumeReadAccessToBaseURL(resourceDirectoryURL);
896     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
897     m_process->responsivenessTimer().start();
898
899     return WTFMove(navigation);
900 }
901
902 RefPtr<API::Navigation> WebPageProxy::loadData(API::Data* data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
903 {
904     if (m_isClosed)
905         return nullptr;
906
907     auto navigation = m_navigationState->createLoadDataNavigation();
908
909     auto transaction = m_pageLoadState.transaction();
910
911     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : blankURL().string());
912
913     if (!isValid())
914         reattachToWebProcess();
915
916     LoadParameters loadParameters;
917     loadParameters.navigationID = navigation->navigationID();
918     loadParameters.data = data->dataReference();
919     loadParameters.MIMEType = MIMEType;
920     loadParameters.encodingName = encoding;
921     loadParameters.baseURLString = baseURL;
922     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
923     addPlatformLoadParameters(loadParameters);
924
925     m_process->assumeReadAccessToBaseURL(baseURL);
926     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
927     m_process->responsivenessTimer().start();
928
929     return WTFMove(navigation);
930 }
931
932 // FIXME: Get rid of loadHTMLString and just use loadData instead.
933 RefPtr<API::Navigation> WebPageProxy::loadHTMLString(const String& htmlString, const String& baseURL, API::Object* userData)
934 {
935     if (m_isClosed)
936         return nullptr;
937
938     auto navigation = m_navigationState->createLoadDataNavigation();
939
940     auto transaction = m_pageLoadState.transaction();
941
942     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : blankURL().string());
943
944     if (!isValid())
945         reattachToWebProcess();
946
947     LoadParameters loadParameters;
948     loadParameters.navigationID = navigation->navigationID();
949     loadParameters.string = htmlString;
950     loadParameters.MIMEType = ASCIILiteral("text/html");
951     loadParameters.baseURLString = baseURL;
952     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
953     addPlatformLoadParameters(loadParameters);
954
955     m_process->assumeReadAccessToBaseURL(baseURL);
956     m_process->send(Messages::WebPage::LoadString(loadParameters), m_pageID);
957     m_process->responsivenessTimer().start();
958
959     return WTFMove(navigation);
960 }
961
962 void WebPageProxy::loadAlternateHTMLString(const String& htmlString, const WebCore::URL& baseURL, const WebCore::URL& unreachableURL, API::Object* userData)
963 {
964     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
965     // start a second alternative HTML load as this will prevent the page load state from being
966     // handled properly.
967     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad)
968         return;
969
970     if (!m_failingProvisionalLoadURL.isEmpty())
971         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
972
973     if (!isValid())
974         reattachToWebProcess();
975
976     auto transaction = m_pageLoadState.transaction();
977
978     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
979     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
980
981     if (m_mainFrame)
982         m_mainFrame->setUnreachableURL(unreachableURL);
983
984     LoadParameters loadParameters;
985     loadParameters.navigationID = 0;
986     loadParameters.string = htmlString;
987     loadParameters.baseURLString = baseURL;
988     loadParameters.unreachableURLString = unreachableURL;
989     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
990     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
991     addPlatformLoadParameters(loadParameters);
992
993     m_process->assumeReadAccessToBaseURL(baseURL);
994     m_process->assumeReadAccessToBaseURL(unreachableURL);
995     m_process->send(Messages::WebPage::LoadAlternateHTMLString(loadParameters), m_pageID);
996     m_process->responsivenessTimer().start();
997 }
998
999 void WebPageProxy::loadPlainTextString(const String& string, API::Object* userData)
1000 {
1001     if (m_isClosed)
1002         return;
1003
1004     if (!isValid())
1005         reattachToWebProcess();
1006
1007     auto transaction = m_pageLoadState.transaction();
1008     m_pageLoadState.setPendingAPIRequestURL(transaction, blankURL().string());
1009
1010     LoadParameters loadParameters;
1011     loadParameters.navigationID = 0;
1012     loadParameters.string = string;
1013     loadParameters.MIMEType = ASCIILiteral("text/plain");
1014     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1015     addPlatformLoadParameters(loadParameters);
1016
1017     m_process->send(Messages::WebPage::LoadString(loadParameters), m_pageID);
1018     m_process->responsivenessTimer().start();
1019 }
1020
1021 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1022 {
1023     if (m_isClosed)
1024         return;
1025
1026     if (!isValid())
1027         reattachToWebProcess();
1028
1029     auto transaction = m_pageLoadState.transaction();
1030     m_pageLoadState.setPendingAPIRequestURL(transaction, blankURL().string());
1031
1032     LoadParameters loadParameters;
1033     loadParameters.navigationID = 0;
1034     loadParameters.data = webArchiveData->dataReference();
1035     loadParameters.MIMEType = ASCIILiteral("application/x-webarchive");
1036     loadParameters.encodingName = ASCIILiteral("utf-16");
1037     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1038     addPlatformLoadParameters(loadParameters);
1039
1040     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1041     m_process->responsivenessTimer().start();
1042 }
1043
1044 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1045 {
1046     if (m_isClosed)
1047         return;
1048
1049     if (WebCore::protocolIsJavaScript(url))
1050         return;
1051
1052     if (!isValid())
1053         reattachToWebProcess();
1054
1055     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1056     m_process->responsivenessTimer().start();
1057 }
1058
1059 void WebPageProxy::stopLoading()
1060 {
1061     if (!isValid())
1062         return;
1063
1064     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1065     m_process->responsivenessTimer().start();
1066 }
1067
1068 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1069 {
1070     SandboxExtension::Handle sandboxExtensionHandle;
1071
1072     String url = m_pageLoadState.activeURL();
1073     if (url.isEmpty() && m_backForwardList->currentItem())
1074         url = m_backForwardList->currentItem()->url();
1075
1076     if (!url.isEmpty()) {
1077         auto transaction = m_pageLoadState.transaction();
1078         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1079
1080         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1081         bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
1082         if (createdExtension)
1083             m_process->willAcquireUniversalFileReadSandboxExtension();
1084     }
1085
1086     if (!isValid())
1087         return reattachToWebProcessForReload();
1088     
1089     auto navigation = m_navigationState->createReloadNavigation();
1090
1091     m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1092     m_process->responsivenessTimer().start();
1093
1094     return WTFMove(navigation);
1095 }
1096
1097 void WebPageProxy::recordAutomaticNavigationSnapshot()
1098 {
1099     if (m_suppressAutomaticNavigationSnapshotting)
1100         return;
1101
1102     if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1103         recordNavigationSnapshot(*item);
1104 }
1105
1106 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1107 {
1108     if (!m_shouldRecordNavigationSnapshots)
1109         return;
1110
1111 #if PLATFORM(COCOA)
1112     ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1113 #else
1114     UNUSED_PARAM(item);
1115 #endif
1116 }
1117
1118 RefPtr<API::Navigation> WebPageProxy::goForward()
1119 {
1120     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1121     if (!forwardItem)
1122         return nullptr;
1123
1124     auto transaction = m_pageLoadState.transaction();
1125
1126     m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
1127
1128     if (!isValid())
1129         return reattachToWebProcessWithItem(forwardItem);
1130
1131     RefPtr<API::Navigation> navigation;
1132     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*forwardItem))
1133         navigation = m_navigationState->createBackForwardNavigation();
1134
1135     m_process->send(Messages::WebPage::GoForward(navigation ? navigation->navigationID() : 0, forwardItem->itemID()), m_pageID);
1136     m_process->responsivenessTimer().start();
1137
1138     return navigation;
1139 }
1140
1141 RefPtr<API::Navigation> WebPageProxy::goBack()
1142 {
1143     WebBackForwardListItem* backItem = m_backForwardList->backItem();
1144     if (!backItem)
1145         return nullptr;
1146
1147     auto transaction = m_pageLoadState.transaction();
1148
1149     m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
1150
1151     if (!isValid())
1152         return reattachToWebProcessWithItem(backItem);
1153
1154     RefPtr<API::Navigation> navigation;
1155     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*backItem))
1156         navigation = m_navigationState->createBackForwardNavigation();
1157
1158     m_process->send(Messages::WebPage::GoBack(navigation ? navigation->navigationID() : 0, backItem->itemID()), m_pageID);
1159     m_process->responsivenessTimer().start();
1160
1161     return navigation;
1162 }
1163
1164 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
1165 {
1166     if (!isValid())
1167         return reattachToWebProcessWithItem(item);
1168
1169     auto transaction = m_pageLoadState.transaction();
1170
1171     m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
1172
1173     RefPtr<API::Navigation> navigation;
1174     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*item))
1175         navigation = m_navigationState->createBackForwardNavigation();
1176
1177     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item->itemID()), m_pageID);
1178     m_process->responsivenessTimer().start();
1179
1180     return navigation;
1181 }
1182
1183 void WebPageProxy::tryRestoreScrollPosition()
1184 {
1185     if (!isValid())
1186         return;
1187
1188     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1189 }
1190
1191 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<RefPtr<WebBackForwardListItem>> removed)
1192 {
1193     PageClientProtector protector(m_pageClient);
1194
1195     m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1196
1197     auto transaction = m_pageLoadState.transaction();
1198
1199     m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1200     m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1201 }
1202
1203 void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, const UserData& userData)
1204 {
1205     PageClientProtector protector(m_pageClient);
1206
1207     if (WebBackForwardListItem* item = m_process->webBackForwardItem(itemID))
1208         m_loaderClient->willGoToBackForwardListItem(*this, item, m_process->transformHandlesToObjects(userData.object()).get());
1209 }
1210
1211 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem* item)
1212 {
1213     PageClientProtector protector(m_pageClient);
1214
1215     return m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1216 }
1217
1218 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1219 {
1220     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1221         return true;
1222
1223 #if ENABLE(NETSCAPE_PLUGIN_API)
1224     String newMimeType = mimeType;
1225     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1226     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1227         return true;
1228 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1229
1230 #if PLATFORM(COCOA)
1231     // On Mac, we can show PDFs.
1232     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1233         return true;
1234 #endif // PLATFORM(COCOA)
1235
1236     return false;
1237 }
1238
1239 void WebPageProxy::setControlledByAutomation(bool controlled)
1240 {
1241     if (m_controlledByAutomation == controlled)
1242         return;
1243
1244     m_controlledByAutomation = controlled;
1245
1246     if (isValid())
1247         m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1248 }
1249
1250 #if ENABLE(REMOTE_INSPECTOR)
1251 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1252 {
1253     if (m_allowsRemoteInspection == allow)
1254         return;
1255
1256     m_allowsRemoteInspection = allow;
1257
1258     if (isValid())
1259         m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
1260 }
1261
1262 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1263 {
1264     if (m_remoteInspectionNameOverride == name)
1265         return;
1266
1267     m_remoteInspectionNameOverride = name;
1268
1269     if (isValid())
1270         m_process->send(Messages::WebPage::SetRemoteInspectionNameOverride(m_remoteInspectionNameOverride), m_pageID);
1271 }
1272
1273 #endif
1274
1275 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1276 {
1277     if (m_drawsBackground == drawsBackground)
1278         return;
1279
1280     m_drawsBackground = drawsBackground;
1281
1282     if (isValid())
1283         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1284 }
1285
1286 void WebPageProxy::setTopContentInset(float contentInset)
1287 {
1288     if (m_topContentInset == contentInset)
1289         return;
1290
1291     m_topContentInset = contentInset;
1292
1293     if (!isValid())
1294         return;
1295 #if PLATFORM(COCOA)
1296     MachSendRight fence = m_drawingArea->createFence();
1297
1298     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1299     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1300 #else
1301     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1302 #endif
1303 }
1304
1305 void WebPageProxy::setUnderlayColor(const Color& color)
1306 {
1307     if (m_underlayColor == color)
1308         return;
1309
1310     m_underlayColor = color;
1311
1312     if (isValid())
1313         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1314 }
1315
1316 void WebPageProxy::viewWillStartLiveResize()
1317 {
1318     if (!isValid())
1319         return;
1320 #if ENABLE(INPUT_TYPE_COLOR_POPOVER) && ENABLE(INPUT_TYPE_COLOR)
1321     if (m_colorPicker)
1322         endColorPicker();
1323 #endif
1324     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1325 }
1326
1327 void WebPageProxy::viewWillEndLiveResize()
1328 {
1329     if (!isValid())
1330         return;
1331     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1332 }
1333
1334 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1335 {
1336     m_pageClient.setViewNeedsDisplay(region);
1337 }
1338
1339 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1340 {
1341     m_pageClient.requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1342 }
1343
1344 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1345 {
1346     return m_pageClient.viewScrollPosition();
1347 }
1348
1349 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1350 {
1351     if (m_suppressVisibilityUpdates == flag)
1352         return;
1353     m_suppressVisibilityUpdates = flag;
1354
1355     if (!m_suppressVisibilityUpdates) {
1356 #if PLATFORM(COCOA)
1357         m_activityStateChangeDispatcher->schedule();
1358 #else
1359         dispatchActivityStateChange();
1360 #endif
1361     }
1362 }
1363
1364 void WebPageProxy::updateActivityState(ActivityState::Flags flagsToUpdate)
1365 {
1366     m_activityState &= ~flagsToUpdate;
1367     if (flagsToUpdate & ActivityState::IsFocused && m_pageClient.isViewFocused())
1368         m_activityState |= ActivityState::IsFocused;
1369     if (flagsToUpdate & ActivityState::WindowIsActive && m_pageClient.isViewWindowActive())
1370         m_activityState |= ActivityState::WindowIsActive;
1371     if (flagsToUpdate & ActivityState::IsVisible && m_pageClient.isViewVisible())
1372         m_activityState |= ActivityState::IsVisible;
1373     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && m_pageClient.isViewVisibleOrOccluded())
1374         m_activityState |= ActivityState::IsVisibleOrOccluded;
1375     if (flagsToUpdate & ActivityState::IsInWindow && m_pageClient.isViewInWindow())
1376         m_activityState |= ActivityState::IsInWindow;
1377     if (flagsToUpdate & ActivityState::IsVisuallyIdle && m_pageClient.isVisuallyIdle())
1378         m_activityState |= ActivityState::IsVisuallyIdle;
1379     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1380         m_activityState |= ActivityState::IsAudible;
1381     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1382         m_activityState |= ActivityState::IsLoading;
1383     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1384         m_activityState |= ActivityState::IsCapturingMedia;
1385 }
1386
1387 void WebPageProxy::activityStateDidChange(ActivityState::Flags mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1388 {
1389     m_potentiallyChangedActivityStateFlags |= mayHaveChanged;
1390     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1391
1392     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1393         return;
1394
1395 #if PLATFORM(COCOA)
1396     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && m_pageClient.isViewInWindow();
1397     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1398         dispatchActivityStateChange();
1399         return;
1400     }
1401     m_activityStateChangeDispatcher->schedule();
1402 #else
1403     UNUSED_PARAM(dispatchMode);
1404     dispatchActivityStateChange();
1405 #endif
1406 }
1407
1408 void WebPageProxy::viewDidLeaveWindow()
1409 {
1410 #if ENABLE(INPUT_TYPE_COLOR_POPOVER) && ENABLE(INPUT_TYPE_COLOR)
1411     // When leaving the current page, close the popover color well.
1412     if (m_colorPicker)
1413         endColorPicker();
1414 #endif
1415 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1416     // When leaving the current page, close the video fullscreen.
1417     if (m_videoFullscreenManager)
1418         m_videoFullscreenManager->requestHideAndExitFullscreen();
1419 #endif
1420 }
1421
1422 void WebPageProxy::viewDidEnterWindow()
1423 {
1424     LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1425     if (m_layerHostingMode != layerHostingMode) {
1426         m_layerHostingMode = layerHostingMode;
1427         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1428     }
1429 }
1430
1431 void WebPageProxy::dispatchActivityStateChange()
1432 {
1433 #if PLATFORM(COCOA)
1434     m_activityStateChangeDispatcher->invalidate();
1435 #endif
1436
1437     if (!isValid())
1438         return;
1439
1440     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1441     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1442         m_potentiallyChangedActivityStateFlags |= ActivityState::IsVisibleOrOccluded | ActivityState::IsVisuallyIdle;
1443
1444     // Record the prior view state, update the flags that may have changed,
1445     // and check which flags have actually changed.
1446     ActivityState::Flags previousActivityState = m_activityState;
1447     updateActivityState(m_potentiallyChangedActivityStateFlags);
1448     ActivityState::Flags changed = m_activityState ^ previousActivityState;
1449
1450     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1451         viewIsBecomingVisible();
1452
1453     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1454     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1455     if (m_viewWasEverInWindow && isNowInWindow) {
1456         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1457             m_activityStateChangeWantsSynchronousReply = true;
1458         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1459     }
1460
1461     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1462     if (!(m_activityState & ActivityState::IsVisible))
1463         m_activityStateChangeWantsSynchronousReply = false;
1464
1465     if (changed || m_activityStateChangeWantsSynchronousReply || !m_nextActivityStateChangeCallbacks.isEmpty())
1466         m_process->send(Messages::WebPage::SetActivityState(m_activityState, m_activityStateChangeWantsSynchronousReply, m_nextActivityStateChangeCallbacks), m_pageID);
1467
1468     m_nextActivityStateChangeCallbacks.clear();
1469
1470     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1471     updateThrottleState();
1472
1473 #if ENABLE(POINTER_LOCK)
1474     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !m_pageClient.isViewWindowActive())
1475         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1476         requestPointerUnlock();
1477 #endif
1478
1479     if (changed & ActivityState::IsVisible) {
1480         if (isViewVisible())
1481             m_visiblePageToken = m_process->visiblePageToken();
1482         else {
1483             m_visiblePageToken = nullptr;
1484
1485             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1486             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1487             // stop the unresponsiveness timer here.
1488             m_process->responsivenessTimer().stop();
1489         }
1490     }
1491
1492     if (changed & ActivityState::IsInWindow) {
1493         if (isInWindow())
1494             viewDidEnterWindow();
1495         else
1496             viewDidLeaveWindow();
1497     }
1498
1499     updateBackingStoreDiscardableState();
1500
1501     if (m_activityStateChangeWantsSynchronousReply)
1502         waitForDidUpdateActivityState();
1503
1504     m_potentiallyChangedActivityStateFlags = ActivityState::NoFlags;
1505     m_activityStateChangeWantsSynchronousReply = false;
1506     m_viewWasEverInWindow |= isNowInWindow;
1507 }
1508
1509 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1510 {
1511     return sessionID().isAlwaysOnLoggingAllowed();
1512 }
1513
1514 void WebPageProxy::updateThrottleState()
1515 {
1516     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1517
1518     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1519     if (!processSuppressionEnabled)
1520         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1521     else if (!m_preventProcessSuppressionCount)
1522         m_preventProcessSuppressionCount = nullptr;
1523
1524     if (m_activityState & ActivityState::IsVisuallyIdle)
1525         m_pageIsUserObservableCount = nullptr;
1526     else if (!m_pageIsUserObservableCount)
1527         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1528
1529 #if PLATFORM(IOS)
1530     bool isCapturingMedia = m_activityState & ActivityState::IsCapturingMedia;
1531     bool isAudible = m_activityState & ActivityState::IsAudible;
1532     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1533         if (m_activityToken) {
1534             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1535             m_activityToken = nullptr;
1536         }
1537     } else if (!m_activityToken) {
1538         if (isViewVisible())
1539             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1540         else if (isAudible)
1541             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1542         else if (isCapturingMedia)
1543             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1544         else
1545             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);
1546         m_activityToken = m_process->throttler().foregroundActivityToken();
1547     }
1548 #endif
1549 }
1550
1551 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1552 {
1553     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1554         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1555     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1556         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1557 }
1558
1559 void WebPageProxy::layerHostingModeDidChange()
1560 {
1561     if (!isValid())
1562         return;
1563
1564     LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1565     if (m_layerHostingMode == layerHostingMode)
1566         return;
1567
1568     m_layerHostingMode = layerHostingMode;
1569     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1570 }
1571
1572 void WebPageProxy::waitForDidUpdateActivityState()
1573 {
1574     if (!isValid())
1575         return;
1576
1577     if (m_process->state() != WebProcessProxy::State::Running)
1578         return;
1579
1580     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1581     if (m_waitingForDidUpdateActivityState)
1582         return;
1583
1584 #if PLATFORM(IOS)
1585     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1586     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1587     if (!m_activityToken) {
1588         ASSERT_NOT_REACHED();
1589         return;
1590     }
1591 #endif
1592
1593     m_waitingForDidUpdateActivityState = true;
1594
1595     m_drawingArea->waitForDidUpdateActivityState();
1596 }
1597
1598 IntSize WebPageProxy::viewSize() const
1599 {
1600     return m_pageClient.viewSize();
1601 }
1602
1603 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1604 {
1605     if (!isValid()) {
1606         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1607         return;
1608     }
1609
1610     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1611     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1612 }
1613
1614 void WebPageProxy::clearSelection()
1615 {
1616     if (!isValid())
1617         return;
1618     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1619 }
1620
1621 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1622 {
1623     if (!isValid())
1624         return;
1625     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1626 }
1627
1628 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1629 {
1630     if (!isValid()) {
1631         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1632         return;
1633     }
1634
1635     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1636     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1637 }
1638
1639 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1640 {
1641     m_maintainsInactiveSelection = newValue;
1642 }
1643
1644 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1645 {
1646     if (!isValid()) {
1647         callbackFunction(CallbackBase::Error::Unknown);
1648         return;
1649     }
1650
1651     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1652     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1653 }
1654     
1655 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1656 {
1657     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1658
1659     if (!isValid())
1660         return;
1661
1662     if (commandName == ignoreSpellingCommandName)
1663         ++m_pendingLearnOrIgnoreWordMessageCount;
1664
1665     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1666 }
1667
1668 void WebPageProxy::setEditable(bool editable)
1669 {
1670     if (editable == m_isEditable)
1671         return;
1672     if (!isValid())
1673         return;
1674
1675     m_isEditable = editable;
1676     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1677 }
1678     
1679 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1680 {
1681     if (muted)
1682         setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1683     else
1684         setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1685 }
1686
1687 void WebPageProxy::activateMediaStreamCaptureInPage()
1688 {
1689 #if ENABLE(MEDIA_STREAM)
1690     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1691 #endif
1692     setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1693 }
1694
1695 #if !PLATFORM(IOS)
1696 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1697 {
1698 }
1699
1700 void WebPageProxy::layerTreeCommitComplete()
1701 {
1702 }
1703 #endif
1704
1705 #if ENABLE(DRAG_SUPPORT)
1706 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1707 {
1708     SandboxExtension::Handle sandboxExtensionHandle;
1709     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1710     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1711 }
1712
1713 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1714 {
1715     SandboxExtension::Handle sandboxExtensionHandle;
1716     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1717     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1718 }
1719
1720 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1721 {
1722     SandboxExtension::Handle sandboxExtensionHandle;
1723     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1724     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1725 }
1726
1727 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1728 {
1729     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload);
1730 }
1731
1732 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1733 {
1734     if (!isValid())
1735         return;
1736 #if PLATFORM(GTK)
1737     UNUSED_PARAM(dragStorageName);
1738     UNUSED_PARAM(sandboxExtensionHandle);
1739     UNUSED_PARAM(sandboxExtensionsForUpload);
1740
1741     String url = dragData.asURL();
1742     if (!url.isEmpty())
1743         m_process->assumeReadAccessToBaseURL(url);
1744
1745     ASSERT(dragData.platformData());
1746     WebSelectionData selection(*dragData.platformData());
1747     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
1748 #else
1749     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1750 #endif
1751 }
1752
1753 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
1754 {
1755     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1756
1757     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1758     m_currentDragIsOverFileInput = mouseIsOverFileInput;
1759     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1760     setDragCaretRect(insertionRect);
1761 }
1762
1763 #if PLATFORM(GTK)
1764 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
1765 {
1766     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
1767     m_pageClient.startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
1768
1769     didStartDrag();
1770 }
1771 #endif
1772
1773 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1774 {
1775     if (!isValid())
1776         return;
1777     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1778     setDragCaretRect({ });
1779 }
1780
1781 void WebPageProxy::didStartDrag()
1782 {
1783     if (isValid())
1784         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
1785 }
1786     
1787 void WebPageProxy::dragCancelled()
1788 {
1789     if (isValid())
1790         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
1791 }
1792
1793 void WebPageProxy::didEndDragging()
1794 {
1795     resetCurrentDragInformation();
1796 }
1797
1798 void WebPageProxy::resetCurrentDragInformation()
1799 {
1800     m_currentDragOperation = WebCore::DragOperationNone;
1801     m_currentDragIsOverFileInput = false;
1802     m_currentDragNumberOfFilesToBeAccepted = 0;
1803     setDragCaretRect({ });
1804 }
1805
1806 #if !ENABLE(DATA_INTERACTION)
1807
1808 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
1809 {
1810     m_currentDragCaretRect = dragCaretRect;
1811 }
1812
1813 #endif
1814
1815 #endif // ENABLE(DRAG_SUPPORT)
1816
1817 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1818 {
1819     if (!isValid())
1820         return;
1821
1822     if (m_pageClient.windowIsFrontWindowUnderMouse(event))
1823         setToolTip(String());
1824
1825     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1826     if (event.type() != WebEvent::MouseMove)
1827         m_process->responsivenessTimer().start();
1828     else {
1829         if (m_processingMouseMoveEvent) {
1830             m_nextMouseMoveEvent = std::make_unique<NativeWebMouseEvent>(event);
1831             return;
1832         }
1833
1834         m_processingMouseMoveEvent = true;
1835     }
1836
1837     // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1838     // display a popup menu for select elements. When the user changes the selected item,
1839     // we fake a mouse up event by using this stored down event. This event gets cleared
1840     // when the mouse up message is received from WebProcess.
1841     if (event.type() == WebEvent::MouseDown)
1842         m_currentlyProcessedMouseDownEvent = std::make_unique<NativeWebMouseEvent>(event);
1843
1844     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1845 }
1846
1847 #if MERGE_WHEEL_EVENTS
1848 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1849 {
1850     if (a.position() != b.position())
1851         return false;
1852     if (a.globalPosition() != b.globalPosition())
1853         return false;
1854     if (a.modifiers() != b.modifiers())
1855         return false;
1856     if (a.granularity() != b.granularity())
1857         return false;
1858 #if PLATFORM(COCOA)
1859     if (a.phase() != b.phase())
1860         return false;
1861     if (a.momentumPhase() != b.momentumPhase())
1862         return false;
1863     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1864         return false;
1865 #endif
1866
1867     return true;
1868 }
1869
1870 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1871 {
1872     ASSERT(canCoalesce(a, b));
1873
1874     FloatSize mergedDelta = a.delta() + b.delta();
1875     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1876
1877 #if PLATFORM(COCOA)
1878     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1879
1880     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());
1881 #else
1882     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1883 #endif
1884 }
1885 #endif // MERGE_WHEEL_EVENTS
1886
1887 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1888 {
1889     ASSERT(!queue.isEmpty());
1890     ASSERT(coalescedEvents.isEmpty());
1891
1892 #if MERGE_WHEEL_EVENTS
1893     NativeWebWheelEvent firstEvent = queue.takeFirst();
1894     coalescedEvents.append(firstEvent);
1895
1896     WebWheelEvent event = firstEvent;
1897     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1898         NativeWebWheelEvent firstEvent = queue.takeFirst();
1899         coalescedEvents.append(firstEvent);
1900         event = coalesce(event, firstEvent);
1901     }
1902
1903     return event;
1904 #else
1905     while (!queue.isEmpty())
1906         coalescedEvents.append(queue.takeFirst());
1907     return coalescedEvents.last();
1908 #endif
1909 }
1910
1911 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1912 {
1913 #if ENABLE(ASYNC_SCROLLING)
1914     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
1915         return;
1916 #endif
1917
1918     if (!isValid())
1919         return;
1920
1921     hideValidationMessage();
1922
1923     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1924         m_wheelEventQueue.append(event);
1925         if (!shouldProcessWheelEventNow(event))
1926             return;
1927         // The queue has too many wheel events, so push a new event.
1928     }
1929
1930     if (!m_wheelEventQueue.isEmpty()) {
1931         processNextQueuedWheelEvent();
1932         return;
1933     }
1934
1935     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1936     coalescedWheelEvent->append(event);
1937     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
1938     sendWheelEvent(event);
1939 }
1940
1941 void WebPageProxy::processNextQueuedWheelEvent()
1942 {
1943     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1944     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1945     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
1946     sendWheelEvent(nextWheelEvent);
1947 }
1948
1949 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1950 {
1951     m_process->send(
1952         Messages::EventDispatcher::WheelEvent(
1953             m_pageID,
1954             event,
1955             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
1956             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
1957             rubberBandsAtTop(),
1958             rubberBandsAtBottom()
1959         ), 0);
1960
1961     // Manually ping the web process to check for responsiveness since our wheel
1962     // event will dispatch to a non-main thread, which always responds.
1963     m_process->isResponsive(nullptr);
1964 }
1965
1966 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
1967 {
1968 #if PLATFORM(GTK)
1969     // Don't queue events representing a non-trivial scrolling phase to
1970     // avoid having them trapped in the queue, potentially preventing a
1971     // scrolling session to beginning or end correctly.
1972     // This is only needed by platforms whose WebWheelEvent has this phase
1973     // information (Cocoa and GTK+) but Cocoa was fine without it.
1974     if (event.phase() == WebWheelEvent::Phase::PhaseNone
1975         || event.phase() == WebWheelEvent::Phase::PhaseChanged
1976         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
1977         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
1978         return true;
1979 #else
1980     UNUSED_PARAM(event);
1981 #endif
1982     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
1983         return true;
1984     return false;
1985 }
1986
1987 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
1988 {
1989     if (!isValid())
1990         return;
1991     
1992     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
1993
1994     m_keyEventQueue.append(event);
1995
1996     m_process->responsivenessTimer().start();
1997     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
1998         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
1999         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2000     }
2001 }
2002
2003 WebPreferencesStore WebPageProxy::preferencesStore() const
2004 {
2005     if (m_configurationPreferenceValues.isEmpty())
2006         return m_preferences->store();
2007
2008     WebPreferencesStore store = m_preferences->store();
2009     for (const auto& preference : m_configurationPreferenceValues)
2010         store.m_values.set(preference.key, preference.value);
2011
2012     return store;
2013 }
2014
2015 #if ENABLE(NETSCAPE_PLUGIN_API)
2016 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)
2017 {
2018     PageClientProtector protector(m_pageClient);
2019
2020     MESSAGE_CHECK_URL(urlString);
2021
2022     newMimeType = mimeType.convertToASCIILowercase();
2023     pluginLoadPolicy = PluginModuleLoadNormally;
2024
2025     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2026     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), urlString), allowedPluginTypes);
2027     if (!plugin.path) {
2028         pluginProcessToken = 0;
2029         return;
2030     }
2031
2032     pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2033
2034 #if PLATFORM(COCOA)
2035     RefPtr<API::Dictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2036     if (m_navigationClient)
2037         pluginLoadPolicy = m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
2038     else
2039         pluginLoadPolicy = m_loaderClient->pluginLoadPolicy(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
2040 #else
2041     UNUSED_PARAM(frameURLString);
2042     UNUSED_PARAM(pageURLString);
2043     UNUSED_PARAM(unavailabilityDescription);
2044 #endif
2045
2046     PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2047     switch (pluginLoadPolicy) {
2048     case PluginModuleLoadNormally:
2049         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2050         break;
2051     case PluginModuleLoadUnsandboxed:
2052         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2053         break;
2054
2055     case PluginModuleBlockedForSecurity:
2056     case PluginModuleBlockedForCompatibility:
2057         pluginProcessToken = 0;
2058         return;
2059     }
2060
2061     pluginProcessToken = PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
2062 }
2063
2064 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2065
2066 #if ENABLE(TOUCH_EVENTS)
2067
2068 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2069 {
2070     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2071         return b;
2072     return a;
2073 }
2074
2075 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2076 {
2077 #if ENABLE(ASYNC_SCROLLING)
2078     const EventNames& names = eventNames();
2079     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2080         IntPoint location = touchPoint.location();
2081         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2082             if (trackingType == TrackingType::Synchronous)
2083                 return;
2084
2085             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2086
2087             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2088         };
2089         updateTrackingType(m_touchEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2090         updateTrackingType(m_touchEventTracking.touchStartTracking, names.touchstartEvent);
2091         updateTrackingType(m_touchEventTracking.touchMoveTracking, names.touchmoveEvent);
2092         updateTrackingType(m_touchEventTracking.touchEndTracking, names.touchendEvent);
2093     }
2094 #else
2095     UNUSED_PARAM(touchStartEvent);
2096     m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2097     m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
2098     m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
2099     m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
2100 #endif // ENABLE(ASYNC_SCROLLING)
2101 }
2102
2103 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2104 {
2105     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2106     //
2107     // Touch events define a sequence with strong dependencies. For example, we can expect
2108     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2109     // the two.
2110     //
2111     // WebCore should not have to set up its state correctly after some events were dismissed.
2112     // For example, we don't want to send a TouchMoved without a TouchPressed.
2113     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2114     TrackingType globalTrackingType = m_touchEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2115
2116     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchForceChangedTracking);
2117     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2118         switch (touchPoint.state()) {
2119         case WebPlatformTouchPoint::TouchReleased:
2120             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchEndTracking);
2121             break;
2122         case WebPlatformTouchPoint::TouchPressed:
2123             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchStartTracking);
2124             break;
2125         case WebPlatformTouchPoint::TouchMoved:
2126         case WebPlatformTouchPoint::TouchStationary:
2127             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchMoveTracking);
2128             break;
2129         case WebPlatformTouchPoint::TouchCancelled:
2130             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2131             break;
2132         }
2133     }
2134
2135     return globalTrackingType;
2136 }
2137
2138 #endif
2139
2140 #if ENABLE(MAC_GESTURE_EVENTS)
2141 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2142 {
2143     if (!isValid())
2144         return;
2145
2146     m_gestureEventQueue.append(event);
2147     // FIXME: Consider doing some coalescing here.
2148     m_process->responsivenessTimer().start();
2149
2150     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2151 }
2152 #endif
2153
2154 #if ENABLE(IOS_TOUCH_EVENTS)
2155 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2156 {
2157     if (!isValid())
2158         return;
2159
2160     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2161
2162     if (event.type() == WebEvent::TouchStart)
2163         updateTouchEventTracking(event);
2164
2165     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2166     if (touchEventsTrackingType == TrackingType::NotTracking)
2167         return;
2168
2169     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2170         // We can end up here if a native gesture has not started but the event handlers are passive.
2171         //
2172         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2173         // can prevent a native gesture.
2174         // But, here we know that all events handlers that can handle this events are passive.
2175         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2176         event.setCanPreventNativeGestures(false);
2177         handleTouchEventAsynchronously(event);
2178         didReceiveEvent(event.type(), false);
2179         return;
2180     }
2181
2182     m_process->responsivenessTimer().start();
2183     bool handled = false;
2184     m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
2185     didReceiveEvent(event.type(), handled);
2186     m_pageClient.doneWithTouchEvent(event, handled);
2187     m_process->responsivenessTimer().stop();
2188
2189     if (event.allTouchPointsAreReleased())
2190         m_touchEventTracking.reset();
2191 }
2192
2193 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2194 {
2195     if (!isValid())
2196         return;
2197
2198     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2199     if (touchEventsTrackingType == TrackingType::NotTracking)
2200         return;
2201
2202     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2203
2204     if (event.allTouchPointsAreReleased())
2205         m_touchEventTracking.reset();
2206 }
2207
2208 #elif ENABLE(TOUCH_EVENTS)
2209 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2210 {
2211     if (!isValid())
2212         return;
2213
2214     if (event.type() == WebEvent::TouchStart)
2215         updateTouchEventTracking(event);
2216
2217     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2218         return;
2219
2220     // If the page is suspended, which should be the case during panning, pinching
2221     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2222     // we do not send any of the events to the page even if is has listeners.
2223     if (!m_isPageSuspended) {
2224         m_touchEventQueue.append(event);
2225         m_process->responsivenessTimer().start();
2226         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2227     } else {
2228         if (m_touchEventQueue.isEmpty()) {
2229             bool isEventHandled = false;
2230             m_pageClient.doneWithTouchEvent(event, isEventHandled);
2231         } else {
2232             // We attach the incoming events to the newest queued event so that all
2233             // the events are delivered in the correct order when the event is dequed.
2234             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2235             lastEvent.deferredTouchEvents.append(event);
2236         }
2237     }
2238
2239     if (event.allTouchPointsAreReleased())
2240         m_touchEventTracking.reset();
2241 }
2242 #endif // ENABLE(TOUCH_EVENTS)
2243
2244 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2245 {
2246     if (!isValid())
2247         return;
2248
2249     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2250 }
2251
2252 void WebPageProxy::centerSelectionInVisibleArea()
2253 {
2254     if (!isValid())
2255         return;
2256
2257     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2258 }
2259
2260 void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& frame, uint64_t listenerID, API::Navigation* navigation, const WebsitePolicies& websitePolicies)
2261 {
2262     if (!isValid())
2263         return;
2264
2265     auto transaction = m_pageLoadState.transaction();
2266
2267     if (action == PolicyIgnore)
2268         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2269
2270 #if ENABLE(DOWNLOAD_ATTRIBUTE)
2271     if (m_syncNavigationActionHasDownloadAttribute && action == PolicyUse)
2272         action = PolicyDownload;
2273 #endif
2274
2275     DownloadID downloadID = { };
2276     if (action == PolicyDownload) {
2277         // Create a download proxy.
2278         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2279         download->setRedirectChain(frame.takeProvisionalLoadRedirectChain());
2280
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     return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
2565 }
2566
2567 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2568 {
2569     if (!isValid())
2570         return;
2571
2572     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2573     // https://bugs.webkit.org/show_bug.cgi?id=133378
2574 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2575     return;
2576 #endif
2577
2578     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
2579         return;
2580
2581     float oldScaleFactor = deviceScaleFactor();
2582
2583     // A value of 0 clears the customScaleFactor.
2584     if (customScaleFactor)
2585         m_customDeviceScaleFactor = customScaleFactor;
2586     else
2587         m_customDeviceScaleFactor = std::nullopt;
2588
2589     if (deviceScaleFactor() != oldScaleFactor)
2590         m_drawingArea->deviceScaleFactorDidChange();
2591 }
2592
2593 void WebPageProxy::accessibilitySettingsDidChange()
2594 {
2595     if (!isValid())
2596         return;
2597
2598     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
2599 }
2600
2601 void WebPageProxy::setUseFixedLayout(bool fixed)
2602 {
2603     if (!isValid())
2604         return;
2605
2606     // This check is fine as the value is initialized in the web
2607     // process as part of the creation parameters.
2608     if (fixed == m_useFixedLayout)
2609         return;
2610
2611     m_useFixedLayout = fixed;
2612     if (!fixed)
2613         m_fixedLayoutSize = IntSize();
2614     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2615 }
2616
2617 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2618 {
2619     if (!isValid())
2620         return;
2621
2622     if (size == m_fixedLayoutSize)
2623         return;
2624
2625     m_fixedLayoutSize = size;
2626     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2627 }
2628
2629 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2630 {
2631     if (!isValid())
2632         return;
2633     
2634     if (milestones == m_observedLayoutMilestones)
2635         return;
2636
2637     m_observedLayoutMilestones = milestones;
2638     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2639 }
2640
2641 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
2642 {
2643     if (!isValid())
2644         return;
2645
2646     if (suppressAnimations == m_suppressScrollbarAnimations)
2647         return;
2648
2649     m_suppressScrollbarAnimations = suppressAnimations;
2650     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
2651 }
2652
2653 bool WebPageProxy::rubberBandsAtLeft() const
2654 {
2655     return m_rubberBandsAtLeft;
2656 }
2657
2658 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
2659 {
2660     m_rubberBandsAtLeft = rubberBandsAtLeft;
2661 }
2662
2663 bool WebPageProxy::rubberBandsAtRight() const
2664 {
2665     return m_rubberBandsAtRight;
2666 }
2667
2668 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
2669 {
2670     m_rubberBandsAtRight = rubberBandsAtRight;
2671 }
2672
2673 bool WebPageProxy::rubberBandsAtTop() const
2674 {
2675     return m_rubberBandsAtTop;
2676 }
2677
2678 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
2679 {
2680     m_rubberBandsAtTop = rubberBandsAtTop;
2681 }
2682
2683 bool WebPageProxy::rubberBandsAtBottom() const
2684 {
2685     return m_rubberBandsAtBottom;
2686 }
2687
2688 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
2689 {
2690     m_rubberBandsAtBottom = rubberBandsAtBottom;
2691 }
2692     
2693 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2694 {
2695     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
2696         return;
2697
2698     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
2699
2700     if (!isValid())
2701         return;
2702     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
2703 }
2704     
2705 bool WebPageProxy::verticalRubberBandingIsEnabled() const
2706 {
2707     return m_enableVerticalRubberBanding;
2708 }
2709     
2710 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2711 {
2712     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
2713         return;
2714
2715     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
2716
2717     if (!isValid())
2718         return;
2719     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
2720 }
2721     
2722 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
2723 {
2724     return m_enableHorizontalRubberBanding;
2725 }
2726
2727 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2728 {
2729     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
2730         return;
2731
2732     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
2733
2734     if (!isValid())
2735         return;
2736     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
2737 }
2738
2739 bool WebPageProxy::backgroundExtendsBeyondPage() const
2740 {
2741     return m_backgroundExtendsBeyondPage;
2742 }
2743
2744 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
2745 {
2746     if (mode == m_paginationMode)
2747         return;
2748
2749     m_paginationMode = mode;
2750
2751     if (!isValid())
2752         return;
2753     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
2754 }
2755
2756 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
2757 {
2758     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
2759         return;
2760
2761     m_paginationBehavesLikeColumns = behavesLikeColumns;
2762
2763     if (!isValid())
2764         return;
2765     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
2766 }
2767
2768 void WebPageProxy::setPageLength(double pageLength)
2769 {
2770     if (pageLength == m_pageLength)
2771         return;
2772
2773     m_pageLength = pageLength;
2774
2775     if (!isValid())
2776         return;
2777     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
2778 }
2779
2780 void WebPageProxy::setGapBetweenPages(double gap)
2781 {
2782     if (gap == m_gapBetweenPages)
2783         return;
2784
2785     m_gapBetweenPages = gap;
2786
2787     if (!isValid())
2788         return;
2789     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
2790 }
2791
2792 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
2793 {
2794     if (lineGridEnabled == m_paginationLineGridEnabled)
2795         return;
2796     
2797     m_paginationLineGridEnabled = lineGridEnabled;
2798     
2799     if (!isValid())
2800         return;
2801     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
2802 }
2803
2804 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
2805 {
2806     m_pageScaleFactor = scaleFactor;
2807 }
2808
2809 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
2810 {
2811     m_pluginScaleFactor = pluginScaleFactor;
2812 }
2813
2814 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
2815 {
2816     m_pluginZoomFactor = pluginZoomFactor;
2817 }
2818
2819 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2820 {
2821     if (string.isEmpty()) {
2822         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
2823         return;
2824     }
2825
2826     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
2827 }
2828
2829 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
2830 {
2831     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
2832 }
2833
2834 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
2835 {
2836     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
2837 }
2838
2839 void WebPageProxy::selectFindMatch(int32_t matchIndex)
2840 {
2841     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
2842 }
2843
2844 void WebPageProxy::hideFindUI()
2845 {
2846     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
2847 }
2848
2849 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2850 {
2851     if (!isValid())
2852         return;
2853
2854     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
2855 }
2856
2857 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
2858 {
2859     if (!isValid()) {
2860         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
2861         return;
2862     }
2863
2864     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2865     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
2866 }
2867
2868 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2869 {
2870     if (!isValid()) {
2871         callbackFunction(String(), CallbackBase::Error::Unknown);
2872         return;
2873     }
2874     
2875     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2876     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
2877 }
2878
2879 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2880 {
2881     if (!isValid()) {
2882         callbackFunction(String(), CallbackBase::Error::Unknown);
2883         return;
2884     }
2885     
2886     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2887     m_loadDependentStringCallbackIDs.add(callbackID);
2888     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
2889 }
2890
2891 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2892 {
2893     if (!isValid()) {
2894         callbackFunction(String(), CallbackBase::Error::Unknown);
2895         return;
2896     }
2897     
2898     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2899     m_loadDependentStringCallbackIDs.add(callbackID);
2900     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2901 }
2902
2903 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2904 {
2905     if (!isValid()) {
2906         callbackFunction(String(), CallbackBase::Error::Unknown);
2907         return;
2908     }
2909     
2910     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2911     m_loadDependentStringCallbackIDs.add(callbackID);
2912     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
2913 }
2914
2915 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2916 {
2917     if (!isValid()) {
2918         callbackFunction(String(), CallbackBase::Error::Unknown);
2919         return;
2920     }
2921     
2922     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2923     m_loadDependentStringCallbackIDs.add(callbackID);
2924     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
2925 }
2926
2927 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
2928 {
2929     if (!isValid()) {
2930         RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
2931             bool isWebProcessResponsive = true;
2932             callbackFunction(isWebProcessResponsive);
2933         });
2934         return;
2935     }
2936
2937     m_process->isResponsive(WTFMove(callbackFunction));
2938 }
2939
2940 #if ENABLE(MHTML)
2941 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2942 {
2943     if (!isValid()) {
2944         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2945         return;
2946     }
2947
2948     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2949     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
2950 }
2951 #endif
2952
2953 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2954 {
2955     if (!isValid()) {
2956         callbackFunction(String(), CallbackBase::Error::Unknown);
2957         return;
2958     }
2959     
2960     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2961     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
2962 }
2963
2964 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2965 {
2966     if (!isValid()) {
2967         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2968         return;
2969     }
2970     
2971     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2972     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
2973 }
2974
2975 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2976 {
2977     if (!isValid() || !frame) {
2978         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2979         return;
2980     }
2981     
2982     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2983     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
2984 }
2985
2986 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2987 {
2988     if (!isValid()) {
2989         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2990         return;
2991     }
2992     
2993     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2994     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
2995 }
2996
2997 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2998 {
2999     if (!isValid()) {
3000         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3001         return;
3002     }
3003     
3004     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3005     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3006 }
3007
3008 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3009 {
3010     if (!isValid()) {
3011         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3012         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3013         return;
3014     }
3015
3016     Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3017         if (error != CallbackBase::Error::None) {
3018             callback->invalidate(error);
3019             return;
3020         }
3021
3022         if (!isValid()) {
3023             callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3024             return;
3025         }
3026     
3027         callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3028             if (error != CallbackBase::Error::None) {
3029                 callback->invalidate(error);
3030                 return;
3031             }
3032
3033             callback->performCallback();
3034         });
3035     };
3036
3037     auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3038     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3039     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
3040 }
3041
3042 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3043 {
3044     if (isPerformingDOMPrintOperation)
3045         return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3046
3047     return { };
3048 }
3049
3050 void WebPageProxy::preferencesDidChange()
3051 {
3052     if (!isValid())
3053         return;
3054
3055     updateThrottleState();
3056     updateHiddenPageThrottlingAutoIncreases();
3057
3058     m_pageClient.preferencesDidChange();
3059
3060     // FIXME: It probably makes more sense to send individual preference changes.
3061     // However, WebKitTestRunner depends on getting a preference change notification
3062     // even if nothing changed in UI process, so that overrides get removed.
3063
3064     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3065     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3066 }
3067
3068 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3069 {
3070     PageClientProtector protector(m_pageClient);
3071
3072     MESSAGE_CHECK(!m_mainFrame);
3073     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3074
3075     m_mainFrame = WebFrameProxy::create(this, frameID);
3076
3077     // Add the frame to the process wide map.
3078     m_process->frameCreated(frameID, m_mainFrame.get());
3079 }
3080
3081 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3082 {
3083     PageClientProtector protector(m_pageClient);
3084
3085     MESSAGE_CHECK(m_mainFrame);
3086     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3087     
3088     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
3089
3090     // Add the frame to the process wide map.
3091     m_process->frameCreated(frameID, subFrame.get());
3092 }
3093
3094 double WebPageProxy::estimatedProgress() const
3095 {
3096     return m_pageLoadState.estimatedProgress();
3097 }
3098
3099 void WebPageProxy::didStartProgress()
3100 {
3101     PageClientProtector protector(m_pageClient);
3102
3103     auto transaction = m_pageLoadState.transaction();
3104     m_pageLoadState.didStartProgress(transaction);
3105
3106     m_pageLoadState.commitChanges();
3107     m_loaderClient->didStartProgress(*this);
3108 }
3109
3110 void WebPageProxy::didChangeProgress(double value)
3111 {
3112     PageClientProtector protector(m_pageClient);
3113
3114     auto transaction = m_pageLoadState.transaction();
3115     m_pageLoadState.didChangeProgress(transaction, value);
3116
3117     m_pageLoadState.commitChanges();
3118     m_loaderClient->didChangeProgress(*this);
3119 }
3120
3121 void WebPageProxy::didFinishProgress()
3122 {
3123     PageClientProtector protector(m_pageClient);
3124
3125     auto transaction = m_pageLoadState.transaction();
3126     m_pageLoadState.didFinishProgress(transaction);
3127
3128     m_pageLoadState.commitChanges();
3129     m_loaderClient->didFinishProgress(*this);
3130 }
3131
3132 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3133 {
3134     auto transaction = m_pageLoadState.transaction();
3135     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3136 }
3137
3138 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3139 {
3140     hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3141 }
3142
3143 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3144 {
3145     PageClientProtector protector(m_pageClient);
3146
3147     // FIXME: Message check the navigationID.
3148     m_navigationState->didDestroyNavigation(navigationID);
3149 }
3150
3151 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, WebCore::URL&& unreachableURL, const UserData& userData)
3152 {
3153     PageClientProtector protector(m_pageClient);
3154
3155     auto transaction = m_pageLoadState.transaction();
3156
3157     m_pageLoadState.clearPendingAPIRequestURL(transaction);
3158
3159     WebFrameProxy* frame = m_process->webFrame(frameID);
3160     MESSAGE_CHECK(frame);
3161     MESSAGE_CHECK_URL(url);
3162
3163     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3164     RefPtr<API::Navigation> navigation;
3165     if (frame->isMainFrame() && navigationID)
3166         navigation = &navigationState().navigation(navigationID);
3167
3168     if (frame->isMainFrame()) {
3169         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
3170         m_pageClient.didStartProvisionalLoadForMainFrame();
3171         hideValidationMessage();
3172     }
3173
3174     frame->setUnreachableURL(unreachableURL);
3175     frame->didStartProvisionalLoad(url);
3176
3177     m_pageLoadState.commitChanges();
3178     if (m_navigationClient) {
3179         if (frame->isMainFrame())
3180             m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3181     } else
3182         m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3183 }
3184
3185 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, const UserData& userData)
3186 {
3187     PageClientProtector protector(m_pageClient);
3188
3189     WebFrameProxy* frame = m_process->webFrame(frameID);
3190     MESSAGE_CHECK(frame);
3191     MESSAGE_CHECK_URL(url);
3192
3193     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3194     RefPtr<API::Navigation> navigation;
3195     if (frame->isMainFrame() && navigationID)
3196         navigation = &navigationState().navigation(navigationID);
3197
3198     auto transaction = m_pageLoadState.transaction();
3199
3200     if (frame->isMainFrame())
3201         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3202
3203     frame->didReceiveServerRedirectForProvisionalLoad(url);
3204
3205     m_pageLoadState.commitChanges();
3206     if (m_navigationClient) {
3207         if (frame->isMainFrame())
3208             m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3209     } else
3210         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3211 }
3212
3213 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay)
3214 {
3215     PageClientProtector protector(m_pageClient);
3216
3217     WebFrameProxy* frame = m_process->webFrame(frameID);
3218     MESSAGE_CHECK(frame);
3219
3220     if (m_navigationClient) {
3221         if (frame->isMainFrame())
3222             m_navigationClient->willPerformClientRedirect(*this, url, delay);
3223     }
3224 }
3225
3226 void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
3227 {
3228     PageClientProtector protector(m_pageClient);
3229
3230     WebFrameProxy* frame = m_process->webFrame(frameID);
3231     MESSAGE_CHECK(frame);
3232
3233     if (m_navigationClient) {
3234         if (frame->isMainFrame())
3235             m_navigationClient->didCancelClientRedirect(*this);
3236     }
3237 }
3238
3239 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, WebCore::URL&& url)
3240 {
3241     PageClientProtector protector(m_pageClient);
3242
3243     WebFrameProxy* frame = m_process->webFrame(frameID);
3244     MESSAGE_CHECK(frame);
3245     MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
3246     MESSAGE_CHECK_URL(url);
3247
3248     auto transaction = m_pageLoadState.transaction();
3249
3250     // Internally, we handle this the same way we handle a server redirect. There are no client callbacks
3251     // for this, but if this is the main frame, clients may observe a change to the page's URL.
3252     if (frame->isMainFrame())
3253         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3254
3255     frame->didReceiveServerRedirectForProvisionalLoad(url);
3256 }
3257
3258 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
3259 {
3260     PageClientProtector protector(m_pageClient);
3261
3262     WebFrameProxy* frame = m_process->webFrame(frameID);
3263     MESSAGE_CHECK(frame);
3264
3265     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3266     RefPtr<API::Navigation> navigation;
3267     if (frame->isMainFrame() && navigationID)
3268         navigation = navigationState().takeNavigation(navigationID);
3269
3270     auto transaction = m_pageLoadState.transaction();
3271
3272     if (frame->isMainFrame()) {
3273         m_pageLoadState.didFailProvisionalLoad(transaction);
3274         m_pageClient.didFailProvisionalLoadForMainFrame();
3275     }
3276
3277     frame->didFailProvisionalLoad();
3278
3279     m_pageLoadState.commitChanges();
3280
3281     ASSERT(!m_failingProvisionalLoadURL);
3282     m_failingProvisionalLoadURL = provisionalURL;
3283
3284     if (m_navigationClient) {
3285         if (frame->isMainFrame())
3286             m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3287         else {
3288             // FIXME: Get the main frame's current navigation.
3289             m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
3290         }
3291     } else
3292         m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3293
3294     m_failingProvisionalLoadURL = { };
3295 }
3296
3297 void WebPageProxy::clearLoadDependentCallbacks()
3298 {
3299     HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);
3300     for (auto& callbackID : loadDependentStringCallbackIDs) {
3301         if (auto callback = m_callbacks.take<StringCallback>(callbackID))
3302             callback->invalidate();
3303     }
3304 }
3305
3306 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)
3307 {
3308     PageClientProtector protector(m_pageClient);
3309
3310     WebFrameProxy* frame = m_process->webFrame(frameID);
3311     MESSAGE_CHECK(frame);
3312
3313     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3314     RefPtr<API::Navigation> navigation;
3315     if (frame->isMainFrame() && navigationID)
3316         navigation = &navigationState().navigation(navigationID);
3317
3318 #if PLATFORM(IOS)
3319     if (frame->isMainFrame()) {
3320         m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
3321         m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
3322     }
3323 #endif
3324
3325     auto transaction = m_pageLoadState.transaction();
3326     Ref<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(certificateInfo);
3327     bool markPageInsecure = hasInsecureContent ? hasInsecureContent.value() == HasInsecureContent::Yes : m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
3328
3329     if (frame->isMainFrame()) {
3330         m_pageLoadState.didCommitLoad(transaction, webCertificateInfo, markPageInsecure);
3331         m_suppressAutomaticNavigationSnapshotting = false;
3332     } else if (markPageInsecure)
3333         m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3334
3335 #if USE(APPKIT)
3336     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
3337     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
3338     m_pageClient.resetSecureInputState();
3339 #endif
3340
3341     clearLoadDependentCallbacks();
3342
3343     frame->didCommitLoad(mimeType, webCertificateInfo, containsPluginDocument);
3344
3345     if (frame->isMainFrame()) {
3346         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
3347
3348         if (m_mainFrameHasCustomContentProvider) {
3349             // Always assume that the main frame is pinned here, since the custom representation view will handle
3350             // any wheel events and dispatch them to the WKView when necessary.
3351             m_mainFrameIsPinnedToLeftSide = true;
3352             m_mainFrameIsPinnedToRightSide = true;
3353             m_mainFrameIsPinnedToTopSide = true;
3354             m_mainFrameIsPinnedToBottomSide = true;
3355
3356             m_uiClient->pinnedStateDidChange(*this);
3357         }
3358         m_pageClient.didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
3359     }
3360
3361     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
3362     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
3363     // plugin is handling page scaling itself) so we should reset it to the default
3364     // for standard main frame loads.
3365     if (frame->isMainFrame()) {
3366         if (static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
3367             m_pageScaleFactor = 1;
3368             m_pluginScaleFactor = 1;
3369             m_mainFramePluginHandlesPageScaleGesture = false;
3370         }
3371     }
3372
3373 #if ENABLE(POINTER_LOCK)
3374     if (frame->isMainFrame())
3375         requestPointerUnlock();
3376 #endif
3377
3378     m_pageLoadState.commitChanges();
3379     if (m_navigationClient) {
3380         if (frame->isMainFrame())
3381             m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3382     } else
3383         m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3384 }
3385
3386 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3387 {
3388     PageClientProtector protector(m_pageClient);
3389
3390     WebFrameProxy* frame = m_process->webFrame(frameID);
3391     MESSAGE_CHECK(frame);
3392
3393     if (m_controlledByAutomation) {
3394         if (auto* automationSession = process().processPool().automationSession())
3395             automationSession->documentLoadedForFrame(*frame);
3396     }
3397
3398     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3399     RefPtr<API::Navigation> navigation;
3400     if (frame->isMainFrame() && navigationID)
3401         navigation = &navigationState().navigation(navigationID);
3402
3403     if (m_navigationClient) {
3404         if (frame->isMainFrame())
3405             m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3406     } else
3407         m_loaderClient->didFinishDocumentLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3408 }
3409
3410 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3411 {
3412     PageClientProtector protector(m_pageClient);
3413
3414     WebFrameProxy* frame = m_process->webFrame(frameID);
3415     MESSAGE_CHECK(frame);
3416
3417     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3418     RefPtr<API::Navigation> navigation;
3419     if (frame->isMainFrame() && navigationID)
3420         navigation = &navigationState().navigation(navigationID);
3421
3422     auto transaction = m_pageLoadState.transaction();
3423
3424     bool isMainFrame = frame->isMainFrame();
3425     if (isMainFrame)
3426         m_pageLoadState.didFinishLoad(transaction);
3427
3428     if (m_controlledByAutomation) {
3429         if (auto* automationSession = process().processPool().automationSession())
3430             automationSession->navigationOccurredForFrame(*frame);
3431     }
3432
3433     frame->didFinishLoad();
3434
3435     m_pageLoadState.commitChanges();
3436     if (m_navigationClient) {
3437         if (isMainFrame)
3438             m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3439     } else
3440         m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3441
3442     if (isMainFrame)
3443         m_pageClient.didFinishLoadForMainFrame();
3444
3445     m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = false;
3446 }
3447
3448 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
3449 {
3450     PageClientProtector protector(m_pageClient);
3451
3452     WebFrameProxy* frame = m_process->webFrame(frameID);
3453     MESSAGE_CHECK(frame);
3454
3455     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3456     RefPtr<API::Navigation> navigation;
3457     if (frame->isMainFrame() && navigationID)
3458         navigation = &navigationState().navigation(navigationID);
3459
3460     clearLoadDependentCallbacks();
3461
3462     auto transaction = m_pageLoadState.transaction();
3463
3464     bool isMainFrame = frame->isMainFrame();
3465
3466     if (isMainFrame)
3467         m_pageLoadState.didFailLoad(transaction);
3468
3469     if (m_controlledByAutomation) {
3470         if (auto* automationSession = process().processPool().automationSession())
3471             automationSession->navigationOccurredForFrame(*frame);
3472     }
3473
3474     frame->didFailLoad();
3475
3476     m_pageLoadState.commitChanges();
3477     if (m_navigationClient) {
3478         if (frame->isMainFrame())
3479             m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3480     } else
3481         m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3482
3483     if (isMainFrame)
3484         m_pageClient.didFailLoadForMainFrame();
3485 }
3486
3487 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, WebCore::URL&& url, const UserData& userData)
3488 {
3489     PageClientProtector protector(m_pageClient);
3490
3491     WebFrameProxy* frame = m_process->webFrame(frameID);
3492     MESSAGE_CHECK(frame);
3493     MESSAGE_CHECK_URL(url);
3494
3495     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3496     RefPtr<API::Navigation> navigation;
3497     if (frame->isMainFrame() && navigationID)
3498         navigation = &navigationState().navigation(navigationID);
3499
3500     auto transaction = m_pageLoadState.transaction();
3501
3502     bool isMainFrame = frame->isMainFrame();
3503     if (isMainFrame)
3504         m_pageLoadState.didSameDocumentNavigation(transaction, url);
3505
3506     if (m_controlledByAutomation) {
3507         if (auto* automationSession = process().processPool().automationSession())
3508             automationSession->navigationOccurredForFrame(*frame);
3509     }
3510
3511     m_pageLoadState.clearPendingAPIRequestURL(transaction);
3512     frame->didSameDocumentNavigation(url);
3513
3514     m_pageLoadState.commitChanges();
3515
3516     SameDocumentNavigationType navigationType = static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType);
3517     if (m_navigationClient) {
3518         if (isMainFrame)
3519             m_navigationClient->didSameDocumentNavigation(*this, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
3520     } else
3521         m_loaderClient->didSameDocumentNavigationForFrame(*this, *frame, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
3522
3523     if (isMainFrame)
3524         m_pageClient.didSameDocumentNavigationForMainFrame(navigationType);
3525 }
3526
3527 void WebPageProxy::didChangeMainDocument(uint64_t frameID)
3528 {
3529 #if ENABLE(MEDIA_STREAM)
3530     userMediaPermissionRequestManager().resetAccess(frameID);
3531 #else
3532     UNUSED_PARAM(frameID);
3533 #endif
3534 }
3535
3536 void WebPageProxy::viewIsBecomingVisible()
3537 {
3538 #if ENABLE(MEDIA_STREAM)
3539     userMediaPermissionRequestManager().processPregrantedRequests();
3540 #endif
3541 }
3542
3543 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
3544 {
3545     PageClientProtector protector(m_pageClient);
3546
3547     WebFrameProxy* frame = m_process->webFrame(frameID);
3548     MESSAGE_CHECK(frame);
3549
3550     auto transaction = m_pageLoadState.transaction();
3551
3552     if (frame->isMainFrame())
3553         m_pageLoadState.setTitle(transaction, title);
3554
3555     frame->didChangeTitle(title);
3556     
3557     m_pageLoadState.commitChanges();
3558     m_loaderClient->didReceiveTitleForFrame(*this, title, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3559 }
3560
3561 void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, const UserData& userData)
3562 {
3563     PageClientProtector protector(m_pageClient);
3564
3565     WebFrameProxy* frame = m_process->webFrame(frameID);
3566     MESSAGE_CHECK(frame);
3567
3568     m_loaderClient->didFirstLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3569 }
3570
3571 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData& userData)
3572 {
3573     PageClientProtector protector(m_pageClient);
3574
3575     WebFrameProxy* frame = m_process->webFrame(frameID);
3576     MESSAGE_CHECK(frame);
3577
3578     m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3579
3580     if (frame->isMainFrame())
3581         m_pageClient.didFirstVisuallyNonEmptyLayoutForMainFrame();
3582 }
3583
3584 void WebPageProxy::didLayoutForCustomContentProvider()
3585 {
3586     didReachLayoutMilestone(DidFirstLayout | DidFirstVisuallyNonEmptyLayout | DidHitRelevantRepaintedObjectsAreaThreshold);
3587 }
3588
3589 void WebPageProxy::didReachLayoutMilestone(uint32_t layoutMilestones)
3590 {
3591     PageClientProtector protector(m_pageClient);
3592
3593     if (m_navigationClient)
3594         m_navigationClient->renderingProgressDidChange(*this, static_cast<LayoutMilestones>(layoutMilestones));
3595     else
3596         m_loaderClient->didReachLayoutMilestone(*this, static_cast<LayoutMilestones>(layoutMilestones));
3597 }
3598
3599 void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3600 {
3601     PageClientProtector protector(m_pageClient);
3602
3603     WebFrameProxy* frame = m_process->webFrame(frameID);
3604     MESSAGE_CHECK(frame);
3605
3606     auto transaction = m_pageLoadState.transaction();
3607     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3608
3609     m_pageLoadState.commitChanges();
3610     m_loaderClient->didDisplayInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3611 }
3612
3613 void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3614 {
3615     PageClientProtector protector(m_pageClient);
3616
3617     WebFrameProxy* frame = m_process->webFrame(frameID);
3618     MESSAGE_CHECK(frame);
3619
3620     auto transaction = m_pageLoadState.transaction();
3621     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3622
3623     m_pageLoadState.commitChanges();
3624     m_loaderClient->didRunInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3625 }
3626
3627 void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, const UserData& userData)
3628 {
3629     PageClientProtector protector(m_pageClient);
3630
3631     WebFrameProxy* frame = m_process->webFrame(frameID);
3632     MESSAGE_CHECK(frame);
3633
3634     m_loaderClient->didDetectXSSForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3635 }
3636
3637 void WebPageProxy::mainFramePluginHandlesPageScaleGestureDidChange(bool mainFramePluginHandlesPageScaleGesture)
3638 {
3639     m_mainFramePluginHandlesPageScaleGesture = mainFramePluginHandlesPageScaleGesture;
3640 }
3641
3642 void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
3643 {
3644     PageClientProtector protector(m_pageClient);
3645
3646     WebFrameProxy* frame = m_process->webFrame(frameID);
3647     MESSAGE_CHECK(frame);
3648
3649     frame->setIsFrameSet(value);
3650     if (frame->isMainFrame())
3651         m_frameSetLargestFrame = value ? m_mainFrame : 0;
3652 }
3653
3654 void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, ResourceRequest&& request, uint64_t listenerID, const UserData& userData, Ref<Messages::WebPageProxy::DecidePolicyForNavigationAction::DelayedReply>&& reply)
3655 {
3656     PageClientProtector protector(m_pageClient);
3657
3658     auto transaction = m_pageLoadState.transaction();
3659
3660     bool fromAPI = request.url() == m_pageLoadState.pendingAPIRequestURL();
3661     if (!fromAPI)
3662         m_pageLoadState.clearPendingAPIRequestURL(transaction);
3663
3664     WebFrameProxy* frame = m_process->webFrame(frameID);
3665     MESSAGE_CHECK(frame);
3666     MESSAGE_CHECK_URL(request.url());
3667     MESSAGE_CHECK_URL(originalRequest.url());
3668     
3669     m_newNavigationID = 0;
3670     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3671     if (!navigationID && frame->isMainFrame()) {
3672         auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
3673         m_newNavigationID = navigation->navigationID();
3674         listener->setNavigation(WTFMove(navigation));
3675     }
3676
3677 #if ENABLE(CONTENT_FILTERING)
3678     if (frame->didHandleContentFilterUnblockNavigation(request)) {
3679         reply->send(m_newNavigationID, PolicyIgnore, { }, { });
3680         m_newNavigationID = 0;
3681         return;
3682     }
3683 #endif
3684
3685 #if ENABLE(DOWNLOAD_ATTRIBUTE)
3686     m_syncNavigationActionHasDownloadAttribute = !navigationActionData.downloadAttribute.isNull();
3687 #endif
3688     m_navigationActionPolicyReply = WTFMove(reply);
3689
3690     WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameInfoData.frameID);
3691
3692     if (m_navigationClient) {
3693         auto destinationFrameInfo = API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin());
3694         RefPtr<API::FrameInfo> sourceFrameInfo;
3695         if (!fromAPI && originatingFrame == frame)
3696             sourceFrameInfo = destinationFrameInfo.copyRef();
3697         else if (!fromAPI)
3698             sourceFrameInfo = API::FrameInfo::create(originatingFrameInfoData, originatingPageID ? m_process->webPage(originatingPageID) : nullptr);
3699
3700         auto userInitiatedActivity = m_process->userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
3701         bool shouldOpenAppLinks = !m_shouldSuppressAppLinksInNextNavigationPolicyDecision && destinationFrameInfo->isMainFrame() && !hostsAreEqual(URL(ParsedURLString, m_mainFrame->url()), request.url()) && navigationActionData.navigationType != WebCore::NavigationType::BackForward;
3702
3703         auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), destinationFrameInfo.ptr(), WTFMove(request), originalRequest.url(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
3704
3705         m_navigationClient->decidePolicyForNavigationAction(*this, WTFMove(navigationAction), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3706     } else
3707         m_policyClient->decidePolicyForNavigationAction(*this, frame, WTFMove(navigationActionData), originatingFrame, originalRequest, WTFMove(request), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3708
3709     m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false;
3710 }
3711
3712 void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, NavigationActionData&& navigationActionData, ResourceRequest&& request, const String& frameName, uint64_t listenerID, const UserData& userData)
3713 {
3714     PageClientProtector protector(m_pageClient);
3715
3716     WebFrameProxy* frame = m_process->webFrame(frameID);
3717     MESSAGE_CHECK(frame);
3718     MESSAGE_CHECK_URL(request.url());
3719
3720     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3721
3722     if (m_navigationClient) {
3723         RefPtr<API::FrameInfo> sourceFrameInfo;
3724         if (frame)
3725             sourceFrameInfo = API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin());
3726
3727         auto userInitiatedActivity = m_process->userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
3728         bool shouldOpenAppLinks = !hostsAreEqual(URL(ParsedURLString, m_mainFrame->url()), request.url());
3729         auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), nullptr, WTFMove(request), request.url(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
3730
3731         m_navigationClient->decidePolicyForNavigationAction(*this, navigationAction.get(), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3732
3733     } else
3734         m_policyClient->decidePolicyForNewWindowAction(*this, *frame, navigationActionData, request, frameName, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3735 }
3736
3737 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
3738 {
3739     PageClientProtector protector(m_pageClient);
3740
3741     WebFrameProxy* frame = m_process->webFrame(frameID);
3742     MESSAGE_CHECK(frame);
3743     MESSAGE_CHECK_URL(request.url());
3744     MESSAGE_CHECK_URL(response.url());
3745
3746     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3747
3748     if (m_navigationClient) {
3749         auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin()).get(), request, response, canShowMIMEType);
3750         m_navigationClient->decidePolicyForNavigationResponse(*this, navigationResponse.get(), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3751     } else
3752         m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3753 }
3754
3755 void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData, Ref<Messages::WebPageProxy::DecidePolicyForResponseSync::DelayedReply>&& reply)
3756 {
3757     PageClientProtector protector(m_pageClient);
3758
3759     m_decidePolicyForResponseRequest = request;
3760     m_responsePolicyReply = WTFMove(reply);
3761
3762     decidePolicyForResponse(frameID, frameSecurityOrigin, response, request, canShowMIMEType, listenerID, userData);
3763 }
3764
3765 void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, const UserData& userData)
3766 {
3767     PageClientProtector protector(m_pageClient);
3768
3769     WebFrameProxy* frame = m_process->webFrame(frameID);
3770     MESSAGE_CHECK(frame);
3771
3772     m_policyClient->unableToImplementPolicy(*this, *frame, error, m_process->transformHandlesToObjects(userData.object()).get());
3773 }
3774
3775 // FormClient
3776
3777 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData& userData)
3778 {
3779     WebFrameProxy* frame = m_process->webFrame(frameID);
3780     MESSAGE_CHECK(frame);
3781
3782     WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
3783     MESSAGE_CHECK(sourceFrame);
3784
3785     m_formClient->willSubmitForm(*this, *frame, *sourceFrame, textFieldValues, m_process->transformHandlesToObjects(userData.object()).get(), [this, protectedThis = makeRef(*this), frameID, listenerID]() {
3786         m_process->send(Messages::WebPage::ContinueWillSubmitForm(frameID, listenerID), m_pageID);
3787     });
3788 }
3789
3790 void WebPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID) 
3791 {
3792     PageClientProtector protector(m_pageClient);
3793
3794     WebFrameProxy* frame = m_process->webFrame(frameID);
3795     MESSAGE_CHECK(frame);
3796     MESSAGE_CHECK(frame->page() == this);
3797
3798     if (m_historyClient) {
3799         if (frame->isMainFrame())
3800             m_historyClient->didNavigateWithNavigationData(*this, store);
3801     } else
3802         m_loaderClient->didNavigateWithNavigationData(*this, store, *frame);
3803     process().processPool().historyClient().didNavigateWithNavigationData(process().processPool(), *this, store, *frame);
3804 }
3805
3806 void WebPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3807 {
3808     PageClientProtector protector(m_pageClient);
3809
3810     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3811         return;
3812     
3813     WebFrameProxy* frame = m_process->webFrame(frameID);
3814     MESSAGE_CHECK(frame);
3815     MESSAGE_CHECK(frame->page() == this);
3816
3817     MESSAGE_CHECK_URL(sourceURLString);
3818     MESSAGE_CHECK_URL(destinationURLString);
3819
3820     if (m_historyClient) {
3821         if (frame->isMainFrame())
3822             m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
3823     } else
3824         m_loaderClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString, *frame);
3825     process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3826 }
3827
3828 void WebPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3829 {
3830     PageClientProtector protector(m_pageClient);
3831
3832     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3833         return;
3834     
3835     WebFrameProxy* frame = m_process->webFrame(frameID);
3836     MESSAGE_CHECK(frame);
3837     MESSAGE_CHECK(frame->page() == this);
3838
3839     MESSAGE_CHECK_URL(sourceURLString);
3840     MESSAGE_CHECK_URL(destinationURLString);
3841
3842     if (m_historyClient) {
3843         if (frame->isMainFrame())
3844             m_historyClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString);
3845     } else
3846         m_loaderClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString, *frame);
3847     process().processPool().historyClient().didPerformServerRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3848 }
3849
3850 void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url, uint64_t frameID)
3851 {
3852     PageClientProtector protector(m_pageClient);
3853
3854     WebFrameProxy* frame = m_process->webFrame(frameID);
3855     MESSAGE_CHECK(frame);
3856     MESSAGE_CHECK(frame->page() == this);
3857
3858     MESSAGE_CHECK_URL(url);
3859
3860     if (m_historyClient) {
3861         if (frame->isMainFrame())
3862             m_historyClient->didUpdateHistoryTitle(*this, title, url);
3863     } else
3864         m_loaderClient->didUpdateHistoryTitle(*this, title, url, *frame);
3865     process().processPool().historyClient().didUpdateHistoryTitle(process().processPool(), *this, title, url, *frame);
3866 }
3867
3868 // UIClient
3869
3870 void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, ResourceRequest&& request, WindowFeatures&& windowFeatures, NavigationActionData&& navigationActionData, Ref<Messages::WebPageProxy::CreateNewPage::DelayedReply>&& reply)
3871 {
3872     MESSAGE_CHECK(m_process->webFrame(originatingFrameInfoData.frameID));
3873     auto originatingFrameInfo = API::FrameInfo::create(originatingFrameInfoData, m_process->webPage(originatingPageID));
3874
3875     auto mainFrameURL = m_mainFrame->url();
3876
3877     m_uiClient->createNewPage(*this, WTFMove(originatingFrameInfo), WTFMove(request), WTFMove(windowFeatures), WTFMove(navigationActionData), [this, protectedThis = RefPtr<WebPageProxy>(this), mainFrameURL, request, reply = WTFMove(reply)](RefPtr<WebPageProxy> newPage) {
3878         if (!newPage) {
3879             reply->send(0, { });
3880             return;
3881         }
3882
3883         reply->send(newPage->pageID(), newPage->creationParameters());
3884
3885         WebsiteDataStore::cloneSessionData(*this, *newPage);
3886         newPage->m_shouldSuppressAppLinksInNextNavigationPolicyDecision = hostsAreEqual(URL(ParsedURLString, mainFrameURL), request.url());
3887     });
3888 }
3889     
3890 void WebPageProxy::showPage()
3891 {
3892     m_uiClient->showPage(this);
3893 }
3894
3895 void WebPageProxy::fullscreenMayReturnToInline()
3896 {
3897     m_uiClient->fullscreenMayReturnToInline(this);
3898 }
3899
3900 void WebPageProxy::didEnterFullscreen()
3901 {
3902     m_uiClient->didEnterFullscreen(this);
3903 }
3904
3905 void WebPageProxy::didExitFullscreen()
3906 {
3907     m_uiClient->didExitFullscreen(this);
3908 }
3909
3910 void WebPageProxy::closePage(bool stopResponsivenessTimer)
3911 {
3912     if (stopResponsivenessTimer)
3913         m_process->responsivenessTimer().stop();
3914
3915     m_pageClient.clearAllEditCommands();
3916     m_uiClient->close(this);
3917 }
3918
3919 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Ref<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply>&& reply)
3920 {
3921     WebFrameProxy* frame = m_process->webFrame(frameID);
3922     MESSAGE_CHECK(frame);
3923
3924     // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
3925     m_process->responsivenessTimer().stop();
3926
3927     if (m_controlledByAutomation) {
3928         if (auto* automationSession = process().processPool().automationSession())
3929             automationSession->willShowJavaScriptDialog(*this);
3930     }
3931     m_uiClient->runJavaScriptAlert(this, message, frame, securityOrigin, [reply = WTFMove(reply)] {
3932         reply->send();
3933     });
3934 }
3935
3936 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Ref<Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply>&& reply)
3937 {
3938     WebFrameProxy* frame = m_process->webFrame(frameID);
3939     MESSAGE_CHECK(frame);
3940
3941     // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
3942     m_process->responsivenessTimer().stop();
3943
3944     if (m_controlledByAutomation) {
3945         if (auto* automationSession = process().processPool().automationSession())
3946             automationSession->willShowJavaScriptDialog(*this);
3947     }
3948
3949     m_uiClient->runJavaScriptConfirm(this, message, frame, securityOrigin, [reply = WTFMove(reply)](bool result) {
3950         reply->send(result);
3951     });
3952 }
3953
3954 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, const String& defaultValue, Ref<Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply>&& reply)
3955 {
3956     WebFrameProxy* frame = m_process->webFrame(frameID);
3957     MESSAGE_CHECK(frame);
3958
3959     // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
3960     m_process->responsivenessTimer().stop();
3961
3962     if (m_controlledByAutomation) {
3963         if (auto* automationSession = process().processPool().automationSession())
3964             automationSession->willShowJavaScriptDialog(*this);
3965     }
3966
3967     m_uiClient->runJavaScriptPrompt(this, message, defaultValue, frame, securityOrigin, [reply = WTFMove(reply)](const String& result) {
3968         reply->send(result);
3969     });
3970 }
3971
3972 void WebPageProxy::setStatusText(const String& text)
3973 {
3974     m_uiClient->setStatusText(this, text);
3975 }
3976
3977 void WebPageProxy::mouseDidMoveOverElement(WebHitTestResultData&& hitTestResultData, uint32_t opaqueModifiers, UserData&& userData)
3978 {
3979     m_lastMouseMoveHitTestResult = API::HitTestResult::create(hitTestResultData);
3980
3981     WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
3982
3983     m_uiClient->mouseDidMoveOverElement(*this, hitTestResultData, modifiers, m_process->transformHandlesToObjects(userData.object()).get());
3984 }
3985
3986 void WebPageProxy::connectionWillOpen(IPC::Connection& connection)
3987 {
3988     ASSERT(&connection == m_process->connection());
3989
3990     m_webProcessLifetimeTracker.connectionWillOpen(connection);
3991 }
3992
3993 void WebPageProxy::webProcessWillShutDown()
3994 {
3995     m_webProcessLifetimeTracker.webProcessWillShutDown();
3996 }
3997
3998 void WebPageProxy::processDidFinishLaunching()
3999 {
4000     ASSERT(m_process->state() == WebProcessProxy::State::Running);
4001     finishInitializingWebPageAfterProcessLaunch();
4002 }
4003
4004 #if ENABLE(NETSCAPE_PLUGIN_API)
4005 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
4006 {
4007     MESSAGE_CHECK_URL(pluginURLString);
4008     MESSAGE_CHECK_URL(pluginspageAttributeURLString);
4009     MESSAGE_CHECK_URL(frameURLString);
4010     MESSAGE_CHECK_URL(pageURLString);
4011
4012     String newMimeType = mimeType;
4013     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
4014     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
4015
4016     WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
4017     switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
4018     case RenderEmbeddedObject::PluginMissing:
4019         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
4020         break;
4021     case RenderEmbeddedObject::InsecurePluginVersion:
4022         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
4023         break;
4024     case RenderEmbeddedObject::PluginCrashed:
4025         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
4026         break;
4027     case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
4028         ASSERT_NOT_REACHED();
4029     }
4030
4031     m_uiClient->unavailablePluginButtonClicked(*this, pluginUnavailabilityReason, pluginInformation.get());
4032 }
4033 #endif // ENABLE(NETSCAPE_PLUGIN_API)
4034
4035 #if ENABLE(WEBGL)
4036 void WebPageProxy::webGLPolicyForURL(URL&& url, Ref<Messages::WebPageProxy::WebGLPolicyForURL::DelayedReply>&& reply)
4037 {
4038     if (m_navigationClient) {
4039         m_navigationClient->webGLLoadPolicy(*this, url, [reply = WTFMove(reply)](WebGLLoadPolicy policy) {
4040             reply->send(static_cast<uint32_t>(policy));
4041         });
4042     } else
4043         reply->send(static_cast<uint32_t>(m_loaderClient->webGLLoadPolicy(*this, url)));
4044 }
4045
4046 void WebPageProxy::resolveWebGLPolicyForURL(URL&& url, Ref<Messages::WebPageProxy::ResolveWebGLPolicyForURL::DelayedReply>&& reply)
4047 {
4048     if (m_navigationClient) {
4049         m_navigationClient->resolveWebGLLoadPolicy(*this, url, [reply = WTFMove(reply)](WebGLLoadPolicy policy) {
4050             reply->send(static_cast<uint32_t>(policy));
4051         });
4052     } else
4053         reply->send(static_cast<uint32_t>(m_loaderClient->resolveWebGLLoadPolicy(*this, url)));
4054 }
4055 #endif // ENABLE(WEBGL)
4056
4057 void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
4058 {
4059     m_uiClient->setToolbarsAreVisible(*this, toolbarsAreVisible);
4060 }
4061
4062 void WebPageProxy::getToolbarsAreVisible(Ref<Messages::WebPageProxy::GetToolbarsAreVisible::DelayedReply>&& reply)
4063 {
4064     m_uiClient->toolbarsAreVisible(*this, [reply = WTFMove(reply)](bool visible) {
4065         reply->send(visible);
4066     });
4067 }
4068
4069 void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
4070 {
4071     m_uiClient->setMenuBarIsVisible(*this, menuBarIsVisible);
4072 }
4073
4074 void WebPageProxy::getMenuBarIsVisible(Ref<Messages::WebPageProxy::GetMenuBarIsVisible::DelayedReply>&& reply)
4075 {
4076     m_uiClient->menuBarIsVisible(*this, [reply = WTFMove(reply)] (bool visible) {
4077         reply->send(visible);
4078     });
4079 }
4080
4081 void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
4082 {
4083     m_uiClient->setStatusBarIsVisible(*this, statusBarIsVisible);
4084 }
4085
4086 void WebPageProxy::getStatusBarIsVisible(Ref<Messages::WebPageProxy::GetStatusBarIsVisible::DelayedReply>&& reply)
4087 {
4088     m_uiClient->statusBarIsVisible(*this, [reply = WTFMove(reply)] (bool visible) {
4089         reply->send(visible);
4090     });
4091 }
4092
4093 void WebPageProxy::setIsResizable(bool isResizable)
4094 {
4095     m_uiClient->setIsResizable(*this, isResizable);
4096 }
4097
4098 void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
4099 {
4100     m_uiClient->setWindowFrame(*this, m_pageClient.convertToDeviceSpace(newWindowFrame));
4101 }
4102
4103 void WebPageProxy::getWindowFrame(Ref<Messages::WebPageProxy::GetWindowFrame::DelayedReply>&& reply)
4104 {
4105     m_uiClient->windowFrame(*this, [this, protectedThis = makeRef(*this), reply = WTFMove(reply)] (FloatRect frame) {
4106         reply->send(m_pageClient.convertToUserSpace(frame));
4107     });
4108 }
4109
4110 void WebPageProxy::getWindowFrameWithCallback(Function<void(FloatRect)>&& completionHandler)
4111 {
4112     m_uiClient->windowFrame(*this, WTFMove(completionHandler));
4113 }
4114
4115 void WebPageProxy::screenToRootView(const IntPoint& screenPoint, Ref<Messages::WebPageProxy::ScreenToRootView::DelayedReply>&& reply)
4116 {
4117     reply->send(m_pageClient.screenToRootView(screenPoint));
4118 }
4119     
4120 void WebPageProxy::rootViewToScreen(const IntRect& viewRect, Ref<Messages::WebPageProxy::RootViewToScreen::DelayedReply>&& reply)
4121 {
4122     reply->send(m_pageClient.rootViewToScreen(viewRect));
4123 }
4124     
4125 #if PLATFORM(IOS)
4126 void WebPageProxy::accessibilityScreenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
4127 {
4128     windowPoint = m_pageClient.accessibilityScreenToRootView(screenPoint);
4129 }
4130
4131 void WebPageProxy::rootViewToAccessibilityScreen(const IntRect& viewRect, IntRect& result)
4132 {
4133     result = m_pageClient.rootViewToAccessibilityScreen(viewRect);
4134 }
4135 #endif
4136
4137 void WebPageProxy::runBeforeUnloadConfirmPanel(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, RefPtr<Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::DelayedReply> reply)
4138 {
4139     WebFrameProxy* frame = m_process->webFrame(frameID);
4140     MESSAGE_CHECK(frame);
4141
4142     // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer.
4143     m_process->responsivenessTimer().stop();
4144
4145     if (m_controlledByAutomation) {
4146         if (auto* automationSession = process().processPool().automationSession())
4147             automationSession->willShowJavaScriptDialog(*this);
4148     }
4149
4150     m_uiClient->runBeforeUnloadConfirmPanel(this, message, frame, securityOrigin, [reply](bool result) { reply->send(result); });
4151 }
4152
4153 void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr)
4154 {
4155     m_pageClient.didChangeViewportProperties(attr);
4156 }
4157
4158 void WebPageProxy::pageDidScroll()
4159 {
4160     m_uiClient->pageDidScroll(this);
4161
4162 #if PLATFORM(IOS)
4163     // Do not hide the validation message if the scrolling was caused by the keyboard showing up.
4164     if (m_isKeyboardAnimatingIn)
4165         return;
4166 #endif
4167     hideValidationMessage();
4168 }
4169
4170 void WebPageProxy::runOpenPanel(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, const FileChooserSettings& settings)
4171 {
4172     if (m_openPanelResultListener) {
4173         m_openPanelResultListener->invalidate();
4174         m_openPanelResultListener = nullptr;
4175     }
4176
4177     WebFrameProxy* frame = m_process->webFrame(frameID);
4178     MESSAGE_CHECK(frame);
4179
4180     Ref<API::OpenPanelParameters> parameters = API::OpenPanelParameters::create(settings);
4181     m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
4182
4183     if (m_controlledByAutomation) {
4184         if (auto* automationSession = process().processPool().automationSession())
4185             automationSession->handleRunOpenPanel(*this, *frame, parameters.get(), *m_openPanelResultListener);
4186
4187         // Don't show a file chooser, since automation will be unable to interact with it.
4188         return;
4189     }
4190
4191     // Since runOpenPanel() can spin a nested run loop we need to turn off the responsiveness timer.
4192     m_process->responsivenessTimer().stop();
4193
4194     if (!m_uiClient->runOpenPanel(this, frame, frameSecurityOrigin, parameters.ptr(), m_openPanelResultListener.get())) {
4195         if (!m_pageClient.handleRunOpenPanel(this, frame, parameters.ptr(), m_openPanelResultListener.get()))
4196             didCancelForOpenPanel();
4197     }
4198 }
4199
4200 void WebPageProxy::printFrame(uint64_t frameID)
4201 {
4202     ASSERT(!m_isPerformingDOMPrintOperation);
4203     m_isPerformingDOMPrintOperation = true;
4204
4205     WebFrameProxy* frame = m_process->webFrame(frameID);
4206     MESSAGE_CHECK(frame);
4207
4208     m_uiClient->printFrame(*this, *frame);
4209
4210     endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true.
4211     m_isPerformingDOMPrintOperation = false;
4212 }
4213
4214 void WebPageProxy::printMainFrame()
4215 {
4216     printFrame(m_mainFrame->frameID());
4217 }
4218
4219 void WebPageProxy::setMediaVolume(float volume)
4220 {
4221     if (volume == m_mediaVolume)
4222         return;
4223     
4224     m_mediaVolume = volume;
4225     
4226     if (!isValid())
4227         return;
4228     
4229     m_process->send(Messages::WebPage::SetMediaVolume(volume), m_pageID);