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