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