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