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