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