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