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