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