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