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