Replace OptionSet |= and -= operators with add() and remove() functions
[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 "ShareSheetCallbackID.h"
81 #include "TextChecker.h"
82 #include "TextCheckerState.h"
83 #include "UIMessagePortChannelProvider.h"
84 #include "URLSchemeTaskParameters.h"
85 #include "UndoOrRedo.h"
86 #include "UserMediaPermissionRequestProxy.h"
87 #include "UserMediaProcessManager.h"
88 #include "WKContextPrivate.h"
89 #include "WebAutomationSession.h"
90 #include "WebBackForwardList.h"
91 #include "WebBackForwardListItem.h"
92 #include "WebCertificateInfo.h"
93 #include "WebContextMenuItem.h"
94 #include "WebContextMenuProxy.h"
95 #include "WebCoreArgumentCoders.h"
96 #include "WebEditCommandProxy.h"
97 #include "WebEvent.h"
98 #include "WebEventConversion.h"
99 #include "WebFramePolicyListenerProxy.h"
100 #include "WebFullScreenManagerProxy.h"
101 #include "WebFullScreenManagerProxyMessages.h"
102 #include "WebImage.h"
103 #include "WebInspectorProxy.h"
104 #include "WebInspectorUtilities.h"
105 #include "WebNavigationState.h"
106 #include "WebNotificationManagerProxy.h"
107 #include "WebOpenPanelResultListenerProxy.h"
108 #include "WebPageCreationParameters.h"
109 #include "WebPageGroup.h"
110 #include "WebPageGroupData.h"
111 #include "WebPageMessages.h"
112 #include "WebPageProxyMessages.h"
113 #include "WebPaymentCoordinatorProxy.h"
114 #include "WebPopupItem.h"
115 #include "WebPopupMenuProxy.h"
116 #include "WebPreferences.h"
117 #include "WebPreferencesKeys.h"
118 #include "WebProcessMessages.h"
119 #include "WebProcessPool.h"
120 #include "WebProcessProxy.h"
121 #include "WebProtectionSpace.h"
122 #include "WebResourceLoadStatisticsStore.h"
123 #include "WebURLSchemeHandler.h"
124 #include "WebUserContentControllerProxy.h"
125 #include "WebsiteDataStore.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/ShareData.h>
150 #include <WebCore/SharedBuffer.h>
151 #include <WebCore/ShouldSkipSafeBrowsingCheck.h>
152 #include <WebCore/ShouldTreatAsContinuingLoad.h>
153 #include <WebCore/TextCheckerClient.h>
154 #include <WebCore/TextIndicator.h>
155 #include <WebCore/URL.h>
156 #include <WebCore/URLParser.h>
157 #include <WebCore/ValidationBubble.h>
158 #include <WebCore/WindowFeatures.h>
159 #include <stdio.h>
160 #include <wtf/NeverDestroyed.h>
161 #include <wtf/SystemTracing.h>
162 #include <wtf/text/StringView.h>
163 #include <wtf/text/TextStream.h>
164
165 #if ENABLE(APPLICATION_MANIFEST)
166 #include "APIApplicationManifest.h"
167 #endif
168
169 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
170 #include "RemoteScrollingCoordinatorProxy.h"
171 #endif
172
173 #ifndef NDEBUG
174 #include <wtf/RefCountedLeakCounter.h>
175 #endif
176
177 #if PLATFORM(COCOA)
178 #include "RemoteLayerTreeDrawingAreaProxy.h"
179 #include "RemoteLayerTreeScrollingPerformanceData.h"
180 #include "TouchBarMenuData.h"
181 #include "TouchBarMenuItemData.h"
182 #include "VideoFullscreenManagerProxy.h"
183 #include "VideoFullscreenManagerProxyMessages.h"
184 #include "ViewSnapshotStore.h"
185 #include <WebCore/RunLoopObserver.h>
186 #include <WebCore/TextIndicatorWindow.h>
187 #include <wtf/MachSendRight.h>
188 #endif
189
190 #if PLATFORM(GTK)
191 #include "WebSelectionData.h"
192 #endif
193
194 #if USE(CAIRO)
195 #include <WebCore/CairoUtilities.h>
196 #endif
197
198 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
199 #include <WebCore/MediaPlaybackTarget.h>
200 #include <WebCore/WebMediaSessionManager.h>
201 #endif
202
203 #if ENABLE(MEDIA_SESSION)
204 #include "WebMediaSessionFocusManager.h"
205 #include "WebMediaSessionMetadata.h"
206 #include <WebCore/MediaSessionMetadata.h>
207 #endif
208
209 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
210 #include "PlaybackSessionManagerProxy.h"
211 #endif
212
213 #if ENABLE(WEB_AUTHN)
214 #include "WebCredentialsMessengerProxy.h"
215 #endif
216
217 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
218 #include "WebResourceLoadStatisticsStore.h"
219 #endif
220
221 #if HAVE(SEC_KEY_PROXY)
222 #include "SecKeyProxyStore.h"
223 #endif
224
225 // This controls what strategy we use for mouse wheel coalescing.
226 #define MERGE_WHEEL_EVENTS 1
227
228 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
229 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
230
231 #define RELEASE_LOG_IF_ALLOWED(channel, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, __VA_ARGS__)
232
233 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
234 static const unsigned wheelEventQueueSizeThreshold = 10;
235
236 static const Seconds resetRecentCrashCountDelay = 30_s;
237 static unsigned maximumWebProcessRelaunchAttempts = 1;
238
239 namespace WebKit {
240 using namespace WebCore;
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)
1289             m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache, m_process->transformHandlesToObjects(userData.object()).get());
1290     }
1291 }
1292
1293 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1294 {
1295     PageClientProtector protector(m_pageClient);
1296
1297     return m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1298 }
1299
1300 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1301 {
1302     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1303         return true;
1304
1305 #if ENABLE(NETSCAPE_PLUGIN_API)
1306     String newMimeType = mimeType;
1307     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1308     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1309         return true;
1310 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1311
1312 #if PLATFORM(COCOA)
1313     // On Mac, we can show PDFs.
1314     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1315         return true;
1316 #endif // PLATFORM(COCOA)
1317
1318     return false;
1319 }
1320
1321 void WebPageProxy::setControlledByAutomation(bool controlled)
1322 {
1323     if (m_controlledByAutomation == controlled)
1324         return;
1325
1326     m_controlledByAutomation = controlled;
1327
1328     if (!isValid())
1329         return;
1330
1331     m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1332     m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1333 }
1334
1335 #if ENABLE(REMOTE_INSPECTOR)
1336 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1337 {
1338     if (m_allowsRemoteInspection == allow)
1339         return;
1340
1341     m_allowsRemoteInspection = allow;
1342
1343     if (isValid())
1344         m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
1345 }
1346
1347 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1348 {
1349     if (m_remoteInspectionNameOverride == name)
1350         return;
1351
1352     m_remoteInspectionNameOverride = name;
1353
1354     if (isValid())
1355         m_process->send(Messages::WebPage::SetRemoteInspectionNameOverride(m_remoteInspectionNameOverride), m_pageID);
1356 }
1357
1358 #endif
1359
1360 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1361 {
1362     if (m_drawsBackground == drawsBackground)
1363         return;
1364
1365     m_drawsBackground = drawsBackground;
1366
1367     if (isValid())
1368         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1369 }
1370
1371 void WebPageProxy::setTopContentInset(float contentInset)
1372 {
1373     if (m_topContentInset == contentInset)
1374         return;
1375
1376     m_topContentInset = contentInset;
1377
1378     if (!isValid())
1379         return;
1380 #if PLATFORM(COCOA)
1381     MachSendRight fence = m_drawingArea->createFence();
1382
1383     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1384     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1385 #else
1386     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1387 #endif
1388 }
1389
1390 void WebPageProxy::setUnderlayColor(const Color& color)
1391 {
1392     if (m_underlayColor == color)
1393         return;
1394
1395     m_underlayColor = color;
1396
1397     if (isValid())
1398         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1399 }
1400
1401 void WebPageProxy::viewWillStartLiveResize()
1402 {
1403     if (!isValid())
1404         return;
1405
1406     closeOverlayedViews();
1407     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1408 }
1409
1410 void WebPageProxy::viewWillEndLiveResize()
1411 {
1412     if (!isValid())
1413         return;
1414     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1415 }
1416
1417 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1418 {
1419     m_pageClient.setViewNeedsDisplay(region);
1420 }
1421
1422 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1423 {
1424     m_pageClient.requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1425 }
1426
1427 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1428 {
1429     return m_pageClient.viewScrollPosition();
1430 }
1431
1432 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1433 {
1434     if (m_suppressVisibilityUpdates == flag)
1435         return;
1436     m_suppressVisibilityUpdates = flag;
1437
1438     if (!m_suppressVisibilityUpdates) {
1439 #if PLATFORM(COCOA)
1440         m_activityStateChangeDispatcher->schedule();
1441 #else
1442         dispatchActivityStateChange();
1443 #endif
1444     }
1445 }
1446
1447 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1448 {
1449     m_activityState.remove(flagsToUpdate);
1450     if (flagsToUpdate & ActivityState::IsFocused && m_pageClient.isViewFocused())
1451         m_activityState.add(ActivityState::IsFocused);
1452     if (flagsToUpdate & ActivityState::WindowIsActive && m_pageClient.isViewWindowActive())
1453         m_activityState.add(ActivityState::WindowIsActive);
1454     if (flagsToUpdate & ActivityState::IsVisible && m_pageClient.isViewVisible())
1455         m_activityState.add(ActivityState::IsVisible);
1456     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && m_pageClient.isViewVisibleOrOccluded())
1457         m_activityState.add(ActivityState::IsVisibleOrOccluded);
1458     if (flagsToUpdate & ActivityState::IsInWindow && m_pageClient.isViewInWindow())
1459         m_activityState.add(ActivityState::IsInWindow);
1460     if (flagsToUpdate & ActivityState::IsVisuallyIdle && m_pageClient.isVisuallyIdle())
1461         m_activityState.add(ActivityState::IsVisuallyIdle);
1462     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1463         m_activityState.add(ActivityState::IsAudible);
1464     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1465         m_activityState.add(ActivityState::IsLoading);
1466     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1467         m_activityState.add(ActivityState::IsCapturingMedia);
1468 }
1469
1470 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1471 {
1472     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1473
1474     m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1475     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1476
1477     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1478         return;
1479
1480 #if PLATFORM(COCOA)
1481     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && m_pageClient.isViewInWindow();
1482     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1483         dispatchActivityStateChange();
1484         return;
1485     }
1486     m_activityStateChangeDispatcher->schedule();
1487 #else
1488     UNUSED_PARAM(dispatchMode);
1489     dispatchActivityStateChange();
1490 #endif
1491 }
1492
1493 void WebPageProxy::viewDidLeaveWindow()
1494 {
1495     closeOverlayedViews();
1496 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1497     // When leaving the current page, close the video fullscreen.
1498     if (m_videoFullscreenManager)
1499         m_videoFullscreenManager->requestHideAndExitFullscreen();
1500 #endif
1501 }
1502
1503 void WebPageProxy::viewDidEnterWindow()
1504 {
1505     LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1506     if (m_layerHostingMode != layerHostingMode) {
1507         m_layerHostingMode = layerHostingMode;
1508         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1509     }
1510 }
1511
1512 void WebPageProxy::dispatchActivityStateChange()
1513 {
1514 #if PLATFORM(COCOA)
1515     m_activityStateChangeDispatcher->invalidate();
1516 #endif
1517
1518     if (!isValid())
1519         return;
1520
1521     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1522
1523     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1524     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1525         m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1526
1527     // Record the prior view state, update the flags that may have changed,
1528     // and check which flags have actually changed.
1529     auto previousActivityState = m_activityState;
1530     updateActivityState(m_potentiallyChangedActivityStateFlags);
1531     auto changed = m_activityState ^ previousActivityState;
1532
1533     if (changed)
1534         LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1535
1536     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1537         viewIsBecomingVisible();
1538
1539     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1540     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1541     if (m_viewWasEverInWindow && isNowInWindow) {
1542         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1543             m_activityStateChangeWantsSynchronousReply = true;
1544         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1545     }
1546
1547     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1548     if (!(m_activityState & ActivityState::IsVisible))
1549         m_activityStateChangeWantsSynchronousReply = false;
1550
1551     auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1552
1553     if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1554         m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1555
1556     m_nextActivityStateChangeCallbacks.clear();
1557
1558     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1559     updateThrottleState();
1560
1561 #if ENABLE(POINTER_LOCK)
1562     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !m_pageClient.isViewWindowActive())
1563         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1564         requestPointerUnlock();
1565 #endif
1566
1567     if (changed & ActivityState::IsVisible) {
1568         if (isViewVisible())
1569             m_visiblePageToken = m_process->visiblePageToken();
1570         else {
1571             m_visiblePageToken = nullptr;
1572
1573             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1574             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1575             // stop the unresponsiveness timer here.
1576             m_process->responsivenessTimer().stop();
1577         }
1578     }
1579
1580     if (changed & ActivityState::IsInWindow) {
1581         if (isInWindow())
1582             viewDidEnterWindow();
1583         else
1584             viewDidLeaveWindow();
1585     }
1586
1587     updateBackingStoreDiscardableState();
1588
1589     if (activityStateChangeID != ActivityStateChangeAsynchronous)
1590         waitForDidUpdateActivityState(activityStateChangeID);
1591
1592     m_potentiallyChangedActivityStateFlags = { };
1593     m_activityStateChangeWantsSynchronousReply = false;
1594     m_viewWasEverInWindow |= isNowInWindow;
1595 }
1596
1597 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1598 {
1599     return sessionID().isAlwaysOnLoggingAllowed();
1600 }
1601
1602 void WebPageProxy::updateThrottleState()
1603 {
1604     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1605
1606     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1607     if (!processSuppressionEnabled)
1608         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1609     else if (!m_preventProcessSuppressionCount)
1610         m_preventProcessSuppressionCount = nullptr;
1611
1612     if (m_activityState & ActivityState::IsVisuallyIdle)
1613         m_pageIsUserObservableCount = nullptr;
1614     else if (!m_pageIsUserObservableCount)
1615         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1616
1617 #if PLATFORM(IOS)
1618     bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1619     bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1620     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1621         if (m_activityToken) {
1622             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1623             m_activityToken = nullptr;
1624         }
1625     } else if (!m_activityToken) {
1626         if (isViewVisible())
1627             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1628         else if (isAudible)
1629             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1630         else if (isCapturingMedia)
1631             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1632         else
1633             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);
1634         m_activityToken = m_process->throttler().foregroundActivityToken();
1635     }
1636 #endif
1637 }
1638
1639 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1640 {
1641     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1642         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1643     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1644         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1645 }
1646
1647 void WebPageProxy::layerHostingModeDidChange()
1648 {
1649     if (!isValid())
1650         return;
1651
1652     LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1653     if (m_layerHostingMode == layerHostingMode)
1654         return;
1655
1656     m_layerHostingMode = layerHostingMode;
1657     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1658 }
1659
1660 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1661 {
1662     if (!isValid())
1663         return;
1664
1665     if (m_process->state() != WebProcessProxy::State::Running)
1666         return;
1667
1668     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1669     if (m_waitingForDidUpdateActivityState)
1670         return;
1671
1672 #if PLATFORM(IOS)
1673     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1674     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1675     if (!m_activityToken) {
1676         ASSERT_NOT_REACHED();
1677         return;
1678     }
1679 #endif
1680
1681     m_waitingForDidUpdateActivityState = true;
1682
1683     m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1684 }
1685
1686 IntSize WebPageProxy::viewSize() const
1687 {
1688     return m_pageClient.viewSize();
1689 }
1690
1691 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1692 {
1693     if (!isValid()) {
1694         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1695         return;
1696     }
1697
1698     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1699     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1700 }
1701
1702 void WebPageProxy::clearSelection()
1703 {
1704     if (!isValid())
1705         return;
1706     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1707 }
1708
1709 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1710 {
1711     if (!isValid())
1712         return;
1713     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1714 }
1715
1716 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1717 {
1718     if (!isValid()) {
1719         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1720         return;
1721     }
1722
1723     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1724     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1725 }
1726
1727 bool WebPageProxy::maintainsInactiveSelection() const
1728 {
1729     // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1730     // Otherwise, there is no way to use the console to inspect the state of a selection.
1731     if (inspector() && inspector()->isVisible())
1732         return true;
1733
1734     return m_maintainsInactiveSelection;
1735 }
1736
1737 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1738 {
1739     m_maintainsInactiveSelection = newValue;
1740 }
1741
1742 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1743 {
1744     if (!isValid()) {
1745         callbackFunction(CallbackBase::Error::Unknown);
1746         return;
1747     }
1748
1749     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1750     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1751 }
1752     
1753 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1754 {
1755     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1756
1757     if (!isValid())
1758         return;
1759
1760     if (commandName == ignoreSpellingCommandName)
1761         ++m_pendingLearnOrIgnoreWordMessageCount;
1762
1763     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1764 }
1765
1766 void WebPageProxy::setEditable(bool editable)
1767 {
1768     if (editable == m_isEditable)
1769         return;
1770     if (!isValid())
1771         return;
1772
1773     m_isEditable = editable;
1774     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1775 }
1776     
1777 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1778 {
1779     if (muted)
1780         setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1781     else
1782         setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1783 }
1784
1785 void WebPageProxy::activateMediaStreamCaptureInPage()
1786 {
1787 #if ENABLE(MEDIA_STREAM)
1788     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1789 #endif
1790     setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1791 }
1792
1793 #if !PLATFORM(IOS)
1794 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1795 {
1796 }
1797
1798 void WebPageProxy::layerTreeCommitComplete()
1799 {
1800 }
1801 #endif
1802
1803 #if ENABLE(DRAG_SUPPORT)
1804 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1805 {
1806     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
1807 }
1808
1809 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1810 {
1811     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
1812 }
1813
1814 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1815 {
1816     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
1817 }
1818
1819 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1820 {
1821     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
1822 }
1823
1824 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1825 {
1826     if (!isValid())
1827         return;
1828 #if PLATFORM(GTK)
1829     UNUSED_PARAM(dragStorageName);
1830     UNUSED_PARAM(sandboxExtensionHandle);
1831     UNUSED_PARAM(sandboxExtensionsForUpload);
1832
1833     String url = dragData.asURL();
1834     if (!url.isEmpty())
1835         m_process->assumeReadAccessToBaseURL(url);
1836
1837     ASSERT(dragData.platformData());
1838     WebSelectionData selection(*dragData.platformData());
1839     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
1840 #else
1841     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1842 #endif
1843 }
1844
1845 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
1846 {
1847     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1848
1849     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1850     m_currentDragIsOverFileInput = mouseIsOverFileInput;
1851     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1852     setDragCaretRect(insertionRect);
1853 }
1854
1855 #if PLATFORM(GTK)
1856 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
1857 {
1858     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
1859     m_pageClient.startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
1860
1861     didStartDrag();
1862 }
1863 #endif
1864
1865 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1866 {
1867     if (!isValid())
1868         return;
1869     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1870     setDragCaretRect({ });
1871 }
1872
1873 void WebPageProxy::didPerformDragOperation(bool handled)
1874 {
1875     m_pageClient.didPerformDragOperation(handled);
1876 }
1877
1878 void WebPageProxy::didStartDrag()
1879 {
1880     if (isValid())
1881         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
1882 }
1883     
1884 void WebPageProxy::dragCancelled()
1885 {
1886     if (isValid())
1887         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
1888 }
1889
1890 void WebPageProxy::didEndDragging()
1891 {
1892     resetCurrentDragInformation();
1893 }
1894
1895 void WebPageProxy::resetCurrentDragInformation()
1896 {
1897     m_currentDragOperation = WebCore::DragOperationNone;
1898     m_currentDragIsOverFileInput = false;
1899     m_currentDragNumberOfFilesToBeAccepted = 0;
1900     setDragCaretRect({ });
1901 }
1902
1903 #if !ENABLE(DATA_INTERACTION)
1904
1905 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
1906 {
1907     m_currentDragCaretRect = dragCaretRect;
1908 }
1909
1910 #endif
1911
1912 #endif // ENABLE(DRAG_SUPPORT)
1913
1914 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
1915 {
1916     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
1917         return false;
1918
1919     auto it = queue.rbegin();
1920     auto end = queue.rend();
1921
1922     // Must not remove the first event in the deque, since it is already being dispatched.
1923     if (it != end)
1924         --end;
1925
1926     for (; it != end; ++it) {
1927         auto type = it->type();
1928         if (type == incomingEventType) {
1929             queue.remove(--it.base());
1930             return true;
1931         }
1932         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
1933             break;
1934     }
1935     return false;
1936 }
1937
1938 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1939 {
1940     if (!isValid())
1941         return;
1942
1943     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
1944     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
1945     // event in the queue.
1946     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
1947     m_mouseEventQueue.append(event);
1948
1949 #if LOG_DISABLED
1950     UNUSED_PARAM(didRemoveEvent);
1951 #else
1952     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
1953 #endif
1954
1955     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
1956         processNextQueuedMouseEvent();
1957 }
1958     
1959 void WebPageProxy::processNextQueuedMouseEvent()
1960 {
1961     if (!isValid())
1962         return;
1963
1964     ASSERT(!m_mouseEventQueue.isEmpty());
1965
1966     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
1967     
1968     if (m_pageClient.windowIsFrontWindowUnderMouse(event))
1969         setToolTip(String());
1970
1971     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1972     if (event.type() != WebEvent::MouseMove)
1973         m_process->responsivenessTimer().start();
1974
1975     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
1976     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1977 }
1978
1979 #if MERGE_WHEEL_EVENTS
1980 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1981 {
1982     if (a.position() != b.position())
1983         return false;
1984     if (a.globalPosition() != b.globalPosition())
1985         return false;
1986     if (a.modifiers() != b.modifiers())
1987         return false;
1988     if (a.granularity() != b.granularity())
1989         return false;
1990 #if PLATFORM(COCOA)
1991     if (a.phase() != b.phase())
1992         return false;
1993     if (a.momentumPhase() != b.momentumPhase())
1994         return false;
1995     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1996         return false;
1997 #endif
1998
1999     return true;
2000 }
2001
2002 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2003 {
2004     ASSERT(canCoalesce(a, b));
2005
2006     FloatSize mergedDelta = a.delta() + b.delta();
2007     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2008
2009 #if PLATFORM(COCOA)
2010     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2011
2012     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());
2013 #else
2014     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2015 #endif
2016 }
2017 #endif // MERGE_WHEEL_EVENTS
2018
2019 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2020 {
2021     ASSERT(!queue.isEmpty());
2022     ASSERT(coalescedEvents.isEmpty());
2023
2024 #if MERGE_WHEEL_EVENTS
2025     NativeWebWheelEvent firstEvent = queue.takeFirst();
2026     coalescedEvents.append(firstEvent);
2027
2028     WebWheelEvent event = firstEvent;
2029     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2030         NativeWebWheelEvent firstEvent = queue.takeFirst();
2031         coalescedEvents.append(firstEvent);
2032         event = coalesce(event, firstEvent);
2033     }
2034
2035     return event;
2036 #else
2037     while (!queue.isEmpty())
2038         coalescedEvents.append(queue.takeFirst());
2039     return coalescedEvents.last();
2040 #endif
2041 }
2042
2043 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2044 {
2045 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2046     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2047         return;
2048 #endif
2049
2050     if (!isValid())
2051         return;
2052
2053     closeOverlayedViews();
2054
2055     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2056         m_wheelEventQueue.append(event);
2057         if (!shouldProcessWheelEventNow(event))
2058             return;
2059         // The queue has too many wheel events, so push a new event.
2060     }
2061
2062     if (!m_wheelEventQueue.isEmpty()) {
2063         processNextQueuedWheelEvent();
2064         return;
2065     }
2066
2067     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2068     coalescedWheelEvent->append(event);
2069     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2070     sendWheelEvent(event);
2071 }
2072
2073 void WebPageProxy::processNextQueuedWheelEvent()
2074 {
2075     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2076     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2077     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2078     sendWheelEvent(nextWheelEvent);
2079 }
2080
2081 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2082 {
2083     m_process->send(
2084         Messages::EventDispatcher::WheelEvent(
2085             m_pageID,
2086             event,
2087             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2088             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2089             rubberBandsAtTop(),
2090             rubberBandsAtBottom()
2091         ), 0);
2092
2093     // Manually ping the web process to check for responsiveness since our wheel
2094     // event will dispatch to a non-main thread, which always responds.
2095     m_process->isResponsive(nullptr);
2096 }
2097
2098 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2099 {
2100 #if PLATFORM(GTK)
2101     // Don't queue events representing a non-trivial scrolling phase to
2102     // avoid having them trapped in the queue, potentially preventing a
2103     // scrolling session to beginning or end correctly.
2104     // This is only needed by platforms whose WebWheelEvent has this phase
2105     // information (Cocoa and GTK+) but Cocoa was fine without it.
2106     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2107         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2108         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2109         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2110         return true;
2111 #else
2112     UNUSED_PARAM(event);
2113 #endif
2114     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2115         return true;
2116     return false;
2117 }
2118
2119 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2120 {
2121     if (!isValid())
2122         return;
2123     
2124     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2125
2126     m_keyEventQueue.append(event);
2127
2128     m_process->responsivenessTimer().start();
2129     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2130         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2131         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2132     }
2133 }
2134
2135 WebPreferencesStore WebPageProxy::preferencesStore() const
2136 {
2137     if (m_configurationPreferenceValues.isEmpty())
2138         return m_preferences->store();
2139
2140     WebPreferencesStore store = m_preferences->store();
2141     for (const auto& preference : m_configurationPreferenceValues)
2142         store.m_values.set(preference.key, preference.value);
2143
2144     return store;
2145 }
2146
2147 #if ENABLE(NETSCAPE_PLUGIN_API)
2148 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)
2149 {
2150     PageClientProtector protector(m_pageClient);
2151
2152     MESSAGE_CHECK_URL(urlString);
2153
2154     URL pluginURL = URL { URL(), urlString };
2155     String newMimeType = mimeType.convertToASCIILowercase();
2156
2157     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2158
2159     URL pageURL = URL { URL(), pageURLString };
2160     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2161         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2162         return;
2163     }
2164
2165     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2166     if (!plugin.path) {
2167         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2168         return;
2169     }
2170
2171     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2172
2173 #if PLATFORM(COCOA)
2174     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2175 #endif
2176
2177     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2178         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2179         switch (pluginLoadPolicy) {
2180         case PluginModuleLoadNormally:
2181             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2182             break;
2183         case PluginModuleLoadUnsandboxed:
2184             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2185             break;
2186
2187         case PluginModuleBlockedForSecurity:
2188         case PluginModuleBlockedForCompatibility:
2189             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2190             return;
2191         }
2192
2193         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2194     };
2195
2196 #if PLATFORM(COCOA)
2197     if (m_navigationClient) {
2198         m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2199         return;
2200     }
2201 #endif
2202     findPluginCompletion(pluginLoadPolicy, { });
2203 }
2204
2205 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2206
2207 #if ENABLE(TOUCH_EVENTS)
2208
2209 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2210 {
2211     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2212         return b;
2213     return a;
2214 }
2215
2216 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2217 {
2218 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2219     const EventNames& names = eventNames();
2220     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2221         IntPoint location = touchPoint.location();
2222         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2223             if (trackingType == TrackingType::Synchronous)
2224                 return;
2225
2226             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2227
2228             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2229         };
2230         updateTrackingType(m_touchEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2231         updateTrackingType(m_touchEventTracking.touchStartTracking, names.touchstartEvent);
2232         updateTrackingType(m_touchEventTracking.touchMoveTracking, names.touchmoveEvent);
2233         updateTrackingType(m_touchEventTracking.touchEndTracking, names.touchendEvent);
2234     }
2235 #else
2236     UNUSED_PARAM(touchStartEvent);
2237     m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2238     m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
2239     m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
2240     m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
2241 #endif // ENABLE(ASYNC_SCROLLING)
2242 }
2243
2244 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2245 {
2246     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2247     //
2248     // Touch events define a sequence with strong dependencies. For example, we can expect
2249     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2250     // the two.
2251     //
2252     // WebCore should not have to set up its state correctly after some events were dismissed.
2253     // For example, we don't want to send a TouchMoved without a TouchPressed.
2254     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2255     TrackingType globalTrackingType = m_touchEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2256
2257     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchForceChangedTracking);
2258     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2259         switch (touchPoint.state()) {
2260         case WebPlatformTouchPoint::TouchReleased:
2261             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchEndTracking);
2262             break;
2263         case WebPlatformTouchPoint::TouchPressed:
2264             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchStartTracking);
2265             break;
2266         case WebPlatformTouchPoint::TouchMoved:
2267         case WebPlatformTouchPoint::TouchStationary:
2268             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchMoveTracking);
2269             break;
2270         case WebPlatformTouchPoint::TouchCancelled:
2271             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2272             break;
2273         }
2274     }
2275
2276     return globalTrackingType;
2277 }
2278
2279 #endif
2280
2281 #if ENABLE(MAC_GESTURE_EVENTS)
2282 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2283 {
2284     if (!isValid())
2285         return;
2286
2287     m_gestureEventQueue.append(event);
2288     // FIXME: Consider doing some coalescing here.
2289     m_process->responsivenessTimer().start();
2290
2291     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2292 }
2293 #endif
2294
2295 #if ENABLE(IOS_TOUCH_EVENTS)
2296 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2297 {
2298     if (!isValid())
2299         return;
2300
2301     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2302
2303     updateTouchEventTracking(event);
2304
2305     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2306     if (touchEventsTrackingType == TrackingType::NotTracking)
2307         return;
2308
2309     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2310         // We can end up here if a native gesture has not started but the event handlers are passive.
2311         //
2312         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2313         // can prevent a native gesture.
2314         // But, here we know that all events handlers that can handle this events are passive.
2315         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2316         event.setCanPreventNativeGestures(false);
2317         handleTouchEventAsynchronously(event);
2318         didReceiveEvent(event.type(), false);
2319         return;
2320     }
2321
2322     m_process->responsivenessTimer().start();
2323     bool handled = false;
2324     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2325     // 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.
2326     if (!replyReceived)
2327         handled = true;
2328     didReceiveEvent(event.type(), handled);
2329     m_pageClient.doneWithTouchEvent(event, handled);
2330     m_process->responsivenessTimer().stop();
2331
2332     if (event.allTouchPointsAreReleased())
2333         m_touchEventTracking.reset();
2334 }
2335
2336 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2337 {
2338     if (!isValid())
2339         return;
2340
2341     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2342     if (touchEventsTrackingType == TrackingType::NotTracking)
2343         return;
2344
2345     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2346
2347     if (event.allTouchPointsAreReleased())
2348         m_touchEventTracking.reset();
2349 }
2350
2351 #elif ENABLE(TOUCH_EVENTS)
2352 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2353 {
2354     if (!isValid())
2355         return;
2356
2357     updateTouchEventTracking(event);
2358
2359     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2360         return;
2361
2362     // If the page is suspended, which should be the case during panning, pinching
2363     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2364     // we do not send any of the events to the page even if is has listeners.
2365     if (!m_isPageSuspended) {
2366         m_touchEventQueue.append(event);
2367         m_process->responsivenessTimer().start();
2368         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2369     } else {
2370         if (m_touchEventQueue.isEmpty()) {
2371             bool isEventHandled = false;
2372             m_pageClient.doneWithTouchEvent(event, isEventHandled);
2373         } else {
2374             // We attach the incoming events to the newest queued event so that all
2375             // the events are delivered in the correct order when the event is dequed.
2376             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2377             lastEvent.deferredTouchEvents.append(event);
2378         }
2379     }
2380
2381     if (event.allTouchPointsAreReleased())
2382         m_touchEventTracking.reset();
2383 }
2384 #endif // ENABLE(TOUCH_EVENTS)
2385
2386 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2387 {
2388     if (!isValid())
2389         return;
2390
2391     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2392 }
2393
2394 void WebPageProxy::centerSelectionInVisibleArea()
2395 {
2396     if (!isValid())
2397         return;
2398
2399     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2400 }
2401
2402 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2403 public:
2404     using SendFunction = CompletionHandler<void(WebCore::PolicyAction, uint64_t newNavigationID, DownloadID, std::optional<WebsitePoliciesData>)>;
2405     static Ref<PolicyDecisionSender> create(SendFunction&& sendFunction)
2406     {
2407         return adoptRef(*new PolicyDecisionSender(WTFMove(sendFunction)));
2408     }
2409
2410     template<typename... Args> void send(Args... args)
2411     {
2412         if (m_sendFunction)
2413             m_sendFunction(std::forward<Args>(args)...);
2414     }
2415 private:
2416     PolicyDecisionSender(SendFunction sendFunction)
2417         : m_sendFunction(WTFMove(sendFunction)) { }
2418
2419     SendFunction m_sendFunction;
2420 };
2421     
2422 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
2423 {
2424     if (!isValid()) {
2425         sender->send(PolicyAction::Ignore, 0, DownloadID(), std::nullopt);
2426         return;
2427     }
2428
2429     auto transaction = m_pageLoadState.transaction();
2430
2431     if (action == PolicyAction::Ignore)
2432         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2433
2434     if (navigation && navigation->shouldForceDownload() && action == PolicyAction::Use)
2435         action = PolicyAction::Download;
2436
2437     DownloadID downloadID = { };
2438     if (action == PolicyAction::Download) {
2439         // Create a download proxy.
2440         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2441         if (navigation) {
2442             download->setWasUserInitiated(navigation->wasUserInitiated());
2443             download->setRedirectChain(navigation->takeRedirectChain());
2444         }
2445
2446         downloadID = download->downloadID();
2447         handleDownloadRequest(download);
2448         m_decidePolicyForResponseRequest = { };
2449     }
2450
2451     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2452 }
2453
2454 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
2455 {
2456     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2457
2458     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
2459     std::optional<uint64_t> navigatedFrameIdentifierInPreviousProcess;
2460     if (m_mainFrame)
2461         navigatedFrameIdentifierInPreviousProcess = m_mainFrame->frameID();
2462
2463     ASSERT(m_process.ptr() != process.ptr());
2464
2465     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2466
2467     // FIXME: this is to fix the ASSERT(isValid()) inside reattachToWebProcess, some other way to fix this is needed.
2468     m_isValid = false;
2469     reattachToWebProcess(WTFMove(process), &navigation, navigation.targetItem() ? ReattachForBackForward::Yes : ReattachForBackForward::No);
2470
2471     if (auto* item = navigation.targetItem()) {
2472         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2473
2474         auto transaction = m_pageLoadState.transaction();
2475         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2476
2477         auto itemStates = m_backForwardList-> filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
2478             if (auto* page = item.suspendedPage()) {
2479                 if (page->process() == m_process.ptr())
2480                     return false;
2481             }
2482             return &item != targetItem;
2483         });
2484         m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
2485         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes), m_pageID);
2486         m_process->responsivenessTimer().start();
2487
2488         return;
2489     }
2490
2491     // FIXME: Work out timing of responding with the last policy delegate, etc
2492     ASSERT(!navigation.currentRequest().isEmpty());
2493     loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
2494
2495     // Normally, notification of a server redirect comes from the WebContent process.
2496     // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
2497     // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
2498     if (navigation.currentRequestIsRedirect()) {
2499         ASSERT(!m_mainFrame);
2500         m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request =  navigation.currentRequest()]() mutable {
2501             ASSERT(m_mainFrame);
2502             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
2503             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
2504         };
2505     }
2506
2507     if (!navigation.isCrossOriginWindowOpenNavigation() || !navigatedFrameIdentifierInPreviousProcess)
2508         return;
2509
2510     m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), navigatedFrameIdentifierInPreviousProcess = *navigatedFrameIdentifierInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
2511         ASSERT(m_mainFrame);
2512         GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
2513         previousProcess->send(Messages::WebPage::FrameBecameRemote(navigatedFrameIdentifierInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
2514     };
2515 }
2516
2517 void WebPageProxy::setUserAgent(String&& userAgent)
2518 {
2519     if (m_userAgent == userAgent)
2520         return;
2521     m_userAgent = WTFMove(userAgent);
2522
2523 #if ENABLE(SERVICE_WORKER)
2524     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2525     // FIXME: Refactor this when we have a better User-Agent story.
2526     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2527 #endif
2528
2529     if (!isValid())
2530         return;
2531     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2532 }
2533
2534 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2535 {
2536     if (m_applicationNameForUserAgent == applicationName)
2537         return;
2538
2539     m_applicationNameForUserAgent = applicationName;
2540     if (!m_customUserAgent.isEmpty())
2541         return;
2542
2543     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2544 }
2545
2546 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2547 {
2548     if (m_customUserAgent == customUserAgent)
2549         return;
2550
2551     m_customUserAgent = customUserAgent;
2552
2553     if (m_customUserAgent.isEmpty()) {
2554         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2555         return;
2556     }
2557
2558     setUserAgent(String { m_customUserAgent });
2559 }
2560
2561 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2562 {
2563     if (!isValid() || !m_isPageSuspended)
2564         return;
2565
2566     m_isPageSuspended = false;
2567
2568     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2569 }
2570
2571 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2572 {
2573     if (!isValid() || m_isPageSuspended)
2574         return;
2575
2576     m_isPageSuspended = true;
2577
2578     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2579 }
2580
2581 bool WebPageProxy::supportsTextEncoding() const
2582 {
2583     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2584     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2585 }
2586
2587 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2588 {
2589     if (m_customTextEncodingName == encodingName)
2590         return;
2591     m_customTextEncodingName = encodingName;
2592
2593     if (!isValid())
2594         return;
2595     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2596 }
2597
2598 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2599 {
2600     SessionState sessionState;
2601
2602     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2603
2604     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2605     if (provisionalURLString.isEmpty())
2606         provisionalURLString = m_pageLoadState.provisionalURL();
2607
2608     if (!provisionalURLString.isEmpty())
2609         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2610
2611     sessionState.renderTreeSize = renderTreeSize();
2612     return sessionState;
2613 }
2614
2615 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2616 {
2617     m_sessionRestorationRenderTreeSize = 0;
2618     m_hitRenderTreeSizeThreshold = false;
2619
2620     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2621
2622     if (hasBackForwardList) {
2623         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2624         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2625
2626         auto transaction = m_pageLoadState.transaction();
2627         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2628         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2629
2630         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2631         // page when navigating away. Suppress navigation snapshotting until the next load has committed
2632         m_suppressAutomaticNavigationSnapshotting = true;
2633     }
2634
2635     // FIXME: Navigating should be separate from state restoration.
2636     if (navigate) {
2637         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2638         if (!m_sessionRestorationRenderTreeSize)
2639             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2640
2641         if (!sessionState.provisionalURL.isNull())
2642             return loadRequest(sessionState.provisionalURL);
2643
2644         if (hasBackForwardList) {
2645             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2646                 return goToBackForwardItem(*item);
2647         }
2648     }
2649
2650     return nullptr;
2651 }
2652
2653 bool WebPageProxy::supportsTextZoom() const
2654 {
2655     // FIXME (118840): This should also return false for standalone media and plug-in documents.
2656     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2657         return false;
2658
2659     return true;
2660 }
2661  
2662 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2663 {
2664     if (!isValid())
2665         return;
2666
2667     if (m_textZoomFactor == zoomFactor)
2668         return;
2669
2670     m_textZoomFactor = zoomFactor;
2671     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
2672 }
2673
2674 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2675 {
2676     if (!isValid())
2677         return;
2678
2679     if (m_pageZoomFactor == zoomFactor)
2680         return;
2681
2682     closeOverlayedViews();
2683
2684     m_pageZoomFactor = zoomFactor;
2685     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
2686 }
2687
2688 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2689 {
2690     if (!isValid())
2691         return;
2692
2693     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2694         return;
2695
2696     closeOverlayedViews();
2697
2698     m_pageZoomFactor = pageZoomFactor;
2699     m_textZoomFactor = textZoomFactor;
2700     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
2701 }
2702
2703 double WebPageProxy::pageZoomFactor() const
2704 {
2705     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2706     // zoom which ensures that we don't use the PDF zoom for a normal page.
2707     if (m_mainFramePluginHandlesPageScaleGesture)
2708         return m_pluginZoomFactor;
2709     return m_pageZoomFactor;
2710 }
2711
2712 double WebPageProxy::pageScaleFactor() const
2713 {
2714     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2715     // separately but decide which to return based on the main frame.
2716     if (m_mainFramePluginHandlesPageScaleGesture)
2717         return m_pluginScaleFactor;
2718     return m_pageScaleFactor;
2719 }
2720
2721 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
2722 {
2723     ASSERT(scale > 0);
2724
2725     if (!isValid())
2726         return;
2727
2728     m_pageScaleFactor = scale;
2729     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
2730 }
2731
2732 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
2733 {
2734     ASSERT(scale > 0);
2735
2736     if (!isValid())
2737         return;
2738
2739     m_pageScaleFactor = scale;
2740     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
2741 }
2742
2743 void WebPageProxy::scaleView(double scale)
2744 {
2745     ASSERT(scale > 0);
2746
2747     if (!isValid())
2748         return;
2749
2750     m_viewScaleFactor = scale;
2751     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
2752 }
2753
2754 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
2755 {
2756     if (m_intrinsicDeviceScaleFactor == scaleFactor)
2757         return;
2758
2759     m_intrinsicDeviceScaleFactor = scaleFactor;
2760
2761     if (m_drawingArea)
2762         m_drawingArea->deviceScaleFactorDidChange();
2763 }
2764
2765 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
2766 {
2767     if (!isValid())
2768         return;
2769
2770     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
2771 }
2772
2773 float WebPageProxy::deviceScaleFactor() const
2774 {
2775     return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
2776 }
2777
2778 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2779 {
2780     if (!isValid())
2781         return;
2782
2783     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2784     // https://bugs.webkit.org/show_bug.cgi?id=133378
2785 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2786     return;
2787 #endif
2788
2789     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
2790         return;
2791
2792     float oldScaleFactor = deviceScaleFactor();
2793
2794     // A value of 0 clears the customScaleFactor.
2795     if (customScaleFactor)
2796         m_customDeviceScaleFactor = customScaleFactor;
2797     else
2798         m_customDeviceScaleFactor = std::nullopt;
2799
2800     if (deviceScaleFactor() != oldScaleFactor)
2801         m_drawingArea->deviceScaleFactorDidChange();
2802 }
2803
2804 void WebPageProxy::accessibilitySettingsDidChange()
2805 {
2806     if (!isValid())
2807         return;
2808
2809     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
2810 }
2811
2812 #if ENABLE(ACCESSIBILITY_EVENTS)
2813 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
2814 {
2815     if (!isValid())
2816         return;
2817
2818     m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
2819 }
2820 #endif
2821
2822 void WebPageProxy::setUseFixedLayout(bool fixed)
2823 {
2824     if (!isValid())
2825         return;
2826
2827     // This check is fine as the value is initialized in the web
2828     // process as part of the creation parameters.
2829     if (fixed == m_useFixedLayout)
2830         return;
2831
2832     m_useFixedLayout = fixed;
2833     if (!fixed)
2834         m_fixedLayoutSize = IntSize();
2835     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2836 }
2837
2838 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2839 {
2840     if (!isValid())
2841         return;
2842
2843     if (size == m_fixedLayoutSize)
2844         return;
2845
2846     m_fixedLayoutSize = size;
2847     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2848 }
2849
2850 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
2851 {
2852     if (!isValid())
2853         return;
2854
2855     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
2856         return;
2857
2858     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
2859     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
2860 }
2861
2862 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
2863 {
2864     if (!isValid())
2865         return;
2866
2867     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
2868         return;
2869
2870     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
2871     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
2872 }
2873
2874 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2875 {
2876     if (!isValid())
2877         return;
2878     
2879     if (milestones == m_observedLayoutMilestones)
2880         return;
2881
2882     m_observedLayoutMilestones = milestones;
2883     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2884 }
2885
2886 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
2887 {
2888     if (!isValid())
2889         return;
2890
2891     if (suppressAnimations == m_suppressScrollbarAnimations)
2892         return;
2893
2894     m_suppressScrollbarAnimations = suppressAnimations;
2895     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
2896 }
2897
2898 bool WebPageProxy::rubberBandsAtLeft() const
2899 {
2900     return m_rubberBandsAtLeft;
2901 }
2902
2903 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
2904 {
2905     m_rubberBandsAtLeft = rubberBandsAtLeft;
2906 }
2907
2908 bool WebPageProxy::rubberBandsAtRight() const
2909 {
2910     return m_rubberBandsAtRight;
2911 }
2912
2913 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
2914 {
2915     m_rubberBandsAtRight = rubberBandsAtRight;
2916 }
2917
2918 bool WebPageProxy::rubberBandsAtTop() const
2919 {
2920     return m_rubberBandsAtTop;
2921 }
2922
2923 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
2924 {
2925     m_rubberBandsAtTop = rubberBandsAtTop;
2926 }
2927
2928 bool WebPageProxy::rubberBandsAtBottom() const
2929 {
2930     return m_rubberBandsAtBottom;
2931 }
2932
2933 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
2934 {
2935     m_rubberBandsAtBottom = rubberBandsAtBottom;
2936 }
2937     
2938 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2939 {
2940     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
2941         return;
2942
2943     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
2944
2945     if (!isValid())
2946         return;
2947     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
2948 }
2949     
2950 bool WebPageProxy::verticalRubberBandingIsEnabled() const
2951 {
2952     return m_enableVerticalRubberBanding;
2953 }
2954     
2955 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2956 {
2957     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
2958         return;
2959
2960     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
2961
2962     if (!isValid())
2963         return;
2964     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
2965 }
2966     
2967 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
2968 {
2969     return m_enableHorizontalRubberBanding;
2970 }
2971
2972 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2973 {
2974     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
2975         return;
2976
2977     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
2978
2979     if (!isValid())
2980         return;
2981     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
2982 }
2983
2984 bool WebPageProxy::backgroundExtendsBeyondPage() const
2985 {
2986     return m_backgroundExtendsBeyondPage;
2987 }
2988
2989 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
2990 {
2991     if (mode == m_paginationMode)
2992         return;
2993
2994     m_paginationMode = mode;
2995
2996     if (!isValid())
2997         return;
2998     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
2999 }
3000
3001 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3002 {
3003     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3004         return;
3005
3006     m_paginationBehavesLikeColumns = behavesLikeColumns;
3007
3008     if (!isValid())
3009         return;
3010     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3011 }
3012
3013 void WebPageProxy::setPageLength(double pageLength)
3014 {
3015     if (pageLength == m_pageLength)
3016         return;
3017
3018     m_pageLength = pageLength;
3019
3020     if (!isValid())
3021         return;
3022     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3023 }
3024
3025 void WebPageProxy::setGapBetweenPages(double gap)
3026 {
3027     if (gap == m_gapBetweenPages)
3028         return;
3029
3030     m_gapBetweenPages = gap;
3031
3032     if (!isValid())
3033         return;
3034     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3035 }
3036
3037 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3038 {
3039     if (lineGridEnabled == m_paginationLineGridEnabled)
3040         return;
3041     
3042     m_paginationLineGridEnabled = lineGridEnabled;
3043     
3044     if (!isValid())
3045         return;
3046     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3047 }
3048
3049 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3050 {
3051     m_pageScaleFactor = scaleFactor;
3052 }
3053
3054 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3055 {
3056     m_pluginScaleFactor = pluginScaleFactor;
3057 }
3058
3059 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3060 {
3061     m_pluginZoomFactor = pluginZoomFactor;
3062 }
3063
3064 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3065 {
3066     if (string.isEmpty()) {
3067         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3068         return;
3069     }
3070
3071     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3072 }
3073
3074 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3075 {
3076     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3077 }
3078
3079 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3080 {
3081     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3082 }
3083
3084 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3085 {
3086     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3087 }
3088
3089 void WebPageProxy::hideFindUI()
3090 {
3091     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3092 }
3093
3094 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3095 {
3096     if (!isValid())
3097         return;
3098
3099     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3100 }
3101
3102 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3103 {
3104     if (!isValid()) {
3105         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3106         return;
3107     }
3108
3109     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3110     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3111 }
3112
3113 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3114 {
3115     if (!isValid()) {
3116         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3117         return;
3118     }
3119
3120     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3121     m_process->send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3122 }
3123
3124 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3125 {
3126     if (!isValid()) {
3127         callbackFunction(String(), CallbackBase::Error::Unknown);
3128         return;
3129     }
3130     
3131     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3132     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3133 }
3134
3135 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3136 {
3137     if (!isValid()) {
3138         callbackFunction(String(), CallbackBase::Error::Unknown);
3139         return;
3140     }
3141     
3142     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3143     m_loadDependentStringCallbackIDs.add(callbackID);
3144     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3145 }
3146
3147 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3148 {
3149     if (!isValid()) {
3150         callbackFunction(String(), CallbackBase::Error::Unknown);
3151         return;
3152     }
3153     
3154     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3155     m_loadDependentStringCallbackIDs.add(callbackID);
3156     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3157 }
3158
3159 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3160 {
3161     if (!isValid()) {
3162         callbackFunction(String(), CallbackBase::Error::Unknown);
3163         return;
3164     }
3165     
3166     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3167     m_loadDependentStringCallbackIDs.add(callbackID);
3168     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3169 }
3170
3171 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3172 {
3173     if (!isValid()) {
3174         callbackFunction(String(), CallbackBase::Error::Unknown);
3175         return;
3176     }
3177     
3178     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3179     m_loadDependentStringCallbackIDs.add(callbackID);
3180     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3181 }
3182
3183 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
3184 {
3185     if (!isValid()) {
3186         RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
3187             bool isWebProcessResponsive = true;
3188             callbackFunction(isWebProcessResponsive);
3189         });
3190         return;
3191     }
3192
3193     m_process->isResponsive(WTFMove(callbackFunction));
3194 }
3195
3196 #if ENABLE(MHTML)
3197 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3198 {
3199     if (!isValid()) {
3200         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3201         return;
3202     }
3203
3204     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3205     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3206 }
3207 #endif
3208
3209 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3210 {
3211     if (!isValid()) {
3212         callbackFunction(String(), CallbackBase::Error::Unknown);
3213         return;
3214     }
3215     
3216     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3217     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
3218 }
3219
3220 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3221 {
3222     if (!isValid()) {
3223         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3224         return;
3225     }
3226     
3227     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3228     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3229 }
3230
3231 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3232 {
3233     if (!isValid() || !frame) {
3234         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3235         return;
3236     }
3237     
3238     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3239     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3240 }
3241
3242 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3243 {
3244     if (!isValid()) {
3245         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3246         return;
3247     }
3248     
3249     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3250     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3251 }
3252
3253 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3254 {
3255     if (!isValid()) {
3256         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3257         return;
3258     }
3259     
3260     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3261     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3262 }
3263
3264 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3265 {
3266     if (!isValid()) {
3267         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3268         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3269         return;
3270     }
3271
3272     Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3273         if (error != CallbackBase::Error::None) {
3274             callback->invalidate(error);
3275             return;
3276         }
3277
3278         if (!isValid()) {
3279             callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3280             return;
3281         }
3282     
3283         callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3284             if (error != CallbackBase::Error::None) {
3285                 callback->invalidate(error);
3286                 return;
3287             }
3288
3289             callback->performCallback();
3290         });
3291     };
3292
3293     auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3294     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3295     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
3296 }
3297
3298 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3299 {
3300     if (isPerformingDOMPrintOperation)
3301         return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3302
3303     return { };
3304 }
3305
3306 void WebPageProxy::preferencesDidChange()
3307 {
3308     if (!isValid())
3309         return;
3310
3311     updateThrottleState();
3312     updateHiddenPageThrottlingAutoIncreases();
3313
3314     m_pageClient.preferencesDidChange();
3315
3316     // FIXME: It probably makes more sense to send individual preference changes.
3317     // However, WebKitTestRunner depends on getting a preference change notification
3318     // even if nothing changed in UI process, so that overrides get removed.
3319
3320     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3321     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3322 }
3323
3324 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3325 {
3326     PageClientProtector protector(m_pageClient);
3327
3328     MESSAGE_CHECK(!m_mainFrame);
3329     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3330
3331     m_mainFrame = WebFrameProxy::create(this, frameID);
3332     m_mainFrameID = frameID;
3333
3334     // Add the frame to the process wide map.
3335     m_process->frameCreated(frameID, *m_mainFrame);
3336
3337     if (m_mainFrameCreationHandler) {
3338         m_mainFrameCreationHandler();
3339         m_mainFrameCreationHandler = nullptr;
3340     }
3341 }
3342
3343 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3344 {
3345     PageClientProtector protector(m_pageClient);
3346
3347     MESSAGE_CHECK(m_mainFrame);
3348     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3349     
3350     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
3351
3352     // Add the frame to the process wide map.
3353     m_process->frameCreated(frameID, *subFrame);
3354 }
3355
3356 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
3357 {
3358     if (m_mainFrame && m_mainFrame->frameID() == frameID) {
3359         if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
3360             mainFrameWindowCreationHandler(windowIdentifier);
3361     }
3362 }
3363
3364 double WebPageProxy::estimatedProgress() const
3365 {
3366     return m_pageLoadState.estimatedProgress();
3367 }
3368
3369 void WebPageProxy::didStartProgress()
3370 {
3371     PageClientProtector protector(m_pageClient);
3372
3373     auto transaction = m_pageLoadState.transaction();
3374     m_pageLoadState.didStartProgress(transaction);
3375
3376     m_pageLoadState.commitChanges();
3377 }
3378
3379 void WebPageProxy::didChangeProgress(double value)
3380 {
3381     PageClientProtector protector(m_pageClient);
3382
3383     auto transaction = m_pageLoadState.transaction();
3384     m_pageLoadState.didChangeProgress(transaction, value);
3385
3386     m_pageLoadState.commitChanges();
3387 }
3388
3389 void WebPageProxy::didFinishProgress()
3390 {
3391     PageClientProtector protector(m_pageClient);
3392
3393     auto transaction = m_pageLoadState.transaction();
3394     m_pageLoadState.didFinishProgress(transaction);
3395
3396     m_pageLoadState.commitChanges();
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()
3590 {
3591     HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);