3a0c62047d20df74dd6e28456cb04919416eda6c
[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::validateCommand(const String& commandName, std::function<void (const String&, bool, int32_t, CallbackBase::Error)> callbackFunction)
1448 {
1449     if (!isValid()) {
1450         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1451         return;
1452     }
1453
1454     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
1455     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1456 }
1457
1458 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1459 {
1460     m_maintainsInactiveSelection = newValue;
1461 }
1462     
1463 void WebPageProxy::executeEditCommand(const String& commandName)
1464 {
1465     static NeverDestroyed<String> ignoreSpellingCommandName(ASCIILiteral("ignoreSpelling"));
1466
1467     if (!isValid())
1468         return;
1469
1470     if (commandName == ignoreSpellingCommandName)
1471         ++m_pendingLearnOrIgnoreWordMessageCount;
1472
1473     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName), m_pageID);
1474 }
1475
1476 void WebPageProxy::setEditable(bool editable)
1477 {
1478     if (editable == m_isEditable)
1479         return;
1480     if (!isValid())
1481         return;
1482
1483     m_isEditable = editable;
1484     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1485 }
1486
1487 #if !PLATFORM(IOS)
1488 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1489 {
1490 }
1491 #endif
1492
1493 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
1494 void WebPageProxy::commitPageTransitionViewport()
1495 {
1496     if (!isValid())
1497         return;
1498
1499     process().send(Messages::WebPage::CommitPageTransitionViewport(), m_pageID);
1500 }
1501 #endif
1502
1503 #if ENABLE(DRAG_SUPPORT)
1504 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1505 {
1506     SandboxExtension::Handle sandboxExtensionHandle;
1507     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1508     performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1509 }
1510
1511 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1512 {
1513     SandboxExtension::Handle sandboxExtensionHandle;
1514     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1515     performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1516 }
1517
1518 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1519 {
1520     SandboxExtension::Handle sandboxExtensionHandle;
1521     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1522     performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1523 }
1524
1525 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1526 {
1527     performDragControllerAction(DragControllerActionPerformDragOperation, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload);
1528 }
1529
1530 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1531 {
1532     if (!isValid())
1533         return;
1534 #if PLATFORM(GTK)
1535     UNUSED_PARAM(dragStorageName);
1536     UNUSED_PARAM(sandboxExtensionHandle);
1537     UNUSED_PARAM(sandboxExtensionsForUpload);
1538
1539     String url = dragData.asURL();
1540     if (!url.isEmpty())
1541         m_process->assumeReadAccessToBaseURL(url);
1542     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData), m_pageID);
1543 #else
1544     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), dragStorageName, dragData.flags(), sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1545 #endif
1546 }
1547
1548 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted)
1549 {
1550     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1551
1552     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1553     m_currentDragIsOverFileInput = mouseIsOverFileInput;
1554     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1555 }
1556
1557 #if PLATFORM(GTK)
1558 void WebPageProxy::startDrag(const DragData& dragData, const ShareableBitmap::Handle& dragImageHandle)
1559 {
1560     RefPtr<ShareableBitmap> dragImage = 0;
1561     if (!dragImageHandle.isNull()) {
1562         dragImage = ShareableBitmap::create(dragImageHandle);
1563         if (!dragImage)
1564             return;
1565     }
1566
1567     m_pageClient.startDrag(dragData, dragImage.release());
1568 }
1569 #endif
1570
1571 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1572 {
1573     if (!isValid())
1574         return;
1575     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1576 }
1577 #endif // ENABLE(DRAG_SUPPORT)
1578
1579 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1580 {
1581     if (!isValid())
1582         return;
1583
1584     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1585     if (event.type() != WebEvent::MouseMove)
1586         m_process->responsivenessTimer()->start();
1587     else {
1588         if (m_processingMouseMoveEvent) {
1589             m_nextMouseMoveEvent = std::make_unique<NativeWebMouseEvent>(event);
1590             return;
1591         }
1592
1593         m_processingMouseMoveEvent = true;
1594     }
1595
1596     // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1597     // display a popup menu for select elements. When the user changes the selected item,
1598     // we fake a mouse up event by using this stored down event. This event gets cleared
1599     // when the mouse up message is received from WebProcess.
1600     if (event.type() == WebEvent::MouseDown)
1601         m_currentlyProcessedMouseDownEvent = std::make_unique<NativeWebMouseEvent>(event);
1602
1603     if (m_shouldSendEventsSynchronously) {
1604         bool handled = false;
1605         m_process->sendSync(Messages::WebPage::MouseEventSyncForTesting(event), Messages::WebPage::MouseEventSyncForTesting::Reply(handled), m_pageID);
1606         didReceiveEvent(event.type(), handled);
1607     } else
1608         m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1609 }
1610
1611 #if MERGE_WHEEL_EVENTS
1612 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1613 {
1614     if (a.position() != b.position())
1615         return false;
1616     if (a.globalPosition() != b.globalPosition())
1617         return false;
1618     if (a.modifiers() != b.modifiers())
1619         return false;
1620     if (a.granularity() != b.granularity())
1621         return false;
1622 #if PLATFORM(COCOA)
1623     if (a.phase() != b.phase())
1624         return false;
1625     if (a.momentumPhase() != b.momentumPhase())
1626         return false;
1627     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1628         return false;
1629 #endif
1630
1631     return true;
1632 }
1633
1634 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1635 {
1636     ASSERT(canCoalesce(a, b));
1637
1638     FloatSize mergedDelta = a.delta() + b.delta();
1639     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1640
1641 #if PLATFORM(COCOA)
1642     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1643
1644     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());
1645 #else
1646     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1647 #endif
1648 }
1649 #endif // MERGE_WHEEL_EVENTS
1650
1651 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1652 {
1653     ASSERT(!queue.isEmpty());
1654     ASSERT(coalescedEvents.isEmpty());
1655
1656 #if MERGE_WHEEL_EVENTS
1657     NativeWebWheelEvent firstEvent = queue.takeFirst();
1658     coalescedEvents.append(firstEvent);
1659
1660     WebWheelEvent event = firstEvent;
1661     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1662         NativeWebWheelEvent firstEvent = queue.takeFirst();
1663         coalescedEvents.append(firstEvent);
1664         event = coalesce(event, firstEvent);
1665     }
1666
1667     return event;
1668 #else
1669     while (!queue.isEmpty())
1670         coalescedEvents.append(queue.takeFirst());
1671     return coalescedEvents.last();
1672 #endif
1673 }
1674
1675 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1676 {
1677 #if ENABLE(ASYNC_SCROLLING)
1678     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
1679         return;
1680 #endif
1681
1682     if (!isValid())
1683         return;
1684
1685     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1686         m_wheelEventQueue.append(event);
1687         if (m_wheelEventQueue.size() < wheelEventQueueSizeThreshold)
1688             return;
1689         // The queue has too many wheel events, so push a new event.
1690     }
1691
1692     if (!m_wheelEventQueue.isEmpty()) {
1693         processNextQueuedWheelEvent();
1694         return;
1695     }
1696
1697     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1698     coalescedWheelEvent->append(event);
1699     m_currentlyProcessedWheelEvents.append(WTF::move(coalescedWheelEvent));
1700     sendWheelEvent(event);
1701 }
1702
1703 void WebPageProxy::processNextQueuedWheelEvent()
1704 {
1705     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1706     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1707     m_currentlyProcessedWheelEvents.append(WTF::move(nextCoalescedEvent));
1708     sendWheelEvent(nextWheelEvent);
1709 }
1710
1711 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1712 {
1713     m_process->responsivenessTimer()->start();
1714
1715     if (m_shouldSendEventsSynchronously) {
1716         bool handled = false;
1717         m_process->sendSync(Messages::WebPage::WheelEventSyncForTesting(event), Messages::WebPage::WheelEventSyncForTesting::Reply(handled), m_pageID);
1718         didReceiveEvent(event.type(), handled);
1719         return;
1720     }
1721
1722     m_process->send(
1723         Messages::EventDispatcher::WheelEvent(
1724             m_pageID,
1725             event,
1726             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
1727             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
1728             rubberBandsAtTop(),
1729             rubberBandsAtBottom()
1730         ), 0);
1731 }
1732
1733 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
1734 {
1735     if (!isValid())
1736         return;
1737     
1738     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
1739
1740     m_keyEventQueue.append(event);
1741
1742     m_process->responsivenessTimer()->start();
1743     if (m_shouldSendEventsSynchronously) {
1744         bool handled = false;
1745         m_process->sendSync(Messages::WebPage::KeyEventSyncForTesting(event), Messages::WebPage::KeyEventSyncForTesting::Reply(handled), m_pageID);
1746         didReceiveEvent(event.type(), handled);
1747     } else if (m_keyEventQueue.size() == 1) // Otherwise, sent from DidReceiveEvent message handler.
1748         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
1749 }
1750
1751 WebPreferencesStore WebPageProxy::preferencesStore() const
1752 {
1753     if (m_configurationPreferenceValues.isEmpty())
1754         return m_preferences->store();
1755
1756     WebPreferencesStore store = m_preferences->store();
1757     for (const auto& preference : m_configurationPreferenceValues)
1758         store.m_values.set(preference.key, preference.value);
1759
1760     return store;
1761 }
1762
1763 #if ENABLE(NETSCAPE_PLUGIN_API)
1764 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)
1765 {
1766     MESSAGE_CHECK_URL(urlString);
1767
1768     newMimeType = mimeType.lower();
1769     pluginLoadPolicy = PluginModuleLoadNormally;
1770
1771     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
1772     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), urlString), allowedPluginTypes);
1773     if (!plugin.path) {
1774         pluginProcessToken = 0;
1775         return;
1776     }
1777
1778     pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
1779
1780 #if PLATFORM(COCOA)
1781     RefPtr<API::Dictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
1782     if (m_navigationClient)
1783         pluginLoadPolicy = m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
1784     else
1785         pluginLoadPolicy = m_loaderClient->pluginLoadPolicy(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
1786 #else
1787     UNUSED_PARAM(frameURLString);
1788     UNUSED_PARAM(pageURLString);
1789     UNUSED_PARAM(unavailabilityDescription);
1790 #endif
1791
1792     PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1793     switch (pluginLoadPolicy) {
1794     case PluginModuleLoadNormally:
1795         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1796         break;
1797     case PluginModuleLoadUnsandboxed:
1798         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
1799         break;
1800
1801     case PluginModuleBlocked:
1802         pluginProcessToken = 0;
1803         return;
1804     }
1805
1806     pluginProcessToken = PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
1807 }
1808
1809 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1810
1811 #if ENABLE(TOUCH_EVENTS)
1812
1813 bool WebPageProxy::shouldStartTrackingTouchEvents(const WebTouchEvent& touchStartEvent) const
1814 {
1815 #if ENABLE(ASYNC_SCROLLING)
1816     for (auto& touchPoint : touchStartEvent.touchPoints()) {
1817         if (m_scrollingCoordinatorProxy->isPointInNonFastScrollableRegion(touchPoint.location()))
1818             return true;
1819     }
1820
1821     return false;
1822 #else
1823     UNUSED_PARAM(touchStartEvent);
1824 #endif // ENABLE(ASYNC_SCROLLING)
1825     return true;
1826 }
1827
1828 #endif
1829
1830 #if ENABLE(IOS_TOUCH_EVENTS)
1831 void WebPageProxy::handleTouchEventSynchronously(const NativeWebTouchEvent& event)
1832 {
1833     if (!isValid())
1834         return;
1835
1836     if (event.type() == WebEvent::TouchStart) {
1837         m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
1838         m_layerTreeTransactionIdAtLastTouchStart = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).lastCommittedLayerTreeTransactionID();
1839     }
1840
1841     if (!m_isTrackingTouchEvents)
1842         return;
1843
1844     m_process->responsivenessTimer()->start();
1845     bool handled = false;
1846     m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
1847     didReceiveEvent(event.type(), handled);
1848     m_pageClient.doneWithTouchEvent(event, handled);
1849     m_process->responsivenessTimer()->stop();
1850
1851     if (event.allTouchPointsAreReleased())
1852         m_isTrackingTouchEvents = false;
1853 }
1854
1855 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
1856 {
1857     if (!isValid())
1858         return;
1859
1860     if (!m_isTrackingTouchEvents)
1861         return;
1862
1863     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
1864
1865     if (event.allTouchPointsAreReleased())
1866         m_isTrackingTouchEvents = false;
1867 }
1868
1869 #elif ENABLE(TOUCH_EVENTS)
1870 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
1871 {
1872     if (!isValid())
1873         return;
1874
1875     if (event.type() == WebEvent::TouchStart)
1876         m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
1877
1878     if (!m_isTrackingTouchEvents)
1879         return;
1880
1881     // If the page is suspended, which should be the case during panning, pinching
1882     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
1883     // we do not send any of the events to the page even if is has listeners.
1884     if (!m_isPageSuspended) {
1885         m_touchEventQueue.append(event);
1886         m_process->responsivenessTimer()->start();
1887         if (m_shouldSendEventsSynchronously) {
1888             bool handled = false;
1889             m_process->sendSync(Messages::WebPage::TouchEventSyncForTesting(event), Messages::WebPage::TouchEventSyncForTesting::Reply(handled), m_pageID);
1890             didReceiveEvent(event.type(), handled);
1891         } else
1892             m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
1893     } else {
1894         if (m_touchEventQueue.isEmpty()) {
1895             bool isEventHandled = false;
1896             m_pageClient.doneWithTouchEvent(event, isEventHandled);
1897         } else {
1898             // We attach the incoming events to the newest queued event so that all
1899             // the events are delivered in the correct order when the event is dequed.
1900             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
1901             lastEvent.deferredTouchEvents.append(event);
1902         }
1903     }
1904
1905     if (event.allTouchPointsAreReleased())
1906         m_isTrackingTouchEvents = false;
1907 }
1908 #endif // ENABLE(TOUCH_EVENTS)
1909
1910 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
1911 {
1912     if (!isValid())
1913         return;
1914
1915     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
1916 }
1917
1918 void WebPageProxy::centerSelectionInVisibleArea()
1919 {
1920     if (!isValid())
1921         return;
1922
1923     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
1924 }
1925
1926 void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* frame, uint64_t listenerID, API::Navigation* navigation)
1927 {
1928     if (!isValid())
1929         return;
1930
1931     auto transaction = m_pageLoadState.transaction();
1932
1933     if (action == PolicyIgnore)
1934         m_pageLoadState.clearPendingAPIRequestURL(transaction);
1935
1936     uint64_t downloadID = 0;
1937     if (action == PolicyDownload) {
1938         // Create a download proxy.
1939         // FIXME: We should ensure that the downloadRequest is never empty.
1940         const ResourceRequest& downloadRequest = m_decidePolicyForResponseRequest ? *m_decidePolicyForResponseRequest : ResourceRequest();
1941         DownloadProxy* download = m_process->processPool().createDownloadProxy(downloadRequest);
1942         downloadID = download->downloadID();
1943         handleDownloadRequest(download);
1944     }
1945
1946     // If we received a policy decision while in decidePolicyForResponse the decision will
1947     // be sent back to the web process by decidePolicyForResponse.
1948     if (m_inDecidePolicyForResponseSync) {
1949         m_syncMimeTypePolicyActionIsValid = true;
1950         m_syncMimeTypePolicyAction = action;
1951         m_syncMimeTypePolicyDownloadID = downloadID;
1952         return;
1953     }
1954
1955     // If we received a policy decision while in decidePolicyForNavigationAction the decision will 
1956     // be sent back to the web process by decidePolicyForNavigationAction. 
1957     if (m_inDecidePolicyForNavigationAction) {
1958         m_syncNavigationActionPolicyActionIsValid = true;
1959         m_syncNavigationActionPolicyAction = action;
1960         m_syncNavigationActionPolicyDownloadID = downloadID;
1961         return;
1962     }
1963     
1964     m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame->frameID(), listenerID, action, navigation ? navigation->navigationID() : 0, downloadID), m_pageID);
1965 }
1966
1967 void WebPageProxy::setUserAgent(const String& userAgent)
1968 {
1969     if (m_userAgent == userAgent)
1970         return;
1971     m_userAgent = userAgent;
1972
1973     if (!isValid())
1974         return;
1975     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
1976 }
1977
1978 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
1979 {
1980     if (m_applicationNameForUserAgent == applicationName)
1981         return;
1982
1983     m_applicationNameForUserAgent = applicationName;
1984     if (!m_customUserAgent.isEmpty())
1985         return;
1986
1987     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1988 }
1989
1990 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
1991 {
1992     if (m_customUserAgent == customUserAgent)
1993         return;
1994
1995     m_customUserAgent = customUserAgent;
1996
1997     if (m_customUserAgent.isEmpty()) {
1998         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1999         return;
2000     }
2001
2002     setUserAgent(m_customUserAgent);
2003 }
2004
2005 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2006 {
2007     if (!isValid() || !m_isPageSuspended)
2008         return;
2009
2010     m_isPageSuspended = false;
2011
2012     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2013 }
2014
2015 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2016 {
2017     if (!isValid() || m_isPageSuspended)
2018         return;
2019
2020     m_isPageSuspended = true;
2021
2022     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2023 }
2024
2025 bool WebPageProxy::supportsTextEncoding() const
2026 {
2027     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2028     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2029 }
2030
2031 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2032 {
2033     if (m_customTextEncodingName == encodingName)
2034         return;
2035     m_customTextEncodingName = encodingName;
2036
2037     if (!isValid())
2038         return;
2039     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2040 }
2041
2042 void WebPageProxy::terminateProcess()
2043 {
2044     // requestTermination() is a no-op for launching processes, so we get into an inconsistent state by calling resetStateAfterProcessExited().
2045     // 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.
2046     // See also <https://bugs.webkit.org/show_bug.cgi?id=136012>.
2047     ASSERT(m_process->state() != WebProcessProxy::State::Launching);
2048
2049     // NOTE: This uses a check of m_isValid rather than calling isValid() since
2050     // we want this to run even for pages being closed or that already closed.
2051     if (!m_isValid)
2052         return;
2053
2054     m_process->requestTermination();
2055     resetStateAfterProcessExited();
2056 }
2057
2058 SessionState WebPageProxy::sessionState(const std::function<bool (WebBackForwardListItem&)>& filter) const
2059 {
2060     SessionState sessionState;
2061
2062     sessionState.backForwardListState = m_backForwardList->backForwardListState(filter);
2063
2064     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2065     if (provisionalURLString.isEmpty())
2066         provisionalURLString = m_pageLoadState.provisionalURL();
2067
2068     if (!provisionalURLString.isEmpty())
2069         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2070
2071     sessionState.renderTreeSize = renderTreeSize();
2072     return sessionState;
2073 }
2074
2075 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2076 {
2077     m_sessionRestorationRenderTreeSize = 0;
2078     m_hitRenderTreeSizeThreshold = false;
2079
2080     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2081
2082     if (hasBackForwardList) {
2083         m_backForwardList->restoreFromState(WTF::move(sessionState.backForwardListState));
2084
2085         for (const auto& entry : m_backForwardList->entries())
2086             process().registerNewWebBackForwardListItem(entry.get());
2087
2088         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2089     }
2090
2091     // FIXME: Navigating should be separate from state restoration.
2092     if (navigate) {
2093         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2094         if (!m_sessionRestorationRenderTreeSize)
2095             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2096
2097         if (!sessionState.provisionalURL.isNull())
2098             return loadRequest(sessionState.provisionalURL);
2099
2100         if (hasBackForwardList) {
2101             // FIXME: Do we have to null check the back forward list item here?
2102             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2103                 return goToBackForwardItem(item);
2104         }
2105     }
2106
2107     return nullptr;
2108 }
2109
2110 bool WebPageProxy::supportsTextZoom() const
2111 {
2112     // FIXME (118840): This should also return false for standalone media and plug-in documents.
2113     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2114         return false;
2115
2116     return true;
2117 }
2118  
2119 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2120 {
2121     if (!isValid())
2122         return;
2123
2124     if (m_textZoomFactor == zoomFactor)
2125         return;
2126
2127     m_textZoomFactor = zoomFactor;
2128     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
2129 }
2130
2131 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2132 {
2133     if (!isValid())
2134         return;
2135
2136     if (m_pageZoomFactor == zoomFactor)
2137         return;
2138
2139     m_pageZoomFactor = zoomFactor;
2140     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
2141 }
2142
2143 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2144 {
2145     if (!isValid())
2146         return;
2147
2148     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2149         return;
2150
2151     m_pageZoomFactor = pageZoomFactor;
2152     m_textZoomFactor = textZoomFactor;
2153     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
2154 }
2155
2156 double WebPageProxy::pageZoomFactor() const
2157 {
2158     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2159     // zoom which ensures that we don't use the PDF zoom for a normal page.
2160     if (m_mainFrame && m_mainFrame->isDisplayingPDFDocument())
2161         return m_pluginZoomFactor;
2162     return m_pageZoomFactor;
2163 }
2164
2165 double WebPageProxy::pageScaleFactor() const
2166 {
2167     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2168     // separately but decide which to return based on the main frame.
2169     if (m_mainFrame && m_mainFrame->isDisplayingPDFDocument())
2170         return m_pluginScaleFactor;
2171     return m_pageScaleFactor;
2172 }
2173
2174 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
2175 {
2176     if (!isValid())
2177         return;
2178
2179     m_pageScaleFactor = scale;
2180     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
2181 }
2182
2183 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
2184 {
2185     if (!isValid())
2186         return;
2187
2188     m_pageScaleFactor = scale;
2189     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
2190 }
2191
2192 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
2193 {
2194     if (m_intrinsicDeviceScaleFactor == scaleFactor)
2195         return;
2196
2197     m_intrinsicDeviceScaleFactor = scaleFactor;
2198
2199     if (m_drawingArea)
2200         m_drawingArea->deviceScaleFactorDidChange();
2201 }
2202
2203 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
2204 {
2205     if (!isValid())
2206         return;
2207
2208     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
2209 }
2210
2211 float WebPageProxy::deviceScaleFactor() const
2212 {
2213     if (m_customDeviceScaleFactor)
2214         return m_customDeviceScaleFactor;
2215     return m_intrinsicDeviceScaleFactor;
2216 }
2217
2218 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2219 {
2220     if (!isValid())
2221         return;
2222
2223     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2224     // https://bugs.webkit.org/show_bug.cgi?id=133378
2225 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2226     return;
2227 #endif
2228
2229     if (m_customDeviceScaleFactor == customScaleFactor)
2230         return;
2231
2232     float oldScaleFactor = deviceScaleFactor();
2233
2234     m_customDeviceScaleFactor = customScaleFactor;
2235
2236     if (deviceScaleFactor() != oldScaleFactor)
2237         m_drawingArea->deviceScaleFactorDidChange();
2238 }
2239
2240 void WebPageProxy::setUseFixedLayout(bool fixed)
2241 {
2242     if (!isValid())
2243         return;
2244
2245     // This check is fine as the value is initialized in the web
2246     // process as part of the creation parameters.
2247     if (fixed == m_useFixedLayout)
2248         return;
2249
2250     m_useFixedLayout = fixed;
2251     if (!fixed)
2252         m_fixedLayoutSize = IntSize();
2253     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2254 }
2255
2256 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2257 {
2258     if (!isValid())
2259         return;
2260
2261     if (size == m_fixedLayoutSize)
2262         return;
2263
2264     m_fixedLayoutSize = size;
2265     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2266 }
2267
2268 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2269 {
2270     if (!isValid())
2271         return;
2272     
2273     m_wantsSessionRestorationRenderTreeSizeThresholdEvent = milestones & WebCore::ReachedSessionRestorationRenderTreeSizeThreshold;
2274
2275     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2276 }
2277
2278 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
2279 {
2280     if (!isValid())
2281         return;
2282
2283     if (suppressAnimations == m_suppressScrollbarAnimations)
2284         return;
2285
2286     m_suppressScrollbarAnimations = suppressAnimations;
2287     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
2288 }
2289
2290 bool WebPageProxy::rubberBandsAtLeft() const
2291 {
2292     return m_rubberBandsAtLeft;
2293 }
2294
2295 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
2296 {
2297     m_rubberBandsAtLeft = rubberBandsAtLeft;
2298 }
2299
2300 bool WebPageProxy::rubberBandsAtRight() const
2301 {
2302     return m_rubberBandsAtRight;
2303 }
2304
2305 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
2306 {
2307     m_rubberBandsAtRight = rubberBandsAtRight;
2308 }
2309
2310 bool WebPageProxy::rubberBandsAtTop() const
2311 {
2312     return m_rubberBandsAtTop;
2313 }
2314
2315 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
2316 {
2317     m_rubberBandsAtTop = rubberBandsAtTop;
2318 }
2319
2320 bool WebPageProxy::rubberBandsAtBottom() const
2321 {
2322     return m_rubberBandsAtBottom;
2323 }
2324
2325 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
2326 {
2327     m_rubberBandsAtBottom = rubberBandsAtBottom;
2328 }
2329     
2330 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2331 {
2332     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
2333         return;
2334
2335     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
2336
2337     if (!isValid())
2338         return;
2339     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
2340 }
2341     
2342 bool WebPageProxy::verticalRubberBandingIsEnabled() const
2343 {
2344     return m_enableVerticalRubberBanding;
2345 }
2346     
2347 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2348 {
2349     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
2350         return;
2351
2352     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
2353
2354     if (!isValid())
2355         return;
2356     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
2357 }
2358     
2359 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
2360 {
2361     return m_enableHorizontalRubberBanding;
2362 }
2363
2364 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2365 {
2366     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
2367         return;
2368
2369     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
2370
2371     if (!isValid())
2372         return;
2373     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
2374 }
2375
2376 bool WebPageProxy::backgroundExtendsBeyondPage() const
2377 {
2378     return m_backgroundExtendsBeyondPage;
2379 }
2380
2381 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
2382 {
2383     if (mode == m_paginationMode)
2384         return;
2385
2386     m_paginationMode = mode;
2387
2388     if (!isValid())
2389         return;
2390     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
2391 }
2392
2393 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
2394 {
2395     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
2396         return;
2397
2398     m_paginationBehavesLikeColumns = behavesLikeColumns;
2399
2400     if (!isValid())
2401         return;
2402     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
2403 }
2404
2405 void WebPageProxy::setPageLength(double pageLength)
2406 {
2407     if (pageLength == m_pageLength)
2408         return;
2409
2410     m_pageLength = pageLength;
2411
2412     if (!isValid())
2413         return;
2414     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
2415 }
2416
2417 void WebPageProxy::setGapBetweenPages(double gap)
2418 {
2419     if (gap == m_gapBetweenPages)
2420         return;
2421
2422     m_gapBetweenPages = gap;
2423
2424     if (!isValid())
2425         return;
2426     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
2427 }
2428
2429 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
2430 {
2431     m_pageScaleFactor = scaleFactor;
2432 }
2433
2434 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
2435 {
2436     m_pluginScaleFactor = pluginScaleFactor;
2437 }
2438
2439 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
2440 {
2441     m_pluginZoomFactor = pluginZoomFactor;
2442 }
2443
2444 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2445 {
2446     if (string.isEmpty()) {
2447         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
2448         return;
2449     }
2450
2451     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
2452 }
2453
2454 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
2455 {
2456     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
2457 }
2458
2459 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
2460 {
2461     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
2462 }
2463
2464 void WebPageProxy::selectFindMatch(int32_t matchIndex)
2465 {
2466     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
2467 }
2468
2469 void WebPageProxy::hideFindUI()
2470 {
2471     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
2472 }
2473
2474 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2475 {
2476     if (!isValid())
2477         return;
2478
2479     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
2480 }
2481
2482 void WebPageProxy::runJavaScriptInMainFrame(const String& script, std::function<void (API::SerializedScriptValue*, CallbackBase::Error)> callbackFunction)
2483 {
2484     if (!isValid()) {
2485         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2486         return;
2487     }
2488
2489     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2490     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID);
2491 }
2492
2493 void WebPageProxy::getRenderTreeExternalRepresentation(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2494 {
2495     if (!isValid()) {
2496         callbackFunction(String(), CallbackBase::Error::Unknown);
2497         return;
2498     }
2499     
2500     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2501     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
2502 }
2503
2504 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2505 {
2506     if (!isValid()) {
2507         callbackFunction(String(), CallbackBase::Error::Unknown);
2508         return;
2509     }
2510     
2511     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2512     m_loadDependentStringCallbackIDs.add(callbackID);
2513     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
2514 }
2515
2516 void WebPageProxy::getContentsAsString(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2517 {
2518     if (!isValid()) {
2519         callbackFunction(String(), CallbackBase::Error::Unknown);
2520         return;
2521     }
2522     
2523     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2524     m_loadDependentStringCallbackIDs.add(callbackID);
2525     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2526 }
2527
2528 void WebPageProxy::getBytecodeProfile(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2529 {
2530     if (!isValid()) {
2531         callbackFunction(String(), CallbackBase::Error::Unknown);
2532         return;
2533     }
2534     
2535     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2536     m_loadDependentStringCallbackIDs.add(callbackID);
2537     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
2538 }
2539     
2540 #if ENABLE(MHTML)
2541 void WebPageProxy::getContentsAsMHTMLData(std::function<void (API::Data*, CallbackBase::Error)> callbackFunction, bool useBinaryEncoding)
2542 {
2543     if (!isValid()) {
2544         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2545         return;
2546     }
2547
2548     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2549     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID, useBinaryEncoding), m_pageID);
2550 }
2551 #endif
2552
2553 void WebPageProxy::getSelectionOrContentsAsString(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2554 {
2555     if (!isValid()) {
2556         callbackFunction(String(), CallbackBase::Error::Unknown);
2557         return;
2558     }
2559     
2560     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2561     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
2562 }
2563
2564 void WebPageProxy::getSelectionAsWebArchiveData(std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2565 {
2566     if (!isValid()) {
2567         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2568         return;
2569     }
2570     
2571     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2572     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
2573 }
2574
2575 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2576 {
2577     if (!isValid() || !frame) {
2578         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2579         return;
2580     }
2581     
2582     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2583     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
2584 }
2585
2586 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2587 {
2588     if (!isValid()) {
2589         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2590         return;
2591     }
2592     
2593     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2594     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
2595 }
2596
2597 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2598 {
2599     if (!isValid()) {
2600         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2601         return;
2602     }
2603     
2604     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
2605     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
2606 }
2607
2608 void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback)
2609 {
2610     RefPtr<VoidCallback> callback = prpCallback;
2611     if (!isValid()) {
2612         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
2613         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
2614         return;
2615     }
2616
2617     uint64_t callbackID = callback->callbackID();
2618     m_callbacks.put(callback);
2619     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
2620     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
2621 }
2622
2623 void WebPageProxy::preferencesDidChange()
2624 {
2625     if (!isValid())
2626         return;
2627
2628 #if ENABLE(INSPECTOR_SERVER)
2629     if (m_preferences->developerExtrasEnabled())
2630         inspector()->enableRemoteInspection();
2631 #endif
2632
2633     updateProccessSuppressionState();
2634
2635     m_pageClient.preferencesDidChange();
2636
2637     // FIXME: It probably makes more sense to send individual preference changes.
2638     // However, WebKitTestRunner depends on getting a preference change notification
2639     // even if nothing changed in UI process, so that overrides get removed.
2640
2641     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
2642     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, m_isPerformingDOMPrintOperation ? IPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2643 }
2644
2645 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
2646 {
2647     MESSAGE_CHECK(!m_mainFrame);
2648     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2649
2650     m_mainFrame = WebFrameProxy::create(this, frameID);
2651
2652     // Add the frame to the process wide map.
2653     m_process->frameCreated(frameID, m_mainFrame.get());
2654 }
2655
2656 void WebPageProxy::didCreateSubframe(uint64_t frameID)
2657 {
2658     MESSAGE_CHECK(m_mainFrame);
2659     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2660     
2661     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
2662
2663     // Add the frame to the process wide map.
2664     m_process->frameCreated(frameID, subFrame.get());
2665 }
2666
2667 double WebPageProxy::estimatedProgress() const
2668 {
2669     return m_pageLoadState.estimatedProgress();
2670 }
2671
2672 void WebPageProxy::didStartProgress()
2673 {
2674     auto transaction = m_pageLoadState.transaction();
2675     m_pageLoadState.didStartProgress(transaction);
2676
2677     m_pageLoadState.commitChanges();
2678     m_loaderClient->didStartProgress(*this);
2679 }
2680
2681 void WebPageProxy::didChangeProgress(double value)
2682 {
2683     auto transaction = m_pageLoadState.transaction();
2684     m_pageLoadState.didChangeProgress(transaction, value);
2685
2686     m_pageLoadState.commitChanges();
2687     m_loaderClient->didChangeProgress(*this);
2688 }
2689
2690 void WebPageProxy::didFinishProgress()
2691 {
2692     auto transaction = m_pageLoadState.transaction();
2693     m_pageLoadState.didFinishProgress(transaction);
2694
2695     m_pageLoadState.commitChanges();
2696     m_loaderClient->didFinishProgress(*this);
2697 }
2698
2699 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
2700 {
2701     auto transaction = m_pageLoadState.transaction();
2702     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
2703 }
2704
2705 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
2706 {
2707     // FIXME: Message check the navigationID.
2708     m_navigationState->didDestroyNavigation(navigationID);
2709 }
2710
2711 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, const String& unreachableURL, const UserData& userData)
2712 {
2713     auto transaction = m_pageLoadState.transaction();
2714
2715     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2716
2717     WebFrameProxy* frame = m_process->webFrame(frameID);
2718     MESSAGE_CHECK(frame);
2719     MESSAGE_CHECK_URL(url);
2720
2721     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2722     RefPtr<API::Navigation> navigation;
2723     if (frame->isMainFrame() && navigationID)
2724         navigation = &navigationState().navigation(navigationID);
2725
2726     if (frame->isMainFrame())
2727         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
2728
2729     frame->setUnreachableURL(unreachableURL);
2730     frame->didStartProvisionalLoad(url);
2731
2732     m_pageLoadState.commitChanges();
2733     if (m_navigationClient) {
2734         if (frame->isMainFrame())
2735             m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2736     } else
2737         m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2738 }
2739
2740 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, const UserData& userData)
2741 {
2742     WebFrameProxy* frame = m_process->webFrame(frameID);
2743     MESSAGE_CHECK(frame);
2744     MESSAGE_CHECK_URL(url);
2745
2746     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2747     RefPtr<API::Navigation> navigation;
2748     if (frame->isMainFrame() && navigationID)
2749         navigation = &navigationState().navigation(navigationID);
2750
2751     auto transaction = m_pageLoadState.transaction();
2752
2753     if (frame->isMainFrame())
2754         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
2755
2756     frame->didReceiveServerRedirectForProvisionalLoad(url);
2757
2758     m_pageLoadState.commitChanges();
2759     if (m_navigationClient) {
2760         if (frame->isMainFrame())
2761             m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2762     } else
2763         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2764 }
2765
2766 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
2767 {
2768     WebFrameProxy* frame = m_process->webFrame(frameID);
2769     MESSAGE_CHECK(frame);
2770
2771     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2772     RefPtr<API::Navigation> navigation;
2773     if (frame->isMainFrame() && navigationID)
2774         navigation = navigationState().takeNavigation(navigationID);
2775
2776     auto transaction = m_pageLoadState.transaction();
2777
2778     if (frame->isMainFrame())
2779         m_pageLoadState.didFailProvisionalLoad(transaction);
2780
2781     frame->didFailProvisionalLoad();
2782
2783     m_pageLoadState.commitChanges();
2784     if (m_navigationClient) {
2785         if (frame->isMainFrame())
2786             m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
2787         else {
2788             // FIXME: Get the main frame's current navigation.
2789             m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
2790         }
2791     } else
2792         m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
2793 }
2794
2795 void WebPageProxy::clearLoadDependentCallbacks()
2796 {
2797     Vector<uint64_t> callbackIDsCopy;
2798     copyToVector(m_loadDependentStringCallbackIDs, callbackIDsCopy);
2799     m_loadDependentStringCallbackIDs.clear();
2800
2801     for (size_t i = 0; i < callbackIDsCopy.size(); ++i) {
2802         auto callback = m_callbacks.take<StringCallback>(callbackIDsCopy[i]);
2803         if (callback)
2804             callback->invalidate();
2805     }
2806 }
2807
2808 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, const UserData& userData)
2809 {
2810     WebFrameProxy* frame = m_process->webFrame(frameID);
2811     MESSAGE_CHECK(frame);
2812
2813     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2814     RefPtr<API::Navigation> navigation;
2815     if (frame->isMainFrame() && navigationID)
2816         navigation = &navigationState().navigation(navigationID);
2817
2818 #if PLATFORM(IOS)
2819     if (frame->isMainFrame()) {
2820         m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
2821         m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
2822     }
2823 #endif
2824
2825     auto transaction = m_pageLoadState.transaction();
2826
2827     if (frame->isMainFrame()) {
2828         bool hasInsecureCertificateChain = m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
2829         m_pageLoadState.didCommitLoad(transaction, hasInsecureCertificateChain);
2830     }
2831
2832 #if USE(APPKIT)
2833     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
2834     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
2835     m_pageClient.resetSecureInputState();
2836     m_pageClient.dismissContentRelativeChildWindows();
2837 #endif
2838
2839     clearLoadDependentCallbacks();
2840
2841     frame->didCommitLoad(mimeType, certificateInfo);
2842
2843     if (frame->isMainFrame()) {
2844         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
2845
2846         if (m_mainFrameHasCustomContentProvider) {
2847             // Always assume that the main frame is pinned here, since the custom representation view will handle
2848             // any wheel events and dispatch them to the WKView when necessary.
2849             m_mainFrameIsPinnedToLeftSide = true;
2850             m_mainFrameIsPinnedToRightSide = true;
2851             m_mainFrameIsPinnedToTopSide = true;
2852             m_mainFrameIsPinnedToBottomSide = true;
2853
2854             m_uiClient->pinnedStateDidChange(*this);
2855         }
2856         m_pageClient.didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
2857     }
2858
2859     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
2860     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
2861     // plugin is handling page scaling itself) so we should reset it to the default
2862     // for standard main frame loads.
2863     if (frame->isMainFrame() && static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
2864         m_pageScaleFactor = 1;
2865         m_pluginScaleFactor = 1;
2866     }
2867
2868     m_pageLoadState.commitChanges();
2869     if (m_navigationClient) {
2870         if (frame->isMainFrame())
2871             m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2872     } else
2873         m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2874 }
2875
2876 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
2877 {
2878     WebFrameProxy* frame = m_process->webFrame(frameID);
2879     MESSAGE_CHECK(frame);
2880
2881     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2882     RefPtr<API::Navigation> navigation;
2883     if (frame->isMainFrame() && navigationID)
2884         navigation = &navigationState().navigation(navigationID);
2885
2886     if (m_navigationClient) {
2887         if (frame->isMainFrame())
2888             m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2889     } else
2890         m_loaderClient->didFinishDocumentLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2891 }
2892
2893 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
2894 {
2895     WebFrameProxy* frame = m_process->webFrame(frameID);
2896     MESSAGE_CHECK(frame);
2897
2898     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2899     RefPtr<API::Navigation> navigation;
2900     if (frame->isMainFrame() && navigationID)
2901         navigation = &navigationState().navigation(navigationID);
2902
2903     auto transaction = m_pageLoadState.transaction();
2904
2905     bool isMainFrame = frame->isMainFrame();
2906     if (isMainFrame)
2907         m_pageLoadState.didFinishLoad(transaction);
2908
2909     frame->didFinishLoad();
2910
2911     m_pageLoadState.commitChanges();
2912     if (m_navigationClient) {
2913         if (isMainFrame)
2914             m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2915     } else
2916         m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
2917
2918     if (isMainFrame)
2919         m_pageClient.didFinishLoadForMainFrame();
2920 }
2921
2922 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
2923 {
2924     WebFrameProxy* frame = m_process->webFrame(frameID);
2925     MESSAGE_CHECK(frame);
2926
2927     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2928     RefPtr<API::Navigation> navigation;
2929     if (frame->isMainFrame() && navigationID)
2930         navigation = &navigationState().navigation(navigationID);
2931
2932     clearLoadDependentCallbacks();
2933
2934     auto transaction = m_pageLoadState.transaction();
2935
2936     if (frame->isMainFrame())
2937         m_pageLoadState.didFailLoad(transaction);
2938
2939     frame->didFailLoad();
2940
2941     m_pageLoadState.commitChanges();
2942     if (m_navigationClient) {
2943         if (frame->isMainFrame())
2944             m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
2945     } else
2946         m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
2947 }
2948
2949 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, const String& url, const UserData& userData)
2950 {
2951     WebFrameProxy* frame = m_process->webFrame(frameID);
2952     MESSAGE_CHECK(frame);
2953     MESSAGE_CHECK_URL(url);
2954
2955     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
2956     RefPtr<API::Navigation> navigation;
2957     if (frame->isMainFrame() && navigationID)
2958         navigation = &navigationState().navigation(navigationID);
2959
2960     auto transaction = m_pageLoadState.transaction();
2961
2962     bool isMainFrame = frame->isMainFrame();
2963     if (isMainFrame)
2964         m_pageLoadState.didSameDocumentNavigation(transaction, url);
2965
2966     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2967     frame->didSameDocumentNavigation(url);
2968
2969     m_pageLoadState.commitChanges();
2970
2971     SameDocumentNavigationType navigationType = static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType);
2972     if (m_navigationClient) {
2973         if (isMainFrame)
2974             m_navigationClient->didSameDocumentNavigation(*this, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
2975     } else
2976         m_loaderClient->didSameDocumentNavigationForFrame(*this, *frame, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
2977
2978     if (isMainFrame)
2979         m_pageClient.didSameDocumentNavigationForMainFrame(navigationType);
2980 }
2981
2982 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
2983 {
2984     WebFrameProxy* frame = m_process->webFrame(frameID);
2985     MESSAGE_CHECK(frame);
2986
2987     auto transaction = m_pageLoadState.transaction();
2988
2989     if (frame->isMainFrame())
2990         m_pageLoadState.setTitle(transaction, title);
2991
2992     frame->didChangeTitle(title);
2993     
2994     m_pageLoadState.commitChanges();
2995     m_loaderClient->didReceiveTitleForFrame(*this, title, *frame, m_process->transformHandlesToObjects(userData.object()).get());
2996 }
2997
2998 void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, const UserData& userData)
2999 {
3000     WebFrameProxy* frame = m_process->webFrame(frameID);
3001     MESSAGE_CHECK(frame);
3002
3003     m_loaderClient->didFirstLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3004 }
3005
3006 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData& userData)
3007 {
3008     WebFrameProxy* frame = m_process->webFrame(frameID);
3009     MESSAGE_CHECK(frame);
3010
3011     m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3012
3013     if (frame->isMainFrame())
3014         m_pageClient.didFirstVisuallyNonEmptyLayoutForMainFrame();
3015 }
3016
3017 void WebPageProxy::didLayout(uint32_t layoutMilestones, const UserData& userData)
3018 {
3019     if (m_navigationClient)
3020         m_navigationClient->renderingProgressDidChange(*this, static_cast<LayoutMilestones>(layoutMilestones), m_process->transformHandlesToObjects(userData.object()).get());
3021     else
3022         m_loaderClient->didLayout(*this, static_cast<LayoutMilestones>(layoutMilestones), m_process->transformHandlesToObjects(userData.object()).get());
3023 }
3024
3025 void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, const UserData& userData)
3026 {
3027     WebFrameProxy* frame = m_process->webFrame(frameID);
3028     MESSAGE_CHECK(frame);
3029
3030     m_loaderClient->didRemoveFrameFromHierarchy(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3031 }
3032
3033 void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3034 {
3035     WebFrameProxy* frame = m_process->webFrame(frameID);
3036     MESSAGE_CHECK(frame);
3037
3038     auto transaction = m_pageLoadState.transaction();
3039     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3040
3041     m_pageLoadState.commitChanges();
3042     m_loaderClient->didDisplayInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3043 }
3044
3045 void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3046 {
3047     WebFrameProxy* frame = m_process->webFrame(frameID);
3048     MESSAGE_CHECK(frame);
3049
3050     auto transaction = m_pageLoadState.transaction();
3051     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3052
3053     m_pageLoadState.commitChanges();
3054     m_loaderClient->didRunInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3055 }
3056
3057 void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, const UserData& userData)
3058 {
3059     WebFrameProxy* frame = m_process->webFrame(frameID);
3060     MESSAGE_CHECK(frame);
3061
3062     m_loaderClient->didDetectXSSForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3063 }
3064
3065 void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
3066 {
3067     WebFrameProxy* frame = m_process->webFrame(frameID);
3068     MESSAGE_CHECK(frame);
3069
3070     frame->setIsFrameSet(value);
3071     if (frame->isMainFrame())
3072         m_frameSetLargestFrame = value ? m_mainFrame : 0;
3073 }
3074
3075 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)
3076 {
3077     auto transaction = m_pageLoadState.transaction();
3078
3079     if (request.url() != m_pageLoadState.pendingAPIRequestURL())
3080         m_pageLoadState.clearPendingAPIRequestURL(transaction);
3081
3082     WebFrameProxy* frame = m_process->webFrame(frameID);
3083     MESSAGE_CHECK(frame);
3084     MESSAGE_CHECK_URL(request.url());
3085     MESSAGE_CHECK_URL(originalRequest.url());
3086
3087     WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameID);
3088     
3089     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3090     if (!navigationID && frame->isMainFrame()) {
3091         auto navigation = m_navigationState->createLoadRequestNavigation(request);
3092         newNavigationID = navigation->navigationID();
3093         listener->setNavigation(WTF::move(navigation));
3094     }
3095
3096 #if ENABLE(CONTENT_FILTERING)
3097     if (frame->didHandleContentFilterUnblockNavigation(request)) {
3098         receivedPolicyAction = true;
3099         policyAction = PolicyIgnore;
3100         return;
3101     }
3102 #endif
3103
3104     ASSERT(!m_inDecidePolicyForNavigationAction);
3105
3106     m_inDecidePolicyForNavigationAction = true;
3107     m_syncNavigationActionPolicyActionIsValid = false;
3108
3109     if (m_navigationClient) {
3110         RefPtr<API::FrameInfo> destinationFrameInfo;
3111         RefPtr<API::FrameInfo> sourceFrameInfo;
3112
3113         if (frame)
3114             destinationFrameInfo = API::FrameInfo::create(*frame);
3115
3116         if (originatingFrame == frame)
3117             sourceFrameInfo = destinationFrameInfo;
3118         else if (originatingFrame)
3119             sourceFrameInfo = API::FrameInfo::create(*originatingFrame);
3120
3121         auto navigationAction = API::NavigationAction::create(navigationActionData, sourceFrameInfo.get(), destinationFrameInfo.get(), request, originalRequest.url());
3122
3123         m_navigationClient->decidePolicyForNavigationAction(*this, navigationAction.get(), WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3124     } else
3125         m_policyClient->decidePolicyForNavigationAction(*this, frame, navigationActionData, originatingFrame, originalRequest, request, WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3126
3127     m_inDecidePolicyForNavigationAction = false;
3128
3129     // Check if we received a policy decision already. If we did, we can just pass it back.
3130     receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
3131     if (m_syncNavigationActionPolicyActionIsValid) {
3132         policyAction = m_syncNavigationActionPolicyAction;
3133         downloadID = m_syncNavigationActionPolicyDownloadID;
3134     }
3135 }
3136
3137 void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const NavigationActionData& navigationActionData, const ResourceRequest& request, const String& frameName, uint64_t listenerID, const UserData& userData)
3138 {
3139     WebFrameProxy* frame = m_process->webFrame(frameID);
3140     MESSAGE_CHECK(frame);
3141     MESSAGE_CHECK_URL(request.url());
3142
3143     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3144
3145     if (m_navigationClient) {
3146         RefPtr<API::FrameInfo> sourceFrameInfo;
3147         if (frame)
3148             sourceFrameInfo = API::FrameInfo::create(*frame);
3149
3150         auto navigationAction = API::NavigationAction::create(navigationActionData, sourceFrameInfo.get(), nullptr, request, request.url());
3151
3152         m_navigationClient->decidePolicyForNavigationAction(*this, navigationAction.get(), WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3153
3154     } else
3155         m_policyClient->decidePolicyForNewWindowAction(*this, *frame, navigationActionData, request, frameName, WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3156 }
3157
3158 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
3159 {
3160     WebFrameProxy* frame = m_process->webFrame(frameID);
3161     MESSAGE_CHECK(frame);
3162     MESSAGE_CHECK_URL(request.url());
3163     MESSAGE_CHECK_URL(response.url());
3164
3165     Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3166
3167     if (m_navigationClient) {
3168         auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(*frame).get(), request, response, canShowMIMEType);
3169         m_navigationClient->decidePolicyForNavigationResponse(*this, navigationResponse.get(), WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3170     } else
3171         m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTF::move(listener), m_process->transformHandlesToObjects(userData.object()).get());
3172 }
3173
3174 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)
3175 {
3176     ASSERT(!m_inDecidePolicyForResponseSync);
3177
3178     m_inDecidePolicyForResponseSync = true;
3179     m_decidePolicyForResponseRequest = &request;
3180     m_syncMimeTypePolicyActionIsValid = false;
3181
3182     decidePolicyForResponse(frameID, response, request, canShowMIMEType, listenerID, userData);
3183
3184     m_inDecidePolicyForResponseSync = false;
3185     m_decidePolicyForResponseRequest = 0;
3186
3187     // Check if we received a policy decision already. If we did, we can just pass it back.
3188     receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
3189     if (m_syncMimeTypePolicyActionIsValid) {
3190         policyAction = m_syncMimeTypePolicyAction;
3191         downloadID = m_syncMimeTypePolicyDownloadID;
3192     }
3193 }
3194
3195 void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, const UserData& userData)
3196 {
3197     WebFrameProxy* frame = m_process->webFrame(frameID);
3198     MESSAGE_CHECK(frame);
3199
3200     m_policyClient->unableToImplementPolicy(*this, *frame, error, m_process->transformHandlesToObjects(userData.object()).get());
3201 }
3202
3203 // FormClient
3204
3205 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData& userData)
3206 {
3207     WebFrameProxy* frame = m_process->webFrame(frameID);
3208     MESSAGE_CHECK(frame);
3209
3210     WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
3211     MESSAGE_CHECK(sourceFrame);
3212
3213     Ref<WebFormSubmissionListenerProxy> listener = frame->setUpFormSubmissionListenerProxy(listenerID);
3214     m_formClient->willSubmitForm(*this, *frame, *sourceFrame, textFieldValues, m_process->transformHandlesToObjects(userData.object()).get(), listener.get());
3215 }
3216
3217 void WebPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID) 
3218 {
3219     WebFrameProxy* frame = m_process->webFrame(frameID);
3220     MESSAGE_CHECK(frame);
3221     MESSAGE_CHECK(frame->page() == this);
3222
3223     if (m_historyClient) {
3224         if (frame->isMainFrame())
3225             m_historyClient->didNavigateWithNavigationData(*this, store);
3226     } else
3227         m_loaderClient->didNavigateWithNavigationData(*this, store, *frame);
3228     process().processPool().historyClient().didNavigateWithNavigationData(process().processPool(), *this, store, *frame);
3229 }
3230
3231 void WebPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3232 {
3233     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3234         return;
3235     
3236     WebFrameProxy* frame = m_process->webFrame(frameID);
3237     MESSAGE_CHECK(frame);
3238     MESSAGE_CHECK(frame->page() == this);
3239
3240     MESSAGE_CHECK_URL(sourceURLString);
3241     MESSAGE_CHECK_URL(destinationURLString);
3242
3243     if (m_historyClient) {
3244         if (frame->isMainFrame())
3245             m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
3246     } else
3247         m_loaderClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString, *frame);
3248     process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3249 }
3250
3251 void WebPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3252 {
3253     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3254         return;
3255     
3256     WebFrameProxy* frame = m_process->webFrame(frameID);
3257     MESSAGE_CHECK(frame);
3258     MESSAGE_CHECK(frame->page() == this);
3259
3260     MESSAGE_CHECK_URL(sourceURLString);
3261     MESSAGE_CHECK_URL(destinationURLString);
3262
3263     if (m_historyClient) {
3264         if (frame->isMainFrame())
3265             m_historyClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString);
3266     } else
3267         m_loaderClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString, *frame);
3268     process().processPool().historyClient().didPerformServerRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3269 }
3270
3271 void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url, uint64_t frameID)
3272 {
3273     WebFrameProxy* frame = m_process->webFrame(frameID);
3274     MESSAGE_CHECK(frame);
3275     MESSAGE_CHECK(frame->page() == this);
3276
3277     MESSAGE_CHECK_URL(url);
3278
3279     if (m_historyClient) {
3280         if (frame->isMainFrame())
3281             m_historyClient->didUpdateHistoryTitle(*this, title, url);
3282     } else
3283         m_loaderClient->didUpdateHistoryTitle(*this, title, url, *frame);
3284     process().processPool().historyClient().didUpdateHistoryTitle(process().processPool(), *this, title, url, *frame);
3285 }
3286
3287 // UIClient
3288
3289 void WebPageProxy::createNewPage(uint64_t frameID, const ResourceRequest& request, const WindowFeatures& windowFeatures, const NavigationActionData& navigationActionData, uint64_t& newPageID, WebPageCreationParameters& newPageParameters)
3290 {
3291     WebFrameProxy* frame = m_process->webFrame(frameID);
3292     MESSAGE_CHECK(frame);
3293
3294     RefPtr<WebPageProxy> newPage = m_uiClient->createNewPage(this, frame, request, windowFeatures, navigationActionData);
3295     if (!newPage) {
3296         newPageID = 0;
3297         return;
3298     }
3299
3300     newPageID = newPage->pageID();
3301     newPageParameters = newPage->creationParameters();
3302
3303     WebsiteDataStore::cloneSessionData(*this, *newPage);
3304 }
3305     
3306 void WebPageProxy::showPage()
3307 {
3308     m_uiClient->showPage(this);
3309 }
3310
3311 void WebPageProxy::fullscreenMayReturnToInline()
3312 {
3313     m_uiClient->fullscreenMayReturnToInline(this);
3314 }
3315
3316 void WebPageProxy::didEnterFullscreen()
3317 {
3318     m_uiClient->didEnterFullscreen(this);
3319 }
3320
3321 void WebPageProxy::didExitFullscreen()
3322 {
3323     m_uiClient->didExitFullscreen(this);
3324 }
3325
3326 void WebPageProxy::closePage(bool stopResponsivenessTimer)
3327 {
3328     if (stopResponsivenessTimer)
3329         m_process->responsivenessTimer()->stop();
3330
3331     m_pageClient.clearAllEditCommands();
3332     m_uiClient->close(this);
3333 }
3334
3335 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply> reply)
3336 {
3337     WebFrameProxy* frame = m_process->webFrame(frameID);
3338     MESSAGE_CHECK(frame);
3339
3340     // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
3341     m_process->responsivenessTimer()->stop();
3342
3343     m_uiClient->runJavaScriptAlert(this, message, frame, [reply]{ reply->send(); });
3344 }
3345
3346 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply> reply)
3347 {
3348     WebFrameProxy* frame = m_process->webFrame(frameID);
3349     MESSAGE_CHECK(frame);
3350
3351     // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
3352     m_process->responsivenessTimer()->stop();
3353
3354     m_uiClient->runJavaScriptConfirm(this, message, frame, [reply](bool result) { reply->send(result); });
3355 }
3356
3357 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const String& message, const String& defaultValue, RefPtr<Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply> reply)
3358 {
3359     WebFrameProxy* frame = m_process->webFrame(frameID);
3360     MESSAGE_CHECK(frame);
3361
3362     // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
3363     m_process->responsivenessTimer()->stop();
3364
3365     m_uiClient->runJavaScriptPrompt(this, message, defaultValue, frame, [reply](const String& result) { reply->send(result); });
3366 }
3367
3368 void WebPageProxy::shouldInterruptJavaScript(bool& result)
3369 {
3370     // Since shouldInterruptJavaScript() can spin a nested run loop we need to turn off the responsiveness timer.
3371     m_process->responsivenessTimer()->stop();
3372
3373     result = m_uiClient->shouldInterruptJavaScript(this);
3374 }
3375
3376 void WebPageProxy::setStatusText(const String& text)
3377 {
3378     m_uiClient->setStatusText(this, text);
3379 }
3380
3381 void WebPageProxy::mouseDidMoveOverElement(const WebHitTestResult::Data& hitTestResultData, uint32_t opaqueModifiers, const UserData& userData)
3382 {
3383     m_lastMouseMoveHitTestResult = WebHitTestResult::create(hitTestResultData);
3384
3385     WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
3386
3387     m_uiClient->mouseDidMoveOverElement(this, hitTestResultData, modifiers, m_process->transformHandlesToObjects(userData.object()).get());
3388 }
3389
3390 void WebPageProxy::didBeginTrackingPotentialLongMousePress(const IntPoint& mouseDownPosition, const WebHitTestResult::Data& hitTestResultData, const UserData& userData)
3391 {
3392     m_uiClient->didBeginTrackingPotentialLongMousePress(this, mouseDownPosition, hitTestResultData, m_process->transformHandlesToObjects(userData.object()).get());
3393 }
3394
3395 void WebPageProxy::didRecognizeLongMousePress(const UserData& userData)
3396 {
3397     m_uiClient->didRecognizeLongMousePress(this, m_process->transformHandlesToObjects(userData.object()).get());
3398 }
3399
3400 void WebPageProxy::didCancelTrackingPotentialLongMousePress(const UserData& userData)
3401 {
3402     m_uiClient->didCancelTrackingPotentialLongMousePress(this, m_process->transformHandlesToObjects(userData.object()).get());
3403 }
3404
3405 void WebPageProxy::connectionWillOpen(IPC::Connection& connection)
3406 {
3407     ASSERT(&connection == m_process->connection());
3408
3409     m_webProcessLifetimeTracker.connectionWillOpen(connection);
3410 }
3411
3412 void WebPageProxy::connectionDidClose(IPC::Connection& connection)
3413 {
3414     ASSERT_UNUSED(connection, &connection == m_process->connection());
3415
3416     m_webProcessLifetimeTracker.connectionDidClose(connection);
3417 }
3418
3419 void WebPageProxy::processDidFinishLaunching()
3420 {
3421     ASSERT(m_process->state() == WebProcessProxy::State::Running);
3422
3423     if (m_userContentController)
3424         m_process->addWebUserContentControllerProxy(*m_userContentController);
3425     m_process->addVisitedLinkProvider(m_visitedLinkProvider);
3426 }
3427
3428 #if ENABLE(NETSCAPE_PLUGIN_API)
3429 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
3430 {
3431     MESSAGE_CHECK_URL(pluginURLString);
3432     MESSAGE_CHECK_URL(pluginspageAttributeURLString);
3433     MESSAGE_CHECK_URL(frameURLString);
3434     MESSAGE_CHECK_URL(pageURLString);
3435
3436     RefPtr<API::Dictionary> pluginInformation;
3437     String newMimeType = mimeType;
3438     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
3439     pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
3440
3441     WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
3442     switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
3443     case RenderEmbeddedObject::PluginMissing:
3444         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
3445         break;
3446     case RenderEmbeddedObject::InsecurePluginVersion:
3447         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
3448         break;
3449     case RenderEmbeddedObject::PluginCrashed:
3450         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
3451         break;
3452     case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
3453         ASSERT_NOT_REACHED();
3454     }
3455
3456     m_uiClient->unavailablePluginButtonClicked(this, pluginUnavailabilityReason, pluginInformation.get());
3457 }
3458 #endif // ENABLE(NETSCAPE_PLUGIN_API)
3459
3460 #if ENABLE(WEBGL)
3461 void WebPageProxy::webGLPolicyForURL(const String& url, uint32_t& loadPolicy)
3462 {
3463     loadPolicy = static_cast<uint32_t>(m_loaderClient->webGLLoadPolicy(*this, url));
3464 }
3465
3466 void WebPageProxy::resolveWebGLPolicyForURL(const String& url, uint32_t& loadPolicy)
3467 {
3468     loadPolicy = static_cast<uint32_t>(m_loaderClient->resolveWebGLLoadPolicy(*this, url));
3469 }
3470 #endif // ENABLE(WEBGL)
3471
3472 void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
3473 {
3474     m_uiClient->setToolbarsAreVisible(this, toolbarsAreVisible);
3475 }
3476
3477 void WebPageProxy::getToolbarsAreVisible(bool& toolbarsAreVisible)
3478 {
3479     toolbarsAreVisible = m_uiClient->toolbarsAreVisible(this);
3480 }
3481
3482 void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
3483 {
3484     m_uiClient->setMenuBarIsVisible(this, menuBarIsVisible);
3485 }
3486
3487 void WebPageProxy::getMenuBarIsVisible(bool& menuBarIsVisible)
3488 {
3489     menuBarIsVisible = m_uiClient->menuBarIsVisible(this);
3490 }
3491
3492 void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
3493 {
3494     m_uiClient->setStatusBarIsVisible(this, statusBarIsVisible);
3495 }
3496
3497 void WebPageProxy::getStatusBarIsVisible(bool& statusBarIsVisible)
3498 {
3499     statusBarIsVisible = m_uiClient->statusBarIsVisible(this);
3500 }
3501
3502 void WebPageProxy::setIsResizable(bool isResizable)
3503 {
3504     m_uiClient->setIsResizable(this, isResizable);
3505 }
3506
3507 void WebPageProxy::getIsResizable(bool& isResizable)
3508 {
3509     isResizable = m_uiClient->isResizable(this);
3510 }
3511
3512 void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
3513 {
3514     m_uiClient->setWindowFrame(this, m_pageClient.convertToDeviceSpace(newWindowFrame));
3515 }
3516
3517 void WebPageProxy::getWindowFrame(FloatRect& newWindowFrame)
3518 {
3519     newWindowFrame = m_pageClient.convertToUserSpace(m_uiClient->windowFrame(this));
3520 }
3521     
3522 void WebPageProxy::screenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
3523 {
3524     windowPoint = m_pageClient.screenToRootView(screenPoint);
3525 }
3526     
3527 void WebPageProxy::rootViewToScreen(const IntRect& viewRect, IntRect& result)
3528 {
3529     result = m_pageClient.rootViewToScreen(viewRect);
3530 }
3531     
3532 #if PLATFORM(IOS)
3533 void WebPageProxy::accessibilityScreenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
3534 {
3535     windowPoint = m_pageClient.accessibilityScreenToRootView(screenPoint);
3536 }
3537
3538 void WebPageProxy::rootViewToAccessibilityScreen(const IntRect& viewRect, IntRect& result)
3539 {
3540     result = m_pageClient.rootViewToAccessibilityScreen(viewRect);
3541 }
3542 #endif
3543     
3544 void WebPageProxy::runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose)
3545 {
3546     WebFrameProxy* frame = m_process->webFrame(frameID);
3547     MESSAGE_CHECK(frame);
3548
3549     // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer.
3550     m_process->responsivenessTimer()->stop();
3551
3552     shouldClose = m_uiClient->runBeforeUnloadConfirmPanel(this, message, frame);
3553 }
3554
3555 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
3556 void WebPageProxy::pageDidRequestScroll(const IntPoint& point)
3557 {
3558     m_pageClient.pageDidRequestScroll(point);
3559 }
3560
3561 void WebPageProxy::pageTransitionViewportReady()
3562 {
3563     m_pageClient.pageTransitionViewportReady();
3564 }
3565
3566 void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
3567 {
3568     m_pageClient.didRenderFrame(contentsSize, coveredRect);
3569 }
3570
3571 #endif
3572
3573 void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr)
3574 {
3575     m_pageClient.didChangeViewportProperties(attr);
3576 }
3577
3578 void WebPageProxy::pageDidScroll()
3579 {
3580     m_uiClient->pageDidScroll(this);
3581 #if PLATFORM(MAC)
3582     m_pageClient.dismissContentRelativeChildWindows();
3583 #endif
3584 }
3585
3586 void WebPageProxy::runOpenPanel(uint64_t frameID, const FileChooserSettings& settings)
3587 {
3588     if (m_openPanelResultListener) {
3589         m_openPanelResultListener->invalidate();
3590         m_openPanelResultListener = 0;
3591     }
3592
3593     WebFrameProxy* frame = m_process->webFrame(frameID);
3594     MESSAGE_CHECK(frame);
3595
3596     RefPtr<WebOpenPanelParameters> parameters = WebOpenPanelParameters::create(settings);
3597     m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
3598
3599     // Since runOpenPanel() can spin a nested run loop we need to turn off the responsiveness timer.
3600     m_process->responsivenessTimer()->stop();
3601
3602     if (!m_uiClient->runOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get())) {
3603         if (!m_pageClient.handleRunOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get()))
3604             didCancelForOpenPanel();
3605     }
3606 }
3607
3608 void WebPageProxy::printFrame(uint64_t frameID)
3609 {
3610     ASSERT(!m_isPerformingDOMPrintOperation);
3611     m_isPerformingDOMPrintOperation = true;
3612
3613     WebFrameProxy* frame = m_process->webFrame(frameID);
3614     MESSAGE_CHECK(frame);
3615
3616     m_uiClient->printFrame(this, frame);
3617
3618     endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true.
3619     m_isPerformingDOMPrintOperation = false;
3620 }
3621
3622 void WebPageProxy::printMainFrame()
3623 {
3624     printFrame(m_mainFrame->frameID());
3625 }
3626
3627 void WebPageProxy::setMediaVolume(float volume)
3628 {
3629     if (volume == m_mediaVolume)
3630         return;
3631     
3632     m_mediaVolume = volume;
3633     
3634     if (!isValid())
3635         return;
3636     
3637     m_process->send(Messages::WebPage::SetMediaVolume(volume), m_pageID);    
3638 }
3639
3640 void WebPageProxy::setMuted(bool muted)
3641 {
3642     if (m_muted == muted)
3643         return;
3644
3645     m_muted = muted;
3646
3647     if (!isValid())
3648         return;
3649
3650     m_process->send(Messages::WebPage::SetMuted(muted), m_pageID);
3651 }
3652
3653 void WebPageProxy::setMayStartMediaWhenInWindow(bool mayStartMedia)
3654 {
3655     if (mayStartMedia == m_mayStartMediaWhenInWindow)
3656         return;
3657
3658     m_mayStartMediaWhenInWindow = mayStartMedia;
3659
3660     if (!isValid())
3661         return;
3662
3663     process().send(Messages::WebPage::SetMayStartMediaWhenInWindow(mayStartMedia), m_pageID);
3664 }
3665
3666 void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
3667 {
3668     m_pageClient.handleDownloadRequest(download);
3669 }
3670
3671 void WebPageProxy::didChangeContentSize(const IntSize& size)
3672 {
3673     m_pageClient.didChangeContentSize(size);
3674 }
3675
3676 #if ENABLE(INPUT_TYPE_COLOR)
3677 void WebPageProxy::showColorPicker(const WebCore::Color& initialColor, const IntRect& elementRect)
3678 {
3679 #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
3680     // A new popover color well needs to be created (and the previous one destroyed) for
3681     // each activation of a color element.
3682     m_colorPicker = 0;
3683 #endif
3684     if (!m_colorPicker)
3685         m_colorPicker = m_pageClient.createColorPicker(this, initialColor, elementRect);
3686     m_colorPicker->showColorPicker(initialColor);
3687 }
3688
3689 void WebPageProxy::setColorPickerColor(const WebCore::Color& color)
3690 {
3691     ASSERT(m_colorPicker);
3692
3693     m_colorPicker->setSelectedColor(color);
3694 }
3695
3696 void WebPageProxy::endColorPicker()
3697 {
3698     ASSERT(m_colorPicker);
3699
3700     m_colorPicker->endPicker();
3701 }
3702
3703 void WebPageProxy::didChooseColor(const WebCore::Color& color)
3704 {
3705     if (!isValid())
3706         return;
3707
3708     m_process->send(Messages::WebPage::DidChooseColor(color), m_pageID);
3709 }
3710
3711 void WebPageProxy::didEndColorPicker()
3712 {
3713     if (!isValid())
3714         return;
3715
3716     if (m_colorPicker) {
3717         m_colorPicker->invalidate();
3718         m_colorPicker = nullptr;
3719     }
3720
3721     m_process->send(Messages::WebPage::DidEndColorPicker(), m_pageID);
3722 }
3723 #endif
3724
3725 void WebPageProxy::didDraw()
3726 {
3727     m_uiClient->didDraw(this);
3728 }
3729
3730 // Inspector
3731 WebInspectorProxy* WebPageProxy::inspector()
3732 {
3733     if (isClosed() || !isValid())
3734         return 0;
3735     return m_inspector.get();
3736 }
3737
3738 #if ENABLE(FULLSCREEN_API)
3739 WebFullScreenManagerProxy* WebPageProxy::fullScreenManager()
3740 {
3741     return m_fullScreenManager.get();
3742 }
3743 #endif
3744     
3745 #if PLATFORM(IOS)
3746 RefPtr<WebVideoFullscreenManagerProxy> WebPageProxy::videoFullscreenManager()
3747 {
3748     return m_videoFullscreenManager;
3749 }
3750 #endif
3751
3752 // BackForwardList
3753
3754 void WebPageProxy::backForwardAddItem(uint64_t itemID)
3755 {
3756     m_backForwardList->addItem(m_process->webBackForwardItem(itemID));
3757 }
3758
3759 void WebPageProxy::backForwardGoToItem(uint64_t itemID, SandboxExtension::Handle& sandboxExtensionHandle)
3760 {
3761     WebBackForwardListItem* item = m_process->webBackForwardItem(itemID);
3762     if (!item)
3763         return;
3764
3765     bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), item->url()), sandboxExtensionHandle);
3766     if (createdExtension)
3767         m_process->willAcquireUniversalFileReadSandboxExtension();
3768     m_backForwardList->goToItem(item);
3769 }
3770
3771 void WebPageProxy::backForwardItemAtIndex(int32_t index, uint64_t& itemID)
3772 {
3773     WebBackForwardListItem* item = m_backForwardList->itemAtIndex(index);
3774     itemID = item ? item->itemID() : 0;
3775 }
3776
3777 void WebPageProxy::backForwardBackListCount(int32_t& count)
3778 {
3779     count = m_backForwardList->backListCount();
3780 }
3781
3782 void WebPageProxy::backForwardForwardListCount(int32_t& count)
3783 {
3784     count = m_backForwardList->forwardListCount();
3785 }
3786
3787 void WebPageProxy::compositionWasCanceled(const EditorState& editorState)
3788 {
3789 #if PLATFORM(COCOA)
3790     m_pageClient.notifyInputContextAboutDiscardedComposition();
3791 #endif
3792     editorStateChanged(editorState);
3793 }
3794
3795 // Undo management
3796
3797 void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editAction)
3798 {
3799     registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
3800 }
3801     
3802 void WebPageProxy::registerInsertionUndoGrouping()
3803 {
3804 #if USE(INSERTION_UNDO_GROUPING)
3805     m_pageClient.registerInsertionUndoGrouping();
3806 #endif
3807 }
3808
3809 void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
3810 {
3811     result = m_pageClient.canUndoRedo(static_cast<UndoOrRedo>(action));
3812 }
3813
3814 void WebPageProxy::executeUndoRedo(uint32_t action, bool& result)
3815 {
3816     m_pageClient.executeUndoRedo(static_cast<UndoOrRedo>(action));
3817     result = true;
3818 }
3819
3820 void WebPageProxy::clearAllEditCommands()
3821 {
3822     m_pageClient.clearAllEditCommands();
3823 }
3824
3825 void WebPageProxy::didCountStringMatches(const String& string, uint32_t matchCount)
3826 {
3827     m_findClient->didCountStringMatches(this, string, matchCount);
3828 }
3829
3830 void WebPageProxy::didGetImageForFindMatch(const ShareableBitmap::Handle& contentImageHandle, uint32_t matchIndex)
3831 {
3832     m_findMatchesClient.didGetImageForMatchResult(this, WebImage::create(ShareableBitmap::create(contentImageHandle)).get(), matchIndex);
3833 }
3834
3835 void WebPageProxy::setTextIndicator(const TextIndicatorData& indicatorData, bool fadeOut)
3836 {
3837     m_pageClient.setTextIndicator(TextIndicator::create(indicatorData), fadeOut);
3838 }
3839
3840 void WebPageProxy::clearTextIndicator()
3841 {
3842     m_pageClient.setTextIndicator(nullptr, false);
3843 }
3844
3845 void WebPageProxy::setTextIndicatorAnimationProgress(float progress)
3846 {
3847     m_pageClient.setTextIndicatorAnimationProgress(progress);
3848 }
3849
3850 void WebPageProxy::didFindString(const String& string, uint32_t matchCount, int32_t matchIndex)
3851 {
3852     m_findClient->didFindString(this, string, matchCount, matchIndex);
3853 }
3854
3855 void WebPageProxy::didFindStringMatches(const String& string, const Vector<Vector<WebCore::IntRect>>& matchRects, int32_t firstIndexAfterSelection)
3856 {
3857     Vector<RefPtr<API::Object>> matches;
3858     matches.reserveInitialCapacity(matchRects.size());
3859
3860     for (const auto& rects : matchRects) {
3861         Vector<RefPtr<API::Object>> apiRects;
3862         apiRects.reserveInitialCapacity(rects.size());
3863
3864         for (const auto& rect : rects)
3865             apiRects.uncheckedAppend(API::Rect::create(toAPI(rect)));
3866
3867         matches.uncheckedAppend(API::Array::create(WTF::move(apiRects)));
3868     }
3869
3870     m_findMatchesClient.didFindStringMatches(this, string, API::Array::create(WTF::move(matches)).get(), firstIndexAfterSelection);
3871 }
3872
3873 void WebPageProxy::didFailToFindString(const String& string)
3874 {
3875     m_findClient->didFailToFindString(this, string);
3876 }
3877
3878 bool WebPageProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
3879 {
3880     return m_process->sendMessage(WTF::move(encoder), messageSendFlags);
3881 }
3882
3883 IPC::Connection* WebPageProxy::messageSenderConnection()
3884 {
3885     return m_process->connection();
3886 }
3887
3888 uint64_t WebPageProxy::messageSenderDestinationID()
3889 {
3890     return m_pageID;
3891 }
3892
3893 void WebPageProxy::valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex)
3894 {
3895     m_process->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
3896 }
3897
3898 void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index)
3899 {
3900     m_process->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID);
3901 }
3902
3903 NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent()
3904 {
3905     return m_currentlyProcessedMouseDownEvent.get();
3906 }
3907
3908 void WebPageProxy::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
3909 {
3910     process().send(Messages::WebPage::PostInjectedBundleMessage(messageName, UserData(process().transformObjectsToHandles(messageBody).get())), m_pageID);
3911 }
3912
3913 #if PLATFORM(GTK)
3914 void WebPageProxy::failedToShowPopupMenu()
3915 {
3916     m_process->send(Messages::WebPage::FailedToShowPopupMenu(), m_pageID);
3917 }
3918 #endif
3919
3920 void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
3921 {
3922     if (m_activePopupMenu) {
3923 #if PLATFORM(EFL)
3924         m_uiPopupMenuClient.hidePopupMenu(this);
3925 #else
3926         m_activePopupMenu->hidePopupMenu();
3927 #endif
3928         m_activePopupMenu->invalidate();
3929         m_activePopupMenu = nullptr;
3930     }
3931
3932     m_activePopupMenu = m_pageClient.createPopupMenuProxy(this);
3933
3934     if (!m_activePopupMenu)
3935         return;
3936
3937     // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3938     m_process->responsivenessTimer()->stop();
3939
3940 #if PLATFORM(EFL)
3941     UNUSED_PARAM(data);
3942     m_uiPopupMenuClient.showPopupMenu(this, m_activePopupMenu.get(), rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, selectedIndex);
3943 #else
3944
3945     // Showing a popup menu runs a nested runloop, which can handle messages that cause |this| to get closed.
3946     Ref<WebPageProxy> protect(*this);
3947     m_activePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex);
3948 #endif
3949 }
3950
3951 void WebPageProxy::hidePopupMenu()
3952 {
3953     if (!m_activePopupMenu)
3954         return;
3955
3956 #if PLATFORM(EFL)
3957     m_uiPopupMenuClient.hidePopupMenu(this);
3958 #else
3959     m_activePopupMenu->hidePopupMenu();
3960 #endif
3961     m_activePopupMenu->invalidate();
3962     m_activePopupMenu = nullptr;
3963 }
3964
3965 #if ENABLE(CONTEXT_MENUS)
3966 void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const ContextMenuContextData& contextMenuContextData, const Vector<WebContextMenuItemData>& proposedItems, const UserData& userData)
3967 {
3968     // Showing a context menu runs a nested runloop, which can handle messages that cause |this| to get closed.
3969     Ref<WebPageProxy> protect(*this);
3970
3971     internalShowContextMenu(menuLocation, contextMenuContextData, proposedItems, ContextMenuClientEligibility::EligibleForClient, userData);
3972     
3973     // No matter the result of internalShowContextMenu, always notify the WebProcess that the menu is hidden so it starts handling mouse events again.
3974     m_process->send(Messages::WebPage::ContextMenuHidden(), m_pageID);
3975 }
3976
3977 void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const ContextMenuContextData& contextMenuContextData, const Vector<WebContextMenuItemData>& proposedItems, ContextMenuClientEligibility clientEligibility, const UserData& userData)
3978 {
3979     m_activeContextMenuContextData = contextMenuContextData;
3980
3981     if (!m_contextMenuClient->hideContextMenu(*this) && m_activeContextMenu) {
3982         m_activeContextMenu->hideContextMenu();
3983         m_activeContextMenu = nullptr;
3984     }
3985
3986     m_activeContextMenu = m_pageClient.createContextMenuProxy(this);
3987     if (!m_activeContextMenu)
3988         return;
3989
3990     // Since showContextMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3991     m_process->responsivenessTimer()->stop();
3992
3993     // Unless this is an image control, give the PageContextMenuClient one last swipe at changing the menu.
3994     Vector<WebContextMenuItemData> items;
3995     bool useProposedItems = true;
3996     bool askClientToChangeMenu = clientEligibility == ContextMenuClientEligibility::EligibleForClient;
3997 #if ENABLE(SERVICE_CONTROLS)
3998     if (contextMenuContextData.controlledImage())
3999         askClientToChangeMenu = false;
4000 #endif
4001
4002     if (askClientToChangeMenu && m_contextMenuClient->getContextMenuFromProposedMenu(*this, proposedItems, items, contextMenuContextData.webHitTestResultData(), m_process->transformHandlesToObjects(userData.object()).get()))
4003         useProposedItems = false;
4004
4005     const Vector<WebContextMenuItemData>& itemsToShow = useProposedItems ? proposedItems : items;
4006     if (!m_contextMenuClient->showContextMenu(*this, menuLocation, itemsToShow))
4007         m_activeContextMenu->showContextMenu(menuLocation, itemsToShow, contextMenuContextData);
4008
4009     m_contextMenuClient->contextMenuDismissed(*this);
4010 }
4011
4012 void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item)
4013 {
4014     // Application custom items don't need to round-trip through to WebCore in the WebProcess.
4015     if (item.action() >= ContextMenuItemBaseApplicationTag) {
4016         m_contextMenuClient->customContextMenuItemSelected(*this, item);
4017         return;
4018     }
4019
4020 #if PLATFORM(COCOA)
4021     if (item.action() == ContextMenuItemTagSmartCopyPaste) {
4022         setSmartInsertDeleteEnabled(!isSmartInsertDeleteEnabled());
4023         return;
4024     }
4025     if (item.action() == ContextMenuItemTagSmartQuotes) {
4026         TextChecker::setAutomaticQuoteSubstitutionEnabled(!TextChecker::state().isAutomaticQuoteSubstitutionEnabled);
4027         m_process->updateTextCheckerState();
4028         return;
4029     }
4030     if (item.action() == ContextMenuItemTagSmartDashes) {
4031         TextChecker::setAutomaticDashSubstitutionEnabled(!TextChecker::state().isAutomaticDashSubstitutionEnabled);
4032         m_process->updateTextCheckerState();
4033         return;
4034     }
4035     if (item.action() == ContextMenuItemTagSmartLinks) {
4036         TextChecker::setAutomaticLinkDetectionEnabled(!TextChecker::state().isAutomaticLinkDetectionEnabled);
4037         m_process->updateTextCheckerState();
4038         return;
4039     }
4040     if (item.action() == ContextMenuItemTagTextReplacement) {
4041         TextChecker::setAutomaticTextReplacementEnabled(!TextChecker::state().isAutomaticTextReplacementEnabled);
4042         m_process->updateTextCheckerState();
4043         return;
4044     }
4045     if (item.action() == ContextMenuItemTagCorrectSpellingAutomatically) {
4046         TextChecker::setAutomaticSpellingCorrectionEnabled(!TextChecker::state().isAutomaticSpellingCorrectionEnabled);
4047         m_process->updateTextCheckerState();
4048         return;        
4049     }
4050     if (item.action() == ContextMenuItemTagShowSubstitutions) {
4051         TextChecker::toggleSubstitutionsPanelIsShowing();
4052         return;
4053     }
4054 #endif
4055     if (item.action() == ContextMenuItemTagDownloadImageToDisk) {
4056         m_process->processPool().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteImageURL));
4057         return;    
4058     }
4059     if (item.action() == ContextMenuItemTagDownloadLinkToDisk) {
4060         m_process->processPool().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteLinkURL));
4061         return;
4062     }
4063     if (item.action() == ContextMenuItemTagDownloadMediaToDisk) {
4064         m_process->processPool().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteMediaURL));
4065         return;
4066     }
4067     if (item.action() == ContextMenuItemTagCheckSpellingWhileTyping) {
4068         TextChecker::setContinuousSpellCheckingEnabled(!TextChecker::state().isContinuousSpellCheckingEnabled);
4069         m_process->updateTextCheckerState();
4070         return;
4071     }
4072     if (item.action() == ContextMenuItemTagCheckGrammarWithSpelling) {
4073         TextChecker::setGrammarCheckingEnabled(!TextChecker::state().isGrammarCheckingEnabled);
4074         m_process->updateTextCheckerState();
4075         return;
4076     }
4077     if (item.action() == ContextMenuItemTagShowSpellingPanel) {
4078         if (!TextChecker::spellingUIIsShowing())
4079             advanceToNextMisspelling(true);
4080         TextChecker::toggleSpellingUIIsShowing();
4081         return;
4082     }
4083     if (item.action() == ContextMenuItemTagLearnSpelling || item.action() == ContextMenuItemTagIgnoreSpelling)
4084         ++m_pendingLearnOrIgnoreWordMessageCount;
4085
4086     m_process->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID);
4087 }
4088 #endif // ENABLE(CONTEXT_MENUS)
4089
4090 #if PLATFORM(IOS)
4091 void WebPageProxy::didChooseFilesForOpenPanelWithDisplayStringAndIcon(const Vector<String>& fileURLs, const String& displayString, const API::Data* iconData)
4092 {
4093     if (!isValid())
4094         return;
4095
4096 #if ENABLE(SANDBOX_EXTENSIONS)
4097     // FIXME: The sandbox extensions should be sent with the DidChooseFilesForOpenPanel message. This
4098     // is gated on a way of passing SandboxExtension::Handles in a Vector.
4099     for (size_t i = 0; i < fileURLs.size(); ++i) {
4100         SandboxExtension::Handle sandboxExtensionHandle;
4101         SandboxExtension::createHandle(fileURLs[i], SandboxExtension::ReadOnly, sandboxExtensionHandle);
4102         m_process->send(Messages::WebPage::ExtendSandboxForFileFromOpenPanel(sandboxExtensionHandle), m_pageID);
4103     }
4104 #endif
4105
4106     m_process->send(Messages::WebPage::DidChooseFilesForOpenPanelWithDisplayStringAndIcon(fileURLs, displayString, iconData ? iconData->dataReference() : IPC::DataReference()), m_pageID);
4107
4108     m_openPanelResultListener->invalidate();
4109     m_openPanelResultListener = nullptr;
4110 }
4111 #endif
4112
4113 void WebPageProxy::didChooseFilesForOpenPanel(const Vector<String>& fileURLs)
4114 {
4115     if (!isValid())
4116         return;
4117
4118 #if ENABLE(SANDBOX_EXTENSIONS)
4119     // FIXME: The sandbox extensions should be sent with the DidChooseFilesForOpenPanel message. This
4120     // is gated on a way of passing SandboxExtension::Handles in a Vector.
4121     for (size_t i = 0; i < fileURLs.size(); ++i) {
4122         SandboxExtension::Handle sandboxExtensionHandle;
4123         SandboxExtension::createHandle(fileURLs[i], SandboxExtension::ReadOnly, sandboxExtensionHandle);
4124         m_process->send(Messages::WebPage::ExtendSandboxForFileFromOpenPanel(sandboxExtensionHandle), m_pageID);
4125     }
4126 #endif
4127
4128     m_process->send(Messages::WebPage::DidChooseFilesForOpenPanel(fileURLs), m_pageID);
4129
4130     m_openPanelResultListener->invalidate();
4131     m_openPanelResultListener = 0;
4132 }
4133
4134 void WebPageProxy::didCancelForOpenPanel()
4135 {
4136     if (!isValid())
4137         return;
4138
4139     m_process->send(Messages::WebPage::DidCancelForOpenPanel(), m_pageID);
4140     
4141     m_openPanelResultListener->invalidate();
4142     m_openPanelResultListener = 0;
4143 }
4144
4145 void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection)
4146 {
4147     m_process->send(Messages::WebPage::AdvanceToNextMisspelling(startBeforeSelection), m_pageID);
4148 }
4149
4150 void WebPageProxy::changeSpellingToWord(const String& word)
4151 {
4152     if (word.isEmpty())
4153         return;
4154
4155     m_process->send(Messages::WebPage::ChangeSpellingToWord(word), m_pageID);
4156 }
4157
4158 void WebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> commandProxy, UndoOrRedo undoOrRedo)
4159 {
4160     m_pageClient.registerEditCommand(commandProxy, undoOrRedo);
4161 }
4162
4163 void WebPageProxy::addEditCommand(WebEditCommandProxy* command)
4164 {
4165     m_editCommandSet.add(command);
4166 }
4167
4168 void WebPageProxy::removeEditCommand(WebEditCommandProxy* command)
4169 {
4170     m_editCommandSet.remove(command);
4171
4172     if (!isValid())
4173         return;
4174     m_process->send(Messages::WebPage::DidRemoveEditCommand(command->commandID()), m_pageID);
4175 }
4176
4177 bool WebPageProxy::isValidEditCommand(WebEditCommandProxy* command)
4178 {
4179     return m_editCommandSet.find(command) != m_editCommandSet.end();
4180 }
4181
4182 int64_t WebPageProxy::spellDocumentTag()
4183 {
4184     if (!m_hasSpellDocumentTag) {
4185         m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(this);
4186         m_hasSpellDocumentTag = true;
4187     }
4188
4189     return m_spellDocumentTag;
4190 }
4191
4192 #if USE(UNIFIED_TEXT_CHECKING)
4193 void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<TextCheckingResult>& results)
4194 {
4195     results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text, checkingTypes);
4196 }
4197 #endif
4198
4199 void WebPageProxy::checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength)
4200 {
4201     TextChecker::checkSpellingOfString(spellDocumentTag(), text, misspellingLocation, misspellingLength);
4202 }
4203
4204 void WebPageProxy::checkGrammarOfString(const String& text, Vector<GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength)
4205 {
4206     TextChecker::checkGrammarOfString(spellDocumentTag(), text, grammarDetails, badGrammarLocation, badGrammarLength);
4207 }
4208
4209 void WebPageProxy::spellingUIIsShowing(bool& isShowing)
4210 {
4211     isShowing = TextChecker::spellingUIIsShowing();
4212 }
4213
4214 void WebPageProxy::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
4215 {
4216     TextChecker::updateSpellingUIWithMisspelledWord(spellDocumentTag(), misspelledWord);
4217 }
4218
4219 void WebPageProxy::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
4220 {
4221     TextChecker::updateSpellingUIWithGrammarString(spellDocumentTag(), badGrammarPhrase, grammarDetail);
4222 }
4223
4224 void WebPageProxy::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
4225 {
4226     TextChecker::getGuessesForWord(spellDocumentTag(), word, context, guesses);
4227 }
4228
4229 void WebPageProxy::learnWord(const String& word)
4230 {
4231     MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
4232     --m_pendingLearnOrIgnoreWordMessageCount;
4233
4234     TextChecker::learnWord(spellDocumentTag(), word);
4235 }
4236
4237 void WebPageProxy::ignoreWord(const String& word)
4238 {
4239     MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
4240     --m_pendingLearnOrIgnoreWordMessageCount;
4241
4242     TextChecker::ignoreWord(spellDocumentTag(), word);
4243 }
4244
4245 void WebPageProxy::requestCheckingOfString(uint64_t requestID, const TextCheckingRequestData& request)
4246 {
4247     TextChecker::requestCheckingOfString(TextCheckerCompletion::create(requestID, request, this));
4248 }
4249
4250 void WebPageProxy::didFinishCheckingText(uint64_t requestID, const Vector<WebCore::TextCheckingResult>& result)
4251 {
4252     m_process->send(Messages::WebPage::DidFinishCheckingText(requestID, result), m_pageID);
4253 }
4254
4255 void WebPageProxy::didCancelCheckingText(uint64_t requestID)
4256 {
4257     m_process->send(Messages::WebPage::DidCancelCheckingText(requestID), m_pageID);
4258 }
4259 // Other
4260