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