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