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