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