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