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