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