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