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