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